aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/direct.c17
-rw-r--r--fs/nfs/internal.h13
-rw-r--r--fs/nfs/nfs3proc.c10
-rw-r--r--fs/nfs/nfs3xdr.c6
-rw-r--r--fs/nfs/nfs4filelayout.c65
-rw-r--r--fs/nfs/nfs4proc.c23
-rw-r--r--fs/nfs/nfs4xdr.c8
-rw-r--r--fs/nfs/proc.c8
-rw-r--r--fs/nfs/write.c50
-rw-r--r--include/linux/nfs_fs.h4
-rw-r--r--include/linux/nfs_xdr.h45
11 files changed, 173 insertions, 76 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 8a8942326758..5897dfe48118 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -82,7 +82,7 @@ struct nfs_direct_req {
82 82
83 /* commit state */ 83 /* commit state */
84 struct list_head rewrite_list; /* saved nfs_write_data structs */ 84 struct list_head rewrite_list; /* saved nfs_write_data structs */
85 struct nfs_write_data * commit_data; /* special write_data for commits */ 85 struct nfs_commit_data *commit_data; /* special write_data for commits */
86 int flags; 86 int flags;
87#define NFS_ODIRECT_DO_COMMIT (1) /* an unstable reply was received */ 87#define NFS_ODIRECT_DO_COMMIT (1) /* an unstable reply was received */
88#define NFS_ODIRECT_RESCHED_WRITES (2) /* write verification failed */ 88#define NFS_ODIRECT_RESCHED_WRITES (2) /* write verification failed */
@@ -524,7 +524,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
524 524
525static void nfs_direct_commit_result(struct rpc_task *task, void *calldata) 525static void nfs_direct_commit_result(struct rpc_task *task, void *calldata)
526{ 526{
527 struct nfs_write_data *data = calldata; 527 struct nfs_commit_data *data = calldata;
528 528
529 /* Call the NFS version-specific code */ 529 /* Call the NFS version-specific code */
530 NFS_PROTO(data->inode)->commit_done(task, data); 530 NFS_PROTO(data->inode)->commit_done(task, data);
@@ -532,8 +532,8 @@ static void nfs_direct_commit_result(struct rpc_task *task, void *calldata)
532 532
533static void nfs_direct_commit_release(void *calldata) 533static void nfs_direct_commit_release(void *calldata)
534{ 534{
535 struct nfs_write_data *data = calldata; 535 struct nfs_commit_data *data = calldata;
536 struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; 536 struct nfs_direct_req *dreq = data->dreq;
537 int status = data->task.tk_status; 537 int status = data->task.tk_status;
538 538
539 if (status < 0) { 539 if (status < 0) {
@@ -551,14 +551,14 @@ static void nfs_direct_commit_release(void *calldata)
551} 551}
552 552
553static const struct rpc_call_ops nfs_commit_direct_ops = { 553static const struct rpc_call_ops nfs_commit_direct_ops = {
554 .rpc_call_prepare = nfs_write_prepare, 554 .rpc_call_prepare = nfs_commit_prepare,
555 .rpc_call_done = nfs_direct_commit_result, 555 .rpc_call_done = nfs_direct_commit_result,
556 .rpc_release = nfs_direct_commit_release, 556 .rpc_release = nfs_direct_commit_release,
557}; 557};
558 558
559static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) 559static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
560{ 560{
561 struct nfs_write_data *data = dreq->commit_data; 561 struct nfs_commit_data *data = dreq->commit_data;
562 struct rpc_task *task; 562 struct rpc_task *task;
563 struct rpc_message msg = { 563 struct rpc_message msg = {
564 .rpc_argp = &data->args, 564 .rpc_argp = &data->args,
@@ -581,9 +581,6 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
581 data->args.fh = NFS_FH(data->inode); 581 data->args.fh = NFS_FH(data->inode);
582 data->args.offset = 0; 582 data->args.offset = 0;
583 data->args.count = 0; 583 data->args.count = 0;
584 data->args.context = dreq->ctx;
585 data->args.lock_context = dreq->l_ctx;
586 data->res.count = 0;
587 data->res.fattr = &data->fattr; 584 data->res.fattr = &data->fattr;
588 data->res.verf = &data->verf; 585 data->res.verf = &data->verf;
589 nfs_fattr_init(&data->fattr); 586 nfs_fattr_init(&data->fattr);
@@ -625,7 +622,7 @@ static void nfs_alloc_commit_data(struct nfs_direct_req *dreq)
625{ 622{
626 dreq->commit_data = nfs_commitdata_alloc(); 623 dreq->commit_data = nfs_commitdata_alloc();
627 if (dreq->commit_data != NULL) 624 if (dreq->commit_data != NULL)
628 dreq->commit_data->req = (struct nfs_page *) dreq; 625 dreq->commit_data->dreq = dreq;
629} 626}
630#else 627#else
631static inline void nfs_alloc_commit_data(struct nfs_direct_req *dreq) 628static inline void nfs_alloc_commit_data(struct nfs_direct_req *dreq)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b777bdaba4c5..29ab441b22b1 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -314,24 +314,25 @@ extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
314 struct inode *inode, int ioflags); 314 struct inode *inode, int ioflags);
315extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); 315extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
316extern void nfs_writedata_release(struct nfs_write_data *wdata); 316extern void nfs_writedata_release(struct nfs_write_data *wdata);
317extern void nfs_commit_free(struct nfs_write_data *p); 317extern void nfs_commit_free(struct nfs_commit_data *p);
318extern int nfs_initiate_write(struct nfs_write_data *data, 318extern int nfs_initiate_write(struct nfs_write_data *data,
319 struct rpc_clnt *clnt, 319 struct rpc_clnt *clnt,
320 const struct rpc_call_ops *call_ops, 320 const struct rpc_call_ops *call_ops,
321 int how); 321 int how);
322extern void nfs_write_prepare(struct rpc_task *task, void *calldata); 322extern void nfs_write_prepare(struct rpc_task *task, void *calldata);
323extern int nfs_initiate_commit(struct nfs_write_data *data, 323extern void nfs_commit_prepare(struct rpc_task *task, void *calldata);
324 struct rpc_clnt *clnt, 324extern int nfs_initiate_commit(struct rpc_clnt *clnt,
325 struct nfs_commit_data *data,
325 const struct rpc_call_ops *call_ops, 326 const struct rpc_call_ops *call_ops,
326 int how); 327 int how);
327extern void nfs_init_commit(struct nfs_write_data *data, 328extern void nfs_init_commit(struct nfs_commit_data *data,
328 struct list_head *head, 329 struct list_head *head,
329 struct pnfs_layout_segment *lseg); 330 struct pnfs_layout_segment *lseg);
330void nfs_retry_commit(struct list_head *page_list, 331void nfs_retry_commit(struct list_head *page_list,
331 struct pnfs_layout_segment *lseg); 332 struct pnfs_layout_segment *lseg);
332void nfs_commit_clear_lock(struct nfs_inode *nfsi); 333void nfs_commit_clear_lock(struct nfs_inode *nfsi);
333void nfs_commitdata_release(void *data); 334void nfs_commitdata_release(struct nfs_commit_data *data);
334void nfs_commit_release_pages(struct nfs_write_data *data); 335void nfs_commit_release_pages(struct nfs_commit_data *data);
335void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *head); 336void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *head);
336void nfs_request_remove_commit_list(struct nfs_page *req); 337void nfs_request_remove_commit_list(struct nfs_page *req);
337 338
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 5242eae6711a..b1daca7f0f7b 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -848,7 +848,12 @@ static void nfs3_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_
848 rpc_call_start(task); 848 rpc_call_start(task);
849} 849}
850 850
851static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) 851static void nfs3_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
852{
853 rpc_call_start(task);
854}
855
856static int nfs3_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
852{ 857{
853 if (nfs3_async_handle_jukebox(task, data->inode)) 858 if (nfs3_async_handle_jukebox(task, data->inode))
854 return -EAGAIN; 859 return -EAGAIN;
@@ -856,7 +861,7 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
856 return 0; 861 return 0;
857} 862}
858 863
859static void nfs3_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) 864static void nfs3_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
860{ 865{
861 msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT]; 866 msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT];
862} 867}
@@ -907,6 +912,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
907 .write_rpc_prepare = nfs3_proc_write_rpc_prepare, 912 .write_rpc_prepare = nfs3_proc_write_rpc_prepare,
908 .write_done = nfs3_write_done, 913 .write_done = nfs3_write_done,
909 .commit_setup = nfs3_proc_commit_setup, 914 .commit_setup = nfs3_proc_commit_setup,
915 .commit_rpc_prepare = nfs3_proc_commit_rpc_prepare,
910 .commit_done = nfs3_commit_done, 916 .commit_done = nfs3_commit_done,
911 .lock = nfs3_proc_lock, 917 .lock = nfs3_proc_lock,
912 .clear_acl_cache = nfs3_forget_cached_acls, 918 .clear_acl_cache = nfs3_forget_cached_acls,
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index a77cc9a3ce55..01e53e94f53d 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -1287,7 +1287,7 @@ static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req,
1287 * }; 1287 * };
1288 */ 1288 */
1289static void encode_commit3args(struct xdr_stream *xdr, 1289static void encode_commit3args(struct xdr_stream *xdr,
1290 const struct nfs_writeargs *args) 1290 const struct nfs_commitargs *args)
1291{ 1291{
1292 __be32 *p; 1292 __be32 *p;
1293 1293
@@ -1300,7 +1300,7 @@ static void encode_commit3args(struct xdr_stream *xdr,
1300 1300
1301static void nfs3_xdr_enc_commit3args(struct rpc_rqst *req, 1301static void nfs3_xdr_enc_commit3args(struct rpc_rqst *req,
1302 struct xdr_stream *xdr, 1302 struct xdr_stream *xdr,
1303 const struct nfs_writeargs *args) 1303 const struct nfs_commitargs *args)
1304{ 1304{
1305 encode_commit3args(xdr, args); 1305 encode_commit3args(xdr, args);
1306} 1306}
@@ -2319,7 +2319,7 @@ out_status:
2319 */ 2319 */
2320static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req, 2320static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
2321 struct xdr_stream *xdr, 2321 struct xdr_stream *xdr,
2322 struct nfs_writeres *result) 2322 struct nfs_commitres *result)
2323{ 2323{
2324 enum nfs_stat status; 2324 enum nfs_stat status;
2325 int error; 2325 int error;
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 15aeba20d57d..675ce3b8663c 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -250,7 +250,7 @@ static int filelayout_write_done_cb(struct rpc_task *task,
250} 250}
251 251
252/* Fake up some data that will cause nfs_commit_release to retry the writes. */ 252/* Fake up some data that will cause nfs_commit_release to retry the writes. */
253static void prepare_to_resend_writes(struct nfs_write_data *data) 253static void prepare_to_resend_writes(struct nfs_commit_data *data)
254{ 254{
255 struct nfs_page *first = nfs_list_entry(data->pages.next); 255 struct nfs_page *first = nfs_list_entry(data->pages.next);
256 256
@@ -261,11 +261,11 @@ static void prepare_to_resend_writes(struct nfs_write_data *data)
261} 261}
262 262
263static int filelayout_commit_done_cb(struct rpc_task *task, 263static int filelayout_commit_done_cb(struct rpc_task *task,
264 struct nfs_write_data *data) 264 struct nfs_commit_data *data)
265{ 265{
266 int reset = 0; 266 int reset = 0;
267 267
268 if (filelayout_async_handle_error(task, data->args.context->state, 268 if (filelayout_async_handle_error(task, data->context->state,
269 data->ds_clp, &reset) == -EAGAIN) { 269 data->ds_clp, &reset) == -EAGAIN) {
270 dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", 270 dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n",
271 __func__, data->ds_clp, data->ds_clp->cl_session); 271 __func__, data->ds_clp, data->ds_clp->cl_session);
@@ -315,15 +315,42 @@ static void filelayout_write_release(void *data)
315 wdata->mds_ops->rpc_release(data); 315 wdata->mds_ops->rpc_release(data);
316} 316}
317 317
318static void filelayout_commit_release(void *data) 318static void filelayout_commit_prepare(struct rpc_task *task, void *data)
319{ 319{
320 struct nfs_write_data *wdata = (struct nfs_write_data *)data; 320 struct nfs_commit_data *wdata = data;
321 321
322 nfs_commit_release_pages(wdata); 322 if (nfs41_setup_sequence(wdata->ds_clp->cl_session,
323 if (atomic_dec_and_test(&NFS_I(wdata->inode)->commits_outstanding)) 323 &wdata->args.seq_args, &wdata->res.seq_res,
324 nfs_commit_clear_lock(NFS_I(wdata->inode)); 324 task))
325 put_lseg(wdata->lseg); 325 return;
326 nfs_commitdata_release(wdata); 326
327 rpc_call_start(task);
328}
329
330static void filelayout_write_commit_done(struct rpc_task *task, void *data)
331{
332 struct nfs_commit_data *wdata = data;
333
334 /* Note this may cause RPC to be resent */
335 wdata->mds_ops->rpc_call_done(task, data);
336}
337
338static void filelayout_commit_count_stats(struct rpc_task *task, void *data)
339{
340 struct nfs_commit_data *cdata = data;
341
342 rpc_count_iostats(task, NFS_SERVER(cdata->inode)->client->cl_metrics);
343}
344
345static void filelayout_commit_release(void *calldata)
346{
347 struct nfs_commit_data *data = calldata;
348
349 nfs_commit_release_pages(data);
350 if (atomic_dec_and_test(&NFS_I(data->inode)->commits_outstanding))
351 nfs_commit_clear_lock(NFS_I(data->inode));
352 put_lseg(data->lseg);
353 nfs_commitdata_release(data);
327} 354}
328 355
329static const struct rpc_call_ops filelayout_read_call_ops = { 356static const struct rpc_call_ops filelayout_read_call_ops = {
@@ -341,9 +368,9 @@ static const struct rpc_call_ops filelayout_write_call_ops = {
341}; 368};
342 369
343static const struct rpc_call_ops filelayout_commit_call_ops = { 370static const struct rpc_call_ops filelayout_commit_call_ops = {
344 .rpc_call_prepare = filelayout_write_prepare, 371 .rpc_call_prepare = filelayout_commit_prepare,
345 .rpc_call_done = filelayout_write_call_done, 372 .rpc_call_done = filelayout_write_commit_done,
346 .rpc_count_stats = filelayout_write_count_stats, 373 .rpc_count_stats = filelayout_commit_count_stats,
347 .rpc_release = filelayout_commit_release, 374 .rpc_release = filelayout_commit_release,
348}; 375};
349 376
@@ -922,7 +949,7 @@ select_ds_fh_from_commit(struct pnfs_layout_segment *lseg, u32 i)
922 return flseg->fh_array[i]; 949 return flseg->fh_array[i];
923} 950}
924 951
925static int filelayout_initiate_commit(struct nfs_write_data *data, int how) 952static int filelayout_initiate_commit(struct nfs_commit_data *data, int how)
926{ 953{
927 struct pnfs_layout_segment *lseg = data->lseg; 954 struct pnfs_layout_segment *lseg = data->lseg;
928 struct nfs4_pnfs_ds *ds; 955 struct nfs4_pnfs_ds *ds;
@@ -941,12 +968,12 @@ static int filelayout_initiate_commit(struct nfs_write_data *data, int how)
941 return -EAGAIN; 968 return -EAGAIN;
942 } 969 }
943 dprintk("%s ino %lu, how %d\n", __func__, data->inode->i_ino, how); 970 dprintk("%s ino %lu, how %d\n", __func__, data->inode->i_ino, how);
944 data->write_done_cb = filelayout_commit_done_cb; 971 data->commit_done_cb = filelayout_commit_done_cb;
945 data->ds_clp = ds->ds_clp; 972 data->ds_clp = ds->ds_clp;
946 fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); 973 fh = select_ds_fh_from_commit(lseg, data->ds_commit_index);
947 if (fh) 974 if (fh)
948 data->args.fh = fh; 975 data->args.fh = fh;
949 return nfs_initiate_commit(data, ds->ds_clp->cl_rpcclient, 976 return nfs_initiate_commit(ds->ds_clp->cl_rpcclient, data,
950 &filelayout_commit_call_ops, how); 977 &filelayout_commit_call_ops, how);
951} 978}
952 979
@@ -1008,7 +1035,7 @@ alloc_ds_commits(struct inode *inode, struct list_head *list)
1008{ 1035{
1009 struct nfs4_fl_commit_info *fl_cinfo; 1036 struct nfs4_fl_commit_info *fl_cinfo;
1010 struct nfs4_fl_commit_bucket *bucket; 1037 struct nfs4_fl_commit_bucket *bucket;
1011 struct nfs_write_data *data; 1038 struct nfs_commit_data *data;
1012 int i, j; 1039 int i, j;
1013 unsigned int nreq = 0; 1040 unsigned int nreq = 0;
1014 1041
@@ -1044,7 +1071,7 @@ static int
1044filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, 1071filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
1045 int how) 1072 int how)
1046{ 1073{
1047 struct nfs_write_data *data, *tmp; 1074 struct nfs_commit_data *data, *tmp;
1048 LIST_HEAD(list); 1075 LIST_HEAD(list);
1049 unsigned int nreq = 0; 1076 unsigned int nreq = 0;
1050 1077
@@ -1071,7 +1098,7 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
1071 list_del_init(&data->pages); 1098 list_del_init(&data->pages);
1072 if (!data->lseg) { 1099 if (!data->lseg) {
1073 nfs_init_commit(data, mds_pages, NULL); 1100 nfs_init_commit(data, mds_pages, NULL);
1074 nfs_initiate_commit(data, NFS_CLIENT(inode), 1101 nfs_initiate_commit(NFS_CLIENT(inode), data,
1075 data->mds_ops, how); 1102 data->mds_ops, how);
1076 } else { 1103 } else {
1077 struct nfs4_fl_commit_info *fl_cinfo; 1104 struct nfs4_fl_commit_info *fl_cinfo;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 75eb883ed4ce..cc04b6e409ed 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3468,7 +3468,17 @@ static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_
3468 rpc_call_start(task); 3468 rpc_call_start(task);
3469} 3469}
3470 3470
3471static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *data) 3471static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
3472{
3473 if (nfs4_setup_sequence(NFS_SERVER(data->inode),
3474 &data->args.seq_args,
3475 &data->res.seq_res,
3476 task))
3477 return;
3478 rpc_call_start(task);
3479}
3480
3481static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data)
3472{ 3482{
3473 struct inode *inode = data->inode; 3483 struct inode *inode = data->inode;
3474 3484
@@ -3480,14 +3490,14 @@ static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *dat
3480 return 0; 3490 return 0;
3481} 3491}
3482 3492
3483static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) 3493static int nfs4_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
3484{ 3494{
3485 if (!nfs4_sequence_done(task, &data->res.seq_res)) 3495 if (!nfs4_sequence_done(task, &data->res.seq_res))
3486 return -EAGAIN; 3496 return -EAGAIN;
3487 return data->write_done_cb(task, data); 3497 return data->commit_done_cb(task, data);
3488} 3498}
3489 3499
3490static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) 3500static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
3491{ 3501{
3492 struct nfs_server *server = NFS_SERVER(data->inode); 3502 struct nfs_server *server = NFS_SERVER(data->inode);
3493 3503
@@ -3496,8 +3506,8 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa
3496 data->res.fattr = NULL; 3506 data->res.fattr = NULL;
3497 } else 3507 } else
3498 data->args.bitmask = server->cache_consistency_bitmask; 3508 data->args.bitmask = server->cache_consistency_bitmask;
3499 if (!data->write_done_cb) 3509 if (data->commit_done_cb == NULL)
3500 data->write_done_cb = nfs4_commit_done_cb; 3510 data->commit_done_cb = nfs4_commit_done_cb;
3501 data->res.server = server; 3511 data->res.server = server;
3502 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; 3512 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
3503 nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); 3513 nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
@@ -6591,6 +6601,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
6591 .write_rpc_prepare = nfs4_proc_write_rpc_prepare, 6601 .write_rpc_prepare = nfs4_proc_write_rpc_prepare,
6592 .write_done = nfs4_write_done, 6602 .write_done = nfs4_write_done,
6593 .commit_setup = nfs4_proc_commit_setup, 6603 .commit_setup = nfs4_proc_commit_setup,
6604 .commit_rpc_prepare = nfs4_proc_commit_rpc_prepare,
6594 .commit_done = nfs4_commit_done, 6605 .commit_done = nfs4_commit_done,
6595 .lock = nfs4_proc_lock, 6606 .lock = nfs4_proc_lock,
6596 .clear_acl_cache = nfs4_zap_acl_attr, 6607 .clear_acl_cache = nfs4_zap_acl_attr,
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index c54aae364bee..4c3cc0ed9543 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1103,7 +1103,7 @@ static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg
1103 encode_nfs4_stateid(xdr, arg->stateid); 1103 encode_nfs4_stateid(xdr, arg->stateid);
1104} 1104}
1105 1105
1106static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) 1106static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr)
1107{ 1107{
1108 __be32 *p; 1108 __be32 *p;
1109 1109
@@ -2448,7 +2448,7 @@ static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr,
2448 * a COMMIT request 2448 * a COMMIT request
2449 */ 2449 */
2450static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, 2450static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr,
2451 struct nfs_writeargs *args) 2451 struct nfs_commitargs *args)
2452{ 2452{
2453 struct compound_hdr hdr = { 2453 struct compound_hdr hdr = {
2454 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2454 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
@@ -4102,7 +4102,7 @@ static int decode_verifier(struct xdr_stream *xdr, void *verifier)
4102 return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE); 4102 return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE);
4103} 4103}
4104 4104
4105static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) 4105static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res)
4106{ 4106{
4107 int status; 4107 int status;
4108 4108
@@ -6353,7 +6353,7 @@ out:
6353 * Decode COMMIT response 6353 * Decode COMMIT response
6354 */ 6354 */
6355static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6355static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6356 struct nfs_writeres *res) 6356 struct nfs_commitres *res)
6357{ 6357{
6358 struct compound_hdr hdr; 6358 struct compound_hdr hdr;
6359 int status; 6359 int status;
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index b63b6f4d14fb..bf80503200f5 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -688,8 +688,13 @@ static void nfs_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_d
688 rpc_call_start(task); 688 rpc_call_start(task);
689} 689}
690 690
691static void nfs_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
692{
693 BUG();
694}
695
691static void 696static void
692nfs_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) 697nfs_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
693{ 698{
694 BUG(); 699 BUG();
695} 700}
@@ -764,6 +769,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
764 .write_rpc_prepare = nfs_proc_write_rpc_prepare, 769 .write_rpc_prepare = nfs_proc_write_rpc_prepare,
765 .write_done = nfs_write_done, 770 .write_done = nfs_write_done,
766 .commit_setup = nfs_proc_commit_setup, 771 .commit_setup = nfs_proc_commit_setup,
772 .commit_rpc_prepare = nfs_proc_commit_rpc_prepare,
767 .lock = nfs_proc_lock, 773 .lock = nfs_proc_lock,
768 .lock_check_bounds = nfs_lock_check_bounds, 774 .lock_check_bounds = nfs_lock_check_bounds,
769 .close_context = nfs_close_context, 775 .close_context = nfs_close_context,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index c07462320f6b..54f7c0ffe5c3 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -48,11 +48,12 @@ static const struct rpc_call_ops nfs_commit_ops;
48 48
49static struct kmem_cache *nfs_wdata_cachep; 49static struct kmem_cache *nfs_wdata_cachep;
50static mempool_t *nfs_wdata_mempool; 50static mempool_t *nfs_wdata_mempool;
51static struct kmem_cache *nfs_cdata_cachep;
51static mempool_t *nfs_commit_mempool; 52static mempool_t *nfs_commit_mempool;
52 53
53struct nfs_write_data *nfs_commitdata_alloc(void) 54struct nfs_commit_data *nfs_commitdata_alloc(void)
54{ 55{
55 struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS); 56 struct nfs_commit_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS);
56 57
57 if (p) { 58 if (p) {
58 memset(p, 0, sizeof(*p)); 59 memset(p, 0, sizeof(*p));
@@ -62,10 +63,8 @@ struct nfs_write_data *nfs_commitdata_alloc(void)
62} 63}
63EXPORT_SYMBOL_GPL(nfs_commitdata_alloc); 64EXPORT_SYMBOL_GPL(nfs_commitdata_alloc);
64 65
65void nfs_commit_free(struct nfs_write_data *p) 66void nfs_commit_free(struct nfs_commit_data *p)
66{ 67{
67 if (p && (p->pagevec != &p->page_array[0]))
68 kfree(p->pagevec);
69 mempool_free(p, nfs_commit_mempool); 68 mempool_free(p, nfs_commit_mempool);
70} 69}
71EXPORT_SYMBOL_GPL(nfs_commit_free); 70EXPORT_SYMBOL_GPL(nfs_commit_free);
@@ -1179,6 +1178,13 @@ void nfs_write_prepare(struct rpc_task *task, void *calldata)
1179 NFS_PROTO(data->inode)->write_rpc_prepare(task, data); 1178 NFS_PROTO(data->inode)->write_rpc_prepare(task, data);
1180} 1179}
1181 1180
1181void nfs_commit_prepare(struct rpc_task *task, void *calldata)
1182{
1183 struct nfs_commit_data *data = calldata;
1184
1185 NFS_PROTO(data->inode)->commit_rpc_prepare(task, data);
1186}
1187
1182static const struct rpc_call_ops nfs_write_partial_ops = { 1188static const struct rpc_call_ops nfs_write_partial_ops = {
1183 .rpc_call_prepare = nfs_write_prepare, 1189 .rpc_call_prepare = nfs_write_prepare,
1184 .rpc_call_done = nfs_writeback_done_partial, 1190 .rpc_call_done = nfs_writeback_done_partial,
@@ -1355,16 +1361,14 @@ void nfs_commit_clear_lock(struct nfs_inode *nfsi)
1355} 1361}
1356EXPORT_SYMBOL_GPL(nfs_commit_clear_lock); 1362EXPORT_SYMBOL_GPL(nfs_commit_clear_lock);
1357 1363
1358void nfs_commitdata_release(void *data) 1364void nfs_commitdata_release(struct nfs_commit_data *data)
1359{ 1365{
1360 struct nfs_write_data *wdata = data; 1366 put_nfs_open_context(data->context);
1361 1367 nfs_commit_free(data);
1362 put_nfs_open_context(wdata->args.context);
1363 nfs_commit_free(wdata);
1364} 1368}
1365EXPORT_SYMBOL_GPL(nfs_commitdata_release); 1369EXPORT_SYMBOL_GPL(nfs_commitdata_release);
1366 1370
1367int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *clnt, 1371int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
1368 const struct rpc_call_ops *call_ops, 1372 const struct rpc_call_ops *call_ops,
1369 int how) 1373 int how)
1370{ 1374{
@@ -1403,7 +1407,7 @@ EXPORT_SYMBOL_GPL(nfs_initiate_commit);
1403/* 1407/*
1404 * Set up the argument/result storage required for the RPC call. 1408 * Set up the argument/result storage required for the RPC call.
1405 */ 1409 */
1406void nfs_init_commit(struct nfs_write_data *data, 1410void nfs_init_commit(struct nfs_commit_data *data,
1407 struct list_head *head, 1411 struct list_head *head,
1408 struct pnfs_layout_segment *lseg) 1412 struct pnfs_layout_segment *lseg)
1409{ 1413{
@@ -1424,8 +1428,7 @@ void nfs_init_commit(struct nfs_write_data *data,
1424 /* Note: we always request a commit of the entire inode */ 1428 /* Note: we always request a commit of the entire inode */
1425 data->args.offset = 0; 1429 data->args.offset = 0;
1426 data->args.count = 0; 1430 data->args.count = 0;
1427 data->args.context = get_nfs_open_context(first->wb_context); 1431 data->context = get_nfs_open_context(first->wb_context);
1428 data->res.count = 0;
1429 data->res.fattr = &data->fattr; 1432 data->res.fattr = &data->fattr;
1430 data->res.verf = &data->verf; 1433 data->res.verf = &data->verf;
1431 nfs_fattr_init(&data->fattr); 1434 nfs_fattr_init(&data->fattr);
@@ -1455,7 +1458,7 @@ EXPORT_SYMBOL_GPL(nfs_retry_commit);
1455static int 1458static int
1456nfs_commit_list(struct inode *inode, struct list_head *head, int how) 1459nfs_commit_list(struct inode *inode, struct list_head *head, int how)
1457{ 1460{
1458 struct nfs_write_data *data; 1461 struct nfs_commit_data *data;
1459 1462
1460 data = nfs_commitdata_alloc(); 1463 data = nfs_commitdata_alloc();
1461 1464
@@ -1464,7 +1467,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
1464 1467
1465 /* Set up the argument struct */ 1468 /* Set up the argument struct */
1466 nfs_init_commit(data, head, NULL); 1469 nfs_init_commit(data, head, NULL);
1467 return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); 1470 return nfs_initiate_commit(NFS_CLIENT(inode), data, data->mds_ops, how);
1468 out_bad: 1471 out_bad:
1469 nfs_retry_commit(head, NULL); 1472 nfs_retry_commit(head, NULL);
1470 nfs_commit_clear_lock(NFS_I(inode)); 1473 nfs_commit_clear_lock(NFS_I(inode));
@@ -1476,7 +1479,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
1476 */ 1479 */
1477static void nfs_commit_done(struct rpc_task *task, void *calldata) 1480static void nfs_commit_done(struct rpc_task *task, void *calldata)
1478{ 1481{
1479 struct nfs_write_data *data = calldata; 1482 struct nfs_commit_data *data = calldata;
1480 1483
1481 dprintk("NFS: %5u nfs_commit_done (status %d)\n", 1484 dprintk("NFS: %5u nfs_commit_done (status %d)\n",
1482 task->tk_pid, task->tk_status); 1485 task->tk_pid, task->tk_status);
@@ -1485,7 +1488,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
1485 NFS_PROTO(data->inode)->commit_done(task, data); 1488 NFS_PROTO(data->inode)->commit_done(task, data);
1486} 1489}
1487 1490
1488void nfs_commit_release_pages(struct nfs_write_data *data) 1491void nfs_commit_release_pages(struct nfs_commit_data *data)
1489{ 1492{
1490 struct nfs_page *req; 1493 struct nfs_page *req;
1491 int status = data->task.tk_status; 1494 int status = data->task.tk_status;
@@ -1526,7 +1529,7 @@ EXPORT_SYMBOL_GPL(nfs_commit_release_pages);
1526 1529
1527static void nfs_commit_release(void *calldata) 1530static void nfs_commit_release(void *calldata)
1528{ 1531{
1529 struct nfs_write_data *data = calldata; 1532 struct nfs_commit_data *data = calldata;
1530 1533
1531 nfs_commit_release_pages(data); 1534 nfs_commit_release_pages(data);
1532 nfs_commit_clear_lock(NFS_I(data->inode)); 1535 nfs_commit_clear_lock(NFS_I(data->inode));
@@ -1534,7 +1537,7 @@ static void nfs_commit_release(void *calldata)
1534} 1537}
1535 1538
1536static const struct rpc_call_ops nfs_commit_ops = { 1539static const struct rpc_call_ops nfs_commit_ops = {
1537 .rpc_call_prepare = nfs_write_prepare, 1540 .rpc_call_prepare = nfs_commit_prepare,
1538 .rpc_call_done = nfs_commit_done, 1541 .rpc_call_done = nfs_commit_done,
1539 .rpc_release = nfs_commit_release, 1542 .rpc_release = nfs_commit_release,
1540}; 1543};
@@ -1753,6 +1756,13 @@ int __init nfs_init_writepagecache(void)
1753 if (nfs_wdata_mempool == NULL) 1756 if (nfs_wdata_mempool == NULL)
1754 return -ENOMEM; 1757 return -ENOMEM;
1755 1758
1759 nfs_cdata_cachep = kmem_cache_create("nfs_commit_data",
1760 sizeof(struct nfs_commit_data),
1761 0, SLAB_HWCACHE_ALIGN,
1762 NULL);
1763 if (nfs_cdata_cachep == NULL)
1764 return -ENOMEM;
1765
1756 nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, 1766 nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT,
1757 nfs_wdata_cachep); 1767 nfs_wdata_cachep);
1758 if (nfs_commit_mempool == NULL) 1768 if (nfs_commit_mempool == NULL)
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 52a1bdb4ee2b..d5d68f322bf0 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -552,8 +552,8 @@ extern int nfs_wb_page(struct inode *inode, struct page* page);
552extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); 552extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
553#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 553#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
554extern int nfs_commit_inode(struct inode *, int); 554extern int nfs_commit_inode(struct inode *, int);
555extern struct nfs_write_data *nfs_commitdata_alloc(void); 555extern struct nfs_commit_data *nfs_commitdata_alloc(void);
556extern void nfs_commit_free(struct nfs_write_data *wdata); 556extern void nfs_commit_free(struct nfs_commit_data *data);
557#else 557#else
558static inline int 558static inline int
559nfs_commit_inode(struct inode *inode, int how) 559nfs_commit_inode(struct inode *inode, int how)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 7ba3551a0414..8fb036a0d489 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -519,6 +519,24 @@ struct nfs_writeres {
519}; 519};
520 520
521/* 521/*
522 * Arguments to the commit call.
523 */
524struct nfs_commitargs {
525 struct nfs_fh *fh;
526 __u64 offset;
527 __u32 count;
528 const u32 *bitmask;
529 struct nfs4_sequence_args seq_args;
530};
531
532struct nfs_commitres {
533 struct nfs_fattr *fattr;
534 struct nfs_writeverf *verf;
535 const struct nfs_server *server;
536 struct nfs4_sequence_res seq_res;
537};
538
539/*
522 * Common arguments to the unlink call 540 * Common arguments to the unlink call
523 */ 541 */
524struct nfs_removeargs { 542struct nfs_removeargs {
@@ -1171,6 +1189,8 @@ struct nfs_read_data {
1171 struct page *page_array[NFS_PAGEVEC_SIZE]; 1189 struct page *page_array[NFS_PAGEVEC_SIZE];
1172}; 1190};
1173 1191
1192struct nfs_direct_req;
1193
1174struct nfs_write_data { 1194struct nfs_write_data {
1175 struct rpc_task task; 1195 struct rpc_task task;
1176 struct inode *inode; 1196 struct inode *inode;
@@ -1186,7 +1206,6 @@ struct nfs_write_data {
1186 struct nfs_writeres res; /* result struct */ 1206 struct nfs_writeres res; /* result struct */
1187 struct pnfs_layout_segment *lseg; 1207 struct pnfs_layout_segment *lseg;
1188 struct nfs_client *ds_clp; /* pNFS data server */ 1208 struct nfs_client *ds_clp; /* pNFS data server */
1189 int ds_commit_index;
1190 const struct rpc_call_ops *mds_ops; 1209 const struct rpc_call_ops *mds_ops;
1191 int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data); 1210 int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data);
1192#ifdef CONFIG_NFS_V4 1211#ifdef CONFIG_NFS_V4
@@ -1197,6 +1216,25 @@ struct nfs_write_data {
1197 struct page *page_array[NFS_PAGEVEC_SIZE]; 1216 struct page *page_array[NFS_PAGEVEC_SIZE];
1198}; 1217};
1199 1218
1219struct nfs_commit_data {
1220 struct rpc_task task;
1221 struct inode *inode;
1222 struct rpc_cred *cred;
1223 struct nfs_fattr fattr;
1224 struct nfs_writeverf verf;
1225 struct list_head pages; /* Coalesced requests we wish to flush */
1226 struct list_head list; /* lists of struct nfs_write_data */
1227 struct nfs_direct_req *dreq; /* O_DIRECT request */
1228 struct nfs_commitargs args; /* argument struct */
1229 struct nfs_commitres res; /* result struct */
1230 struct nfs_open_context *context;
1231 struct pnfs_layout_segment *lseg;
1232 struct nfs_client *ds_clp; /* pNFS data server */
1233 int ds_commit_index;
1234 const struct rpc_call_ops *mds_ops;
1235 int (*commit_done_cb) (struct rpc_task *task, struct nfs_commit_data *data);
1236};
1237
1200struct nfs_unlinkdata { 1238struct nfs_unlinkdata {
1201 struct hlist_node list; 1239 struct hlist_node list;
1202 struct nfs_removeargs args; 1240 struct nfs_removeargs args;
@@ -1277,8 +1315,9 @@ struct nfs_rpc_ops {
1277 void (*write_setup) (struct nfs_write_data *, struct rpc_message *); 1315 void (*write_setup) (struct nfs_write_data *, struct rpc_message *);
1278 void (*write_rpc_prepare)(struct rpc_task *, struct nfs_write_data *); 1316 void (*write_rpc_prepare)(struct rpc_task *, struct nfs_write_data *);
1279 int (*write_done) (struct rpc_task *, struct nfs_write_data *); 1317 int (*write_done) (struct rpc_task *, struct nfs_write_data *);
1280 void (*commit_setup) (struct nfs_write_data *, struct rpc_message *); 1318 void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *);
1281 int (*commit_done) (struct rpc_task *, struct nfs_write_data *); 1319 void (*commit_rpc_prepare)(struct rpc_task *, struct nfs_commit_data *);
1320 int (*commit_done) (struct rpc_task *, struct nfs_commit_data *);
1282 int (*lock)(struct file *, int, struct file_lock *); 1321 int (*lock)(struct file *, int, struct file_lock *);
1283 int (*lock_check_bounds)(const struct file_lock *); 1322 int (*lock_check_bounds)(const struct file_lock *);
1284 void (*clear_acl_cache)(struct inode *); 1323 void (*clear_acl_cache)(struct inode *);