0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #include <linux/nfs_fs.h>
0033 #include <linux/nfs_page.h>
0034 #include <linux/module.h>
0035 #include <linux/backing-dev.h>
0036
0037 #include <linux/sunrpc/metrics.h>
0038
0039 #include "../nfs4session.h"
0040 #include "../internal.h"
0041 #include "../delegation.h"
0042 #include "filelayout.h"
0043 #include "../nfs4trace.h"
0044
0045 #define NFSDBG_FACILITY NFSDBG_PNFS_LD
0046
0047 MODULE_LICENSE("GPL");
0048 MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>");
0049 MODULE_DESCRIPTION("The NFSv4 file layout driver");
0050
0051 #define FILELAYOUT_POLL_RETRY_MAX (15*HZ)
0052 static const struct pnfs_commit_ops filelayout_commit_ops;
0053
0054 static loff_t
0055 filelayout_get_dense_offset(struct nfs4_filelayout_segment *flseg,
0056 loff_t offset)
0057 {
0058 u32 stripe_width = flseg->stripe_unit * flseg->dsaddr->stripe_count;
0059 u64 stripe_no;
0060 u32 rem;
0061
0062 offset -= flseg->pattern_offset;
0063 stripe_no = div_u64(offset, stripe_width);
0064 div_u64_rem(offset, flseg->stripe_unit, &rem);
0065
0066 return stripe_no * flseg->stripe_unit + rem;
0067 }
0068
0069
0070
0071
0072
0073 static loff_t
0074 filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset)
0075 {
0076 struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
0077
0078 switch (flseg->stripe_type) {
0079 case STRIPE_SPARSE:
0080 return offset;
0081
0082 case STRIPE_DENSE:
0083 return filelayout_get_dense_offset(flseg, offset);
0084 }
0085
0086 BUG();
0087 }
0088
0089 static void filelayout_reset_write(struct nfs_pgio_header *hdr)
0090 {
0091 struct rpc_task *task = &hdr->task;
0092
0093 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
0094 dprintk("%s Reset task %5u for i/o through MDS "
0095 "(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
0096 hdr->task.tk_pid,
0097 hdr->inode->i_sb->s_id,
0098 (unsigned long long)NFS_FILEID(hdr->inode),
0099 hdr->args.count,
0100 (unsigned long long)hdr->args.offset);
0101
0102 task->tk_status = pnfs_write_done_resend_to_mds(hdr);
0103 }
0104 }
0105
0106 static void filelayout_reset_read(struct nfs_pgio_header *hdr)
0107 {
0108 struct rpc_task *task = &hdr->task;
0109
0110 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
0111 dprintk("%s Reset task %5u for i/o through MDS "
0112 "(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
0113 hdr->task.tk_pid,
0114 hdr->inode->i_sb->s_id,
0115 (unsigned long long)NFS_FILEID(hdr->inode),
0116 hdr->args.count,
0117 (unsigned long long)hdr->args.offset);
0118
0119 task->tk_status = pnfs_read_done_resend_to_mds(hdr);
0120 }
0121 }
0122
0123 static int filelayout_async_handle_error(struct rpc_task *task,
0124 struct nfs4_state *state,
0125 struct nfs_client *clp,
0126 struct pnfs_layout_segment *lseg)
0127 {
0128 struct pnfs_layout_hdr *lo = lseg->pls_layout;
0129 struct inode *inode = lo->plh_inode;
0130 struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
0131 struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table;
0132
0133 if (task->tk_status >= 0)
0134 return 0;
0135
0136 switch (task->tk_status) {
0137
0138 case -NFS4ERR_BADSESSION:
0139 case -NFS4ERR_BADSLOT:
0140 case -NFS4ERR_BAD_HIGH_SLOT:
0141 case -NFS4ERR_DEADSESSION:
0142 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
0143 case -NFS4ERR_SEQ_FALSE_RETRY:
0144 case -NFS4ERR_SEQ_MISORDERED:
0145 dprintk("%s ERROR %d, Reset session. Exchangeid "
0146 "flags 0x%x\n", __func__, task->tk_status,
0147 clp->cl_exchange_flags);
0148 nfs4_schedule_session_recovery(clp->cl_session, task->tk_status);
0149 break;
0150 case -NFS4ERR_DELAY:
0151 case -NFS4ERR_GRACE:
0152 rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX);
0153 break;
0154 case -NFS4ERR_RETRY_UNCACHED_REP:
0155 break;
0156
0157 case -NFS4ERR_ACCESS:
0158 case -NFS4ERR_PNFS_NO_LAYOUT:
0159 case -ESTALE:
0160 case -EBADHANDLE:
0161 case -EISDIR:
0162 case -NFS4ERR_FHEXPIRED:
0163 case -NFS4ERR_WRONG_TYPE:
0164 dprintk("%s Invalid layout error %d\n", __func__,
0165 task->tk_status);
0166
0167
0168
0169
0170
0171
0172
0173 pnfs_destroy_layout(NFS_I(inode));
0174 rpc_wake_up(&tbl->slot_tbl_waitq);
0175 goto reset;
0176
0177 case -ECONNREFUSED:
0178 case -EHOSTDOWN:
0179 case -EHOSTUNREACH:
0180 case -ENETUNREACH:
0181 case -EIO:
0182 case -ETIMEDOUT:
0183 case -EPIPE:
0184 case -EPROTO:
0185 case -ENODEV:
0186 dprintk("%s DS connection error %d\n", __func__,
0187 task->tk_status);
0188 nfs4_mark_deviceid_unavailable(devid);
0189 pnfs_error_mark_layout_for_return(inode, lseg);
0190 pnfs_set_lo_fail(lseg);
0191 rpc_wake_up(&tbl->slot_tbl_waitq);
0192 fallthrough;
0193 default:
0194 reset:
0195 dprintk("%s Retry through MDS. Error %d\n", __func__,
0196 task->tk_status);
0197 return -NFS4ERR_RESET_TO_MDS;
0198 }
0199 task->tk_status = 0;
0200 return -EAGAIN;
0201 }
0202
0203
0204
0205 static int filelayout_read_done_cb(struct rpc_task *task,
0206 struct nfs_pgio_header *hdr)
0207 {
0208 int err;
0209
0210 trace_nfs4_pnfs_read(hdr, task->tk_status);
0211 err = filelayout_async_handle_error(task, hdr->args.context->state,
0212 hdr->ds_clp, hdr->lseg);
0213
0214 switch (err) {
0215 case -NFS4ERR_RESET_TO_MDS:
0216 filelayout_reset_read(hdr);
0217 return task->tk_status;
0218 case -EAGAIN:
0219 rpc_restart_call_prepare(task);
0220 return -EAGAIN;
0221 }
0222
0223 return 0;
0224 }
0225
0226
0227
0228
0229
0230
0231 static void
0232 filelayout_set_layoutcommit(struct nfs_pgio_header *hdr)
0233 {
0234 loff_t end_offs = 0;
0235
0236 if (FILELAYOUT_LSEG(hdr->lseg)->commit_through_mds ||
0237 hdr->res.verf->committed == NFS_FILE_SYNC)
0238 return;
0239 if (hdr->res.verf->committed == NFS_DATA_SYNC)
0240 end_offs = hdr->mds_offset + (loff_t)hdr->res.count;
0241
0242
0243 pnfs_set_layoutcommit(hdr->inode, hdr->lseg, end_offs);
0244 dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino,
0245 (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb);
0246 }
0247
0248 bool
0249 filelayout_test_devid_unavailable(struct nfs4_deviceid_node *node)
0250 {
0251 return filelayout_test_devid_invalid(node) ||
0252 nfs4_test_deviceid_unavailable(node);
0253 }
0254
0255 static bool
0256 filelayout_reset_to_mds(struct pnfs_layout_segment *lseg)
0257 {
0258 struct nfs4_deviceid_node *node = FILELAYOUT_DEVID_NODE(lseg);
0259
0260 return filelayout_test_devid_unavailable(node);
0261 }
0262
0263
0264
0265
0266
0267
0268 static void filelayout_read_prepare(struct rpc_task *task, void *data)
0269 {
0270 struct nfs_pgio_header *hdr = data;
0271
0272 if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) {
0273 rpc_exit(task, -EIO);
0274 return;
0275 }
0276 if (filelayout_reset_to_mds(hdr->lseg)) {
0277 dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
0278 filelayout_reset_read(hdr);
0279 rpc_exit(task, 0);
0280 return;
0281 }
0282 hdr->pgio_done_cb = filelayout_read_done_cb;
0283
0284 if (nfs4_setup_sequence(hdr->ds_clp,
0285 &hdr->args.seq_args,
0286 &hdr->res.seq_res,
0287 task))
0288 return;
0289 if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
0290 hdr->args.lock_context, FMODE_READ) == -EIO)
0291 rpc_exit(task, -EIO);
0292 }
0293
0294 static void filelayout_read_call_done(struct rpc_task *task, void *data)
0295 {
0296 struct nfs_pgio_header *hdr = data;
0297
0298 if (test_bit(NFS_IOHDR_REDO, &hdr->flags) &&
0299 task->tk_status == 0) {
0300 nfs41_sequence_done(task, &hdr->res.seq_res);
0301 return;
0302 }
0303
0304
0305 hdr->mds_ops->rpc_call_done(task, data);
0306 }
0307
0308 static void filelayout_read_count_stats(struct rpc_task *task, void *data)
0309 {
0310 struct nfs_pgio_header *hdr = data;
0311
0312 rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics);
0313 }
0314
0315 static int filelayout_write_done_cb(struct rpc_task *task,
0316 struct nfs_pgio_header *hdr)
0317 {
0318 int err;
0319
0320 trace_nfs4_pnfs_write(hdr, task->tk_status);
0321 err = filelayout_async_handle_error(task, hdr->args.context->state,
0322 hdr->ds_clp, hdr->lseg);
0323
0324 switch (err) {
0325 case -NFS4ERR_RESET_TO_MDS:
0326 filelayout_reset_write(hdr);
0327 return task->tk_status;
0328 case -EAGAIN:
0329 rpc_restart_call_prepare(task);
0330 return -EAGAIN;
0331 }
0332
0333 filelayout_set_layoutcommit(hdr);
0334
0335
0336 hdr->fattr.valid = 0;
0337 if (task->tk_status >= 0)
0338 nfs_writeback_update_inode(hdr);
0339
0340 return 0;
0341 }
0342
0343 static int filelayout_commit_done_cb(struct rpc_task *task,
0344 struct nfs_commit_data *data)
0345 {
0346 int err;
0347
0348 trace_nfs4_pnfs_commit_ds(data, task->tk_status);
0349 err = filelayout_async_handle_error(task, NULL, data->ds_clp,
0350 data->lseg);
0351
0352 switch (err) {
0353 case -NFS4ERR_RESET_TO_MDS:
0354 pnfs_generic_prepare_to_resend_writes(data);
0355 return -EAGAIN;
0356 case -EAGAIN:
0357 rpc_restart_call_prepare(task);
0358 return -EAGAIN;
0359 }
0360
0361 pnfs_set_layoutcommit(data->inode, data->lseg, data->lwb);
0362
0363 return 0;
0364 }
0365
0366 static void filelayout_write_prepare(struct rpc_task *task, void *data)
0367 {
0368 struct nfs_pgio_header *hdr = data;
0369
0370 if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) {
0371 rpc_exit(task, -EIO);
0372 return;
0373 }
0374 if (filelayout_reset_to_mds(hdr->lseg)) {
0375 dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
0376 filelayout_reset_write(hdr);
0377 rpc_exit(task, 0);
0378 return;
0379 }
0380 if (nfs4_setup_sequence(hdr->ds_clp,
0381 &hdr->args.seq_args,
0382 &hdr->res.seq_res,
0383 task))
0384 return;
0385 if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
0386 hdr->args.lock_context, FMODE_WRITE) == -EIO)
0387 rpc_exit(task, -EIO);
0388 }
0389
0390 static void filelayout_write_call_done(struct rpc_task *task, void *data)
0391 {
0392 struct nfs_pgio_header *hdr = data;
0393
0394 if (test_bit(NFS_IOHDR_REDO, &hdr->flags) &&
0395 task->tk_status == 0) {
0396 nfs41_sequence_done(task, &hdr->res.seq_res);
0397 return;
0398 }
0399
0400
0401 hdr->mds_ops->rpc_call_done(task, data);
0402 }
0403
0404 static void filelayout_write_count_stats(struct rpc_task *task, void *data)
0405 {
0406 struct nfs_pgio_header *hdr = data;
0407
0408 rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics);
0409 }
0410
0411 static void filelayout_commit_prepare(struct rpc_task *task, void *data)
0412 {
0413 struct nfs_commit_data *wdata = data;
0414
0415 nfs4_setup_sequence(wdata->ds_clp,
0416 &wdata->args.seq_args,
0417 &wdata->res.seq_res,
0418 task);
0419 }
0420
0421 static void filelayout_commit_count_stats(struct rpc_task *task, void *data)
0422 {
0423 struct nfs_commit_data *cdata = data;
0424
0425 rpc_count_iostats(task, NFS_SERVER(cdata->inode)->client->cl_metrics);
0426 }
0427
0428 static const struct rpc_call_ops filelayout_read_call_ops = {
0429 .rpc_call_prepare = filelayout_read_prepare,
0430 .rpc_call_done = filelayout_read_call_done,
0431 .rpc_count_stats = filelayout_read_count_stats,
0432 .rpc_release = pnfs_generic_rw_release,
0433 };
0434
0435 static const struct rpc_call_ops filelayout_write_call_ops = {
0436 .rpc_call_prepare = filelayout_write_prepare,
0437 .rpc_call_done = filelayout_write_call_done,
0438 .rpc_count_stats = filelayout_write_count_stats,
0439 .rpc_release = pnfs_generic_rw_release,
0440 };
0441
0442 static const struct rpc_call_ops filelayout_commit_call_ops = {
0443 .rpc_call_prepare = filelayout_commit_prepare,
0444 .rpc_call_done = pnfs_generic_write_commit_done,
0445 .rpc_count_stats = filelayout_commit_count_stats,
0446 .rpc_release = pnfs_generic_commit_release,
0447 };
0448
0449 static enum pnfs_try_status
0450 filelayout_read_pagelist(struct nfs_pgio_header *hdr)
0451 {
0452 struct pnfs_layout_segment *lseg = hdr->lseg;
0453 struct nfs4_pnfs_ds *ds;
0454 struct rpc_clnt *ds_clnt;
0455 loff_t offset = hdr->args.offset;
0456 u32 j, idx;
0457 struct nfs_fh *fh;
0458
0459 dprintk("--> %s ino %lu pgbase %u req %zu@%llu\n",
0460 __func__, hdr->inode->i_ino,
0461 hdr->args.pgbase, (size_t)hdr->args.count, offset);
0462
0463
0464 j = nfs4_fl_calc_j_index(lseg, offset);
0465 idx = nfs4_fl_calc_ds_index(lseg, j);
0466 ds = nfs4_fl_prepare_ds(lseg, idx);
0467 if (!ds)
0468 return PNFS_NOT_ATTEMPTED;
0469
0470 ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, hdr->inode);
0471 if (IS_ERR(ds_clnt))
0472 return PNFS_NOT_ATTEMPTED;
0473
0474 dprintk("%s USE DS: %s cl_count %d\n", __func__,
0475 ds->ds_remotestr, refcount_read(&ds->ds_clp->cl_count));
0476
0477
0478 refcount_inc(&ds->ds_clp->cl_count);
0479 hdr->ds_clp = ds->ds_clp;
0480 hdr->ds_commit_idx = idx;
0481 fh = nfs4_fl_select_ds_fh(lseg, j);
0482 if (fh)
0483 hdr->args.fh = fh;
0484
0485 hdr->args.offset = filelayout_get_dserver_offset(lseg, offset);
0486 hdr->mds_offset = offset;
0487
0488
0489 nfs_initiate_pgio(ds_clnt, hdr, hdr->cred,
0490 NFS_PROTO(hdr->inode), &filelayout_read_call_ops,
0491 0, RPC_TASK_SOFTCONN);
0492 return PNFS_ATTEMPTED;
0493 }
0494
0495
0496 static enum pnfs_try_status
0497 filelayout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
0498 {
0499 struct pnfs_layout_segment *lseg = hdr->lseg;
0500 struct nfs4_pnfs_ds *ds;
0501 struct rpc_clnt *ds_clnt;
0502 loff_t offset = hdr->args.offset;
0503 u32 j, idx;
0504 struct nfs_fh *fh;
0505
0506
0507 j = nfs4_fl_calc_j_index(lseg, offset);
0508 idx = nfs4_fl_calc_ds_index(lseg, j);
0509 ds = nfs4_fl_prepare_ds(lseg, idx);
0510 if (!ds)
0511 return PNFS_NOT_ATTEMPTED;
0512
0513 ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, hdr->inode);
0514 if (IS_ERR(ds_clnt))
0515 return PNFS_NOT_ATTEMPTED;
0516
0517 dprintk("%s ino %lu sync %d req %zu@%llu DS: %s cl_count %d\n",
0518 __func__, hdr->inode->i_ino, sync, (size_t) hdr->args.count,
0519 offset, ds->ds_remotestr, refcount_read(&ds->ds_clp->cl_count));
0520
0521 hdr->pgio_done_cb = filelayout_write_done_cb;
0522 refcount_inc(&ds->ds_clp->cl_count);
0523 hdr->ds_clp = ds->ds_clp;
0524 hdr->ds_commit_idx = idx;
0525 fh = nfs4_fl_select_ds_fh(lseg, j);
0526 if (fh)
0527 hdr->args.fh = fh;
0528 hdr->args.offset = filelayout_get_dserver_offset(lseg, offset);
0529
0530
0531 nfs_initiate_pgio(ds_clnt, hdr, hdr->cred,
0532 NFS_PROTO(hdr->inode), &filelayout_write_call_ops,
0533 sync, RPC_TASK_SOFTCONN);
0534 return PNFS_ATTEMPTED;
0535 }
0536
0537 static int
0538 filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
0539 struct nfs4_filelayout_segment *fl,
0540 gfp_t gfp_flags)
0541 {
0542 struct nfs4_deviceid_node *d;
0543 struct nfs4_file_layout_dsaddr *dsaddr;
0544 int status = -EINVAL;
0545
0546
0547 if (fl->dsaddr != NULL)
0548 return 0;
0549
0550
0551 d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid,
0552 lo->plh_lc_cred, gfp_flags);
0553 if (d == NULL)
0554 goto out;
0555
0556 dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
0557
0558 if (filelayout_test_devid_unavailable(&dsaddr->id_node))
0559 goto out_put;
0560
0561 if (fl->first_stripe_index >= dsaddr->stripe_count) {
0562 dprintk("%s Bad first_stripe_index %u\n",
0563 __func__, fl->first_stripe_index);
0564 goto out_put;
0565 }
0566
0567 if ((fl->stripe_type == STRIPE_SPARSE &&
0568 fl->num_fh > 1 && fl->num_fh != dsaddr->ds_num) ||
0569 (fl->stripe_type == STRIPE_DENSE &&
0570 fl->num_fh != dsaddr->stripe_count)) {
0571 dprintk("%s num_fh %u not valid for given packing\n",
0572 __func__, fl->num_fh);
0573 goto out_put;
0574 }
0575 status = 0;
0576
0577
0578
0579
0580
0581 if (cmpxchg(&fl->dsaddr, NULL, dsaddr) != NULL)
0582 goto out_put;
0583 out:
0584 return status;
0585 out_put:
0586 nfs4_fl_put_deviceid(dsaddr);
0587 goto out;
0588 }
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598 static int
0599 filelayout_check_layout(struct pnfs_layout_hdr *lo,
0600 struct nfs4_filelayout_segment *fl,
0601 struct nfs4_layoutget_res *lgr,
0602 gfp_t gfp_flags)
0603 {
0604 int status = -EINVAL;
0605
0606 dprintk("--> %s\n", __func__);
0607
0608
0609 if (lgr->range.offset != 0 ||
0610 lgr->range.length != NFS4_MAX_UINT64) {
0611 dprintk("%s Only whole file layouts supported. Use MDS i/o\n",
0612 __func__);
0613 goto out;
0614 }
0615
0616 if (fl->pattern_offset > lgr->range.offset) {
0617 dprintk("%s pattern_offset %lld too large\n",
0618 __func__, fl->pattern_offset);
0619 goto out;
0620 }
0621
0622 if (!fl->stripe_unit) {
0623 dprintk("%s Invalid stripe unit (%u)\n",
0624 __func__, fl->stripe_unit);
0625 goto out;
0626 }
0627
0628 status = 0;
0629 out:
0630 dprintk("--> %s returns %d\n", __func__, status);
0631 return status;
0632 }
0633
0634 static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl)
0635 {
0636 int i;
0637
0638 if (fl->fh_array) {
0639 for (i = 0; i < fl->num_fh; i++) {
0640 if (!fl->fh_array[i])
0641 break;
0642 kfree(fl->fh_array[i]);
0643 }
0644 kfree(fl->fh_array);
0645 }
0646 kfree(fl);
0647 }
0648
0649 static int
0650 filelayout_decode_layout(struct pnfs_layout_hdr *flo,
0651 struct nfs4_filelayout_segment *fl,
0652 struct nfs4_layoutget_res *lgr,
0653 gfp_t gfp_flags)
0654 {
0655 struct xdr_stream stream;
0656 struct xdr_buf buf;
0657 struct page *scratch;
0658 __be32 *p;
0659 uint32_t nfl_util;
0660 int i;
0661
0662 dprintk("%s: set_layout_map Begin\n", __func__);
0663
0664 scratch = alloc_page(gfp_flags);
0665 if (!scratch)
0666 return -ENOMEM;
0667
0668 xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len);
0669 xdr_set_scratch_page(&stream, scratch);
0670
0671
0672
0673 p = xdr_inline_decode(&stream, NFS4_DEVICEID4_SIZE + 20);
0674 if (unlikely(!p))
0675 goto out_err;
0676
0677 memcpy(&fl->deviceid, p, sizeof(fl->deviceid));
0678 p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
0679 nfs4_print_deviceid(&fl->deviceid);
0680
0681 nfl_util = be32_to_cpup(p++);
0682 if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS)
0683 fl->commit_through_mds = 1;
0684 if (nfl_util & NFL4_UFLG_DENSE)
0685 fl->stripe_type = STRIPE_DENSE;
0686 else
0687 fl->stripe_type = STRIPE_SPARSE;
0688 fl->stripe_unit = nfl_util & ~NFL4_UFLG_MASK;
0689
0690 fl->first_stripe_index = be32_to_cpup(p++);
0691 p = xdr_decode_hyper(p, &fl->pattern_offset);
0692 fl->num_fh = be32_to_cpup(p++);
0693
0694 dprintk("%s: nfl_util 0x%X num_fh %u fsi %u po %llu\n",
0695 __func__, nfl_util, fl->num_fh, fl->first_stripe_index,
0696 fl->pattern_offset);
0697
0698
0699
0700 if (fl->num_fh >
0701 max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT))
0702 goto out_err;
0703
0704 if (fl->num_fh > 0) {
0705 fl->fh_array = kcalloc(fl->num_fh, sizeof(fl->fh_array[0]),
0706 gfp_flags);
0707 if (!fl->fh_array)
0708 goto out_err;
0709 }
0710
0711 for (i = 0; i < fl->num_fh; i++) {
0712
0713 fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), gfp_flags);
0714 if (!fl->fh_array[i])
0715 goto out_err;
0716
0717 p = xdr_inline_decode(&stream, 4);
0718 if (unlikely(!p))
0719 goto out_err;
0720 fl->fh_array[i]->size = be32_to_cpup(p++);
0721 if (fl->fh_array[i]->size > NFS_MAXFHSIZE) {
0722 printk(KERN_ERR "NFS: Too big fh %d received %d\n",
0723 i, fl->fh_array[i]->size);
0724 goto out_err;
0725 }
0726
0727 p = xdr_inline_decode(&stream, fl->fh_array[i]->size);
0728 if (unlikely(!p))
0729 goto out_err;
0730 memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size);
0731 dprintk("DEBUG: %s: fh len %d\n", __func__,
0732 fl->fh_array[i]->size);
0733 }
0734
0735 __free_page(scratch);
0736 return 0;
0737
0738 out_err:
0739 __free_page(scratch);
0740 return -EIO;
0741 }
0742
0743 static void
0744 filelayout_free_lseg(struct pnfs_layout_segment *lseg)
0745 {
0746 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
0747
0748 dprintk("--> %s\n", __func__);
0749 if (fl->dsaddr != NULL)
0750 nfs4_fl_put_deviceid(fl->dsaddr);
0751
0752 if (lseg->pls_range.iomode == IOMODE_RW) {
0753 struct nfs4_filelayout *flo;
0754 struct inode *inode;
0755
0756 flo = FILELAYOUT_FROM_HDR(lseg->pls_layout);
0757 inode = flo->generic_hdr.plh_inode;
0758 spin_lock(&inode->i_lock);
0759 pnfs_generic_ds_cinfo_release_lseg(&flo->commit_info, lseg);
0760 spin_unlock(&inode->i_lock);
0761 }
0762 _filelayout_free_lseg(fl);
0763 }
0764
0765 static struct pnfs_layout_segment *
0766 filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
0767 struct nfs4_layoutget_res *lgr,
0768 gfp_t gfp_flags)
0769 {
0770 struct nfs4_filelayout_segment *fl;
0771 int rc;
0772
0773 dprintk("--> %s\n", __func__);
0774 fl = kzalloc(sizeof(*fl), gfp_flags);
0775 if (!fl)
0776 return NULL;
0777
0778 rc = filelayout_decode_layout(layoutid, fl, lgr, gfp_flags);
0779 if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, gfp_flags)) {
0780 _filelayout_free_lseg(fl);
0781 return NULL;
0782 }
0783 return &fl->generic_hdr;
0784 }
0785
0786
0787
0788
0789
0790
0791
0792 static size_t
0793 filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
0794 struct nfs_page *req)
0795 {
0796 unsigned int size;
0797 u64 p_stripe, r_stripe;
0798 u32 stripe_offset;
0799 u64 segment_offset = pgio->pg_lseg->pls_range.offset;
0800 u32 stripe_unit = FILELAYOUT_LSEG(pgio->pg_lseg)->stripe_unit;
0801
0802
0803 size = pnfs_generic_pg_test(pgio, prev, req);
0804 if (!size)
0805 return 0;
0806
0807
0808 if (prev) {
0809 p_stripe = (u64)req_offset(prev) - segment_offset;
0810 r_stripe = (u64)req_offset(req) - segment_offset;
0811 do_div(p_stripe, stripe_unit);
0812 do_div(r_stripe, stripe_unit);
0813
0814 if (p_stripe != r_stripe)
0815 return 0;
0816 }
0817
0818
0819 div_u64_rem((u64)req_offset(req) - segment_offset,
0820 stripe_unit,
0821 &stripe_offset);
0822 WARN_ON_ONCE(stripe_offset > stripe_unit);
0823 if (stripe_offset >= stripe_unit)
0824 return 0;
0825 return min(stripe_unit - (unsigned int)stripe_offset, size);
0826 }
0827
0828 static struct pnfs_layout_segment *
0829 fl_pnfs_update_layout(struct inode *ino,
0830 struct nfs_open_context *ctx,
0831 loff_t pos,
0832 u64 count,
0833 enum pnfs_iomode iomode,
0834 bool strict_iomode,
0835 gfp_t gfp_flags)
0836 {
0837 struct pnfs_layout_segment *lseg = NULL;
0838 struct pnfs_layout_hdr *lo;
0839 struct nfs4_filelayout_segment *fl;
0840 int status;
0841
0842 lseg = pnfs_update_layout(ino, ctx, pos, count, iomode, strict_iomode,
0843 gfp_flags);
0844 if (IS_ERR(lseg)) {
0845
0846 if (!nfs_error_is_fatal_on_server(PTR_ERR(lseg)))
0847 lseg = NULL;
0848 goto out;
0849 } else if (!lseg)
0850 goto out;
0851
0852 lo = NFS_I(ino)->layout;
0853 fl = FILELAYOUT_LSEG(lseg);
0854
0855 status = filelayout_check_deviceid(lo, fl, gfp_flags);
0856 if (status) {
0857 pnfs_put_lseg(lseg);
0858 lseg = NULL;
0859 }
0860 out:
0861 return lseg;
0862 }
0863
0864 static void
0865 filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
0866 struct nfs_page *req)
0867 {
0868 pnfs_generic_pg_check_layout(pgio);
0869 if (!pgio->pg_lseg) {
0870 pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
0871 nfs_req_openctx(req),
0872 0,
0873 NFS4_MAX_UINT64,
0874 IOMODE_READ,
0875 false,
0876 GFP_KERNEL);
0877 if (IS_ERR(pgio->pg_lseg)) {
0878 pgio->pg_error = PTR_ERR(pgio->pg_lseg);
0879 pgio->pg_lseg = NULL;
0880 return;
0881 }
0882 }
0883
0884 if (pgio->pg_lseg == NULL)
0885 nfs_pageio_reset_read_mds(pgio);
0886 }
0887
0888 static void
0889 filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
0890 struct nfs_page *req)
0891 {
0892 pnfs_generic_pg_check_layout(pgio);
0893 if (!pgio->pg_lseg) {
0894 pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
0895 nfs_req_openctx(req),
0896 0,
0897 NFS4_MAX_UINT64,
0898 IOMODE_RW,
0899 false,
0900 GFP_NOFS);
0901 if (IS_ERR(pgio->pg_lseg)) {
0902 pgio->pg_error = PTR_ERR(pgio->pg_lseg);
0903 pgio->pg_lseg = NULL;
0904 return;
0905 }
0906 }
0907
0908
0909 if (pgio->pg_lseg == NULL)
0910 nfs_pageio_reset_write_mds(pgio);
0911 }
0912
0913 static const struct nfs_pageio_ops filelayout_pg_read_ops = {
0914 .pg_init = filelayout_pg_init_read,
0915 .pg_test = filelayout_pg_test,
0916 .pg_doio = pnfs_generic_pg_readpages,
0917 .pg_cleanup = pnfs_generic_pg_cleanup,
0918 };
0919
0920 static const struct nfs_pageio_ops filelayout_pg_write_ops = {
0921 .pg_init = filelayout_pg_init_write,
0922 .pg_test = filelayout_pg_test,
0923 .pg_doio = pnfs_generic_pg_writepages,
0924 .pg_cleanup = pnfs_generic_pg_cleanup,
0925 };
0926
0927 static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j)
0928 {
0929 if (fl->stripe_type == STRIPE_SPARSE)
0930 return nfs4_fl_calc_ds_index(&fl->generic_hdr, j);
0931 else
0932 return j;
0933 }
0934
0935 static void
0936 filelayout_mark_request_commit(struct nfs_page *req,
0937 struct pnfs_layout_segment *lseg,
0938 struct nfs_commit_info *cinfo,
0939 u32 ds_commit_idx)
0940
0941 {
0942 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
0943 u32 i, j;
0944
0945 if (fl->commit_through_mds) {
0946 nfs_request_add_commit_list(req, cinfo);
0947 } else {
0948
0949
0950
0951
0952
0953
0954 j = nfs4_fl_calc_j_index(lseg, req_offset(req));
0955 i = select_bucket_index(fl, j);
0956 pnfs_layout_mark_request_commit(req, lseg, cinfo, i);
0957 }
0958 }
0959
0960 static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i)
0961 {
0962 struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
0963
0964 if (flseg->stripe_type == STRIPE_SPARSE)
0965 return i;
0966 else
0967 return nfs4_fl_calc_ds_index(lseg, i);
0968 }
0969
0970 static struct nfs_fh *
0971 select_ds_fh_from_commit(struct pnfs_layout_segment *lseg, u32 i)
0972 {
0973 struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
0974
0975 if (flseg->stripe_type == STRIPE_SPARSE) {
0976 if (flseg->num_fh == 1)
0977 i = 0;
0978 else if (flseg->num_fh == 0)
0979
0980 return NULL;
0981 }
0982 return flseg->fh_array[i];
0983 }
0984
0985 static int filelayout_initiate_commit(struct nfs_commit_data *data, int how)
0986 {
0987 struct pnfs_layout_segment *lseg = data->lseg;
0988 struct nfs4_pnfs_ds *ds;
0989 struct rpc_clnt *ds_clnt;
0990 u32 idx;
0991 struct nfs_fh *fh;
0992
0993 idx = calc_ds_index_from_commit(lseg, data->ds_commit_index);
0994 ds = nfs4_fl_prepare_ds(lseg, idx);
0995 if (!ds)
0996 goto out_err;
0997
0998 ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, data->inode);
0999 if (IS_ERR(ds_clnt))
1000 goto out_err;
1001
1002 dprintk("%s ino %lu, how %d cl_count %d\n", __func__,
1003 data->inode->i_ino, how, refcount_read(&ds->ds_clp->cl_count));
1004 data->commit_done_cb = filelayout_commit_done_cb;
1005 refcount_inc(&ds->ds_clp->cl_count);
1006 data->ds_clp = ds->ds_clp;
1007 fh = select_ds_fh_from_commit(lseg, data->ds_commit_index);
1008 if (fh)
1009 data->args.fh = fh;
1010 return nfs_initiate_commit(ds_clnt, data, NFS_PROTO(data->inode),
1011 &filelayout_commit_call_ops, how,
1012 RPC_TASK_SOFTCONN);
1013 out_err:
1014 pnfs_generic_prepare_to_resend_writes(data);
1015 pnfs_generic_commit_release(data);
1016 return -EAGAIN;
1017 }
1018
1019 static int
1020 filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
1021 int how, struct nfs_commit_info *cinfo)
1022 {
1023 return pnfs_generic_commit_pagelist(inode, mds_pages, how, cinfo,
1024 filelayout_initiate_commit);
1025 }
1026
1027 static struct nfs4_deviceid_node *
1028 filelayout_alloc_deviceid_node(struct nfs_server *server,
1029 struct pnfs_device *pdev, gfp_t gfp_flags)
1030 {
1031 struct nfs4_file_layout_dsaddr *dsaddr;
1032
1033 dsaddr = nfs4_fl_alloc_deviceid_node(server, pdev, gfp_flags);
1034 if (!dsaddr)
1035 return NULL;
1036 return &dsaddr->id_node;
1037 }
1038
1039 static void
1040 filelayout_free_deviceid_node(struct nfs4_deviceid_node *d)
1041 {
1042 nfs4_fl_free_deviceid(container_of(d, struct nfs4_file_layout_dsaddr, id_node));
1043 }
1044
1045 static struct pnfs_layout_hdr *
1046 filelayout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
1047 {
1048 struct nfs4_filelayout *flo;
1049
1050 flo = kzalloc(sizeof(*flo), gfp_flags);
1051 if (flo == NULL)
1052 return NULL;
1053 pnfs_init_ds_commit_info(&flo->commit_info);
1054 flo->commit_info.ops = &filelayout_commit_ops;
1055 return &flo->generic_hdr;
1056 }
1057
1058 static void
1059 filelayout_free_layout_hdr(struct pnfs_layout_hdr *lo)
1060 {
1061 kfree_rcu(FILELAYOUT_FROM_HDR(lo), generic_hdr.plh_rcu);
1062 }
1063
1064 static struct pnfs_ds_commit_info *
1065 filelayout_get_ds_info(struct inode *inode)
1066 {
1067 struct pnfs_layout_hdr *layout = NFS_I(inode)->layout;
1068
1069 if (layout == NULL)
1070 return NULL;
1071 else
1072 return &FILELAYOUT_FROM_HDR(layout)->commit_info;
1073 }
1074
1075 static void
1076 filelayout_setup_ds_info(struct pnfs_ds_commit_info *fl_cinfo,
1077 struct pnfs_layout_segment *lseg)
1078 {
1079 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
1080 struct inode *inode = lseg->pls_layout->plh_inode;
1081 struct pnfs_commit_array *array, *new;
1082 unsigned int size = (fl->stripe_type == STRIPE_SPARSE) ?
1083 fl->dsaddr->ds_num : fl->dsaddr->stripe_count;
1084
1085 new = pnfs_alloc_commit_array(size, nfs_io_gfp_mask());
1086 if (new) {
1087 spin_lock(&inode->i_lock);
1088 array = pnfs_add_commit_array(fl_cinfo, new, lseg);
1089 spin_unlock(&inode->i_lock);
1090 if (array != new)
1091 pnfs_free_commit_array(new);
1092 }
1093 }
1094
1095 static void
1096 filelayout_release_ds_info(struct pnfs_ds_commit_info *fl_cinfo,
1097 struct inode *inode)
1098 {
1099 spin_lock(&inode->i_lock);
1100 pnfs_generic_ds_cinfo_destroy(fl_cinfo);
1101 spin_unlock(&inode->i_lock);
1102 }
1103
1104 static const struct pnfs_commit_ops filelayout_commit_ops = {
1105 .setup_ds_info = filelayout_setup_ds_info,
1106 .release_ds_info = filelayout_release_ds_info,
1107 .mark_request_commit = filelayout_mark_request_commit,
1108 .clear_request_commit = pnfs_generic_clear_request_commit,
1109 .scan_commit_lists = pnfs_generic_scan_commit_lists,
1110 .recover_commit_reqs = pnfs_generic_recover_commit_reqs,
1111 .search_commit_reqs = pnfs_generic_search_commit_reqs,
1112 .commit_pagelist = filelayout_commit_pagelist,
1113 };
1114
1115 static struct pnfs_layoutdriver_type filelayout_type = {
1116 .id = LAYOUT_NFSV4_1_FILES,
1117 .name = "LAYOUT_NFSV4_1_FILES",
1118 .owner = THIS_MODULE,
1119 .flags = PNFS_LAYOUTGET_ON_OPEN,
1120 .max_layoutget_response = 4096,
1121 .alloc_layout_hdr = filelayout_alloc_layout_hdr,
1122 .free_layout_hdr = filelayout_free_layout_hdr,
1123 .alloc_lseg = filelayout_alloc_lseg,
1124 .free_lseg = filelayout_free_lseg,
1125 .pg_read_ops = &filelayout_pg_read_ops,
1126 .pg_write_ops = &filelayout_pg_write_ops,
1127 .get_ds_info = &filelayout_get_ds_info,
1128 .read_pagelist = filelayout_read_pagelist,
1129 .write_pagelist = filelayout_write_pagelist,
1130 .alloc_deviceid_node = filelayout_alloc_deviceid_node,
1131 .free_deviceid_node = filelayout_free_deviceid_node,
1132 .sync = pnfs_nfs_generic_sync,
1133 };
1134
1135 static int __init nfs4filelayout_init(void)
1136 {
1137 printk(KERN_INFO "%s: NFSv4 File Layout Driver Registering...\n",
1138 __func__);
1139 return pnfs_register_layoutdriver(&filelayout_type);
1140 }
1141
1142 static void __exit nfs4filelayout_exit(void)
1143 {
1144 printk(KERN_INFO "%s: NFSv4 File Layout Driver Unregistering...\n",
1145 __func__);
1146 pnfs_unregister_layoutdriver(&filelayout_type);
1147 }
1148
1149 MODULE_ALIAS("nfs-layouttype4-1");
1150
1151 module_init(nfs4filelayout_init);
1152 module_exit(nfs4filelayout_exit);