linux/fs/nfs/filelayout/filelayout.c
<<
>>
Prefs
   1/*
   2 *  Module for the pnfs nfs4 file layout driver.
   3 *  Defines all I/O and Policy interface operations, plus code
   4 *  to register itself with the pNFS client.
   5 *
   6 *  Copyright (c) 2002
   7 *  The Regents of the University of Michigan
   8 *  All Rights Reserved
   9 *
  10 *  Dean Hildebrand <dhildebz@umich.edu>
  11 *
  12 *  Permission is granted to use, copy, create derivative works, and
  13 *  redistribute this software and such derivative works for any purpose,
  14 *  so long as the name of the University of Michigan is not used in
  15 *  any advertising or publicity pertaining to the use or distribution
  16 *  of this software without specific, written prior authorization. If
  17 *  the above copyright notice or any other identification of the
  18 *  University of Michigan is included in any copy of any portion of
  19 *  this software, then the disclaimer below must also be included.
  20 *
  21 *  This software is provided as is, without representation or warranty
  22 *  of any kind either express or implied, including without limitation
  23 *  the implied warranties of merchantability, fitness for a particular
  24 *  purpose, or noninfringement.  The Regents of the University of
  25 *  Michigan shall not be liable for any damages, including special,
  26 *  indirect, incidental, or consequential damages, with respect to any
  27 *  claim arising out of or in connection with the use of the software,
  28 *  even if it has been or is hereafter advised of the possibility of
  29 *  such damages.
  30 */
  31
  32#include <linux/nfs_fs.h>
  33#include <linux/nfs_page.h>
  34#include <linux/module.h>
  35#include <linux/backing-dev.h>
  36
  37#include <linux/sunrpc/metrics.h>
  38
  39#include "../nfs4session.h"
  40#include "../internal.h"
  41#include "../delegation.h"
  42#include "filelayout.h"
  43#include "../nfs4trace.h"
  44
  45#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
  46
  47MODULE_LICENSE("GPL");
  48MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>");
  49MODULE_DESCRIPTION("The NFSv4 file layout driver");
  50
  51#define FILELAYOUT_POLL_RETRY_MAX     (15*HZ)
  52
  53static loff_t
  54filelayout_get_dense_offset(struct nfs4_filelayout_segment *flseg,
  55                            loff_t offset)
  56{
  57        u32 stripe_width = flseg->stripe_unit * flseg->dsaddr->stripe_count;
  58        u64 stripe_no;
  59        u32 rem;
  60
  61        offset -= flseg->pattern_offset;
  62        stripe_no = div_u64(offset, stripe_width);
  63        div_u64_rem(offset, flseg->stripe_unit, &rem);
  64
  65        return stripe_no * flseg->stripe_unit + rem;
  66}
  67
  68/* This function is used by the layout driver to calculate the
  69 * offset of the file on the dserver based on whether the
  70 * layout type is STRIPE_DENSE or STRIPE_SPARSE
  71 */
  72static loff_t
  73filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset)
  74{
  75        struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
  76
  77        switch (flseg->stripe_type) {
  78        case STRIPE_SPARSE:
  79                return offset;
  80
  81        case STRIPE_DENSE:
  82                return filelayout_get_dense_offset(flseg, offset);
  83        }
  84
  85        BUG();
  86}
  87
  88static void filelayout_reset_write(struct nfs_pgio_header *hdr)
  89{
  90        struct rpc_task *task = &hdr->task;
  91
  92        if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
  93                dprintk("%s Reset task %5u for i/o through MDS "
  94                        "(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
  95                        hdr->task.tk_pid,
  96                        hdr->inode->i_sb->s_id,
  97                        (unsigned long long)NFS_FILEID(hdr->inode),
  98                        hdr->args.count,
  99                        (unsigned long long)hdr->args.offset);
 100
 101                task->tk_status = pnfs_write_done_resend_to_mds(hdr);
 102        }
 103}
 104
 105static void filelayout_reset_read(struct nfs_pgio_header *hdr)
 106{
 107        struct rpc_task *task = &hdr->task;
 108
 109        if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
 110                dprintk("%s Reset task %5u for i/o through MDS "
 111                        "(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
 112                        hdr->task.tk_pid,
 113                        hdr->inode->i_sb->s_id,
 114                        (unsigned long long)NFS_FILEID(hdr->inode),
 115                        hdr->args.count,
 116                        (unsigned long long)hdr->args.offset);
 117
 118                task->tk_status = pnfs_read_done_resend_to_mds(hdr);
 119        }
 120}
 121
 122static int filelayout_async_handle_error(struct rpc_task *task,
 123                                         struct nfs4_state *state,
 124                                         struct nfs_client *clp,
 125                                         struct pnfs_layout_segment *lseg)
 126{
 127        struct pnfs_layout_hdr *lo = lseg->pls_layout;
 128        struct inode *inode = lo->plh_inode;
 129        struct nfs_server *mds_server = NFS_SERVER(inode);
 130        struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
 131        struct nfs_client *mds_client = mds_server->nfs_client;
 132        struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table;
 133
 134        if (task->tk_status >= 0)
 135                return 0;
 136
 137        switch (task->tk_status) {
 138        /* MDS state errors */
 139        case -NFS4ERR_DELEG_REVOKED:
 140        case -NFS4ERR_ADMIN_REVOKED:
 141        case -NFS4ERR_BAD_STATEID:
 142        case -NFS4ERR_OPENMODE:
 143                if (state == NULL)
 144                        break;
 145                if (nfs4_schedule_stateid_recovery(mds_server, state) < 0)
 146                        goto out_bad_stateid;
 147                goto wait_on_recovery;
 148        case -NFS4ERR_EXPIRED:
 149                if (state != NULL) {
 150                        if (nfs4_schedule_stateid_recovery(mds_server, state) < 0)
 151                                goto out_bad_stateid;
 152                }
 153                nfs4_schedule_lease_recovery(mds_client);
 154                goto wait_on_recovery;
 155        /* DS session errors */
 156        case -NFS4ERR_BADSESSION:
 157        case -NFS4ERR_BADSLOT:
 158        case -NFS4ERR_BAD_HIGH_SLOT:
 159        case -NFS4ERR_DEADSESSION:
 160        case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
 161        case -NFS4ERR_SEQ_FALSE_RETRY:
 162        case -NFS4ERR_SEQ_MISORDERED:
 163                dprintk("%s ERROR %d, Reset session. Exchangeid "
 164                        "flags 0x%x\n", __func__, task->tk_status,
 165                        clp->cl_exchange_flags);
 166                nfs4_schedule_session_recovery(clp->cl_session, task->tk_status);
 167                break;
 168        case -NFS4ERR_DELAY:
 169        case -NFS4ERR_GRACE:
 170                rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX);
 171                break;
 172        case -NFS4ERR_RETRY_UNCACHED_REP:
 173                break;
 174        /* Invalidate Layout errors */
 175        case -NFS4ERR_PNFS_NO_LAYOUT:
 176        case -ESTALE:           /* mapped NFS4ERR_STALE */
 177        case -EBADHANDLE:       /* mapped NFS4ERR_BADHANDLE */
 178        case -EISDIR:           /* mapped NFS4ERR_ISDIR */
 179        case -NFS4ERR_FHEXPIRED:
 180        case -NFS4ERR_WRONG_TYPE:
 181                dprintk("%s Invalid layout error %d\n", __func__,
 182                        task->tk_status);
 183                /*
 184                 * Destroy layout so new i/o will get a new layout.
 185                 * Layout will not be destroyed until all current lseg
 186                 * references are put. Mark layout as invalid to resend failed
 187                 * i/o and all i/o waiting on the slot table to the MDS until
 188                 * layout is destroyed and a new valid layout is obtained.
 189                 */
 190                pnfs_destroy_layout(NFS_I(inode));
 191                rpc_wake_up(&tbl->slot_tbl_waitq);
 192                goto reset;
 193        /* RPC connection errors */
 194        case -ECONNREFUSED:
 195        case -EHOSTDOWN:
 196        case -EHOSTUNREACH:
 197        case -ENETUNREACH:
 198        case -EIO:
 199        case -ETIMEDOUT:
 200        case -EPIPE:
 201                dprintk("%s DS connection error %d\n", __func__,
 202                        task->tk_status);
 203                nfs4_mark_deviceid_unavailable(devid);
 204                pnfs_error_mark_layout_for_return(inode, lseg);
 205                pnfs_set_lo_fail(lseg);
 206                rpc_wake_up(&tbl->slot_tbl_waitq);
 207                /* fall through */
 208        default:
 209reset:
 210                dprintk("%s Retry through MDS. Error %d\n", __func__,
 211                        task->tk_status);
 212                return -NFS4ERR_RESET_TO_MDS;
 213        }
 214out:
 215        task->tk_status = 0;
 216        return -EAGAIN;
 217out_bad_stateid:
 218        task->tk_status = -EIO;
 219        return 0;
 220wait_on_recovery:
 221        rpc_sleep_on(&mds_client->cl_rpcwaitq, task, NULL);
 222        if (test_bit(NFS4CLNT_MANAGER_RUNNING, &mds_client->cl_state) == 0)
 223                rpc_wake_up_queued_task(&mds_client->cl_rpcwaitq, task);
 224        goto out;
 225}
 226
 227/* NFS_PROTO call done callback routines */
 228
 229static int filelayout_read_done_cb(struct rpc_task *task,
 230                                struct nfs_pgio_header *hdr)
 231{
 232        int err;
 233
 234        trace_nfs4_pnfs_read(hdr, task->tk_status);
 235        err = filelayout_async_handle_error(task, hdr->args.context->state,
 236                                            hdr->ds_clp, hdr->lseg);
 237
 238        switch (err) {
 239        case -NFS4ERR_RESET_TO_MDS:
 240                filelayout_reset_read(hdr);
 241                return task->tk_status;
 242        case -EAGAIN:
 243                rpc_restart_call_prepare(task);
 244                return -EAGAIN;
 245        }
 246
 247        return 0;
 248}
 249
 250/*
 251 * We reference the rpc_cred of the first WRITE that triggers the need for
 252 * a LAYOUTCOMMIT, and use it to send the layoutcommit compound.
 253 * rfc5661 is not clear about which credential should be used.
 254 */
 255static void
 256filelayout_set_layoutcommit(struct nfs_pgio_header *hdr)
 257{
 258        loff_t end_offs = 0;
 259
 260        if (FILELAYOUT_LSEG(hdr->lseg)->commit_through_mds ||
 261            hdr->res.verf->committed == NFS_FILE_SYNC)
 262                return;
 263        if (hdr->res.verf->committed == NFS_DATA_SYNC)
 264                end_offs = hdr->mds_offset + (loff_t)hdr->res.count;
 265
 266        /* Note: if the write is unstable, don't set end_offs until commit */
 267        pnfs_set_layoutcommit(hdr->inode, hdr->lseg, end_offs);
 268        dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino,
 269                (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb);
 270}
 271
 272bool
 273filelayout_test_devid_unavailable(struct nfs4_deviceid_node *node)
 274{
 275        return filelayout_test_devid_invalid(node) ||
 276                nfs4_test_deviceid_unavailable(node);
 277}
 278
 279static bool
 280filelayout_reset_to_mds(struct pnfs_layout_segment *lseg)
 281{
 282        struct nfs4_deviceid_node *node = FILELAYOUT_DEVID_NODE(lseg);
 283
 284        return filelayout_test_devid_unavailable(node);
 285}
 286
 287/*
 288 * Call ops for the async read/write cases
 289 * In the case of dense layouts, the offset needs to be reset to its
 290 * original value.
 291 */
 292static void filelayout_read_prepare(struct rpc_task *task, void *data)
 293{
 294        struct nfs_pgio_header *hdr = data;
 295
 296        if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) {
 297                rpc_exit(task, -EIO);
 298                return;
 299        }
 300        if (filelayout_reset_to_mds(hdr->lseg)) {
 301                dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
 302                filelayout_reset_read(hdr);
 303                rpc_exit(task, 0);
 304                return;
 305        }
 306        hdr->pgio_done_cb = filelayout_read_done_cb;
 307
 308        if (nfs41_setup_sequence(hdr->ds_clp->cl_session,
 309                        &hdr->args.seq_args,
 310                        &hdr->res.seq_res,
 311                        task))
 312                return;
 313        if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
 314                        hdr->args.lock_context, FMODE_READ) == -EIO)
 315                rpc_exit(task, -EIO); /* lost lock, terminate I/O */
 316}
 317
 318static void filelayout_read_call_done(struct rpc_task *task, void *data)
 319{
 320        struct nfs_pgio_header *hdr = data;
 321
 322        dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status);
 323
 324        if (test_bit(NFS_IOHDR_REDO, &hdr->flags) &&
 325            task->tk_status == 0) {
 326                nfs41_sequence_done(task, &hdr->res.seq_res);
 327                return;
 328        }
 329
 330        /* Note this may cause RPC to be resent */
 331        hdr->mds_ops->rpc_call_done(task, data);
 332}
 333
 334static void filelayout_read_count_stats(struct rpc_task *task, void *data)
 335{
 336        struct nfs_pgio_header *hdr = data;
 337
 338        rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics);
 339}
 340
 341static int filelayout_write_done_cb(struct rpc_task *task,
 342                                struct nfs_pgio_header *hdr)
 343{
 344        int err;
 345
 346        trace_nfs4_pnfs_write(hdr, task->tk_status);
 347        err = filelayout_async_handle_error(task, hdr->args.context->state,
 348                                            hdr->ds_clp, hdr->lseg);
 349
 350        switch (err) {
 351        case -NFS4ERR_RESET_TO_MDS:
 352                filelayout_reset_write(hdr);
 353                return task->tk_status;
 354        case -EAGAIN:
 355                rpc_restart_call_prepare(task);
 356                return -EAGAIN;
 357        }
 358
 359        filelayout_set_layoutcommit(hdr);
 360
 361        /* zero out the fattr */
 362        hdr->fattr.valid = 0;
 363        if (task->tk_status >= 0)
 364                nfs_writeback_update_inode(hdr);
 365
 366        return 0;
 367}
 368
 369static int filelayout_commit_done_cb(struct rpc_task *task,
 370                                     struct nfs_commit_data *data)
 371{
 372        int err;
 373
 374        trace_nfs4_pnfs_commit_ds(data, task->tk_status);
 375        err = filelayout_async_handle_error(task, NULL, data->ds_clp,
 376                                            data->lseg);
 377
 378        switch (err) {
 379        case -NFS4ERR_RESET_TO_MDS:
 380                pnfs_generic_prepare_to_resend_writes(data);
 381                return -EAGAIN;
 382        case -EAGAIN:
 383                rpc_restart_call_prepare(task);
 384                return -EAGAIN;
 385        }
 386
 387        pnfs_set_layoutcommit(data->inode, data->lseg, data->lwb);
 388
 389        return 0;
 390}
 391
 392static void filelayout_write_prepare(struct rpc_task *task, void *data)
 393{
 394        struct nfs_pgio_header *hdr = data;
 395
 396        if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) {
 397                rpc_exit(task, -EIO);
 398                return;
 399        }
 400        if (filelayout_reset_to_mds(hdr->lseg)) {
 401                dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
 402                filelayout_reset_write(hdr);
 403                rpc_exit(task, 0);
 404                return;
 405        }
 406        if (nfs41_setup_sequence(hdr->ds_clp->cl_session,
 407                        &hdr->args.seq_args,
 408                        &hdr->res.seq_res,
 409                        task))
 410                return;
 411        if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
 412                        hdr->args.lock_context, FMODE_WRITE) == -EIO)
 413                rpc_exit(task, -EIO); /* lost lock, terminate I/O */
 414}
 415
 416static void filelayout_write_call_done(struct rpc_task *task, void *data)
 417{
 418        struct nfs_pgio_header *hdr = data;
 419
 420        if (test_bit(NFS_IOHDR_REDO, &hdr->flags) &&
 421            task->tk_status == 0) {
 422                nfs41_sequence_done(task, &hdr->res.seq_res);
 423                return;
 424        }
 425
 426        /* Note this may cause RPC to be resent */
 427        hdr->mds_ops->rpc_call_done(task, data);
 428}
 429
 430static void filelayout_write_count_stats(struct rpc_task *task, void *data)
 431{
 432        struct nfs_pgio_header *hdr = data;
 433
 434        rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics);
 435}
 436
 437static void filelayout_commit_prepare(struct rpc_task *task, void *data)
 438{
 439        struct nfs_commit_data *wdata = data;
 440
 441        nfs41_setup_sequence(wdata->ds_clp->cl_session,
 442                        &wdata->args.seq_args,
 443                        &wdata->res.seq_res,
 444                        task);
 445}
 446
 447static void filelayout_commit_count_stats(struct rpc_task *task, void *data)
 448{
 449        struct nfs_commit_data *cdata = data;
 450
 451        rpc_count_iostats(task, NFS_SERVER(cdata->inode)->client->cl_metrics);
 452}
 453
 454static const struct rpc_call_ops filelayout_read_call_ops = {
 455        .rpc_call_prepare = filelayout_read_prepare,
 456        .rpc_call_done = filelayout_read_call_done,
 457        .rpc_count_stats = filelayout_read_count_stats,
 458        .rpc_release = pnfs_generic_rw_release,
 459};
 460
 461static const struct rpc_call_ops filelayout_write_call_ops = {
 462        .rpc_call_prepare = filelayout_write_prepare,
 463        .rpc_call_done = filelayout_write_call_done,
 464        .rpc_count_stats = filelayout_write_count_stats,
 465        .rpc_release = pnfs_generic_rw_release,
 466};
 467
 468static const struct rpc_call_ops filelayout_commit_call_ops = {
 469        .rpc_call_prepare = filelayout_commit_prepare,
 470        .rpc_call_done = pnfs_generic_write_commit_done,
 471        .rpc_count_stats = filelayout_commit_count_stats,
 472        .rpc_release = pnfs_generic_commit_release,
 473};
 474
 475static enum pnfs_try_status
 476filelayout_read_pagelist(struct nfs_pgio_header *hdr)
 477{
 478        struct pnfs_layout_segment *lseg = hdr->lseg;
 479        struct nfs4_pnfs_ds *ds;
 480        struct rpc_clnt *ds_clnt;
 481        loff_t offset = hdr->args.offset;
 482        u32 j, idx;
 483        struct nfs_fh *fh;
 484
 485        dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n",
 486                __func__, hdr->inode->i_ino,
 487                hdr->args.pgbase, (size_t)hdr->args.count, offset);
 488
 489        /* Retrieve the correct rpc_client for the byte range */
 490        j = nfs4_fl_calc_j_index(lseg, offset);
 491        idx = nfs4_fl_calc_ds_index(lseg, j);
 492        ds = nfs4_fl_prepare_ds(lseg, idx);
 493        if (!ds)
 494                return PNFS_NOT_ATTEMPTED;
 495
 496        ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, hdr->inode);
 497        if (IS_ERR(ds_clnt))
 498                return PNFS_NOT_ATTEMPTED;
 499
 500        dprintk("%s USE DS: %s cl_count %d\n", __func__,
 501                ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count));
 502
 503        /* No multipath support. Use first DS */
 504        atomic_inc(&ds->ds_clp->cl_count);
 505        hdr->ds_clp = ds->ds_clp;
 506        hdr->ds_commit_idx = idx;
 507        fh = nfs4_fl_select_ds_fh(lseg, j);
 508        if (fh)
 509                hdr->args.fh = fh;
 510
 511        hdr->args.offset = filelayout_get_dserver_offset(lseg, offset);
 512        hdr->mds_offset = offset;
 513
 514        /* Perform an asynchronous read to ds */
 515        nfs_initiate_pgio(ds_clnt, hdr, hdr->cred,
 516                          NFS_PROTO(hdr->inode), &filelayout_read_call_ops,
 517                          0, RPC_TASK_SOFTCONN);
 518        return PNFS_ATTEMPTED;
 519}
 520
 521/* Perform async writes. */
 522static enum pnfs_try_status
 523filelayout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
 524{
 525        struct pnfs_layout_segment *lseg = hdr->lseg;
 526        struct nfs4_pnfs_ds *ds;
 527        struct rpc_clnt *ds_clnt;
 528        loff_t offset = hdr->args.offset;
 529        u32 j, idx;
 530        struct nfs_fh *fh;
 531
 532        /* Retrieve the correct rpc_client for the byte range */
 533        j = nfs4_fl_calc_j_index(lseg, offset);
 534        idx = nfs4_fl_calc_ds_index(lseg, j);
 535        ds = nfs4_fl_prepare_ds(lseg, idx);
 536        if (!ds)
 537                return PNFS_NOT_ATTEMPTED;
 538
 539        ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, hdr->inode);
 540        if (IS_ERR(ds_clnt))
 541                return PNFS_NOT_ATTEMPTED;
 542
 543        dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d\n",
 544                __func__, hdr->inode->i_ino, sync, (size_t) hdr->args.count,
 545                offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count));
 546
 547        hdr->pgio_done_cb = filelayout_write_done_cb;
 548        atomic_inc(&ds->ds_clp->cl_count);
 549        hdr->ds_clp = ds->ds_clp;
 550        hdr->ds_commit_idx = idx;
 551        fh = nfs4_fl_select_ds_fh(lseg, j);
 552        if (fh)
 553                hdr->args.fh = fh;
 554        hdr->args.offset = filelayout_get_dserver_offset(lseg, offset);
 555
 556        /* Perform an asynchronous write */
 557        nfs_initiate_pgio(ds_clnt, hdr, hdr->cred,
 558                          NFS_PROTO(hdr->inode), &filelayout_write_call_ops,
 559                          sync, RPC_TASK_SOFTCONN);
 560        return PNFS_ATTEMPTED;
 561}
 562
 563/*
 564 * filelayout_check_layout()
 565 *
 566 * Make sure layout segment parameters are sane WRT the device.
 567 * At this point no generic layer initialization of the lseg has occurred,
 568 * and nothing has been added to the layout_hdr cache.
 569 *
 570 */
 571static int
 572filelayout_check_layout(struct pnfs_layout_hdr *lo,
 573                        struct nfs4_filelayout_segment *fl,
 574                        struct nfs4_layoutget_res *lgr,
 575                        struct nfs4_deviceid *id,
 576                        gfp_t gfp_flags)
 577{
 578        struct nfs4_deviceid_node *d;
 579        struct nfs4_file_layout_dsaddr *dsaddr;
 580        int status = -EINVAL;
 581
 582        dprintk("--> %s\n", __func__);
 583
 584        /* FIXME: remove this check when layout segment support is added */
 585        if (lgr->range.offset != 0 ||
 586            lgr->range.length != NFS4_MAX_UINT64) {
 587                dprintk("%s Only whole file layouts supported. Use MDS i/o\n",
 588                        __func__);
 589                goto out;
 590        }
 591
 592        if (fl->pattern_offset > lgr->range.offset) {
 593                dprintk("%s pattern_offset %lld too large\n",
 594                                __func__, fl->pattern_offset);
 595                goto out;
 596        }
 597
 598        if (!fl->stripe_unit) {
 599                dprintk("%s Invalid stripe unit (%u)\n",
 600                        __func__, fl->stripe_unit);
 601                goto out;
 602        }
 603
 604        /* find and reference the deviceid */
 605        d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), id,
 606                        lo->plh_lc_cred, gfp_flags);
 607        if (d == NULL)
 608                goto out;
 609
 610        dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
 611        /* Found deviceid is unavailable */
 612        if (filelayout_test_devid_unavailable(&dsaddr->id_node))
 613                goto out_put;
 614
 615        fl->dsaddr = dsaddr;
 616
 617        if (fl->first_stripe_index >= dsaddr->stripe_count) {
 618                dprintk("%s Bad first_stripe_index %u\n",
 619                                __func__, fl->first_stripe_index);
 620                goto out_put;
 621        }
 622
 623        if ((fl->stripe_type == STRIPE_SPARSE &&
 624            fl->num_fh > 1 && fl->num_fh != dsaddr->ds_num) ||
 625            (fl->stripe_type == STRIPE_DENSE &&
 626            fl->num_fh != dsaddr->stripe_count)) {
 627                dprintk("%s num_fh %u not valid for given packing\n",
 628                        __func__, fl->num_fh);
 629                goto out_put;
 630        }
 631
 632        status = 0;
 633out:
 634        dprintk("--> %s returns %d\n", __func__, status);
 635        return status;
 636out_put:
 637        nfs4_fl_put_deviceid(dsaddr);
 638        goto out;
 639}
 640
 641static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl)
 642{
 643        int i;
 644
 645        if (fl->fh_array) {
 646                for (i = 0; i < fl->num_fh; i++) {
 647                        if (!fl->fh_array[i])
 648                                break;
 649                        kfree(fl->fh_array[i]);
 650                }
 651                kfree(fl->fh_array);
 652        }
 653        kfree(fl);
 654}
 655
 656static int
 657filelayout_decode_layout(struct pnfs_layout_hdr *flo,
 658                         struct nfs4_filelayout_segment *fl,
 659                         struct nfs4_layoutget_res *lgr,
 660                         struct nfs4_deviceid *id,
 661                         gfp_t gfp_flags)
 662{
 663        struct xdr_stream stream;
 664        struct xdr_buf buf;
 665        struct page *scratch;
 666        __be32 *p;
 667        uint32_t nfl_util;
 668        int i;
 669
 670        dprintk("%s: set_layout_map Begin\n", __func__);
 671
 672        scratch = alloc_page(gfp_flags);
 673        if (!scratch)
 674                return -ENOMEM;
 675
 676        xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len);
 677        xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
 678
 679        /* 20 = ufl_util (4), first_stripe_index (4), pattern_offset (8),
 680         * num_fh (4) */
 681        p = xdr_inline_decode(&stream, NFS4_DEVICEID4_SIZE + 20);
 682        if (unlikely(!p))
 683                goto out_err;
 684
 685        memcpy(id, p, sizeof(*id));
 686        p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
 687        nfs4_print_deviceid(id);
 688
 689        nfl_util = be32_to_cpup(p++);
 690        if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS)
 691                fl->commit_through_mds = 1;
 692        if (nfl_util & NFL4_UFLG_DENSE)
 693                fl->stripe_type = STRIPE_DENSE;
 694        else
 695                fl->stripe_type = STRIPE_SPARSE;
 696        fl->stripe_unit = nfl_util & ~NFL4_UFLG_MASK;
 697
 698        fl->first_stripe_index = be32_to_cpup(p++);
 699        p = xdr_decode_hyper(p, &fl->pattern_offset);
 700        fl->num_fh = be32_to_cpup(p++);
 701
 702        dprintk("%s: nfl_util 0x%X num_fh %u fsi %u po %llu\n",
 703                __func__, nfl_util, fl->num_fh, fl->first_stripe_index,
 704                fl->pattern_offset);
 705
 706        /* Note that a zero value for num_fh is legal for STRIPE_SPARSE.
 707         * Futher checking is done in filelayout_check_layout */
 708        if (fl->num_fh >
 709            max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT))
 710                goto out_err;
 711
 712        if (fl->num_fh > 0) {
 713                fl->fh_array = kcalloc(fl->num_fh, sizeof(fl->fh_array[0]),
 714                                       gfp_flags);
 715                if (!fl->fh_array)
 716                        goto out_err;
 717        }
 718
 719        for (i = 0; i < fl->num_fh; i++) {
 720                /* Do we want to use a mempool here? */
 721                fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), gfp_flags);
 722                if (!fl->fh_array[i])
 723                        goto out_err;
 724
 725                p = xdr_inline_decode(&stream, 4);
 726                if (unlikely(!p))
 727                        goto out_err;
 728                fl->fh_array[i]->size = be32_to_cpup(p++);
 729                if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) {
 730                        printk(KERN_ERR "NFS: Too big fh %d received %d\n",
 731                               i, fl->fh_array[i]->size);
 732                        goto out_err;
 733                }
 734
 735                p = xdr_inline_decode(&stream, fl->fh_array[i]->size);
 736                if (unlikely(!p))
 737                        goto out_err;
 738                memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size);
 739                dprintk("DEBUG: %s: fh len %d\n", __func__,
 740                        fl->fh_array[i]->size);
 741        }
 742
 743        __free_page(scratch);
 744        return 0;
 745
 746out_err:
 747        __free_page(scratch);
 748        return -EIO;
 749}
 750
 751static void
 752filelayout_free_lseg(struct pnfs_layout_segment *lseg)
 753{
 754        struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
 755
 756        dprintk("--> %s\n", __func__);
 757        nfs4_fl_put_deviceid(fl->dsaddr);
 758        /* This assumes a single RW lseg */
 759        if (lseg->pls_range.iomode == IOMODE_RW) {
 760                struct nfs4_filelayout *flo;
 761
 762                flo = FILELAYOUT_FROM_HDR(lseg->pls_layout);
 763                flo->commit_info.nbuckets = 0;
 764                kfree(flo->commit_info.buckets);
 765                flo->commit_info.buckets = NULL;
 766        }
 767        _filelayout_free_lseg(fl);
 768}
 769
 770static int
 771filelayout_alloc_commit_info(struct pnfs_layout_segment *lseg,
 772                             struct nfs_commit_info *cinfo,
 773                             gfp_t gfp_flags)
 774{
 775        struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
 776        struct pnfs_commit_bucket *buckets;
 777        int size, i;
 778
 779        if (fl->commit_through_mds)
 780                return 0;
 781
 782        size = (fl->stripe_type == STRIPE_SPARSE) ?
 783                fl->dsaddr->ds_num : fl->dsaddr->stripe_count;
 784
 785        if (cinfo->ds->nbuckets >= size) {
 786                /* This assumes there is only one IOMODE_RW lseg.  What
 787                 * we really want to do is have a layout_hdr level
 788                 * dictionary of <multipath_list4, fh> keys, each
 789                 * associated with a struct list_head, populated by calls
 790                 * to filelayout_write_pagelist().
 791                 * */
 792                return 0;
 793        }
 794
 795        buckets = kcalloc(size, sizeof(struct pnfs_commit_bucket),
 796                          gfp_flags);
 797        if (!buckets)
 798                return -ENOMEM;
 799        for (i = 0; i < size; i++) {
 800                INIT_LIST_HEAD(&buckets[i].written);
 801                INIT_LIST_HEAD(&buckets[i].committing);
 802                /* mark direct verifier as unset */
 803                buckets[i].direct_verf.committed = NFS_INVALID_STABLE_HOW;
 804        }
 805
 806        spin_lock(&cinfo->inode->i_lock);
 807        if (cinfo->ds->nbuckets >= size)
 808                goto out;
 809        for (i = 0; i < cinfo->ds->nbuckets; i++) {
 810                list_splice(&cinfo->ds->buckets[i].written,
 811                            &buckets[i].written);
 812                list_splice(&cinfo->ds->buckets[i].committing,
 813                            &buckets[i].committing);
 814                buckets[i].direct_verf.committed =
 815                        cinfo->ds->buckets[i].direct_verf.committed;
 816                buckets[i].wlseg = cinfo->ds->buckets[i].wlseg;
 817                buckets[i].clseg = cinfo->ds->buckets[i].clseg;
 818        }
 819        swap(cinfo->ds->buckets, buckets);
 820        cinfo->ds->nbuckets = size;
 821out:
 822        spin_unlock(&cinfo->inode->i_lock);
 823        kfree(buckets);
 824        return 0;
 825}
 826
 827static struct pnfs_layout_segment *
 828filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
 829                      struct nfs4_layoutget_res *lgr,
 830                      gfp_t gfp_flags)
 831{
 832        struct nfs4_filelayout_segment *fl;
 833        int rc;
 834        struct nfs4_deviceid id;
 835
 836        dprintk("--> %s\n", __func__);
 837        fl = kzalloc(sizeof(*fl), gfp_flags);
 838        if (!fl)
 839                return NULL;
 840
 841        rc = filelayout_decode_layout(layoutid, fl, lgr, &id, gfp_flags);
 842        if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id, gfp_flags)) {
 843                _filelayout_free_lseg(fl);
 844                return NULL;
 845        }
 846        return &fl->generic_hdr;
 847}
 848
 849/*
 850 * filelayout_pg_test(). Called by nfs_can_coalesce_requests()
 851 *
 852 * Return 0 if @req cannot be coalesced into @pgio, otherwise return the number
 853 * of bytes (maximum @req->wb_bytes) that can be coalesced.
 854 */
 855static size_t
 856filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
 857                   struct nfs_page *req)
 858{
 859        unsigned int size;
 860        u64 p_stripe, r_stripe;
 861        u32 stripe_offset;
 862        u64 segment_offset = pgio->pg_lseg->pls_range.offset;
 863        u32 stripe_unit = FILELAYOUT_LSEG(pgio->pg_lseg)->stripe_unit;
 864
 865        /* calls nfs_generic_pg_test */
 866        size = pnfs_generic_pg_test(pgio, prev, req);
 867        if (!size)
 868                return 0;
 869
 870        /* see if req and prev are in the same stripe */
 871        if (prev) {
 872                p_stripe = (u64)req_offset(prev) - segment_offset;
 873                r_stripe = (u64)req_offset(req) - segment_offset;
 874                do_div(p_stripe, stripe_unit);
 875                do_div(r_stripe, stripe_unit);
 876
 877                if (p_stripe != r_stripe)
 878                        return 0;
 879        }
 880
 881        /* calculate remaining bytes in the current stripe */
 882        div_u64_rem((u64)req_offset(req) - segment_offset,
 883                        stripe_unit,
 884                        &stripe_offset);
 885        WARN_ON_ONCE(stripe_offset > stripe_unit);
 886        if (stripe_offset >= stripe_unit)
 887                return 0;
 888        return min(stripe_unit - (unsigned int)stripe_offset, size);
 889}
 890
 891static void
 892filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
 893                        struct nfs_page *req)
 894{
 895        if (!pgio->pg_lseg) {
 896                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
 897                                           req->wb_context,
 898                                           0,
 899                                           NFS4_MAX_UINT64,
 900                                           IOMODE_READ,
 901                                           false,
 902                                           GFP_KERNEL);
 903                if (IS_ERR(pgio->pg_lseg)) {
 904                        pgio->pg_error = PTR_ERR(pgio->pg_lseg);
 905                        pgio->pg_lseg = NULL;
 906                        return;
 907                }
 908        }
 909        /* If no lseg, fall back to read through mds */
 910        if (pgio->pg_lseg == NULL)
 911                nfs_pageio_reset_read_mds(pgio);
 912}
 913
 914static void
 915filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
 916                         struct nfs_page *req)
 917{
 918        struct nfs_commit_info cinfo;
 919        int status;
 920
 921        if (!pgio->pg_lseg) {
 922                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
 923                                           req->wb_context,
 924                                           0,
 925                                           NFS4_MAX_UINT64,
 926                                           IOMODE_RW,
 927                                           false,
 928                                           GFP_NOFS);
 929                if (IS_ERR(pgio->pg_lseg)) {
 930                        pgio->pg_error = PTR_ERR(pgio->pg_lseg);
 931                        pgio->pg_lseg = NULL;
 932                        return;
 933                }
 934        }
 935
 936        /* If no lseg, fall back to write through mds */
 937        if (pgio->pg_lseg == NULL)
 938                goto out_mds;
 939        nfs_init_cinfo(&cinfo, pgio->pg_inode, pgio->pg_dreq);
 940        status = filelayout_alloc_commit_info(pgio->pg_lseg, &cinfo, GFP_NOFS);
 941        if (status < 0) {
 942                pnfs_put_lseg(pgio->pg_lseg);
 943                pgio->pg_lseg = NULL;
 944                goto out_mds;
 945        }
 946        return;
 947out_mds:
 948        nfs_pageio_reset_write_mds(pgio);
 949}
 950
 951static const struct nfs_pageio_ops filelayout_pg_read_ops = {
 952        .pg_init = filelayout_pg_init_read,
 953        .pg_test = filelayout_pg_test,
 954        .pg_doio = pnfs_generic_pg_readpages,
 955        .pg_cleanup = pnfs_generic_pg_cleanup,
 956};
 957
 958static const struct nfs_pageio_ops filelayout_pg_write_ops = {
 959        .pg_init = filelayout_pg_init_write,
 960        .pg_test = filelayout_pg_test,
 961        .pg_doio = pnfs_generic_pg_writepages,
 962        .pg_cleanup = pnfs_generic_pg_cleanup,
 963};
 964
 965static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j)
 966{
 967        if (fl->stripe_type == STRIPE_SPARSE)
 968                return nfs4_fl_calc_ds_index(&fl->generic_hdr, j);
 969        else
 970                return j;
 971}
 972
 973static void
 974filelayout_mark_request_commit(struct nfs_page *req,
 975                               struct pnfs_layout_segment *lseg,
 976                               struct nfs_commit_info *cinfo,
 977                               u32 ds_commit_idx)
 978
 979{
 980        struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
 981        u32 i, j;
 982
 983        if (fl->commit_through_mds) {
 984                nfs_request_add_commit_list(req, cinfo);
 985        } else {
 986                /* Note that we are calling nfs4_fl_calc_j_index on each page
 987                 * that ends up being committed to a data server.  An attractive
 988                 * alternative is to add a field to nfs_write_data and nfs_page
 989                 * to store the value calculated in filelayout_write_pagelist
 990                 * and just use that here.
 991                 */
 992                j = nfs4_fl_calc_j_index(lseg, req_offset(req));
 993                i = select_bucket_index(fl, j);
 994                pnfs_layout_mark_request_commit(req, lseg, cinfo, i);
 995        }
 996}
 997
 998static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i)
 999{
1000        struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
1001
1002        if (flseg->stripe_type == STRIPE_SPARSE)
1003                return i;
1004        else
1005                return nfs4_fl_calc_ds_index(lseg, i);
1006}
1007
1008static struct nfs_fh *
1009select_ds_fh_from_commit(struct pnfs_layout_segment *lseg, u32 i)
1010{
1011        struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
1012
1013        if (flseg->stripe_type == STRIPE_SPARSE) {
1014                if (flseg->num_fh == 1)
1015                        i = 0;
1016                else if (flseg->num_fh == 0)
1017                        /* Use the MDS OPEN fh set in nfs_read_rpcsetup */
1018                        return NULL;
1019        }
1020        return flseg->fh_array[i];
1021}
1022
1023static int filelayout_initiate_commit(struct nfs_commit_data *data, int how)
1024{
1025        struct pnfs_layout_segment *lseg = data->lseg;
1026        struct nfs4_pnfs_ds *ds;
1027        struct rpc_clnt *ds_clnt;
1028        u32 idx;
1029        struct nfs_fh *fh;
1030
1031        idx = calc_ds_index_from_commit(lseg, data->ds_commit_index);
1032        ds = nfs4_fl_prepare_ds(lseg, idx);
1033        if (!ds)
1034                goto out_err;
1035
1036        ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, data->inode);
1037        if (IS_ERR(ds_clnt))
1038                goto out_err;
1039
1040        dprintk("%s ino %lu, how %d cl_count %d\n", __func__,
1041                data->inode->i_ino, how, atomic_read(&ds->ds_clp->cl_count));
1042        data->commit_done_cb = filelayout_commit_done_cb;
1043        atomic_inc(&ds->ds_clp->cl_count);
1044        data->ds_clp = ds->ds_clp;
1045        fh = select_ds_fh_from_commit(lseg, data->ds_commit_index);
1046        if (fh)
1047                data->args.fh = fh;
1048        return nfs_initiate_commit(ds_clnt, data, NFS_PROTO(data->inode),
1049                                   &filelayout_commit_call_ops, how,
1050                                   RPC_TASK_SOFTCONN);
1051out_err:
1052        pnfs_generic_prepare_to_resend_writes(data);
1053        pnfs_generic_commit_release(data);
1054        return -EAGAIN;
1055}
1056
1057/* filelayout_search_commit_reqs - Search lists in @cinfo for the head reqest
1058 *                                 for @page
1059 * @cinfo - commit info for current inode
1060 * @page - page to search for matching head request
1061 *
1062 * Returns a the head request if one is found, otherwise returns NULL.
1063 */
1064static struct nfs_page *
1065filelayout_search_commit_reqs(struct nfs_commit_info *cinfo, struct page *page)
1066{
1067        struct nfs_page *freq, *t;
1068        struct pnfs_commit_bucket *b;
1069        int i;
1070
1071        /* Linearly search the commit lists for each bucket until a matching
1072         * request is found */
1073        for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
1074                list_for_each_entry_safe(freq, t, &b->written, wb_list) {
1075                        if (freq->wb_page == page)
1076                                return freq->wb_head;
1077                }
1078                list_for_each_entry_safe(freq, t, &b->committing, wb_list) {
1079                        if (freq->wb_page == page)
1080                                return freq->wb_head;
1081                }
1082        }
1083
1084        return NULL;
1085}
1086
1087static int
1088filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
1089                           int how, struct nfs_commit_info *cinfo)
1090{
1091        return pnfs_generic_commit_pagelist(inode, mds_pages, how, cinfo,
1092                                            filelayout_initiate_commit);
1093}
1094
1095static struct nfs4_deviceid_node *
1096filelayout_alloc_deviceid_node(struct nfs_server *server,
1097                struct pnfs_device *pdev, gfp_t gfp_flags)
1098{
1099        struct nfs4_file_layout_dsaddr *dsaddr;
1100
1101        dsaddr = nfs4_fl_alloc_deviceid_node(server, pdev, gfp_flags);
1102        if (!dsaddr)
1103                return NULL;
1104        return &dsaddr->id_node;
1105}
1106
1107static void
1108filelayout_free_deviceid_node(struct nfs4_deviceid_node *d)
1109{
1110        nfs4_fl_free_deviceid(container_of(d, struct nfs4_file_layout_dsaddr, id_node));
1111}
1112
1113static struct pnfs_layout_hdr *
1114filelayout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
1115{
1116        struct nfs4_filelayout *flo;
1117
1118        flo = kzalloc(sizeof(*flo), gfp_flags);
1119        return flo != NULL ? &flo->generic_hdr : NULL;
1120}
1121
1122static void
1123filelayout_free_layout_hdr(struct pnfs_layout_hdr *lo)
1124{
1125        kfree(FILELAYOUT_FROM_HDR(lo));
1126}
1127
1128static struct pnfs_ds_commit_info *
1129filelayout_get_ds_info(struct inode *inode)
1130{
1131        struct pnfs_layout_hdr *layout = NFS_I(inode)->layout;
1132
1133        if (layout == NULL)
1134                return NULL;
1135        else
1136                return &FILELAYOUT_FROM_HDR(layout)->commit_info;
1137}
1138
1139static struct pnfs_layoutdriver_type filelayout_type = {
1140        .id                     = LAYOUT_NFSV4_1_FILES,
1141        .name                   = "LAYOUT_NFSV4_1_FILES",
1142        .owner                  = THIS_MODULE,
1143        .alloc_layout_hdr       = filelayout_alloc_layout_hdr,
1144        .free_layout_hdr        = filelayout_free_layout_hdr,
1145        .alloc_lseg             = filelayout_alloc_lseg,
1146        .free_lseg              = filelayout_free_lseg,
1147        .pg_read_ops            = &filelayout_pg_read_ops,
1148        .pg_write_ops           = &filelayout_pg_write_ops,
1149        .get_ds_info            = &filelayout_get_ds_info,
1150        .mark_request_commit    = filelayout_mark_request_commit,
1151        .clear_request_commit   = pnfs_generic_clear_request_commit,
1152        .scan_commit_lists      = pnfs_generic_scan_commit_lists,
1153        .recover_commit_reqs    = pnfs_generic_recover_commit_reqs,
1154        .search_commit_reqs     = filelayout_search_commit_reqs,
1155        .commit_pagelist        = filelayout_commit_pagelist,
1156        .read_pagelist          = filelayout_read_pagelist,
1157        .write_pagelist         = filelayout_write_pagelist,
1158        .alloc_deviceid_node    = filelayout_alloc_deviceid_node,
1159        .free_deviceid_node     = filelayout_free_deviceid_node,
1160        .sync                   = pnfs_nfs_generic_sync,
1161};
1162
1163static int __init nfs4filelayout_init(void)
1164{
1165        printk(KERN_INFO "%s: NFSv4 File Layout Driver Registering...\n",
1166               __func__);
1167        return pnfs_register_layoutdriver(&filelayout_type);
1168}
1169
1170static void __exit nfs4filelayout_exit(void)
1171{
1172        printk(KERN_INFO "%s: NFSv4 File Layout Driver Unregistering...\n",
1173               __func__);
1174        pnfs_unregister_layoutdriver(&filelayout_type);
1175}
1176
1177MODULE_ALIAS("nfs-layouttype4-1");
1178
1179module_init(nfs4filelayout_init);
1180module_exit(nfs4filelayout_exit);
1181