aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:27 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:27 -0500
commit788e7a89a03e364855583c0ab4649b94925efbb9 (patch)
tree4434c93af133a92f550ba0ecc8d3254cb222e72d
parent7117bf3dfb10b534a017260d9fc643bc1d0afd2a (diff)
NFS: Cleanup of NFS write code in preparation for asynchronous o_direct
This patch inverts the callback hierarchy for NFS write calls. Instead of having the NFSv2/v3/v4-specific code set up the RPC callback ops, we allow the original caller to do so. This allows for more flexibility w.r.t. how to set up and tear down the nfs_write_data structure while still allowing the NFSv3/v4 code to perform error handling. The greater flexibility is needed by the asynchronous O_DIRECT code, which wants to be able to hold on to the original nfs_write_data structures after the WRITE RPC call has completed in order to be able to replay them if the COMMIT call determines that the server has rebooted. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs3proc.c66
-rw-r--r--fs/nfs/nfs4proc.c54
-rw-r--r--fs/nfs/proc.c24
-rw-r--r--fs/nfs/write.c92
-rw-r--r--include/linux/nfs_fs.h7
-rw-r--r--include/linux/nfs_xdr.h3
6 files changed, 103 insertions, 143 deletions
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 740f8b1ab04d..c4f7de8830e9 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -849,29 +849,17 @@ nfs3_proc_read_setup(struct nfs_read_data *data)
849 rpc_call_setup(task, &msg, 0); 849 rpc_call_setup(task, &msg, 0);
850} 850}
851 851
852static void nfs3_write_done(struct rpc_task *task, void *calldata) 852static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
853{ 853{
854 struct nfs_write_data *data = calldata;
855
856 if (nfs3_async_handle_jukebox(task, data->inode)) 854 if (nfs3_async_handle_jukebox(task, data->inode))
857 return; 855 return -EAGAIN;
858 if (task->tk_status >= 0) 856 if (task->tk_status >= 0)
859 nfs_post_op_update_inode(data->inode, data->res.fattr); 857 nfs_post_op_update_inode(data->inode, data->res.fattr);
860 nfs_writeback_done(task, calldata); 858 return 0;
861} 859}
862 860
863static const struct rpc_call_ops nfs3_write_ops = { 861static void nfs3_proc_write_setup(struct nfs_write_data *data, int how)
864 .rpc_call_done = nfs3_write_done,
865 .rpc_release = nfs_writedata_release,
866};
867
868static void
869nfs3_proc_write_setup(struct nfs_write_data *data, int how)
870{ 862{
871 struct rpc_task *task = &data->task;
872 struct inode *inode = data->inode;
873 int stable;
874 int flags;
875 struct rpc_message msg = { 863 struct rpc_message msg = {
876 .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE], 864 .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE],
877 .rpc_argp = &data->args, 865 .rpc_argp = &data->args,
@@ -879,45 +867,28 @@ nfs3_proc_write_setup(struct nfs_write_data *data, int how)
879 .rpc_cred = data->cred, 867 .rpc_cred = data->cred,
880 }; 868 };
881 869
870 data->args.stable = NFS_UNSTABLE;
882 if (how & FLUSH_STABLE) { 871 if (how & FLUSH_STABLE) {
883 if (!NFS_I(inode)->ncommit) 872 data->args.stable = NFS_FILE_SYNC;
884 stable = NFS_FILE_SYNC; 873 if (NFS_I(data->inode)->ncommit)
885 else 874 data->args.stable = NFS_DATA_SYNC;
886 stable = NFS_DATA_SYNC; 875 }
887 } else
888 stable = NFS_UNSTABLE;
889 data->args.stable = stable;
890
891 /* Set the initial flags for the task. */
892 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
893 876
894 /* Finalize the task. */ 877 /* Finalize the task. */
895 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_write_ops, data); 878 rpc_call_setup(&data->task, &msg, 0);
896 rpc_call_setup(task, &msg, 0);
897} 879}
898 880
899static void nfs3_commit_done(struct rpc_task *task, void *calldata) 881static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
900{ 882{
901 struct nfs_write_data *data = calldata;
902
903 if (nfs3_async_handle_jukebox(task, data->inode)) 883 if (nfs3_async_handle_jukebox(task, data->inode))
904 return; 884 return -EAGAIN;
905 if (task->tk_status >= 0) 885 if (task->tk_status >= 0)
906 nfs_post_op_update_inode(data->inode, data->res.fattr); 886 nfs_post_op_update_inode(data->inode, data->res.fattr);
907 nfs_commit_done(task, calldata); 887 return 0;
908} 888}
909 889
910static const struct rpc_call_ops nfs3_commit_ops = { 890static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
911 .rpc_call_done = nfs3_commit_done,
912 .rpc_release = nfs_commit_release,
913};
914
915static void
916nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
917{ 891{
918 struct rpc_task *task = &data->task;
919 struct inode *inode = data->inode;
920 int flags;
921 struct rpc_message msg = { 892 struct rpc_message msg = {
922 .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT], 893 .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT],
923 .rpc_argp = &data->args, 894 .rpc_argp = &data->args,
@@ -925,12 +896,7 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
925 .rpc_cred = data->cred, 896 .rpc_cred = data->cred,
926 }; 897 };
927 898
928 /* Set the initial flags for the task. */ 899 rpc_call_setup(&data->task, &msg, 0);
929 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
930
931 /* Finalize the task. */
932 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_commit_ops, data);
933 rpc_call_setup(task, &msg, 0);
934} 900}
935 901
936static int 902static int
@@ -970,7 +936,9 @@ struct nfs_rpc_ops nfs_v3_clientops = {
970 .decode_dirent = nfs3_decode_dirent, 936 .decode_dirent = nfs3_decode_dirent,
971 .read_setup = nfs3_proc_read_setup, 937 .read_setup = nfs3_proc_read_setup,
972 .write_setup = nfs3_proc_write_setup, 938 .write_setup = nfs3_proc_write_setup,
939 .write_done = nfs3_write_done,
973 .commit_setup = nfs3_proc_commit_setup, 940 .commit_setup = nfs3_proc_commit_setup,
941 .commit_done = nfs3_commit_done,
974 .file_open = nfs_open, 942 .file_open = nfs_open,
975 .file_release = nfs_release, 943 .file_release = nfs_release,
976 .lock = nfs3_proc_lock, 944 .lock = nfs3_proc_lock,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f1ff4fa6cce5..ef4dc315ecc2 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2388,32 +2388,23 @@ nfs4_proc_read_setup(struct nfs_read_data *data)
2388 rpc_call_setup(task, &msg, 0); 2388 rpc_call_setup(task, &msg, 0);
2389} 2389}
2390 2390
2391static void nfs4_write_done(struct rpc_task *task, void *calldata) 2391static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
2392{ 2392{
2393 struct nfs_write_data *data = calldata;
2394 struct inode *inode = data->inode; 2393 struct inode *inode = data->inode;
2395 2394
2396 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { 2395 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
2397 rpc_restart_call(task); 2396 rpc_restart_call(task);
2398 return; 2397 return -EAGAIN;
2399 } 2398 }
2400 if (task->tk_status >= 0) { 2399 if (task->tk_status >= 0) {
2401 renew_lease(NFS_SERVER(inode), data->timestamp); 2400 renew_lease(NFS_SERVER(inode), data->timestamp);
2402 nfs_post_op_update_inode(inode, data->res.fattr); 2401 nfs_post_op_update_inode(inode, data->res.fattr);
2403 } 2402 }
2404 /* Call back common NFS writeback processing */ 2403 return 0;
2405 nfs_writeback_done(task, calldata);
2406} 2404}
2407 2405
2408static const struct rpc_call_ops nfs4_write_ops = { 2406static void nfs4_proc_write_setup(struct nfs_write_data *data, int how)
2409 .rpc_call_done = nfs4_write_done,
2410 .rpc_release = nfs_writedata_release,
2411};
2412
2413static void
2414nfs4_proc_write_setup(struct nfs_write_data *data, int how)
2415{ 2407{
2416 struct rpc_task *task = &data->task;
2417 struct rpc_message msg = { 2408 struct rpc_message msg = {
2418 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], 2409 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
2419 .rpc_argp = &data->args, 2410 .rpc_argp = &data->args,
@@ -2423,7 +2414,6 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
2423 struct inode *inode = data->inode; 2414 struct inode *inode = data->inode;
2424 struct nfs_server *server = NFS_SERVER(inode); 2415 struct nfs_server *server = NFS_SERVER(inode);
2425 int stable; 2416 int stable;
2426 int flags;
2427 2417
2428 if (how & FLUSH_STABLE) { 2418 if (how & FLUSH_STABLE) {
2429 if (!NFS_I(inode)->ncommit) 2419 if (!NFS_I(inode)->ncommit)
@@ -2438,57 +2428,37 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
2438 2428
2439 data->timestamp = jiffies; 2429 data->timestamp = jiffies;
2440 2430
2441 /* Set the initial flags for the task. */
2442 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
2443
2444 /* Finalize the task. */ 2431 /* Finalize the task. */
2445 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_write_ops, data); 2432 rpc_call_setup(&data->task, &msg, 0);
2446 rpc_call_setup(task, &msg, 0);
2447} 2433}
2448 2434
2449static void nfs4_commit_done(struct rpc_task *task, void *calldata) 2435static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
2450{ 2436{
2451 struct nfs_write_data *data = calldata;
2452 struct inode *inode = data->inode; 2437 struct inode *inode = data->inode;
2453 2438
2454 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { 2439 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
2455 rpc_restart_call(task); 2440 rpc_restart_call(task);
2456 return; 2441 return -EAGAIN;
2457 } 2442 }
2458 if (task->tk_status >= 0) 2443 if (task->tk_status >= 0)
2459 nfs_post_op_update_inode(inode, data->res.fattr); 2444 nfs_post_op_update_inode(inode, data->res.fattr);
2460 /* Call back common NFS writeback processing */ 2445 return 0;
2461 nfs_commit_done(task, calldata);
2462} 2446}
2463 2447
2464static const struct rpc_call_ops nfs4_commit_ops = { 2448static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
2465 .rpc_call_done = nfs4_commit_done,
2466 .rpc_release = nfs_commit_release,
2467};
2468
2469static void
2470nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
2471{ 2449{
2472 struct rpc_task *task = &data->task;
2473 struct rpc_message msg = { 2450 struct rpc_message msg = {
2474 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT], 2451 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
2475 .rpc_argp = &data->args, 2452 .rpc_argp = &data->args,
2476 .rpc_resp = &data->res, 2453 .rpc_resp = &data->res,
2477 .rpc_cred = data->cred, 2454 .rpc_cred = data->cred,
2478 }; 2455 };
2479 struct inode *inode = data->inode; 2456 struct nfs_server *server = NFS_SERVER(data->inode);
2480 struct nfs_server *server = NFS_SERVER(inode);
2481 int flags;
2482 2457
2483 data->args.bitmask = server->attr_bitmask; 2458 data->args.bitmask = server->attr_bitmask;
2484 data->res.server = server; 2459 data->res.server = server;
2485 2460
2486 /* Set the initial flags for the task. */ 2461 rpc_call_setup(&data->task, &msg, 0);
2487 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
2488
2489 /* Finalize the task. */
2490 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_commit_ops, data);
2491 rpc_call_setup(task, &msg, 0);
2492} 2462}
2493 2463
2494/* 2464/*
@@ -3648,7 +3618,9 @@ struct nfs_rpc_ops nfs_v4_clientops = {
3648 .decode_dirent = nfs4_decode_dirent, 3618 .decode_dirent = nfs4_decode_dirent,
3649 .read_setup = nfs4_proc_read_setup, 3619 .read_setup = nfs4_proc_read_setup,
3650 .write_setup = nfs4_proc_write_setup, 3620 .write_setup = nfs4_proc_write_setup,
3621 .write_done = nfs4_write_done,
3651 .commit_setup = nfs4_proc_commit_setup, 3622 .commit_setup = nfs4_proc_commit_setup,
3623 .commit_done = nfs4_commit_done,
3652 .file_open = nfs_open, 3624 .file_open = nfs_open,
3653 .file_release = nfs_release, 3625 .file_release = nfs_release,
3654 .lock = nfs4_proc_lock, 3626 .lock = nfs4_proc_lock,
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 2b051ab8bea8..608aa5932a1d 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -654,26 +654,15 @@ nfs_proc_read_setup(struct nfs_read_data *data)
654 rpc_call_setup(task, &msg, 0); 654 rpc_call_setup(task, &msg, 0);
655} 655}
656 656
657static void nfs_write_done(struct rpc_task *task, void *calldata) 657static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
658{ 658{
659 struct nfs_write_data *data = calldata;
660
661 if (task->tk_status >= 0) 659 if (task->tk_status >= 0)
662 nfs_post_op_update_inode(data->inode, data->res.fattr); 660 nfs_post_op_update_inode(data->inode, data->res.fattr);
663 nfs_writeback_done(task, calldata); 661 return 0;
664} 662}
665 663
666static const struct rpc_call_ops nfs_write_ops = { 664static void nfs_proc_write_setup(struct nfs_write_data *data, int how)
667 .rpc_call_done = nfs_write_done,
668 .rpc_release = nfs_writedata_release,
669};
670
671static void
672nfs_proc_write_setup(struct nfs_write_data *data, int how)
673{ 665{
674 struct rpc_task *task = &data->task;
675 struct inode *inode = data->inode;
676 int flags;
677 struct rpc_message msg = { 666 struct rpc_message msg = {
678 .rpc_proc = &nfs_procedures[NFSPROC_WRITE], 667 .rpc_proc = &nfs_procedures[NFSPROC_WRITE],
679 .rpc_argp = &data->args, 668 .rpc_argp = &data->args,
@@ -684,12 +673,8 @@ nfs_proc_write_setup(struct nfs_write_data *data, int how)
684 /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */ 673 /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
685 data->args.stable = NFS_FILE_SYNC; 674 data->args.stable = NFS_FILE_SYNC;
686 675
687 /* Set the initial flags for the task. */
688 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
689
690 /* Finalize the task. */ 676 /* Finalize the task. */
691 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_write_ops, data); 677 rpc_call_setup(&data->task, &msg, 0);
692 rpc_call_setup(task, &msg, 0);
693} 678}
694 679
695static void 680static void
@@ -736,6 +721,7 @@ struct nfs_rpc_ops nfs_v2_clientops = {
736 .decode_dirent = nfs_decode_dirent, 721 .decode_dirent = nfs_decode_dirent,
737 .read_setup = nfs_proc_read_setup, 722 .read_setup = nfs_proc_read_setup,
738 .write_setup = nfs_proc_write_setup, 723 .write_setup = nfs_proc_write_setup,
724 .write_done = nfs_write_done,
739 .commit_setup = nfs_proc_commit_setup, 725 .commit_setup = nfs_proc_commit_setup,
740 .file_open = nfs_open, 726 .file_open = nfs_open,
741 .file_release = nfs_release, 727 .file_release = nfs_release,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e7c8361cf201..5912274ff1a1 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -77,12 +77,14 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context*,
77 struct inode *, 77 struct inode *,
78 struct page *, 78 struct page *,
79 unsigned int, unsigned int); 79 unsigned int, unsigned int);
80static void nfs_writeback_done_partial(struct nfs_write_data *, int); 80static int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
81static void nfs_writeback_done_full(struct nfs_write_data *, int);
82static int nfs_wait_on_write_congestion(struct address_space *, int); 81static int nfs_wait_on_write_congestion(struct address_space *, int);
83static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int); 82static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int);
84static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, 83static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
85 unsigned int npages, int how); 84 unsigned int npages, int how);
85static const struct rpc_call_ops nfs_write_partial_ops;
86static const struct rpc_call_ops nfs_write_full_ops;
87static const struct rpc_call_ops nfs_commit_ops;
86 88
87static kmem_cache_t *nfs_wdata_cachep; 89static kmem_cache_t *nfs_wdata_cachep;
88mempool_t *nfs_wdata_mempool; 90mempool_t *nfs_wdata_mempool;
@@ -872,10 +874,12 @@ static inline int flush_task_priority(int how)
872 */ 874 */
873static void nfs_write_rpcsetup(struct nfs_page *req, 875static void nfs_write_rpcsetup(struct nfs_page *req,
874 struct nfs_write_data *data, 876 struct nfs_write_data *data,
877 const struct rpc_call_ops *call_ops,
875 unsigned int count, unsigned int offset, 878 unsigned int count, unsigned int offset,
876 int how) 879 int how)
877{ 880{
878 struct inode *inode; 881 struct inode *inode;
882 int flags;
879 883
880 /* Set up the RPC argument and reply structs 884 /* Set up the RPC argument and reply structs
881 * NB: take care not to mess about with data->commit et al. */ 885 * NB: take care not to mess about with data->commit et al. */
@@ -896,6 +900,9 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
896 data->res.verf = &data->verf; 900 data->res.verf = &data->verf;
897 nfs_fattr_init(&data->fattr); 901 nfs_fattr_init(&data->fattr);
898 902
903 /* Set up the initial task struct. */
904 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
905 rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data);
899 NFS_PROTO(inode)->write_setup(data, how); 906 NFS_PROTO(inode)->write_setup(data, how);
900 907
901 data->task.tk_priority = flush_task_priority(how); 908 data->task.tk_priority = flush_task_priority(how);
@@ -959,14 +966,15 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how)
959 list_del_init(&data->pages); 966 list_del_init(&data->pages);
960 967
961 data->pagevec[0] = page; 968 data->pagevec[0] = page;
962 data->complete = nfs_writeback_done_partial;
963 969
964 if (nbytes > wsize) { 970 if (nbytes > wsize) {
965 nfs_write_rpcsetup(req, data, wsize, offset, how); 971 nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
972 wsize, offset, how);
966 offset += wsize; 973 offset += wsize;
967 nbytes -= wsize; 974 nbytes -= wsize;
968 } else { 975 } else {
969 nfs_write_rpcsetup(req, data, nbytes, offset, how); 976 nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
977 nbytes, offset, how);
970 nbytes = 0; 978 nbytes = 0;
971 } 979 }
972 nfs_execute_write(data); 980 nfs_execute_write(data);
@@ -1020,9 +1028,8 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
1020 } 1028 }
1021 req = nfs_list_entry(data->pages.next); 1029 req = nfs_list_entry(data->pages.next);
1022 1030
1023 data->complete = nfs_writeback_done_full;
1024 /* Set up the argument struct */ 1031 /* Set up the argument struct */
1025 nfs_write_rpcsetup(req, data, count, 0, how); 1032 nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
1026 1033
1027 nfs_execute_write(data); 1034 nfs_execute_write(data);
1028 return 0; 1035 return 0;
@@ -1066,8 +1073,9 @@ nfs_flush_list(struct list_head *head, int wpages, int how)
1066/* 1073/*
1067 * Handle a write reply that flushed part of a page. 1074 * Handle a write reply that flushed part of a page.
1068 */ 1075 */
1069static void nfs_writeback_done_partial(struct nfs_write_data *data, int status) 1076static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
1070{ 1077{
1078 struct nfs_write_data *data = calldata;
1071 struct nfs_page *req = data->req; 1079 struct nfs_page *req = data->req;
1072 struct page *page = req->wb_page; 1080 struct page *page = req->wb_page;
1073 1081
@@ -1077,11 +1085,14 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
1077 req->wb_bytes, 1085 req->wb_bytes,
1078 (long long)req_offset(req)); 1086 (long long)req_offset(req));
1079 1087
1080 if (status < 0) { 1088 if (nfs_writeback_done(task, data) != 0)
1089 return;
1090
1091 if (task->tk_status < 0) {
1081 ClearPageUptodate(page); 1092 ClearPageUptodate(page);
1082 SetPageError(page); 1093 SetPageError(page);
1083 req->wb_context->error = status; 1094 req->wb_context->error = task->tk_status;
1084 dprintk(", error = %d\n", status); 1095 dprintk(", error = %d\n", task->tk_status);
1085 } else { 1096 } else {
1086#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1097#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
1087 if (data->verf.committed < NFS_FILE_SYNC) { 1098 if (data->verf.committed < NFS_FILE_SYNC) {
@@ -1102,6 +1113,11 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
1102 nfs_writepage_release(req); 1113 nfs_writepage_release(req);
1103} 1114}
1104 1115
1116static const struct rpc_call_ops nfs_write_partial_ops = {
1117 .rpc_call_done = nfs_writeback_done_partial,
1118 .rpc_release = nfs_writedata_release,
1119};
1120
1105/* 1121/*
1106 * Handle a write reply that flushes a whole page. 1122 * Handle a write reply that flushes a whole page.
1107 * 1123 *
@@ -1109,11 +1125,15 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
1109 * writebacks since the page->count is kept > 1 for as long 1125 * writebacks since the page->count is kept > 1 for as long
1110 * as the page has a write request pending. 1126 * as the page has a write request pending.
1111 */ 1127 */
1112static void nfs_writeback_done_full(struct nfs_write_data *data, int status) 1128static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
1113{ 1129{
1130 struct nfs_write_data *data = calldata;
1114 struct nfs_page *req; 1131 struct nfs_page *req;
1115 struct page *page; 1132 struct page *page;
1116 1133
1134 if (nfs_writeback_done(task, data) != 0)
1135 return;
1136
1117 /* Update attributes as result of writeback. */ 1137 /* Update attributes as result of writeback. */
1118 while (!list_empty(&data->pages)) { 1138 while (!list_empty(&data->pages)) {
1119 req = nfs_list_entry(data->pages.next); 1139 req = nfs_list_entry(data->pages.next);
@@ -1126,13 +1146,13 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
1126 req->wb_bytes, 1146 req->wb_bytes,
1127 (long long)req_offset(req)); 1147 (long long)req_offset(req));
1128 1148
1129 if (status < 0) { 1149 if (task->tk_status < 0) {
1130 ClearPageUptodate(page); 1150 ClearPageUptodate(page);
1131 SetPageError(page); 1151 SetPageError(page);
1132 req->wb_context->error = status; 1152 req->wb_context->error = task->tk_status;
1133 end_page_writeback(page); 1153 end_page_writeback(page);
1134 nfs_inode_remove_request(req); 1154 nfs_inode_remove_request(req);
1135 dprintk(", error = %d\n", status); 1155 dprintk(", error = %d\n", task->tk_status);
1136 goto next; 1156 goto next;
1137 } 1157 }
1138 end_page_writeback(page); 1158 end_page_writeback(page);
@@ -1154,18 +1174,28 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
1154 } 1174 }
1155} 1175}
1156 1176
1177static const struct rpc_call_ops nfs_write_full_ops = {
1178 .rpc_call_done = nfs_writeback_done_full,
1179 .rpc_release = nfs_writedata_release,
1180};
1181
1182
1157/* 1183/*
1158 * This function is called when the WRITE call is complete. 1184 * This function is called when the WRITE call is complete.
1159 */ 1185 */
1160void nfs_writeback_done(struct rpc_task *task, void *calldata) 1186static int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
1161{ 1187{
1162 struct nfs_write_data *data = calldata;
1163 struct nfs_writeargs *argp = &data->args; 1188 struct nfs_writeargs *argp = &data->args;
1164 struct nfs_writeres *resp = &data->res; 1189 struct nfs_writeres *resp = &data->res;
1190 int status;
1165 1191
1166 dprintk("NFS: %4d nfs_writeback_done (status %d)\n", 1192 dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
1167 task->tk_pid, task->tk_status); 1193 task->tk_pid, task->tk_status);
1168 1194
1195 /* Call the NFS version-specific code */
1196 status = NFS_PROTO(data->inode)->write_done(task, data);
1197 if (status != 0)
1198 return status;
1169 nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count); 1199 nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count);
1170 1200
1171#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1201#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
@@ -1210,7 +1240,7 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata)
1210 argp->stable = NFS_FILE_SYNC; 1240 argp->stable = NFS_FILE_SYNC;
1211 } 1241 }
1212 rpc_restart_call(task); 1242 rpc_restart_call(task);
1213 return; 1243 return -EAGAIN;
1214 } 1244 }
1215 if (time_before(complain, jiffies)) { 1245 if (time_before(complain, jiffies)) {
1216 printk(KERN_WARNING 1246 printk(KERN_WARNING
@@ -1221,11 +1251,7 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata)
1221 /* Can't do anything about it except throw an error. */ 1251 /* Can't do anything about it except throw an error. */
1222 task->tk_status = -EIO; 1252 task->tk_status = -EIO;
1223 } 1253 }
1224 1254 return 0;
1225 /*
1226 * Process the nfs_page list
1227 */
1228 data->complete(data, task->tk_status);
1229} 1255}
1230 1256
1231 1257
@@ -1239,10 +1265,12 @@ void nfs_commit_release(void *wdata)
1239 * Set up the argument/result storage required for the RPC call. 1265 * Set up the argument/result storage required for the RPC call.
1240 */ 1266 */
1241static void nfs_commit_rpcsetup(struct list_head *head, 1267static void nfs_commit_rpcsetup(struct list_head *head,
1242 struct nfs_write_data *data, int how) 1268 struct nfs_write_data *data,
1269 int how)
1243{ 1270{
1244 struct nfs_page *first; 1271 struct nfs_page *first;
1245 struct inode *inode; 1272 struct inode *inode;
1273 int flags;
1246 1274
1247 /* Set up the RPC argument and reply structs 1275 /* Set up the RPC argument and reply structs
1248 * NB: take care not to mess about with data->commit et al. */ 1276 * NB: take care not to mess about with data->commit et al. */
@@ -1262,7 +1290,10 @@ static void nfs_commit_rpcsetup(struct list_head *head,
1262 data->res.fattr = &data->fattr; 1290 data->res.fattr = &data->fattr;
1263 data->res.verf = &data->verf; 1291 data->res.verf = &data->verf;
1264 nfs_fattr_init(&data->fattr); 1292 nfs_fattr_init(&data->fattr);
1265 1293
1294 /* Set up the initial task struct. */
1295 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
1296 rpc_init_task(&data->task, NFS_CLIENT(inode), flags, &nfs_commit_ops, data);
1266 NFS_PROTO(inode)->commit_setup(data, how); 1297 NFS_PROTO(inode)->commit_setup(data, how);
1267 1298
1268 data->task.tk_priority = flush_task_priority(how); 1299 data->task.tk_priority = flush_task_priority(how);
@@ -1303,7 +1334,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
1303/* 1334/*
1304 * COMMIT call returned 1335 * COMMIT call returned
1305 */ 1336 */
1306void nfs_commit_done(struct rpc_task *task, void *calldata) 1337static void nfs_commit_done(struct rpc_task *task, void *calldata)
1307{ 1338{
1308 struct nfs_write_data *data = calldata; 1339 struct nfs_write_data *data = calldata;
1309 struct nfs_page *req; 1340 struct nfs_page *req;
@@ -1312,6 +1343,10 @@ void nfs_commit_done(struct rpc_task *task, void *calldata)
1312 dprintk("NFS: %4d nfs_commit_done (status %d)\n", 1343 dprintk("NFS: %4d nfs_commit_done (status %d)\n",
1313 task->tk_pid, task->tk_status); 1344 task->tk_pid, task->tk_status);
1314 1345
1346 /* Call the NFS version-specific code */
1347 if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
1348 return;
1349
1315 while (!list_empty(&data->pages)) { 1350 while (!list_empty(&data->pages)) {
1316 req = nfs_list_entry(data->pages.next); 1351 req = nfs_list_entry(data->pages.next);
1317 nfs_list_remove_request(req); 1352 nfs_list_remove_request(req);
@@ -1345,6 +1380,11 @@ void nfs_commit_done(struct rpc_task *task, void *calldata)
1345 } 1380 }
1346 sub_page_state(nr_unstable,res); 1381 sub_page_state(nr_unstable,res);
1347} 1382}
1383
1384static const struct rpc_call_ops nfs_commit_ops = {
1385 .rpc_call_done = nfs_commit_done,
1386 .rpc_release = nfs_commit_release,
1387};
1348#endif 1388#endif
1349 1389
1350static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, 1390static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index b71da4d4b137..782e59765696 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -407,13 +407,6 @@ extern int nfs_writepage(struct page *page, struct writeback_control *wbc);
407extern int nfs_writepages(struct address_space *, struct writeback_control *); 407extern int nfs_writepages(struct address_space *, struct writeback_control *);
408extern int nfs_flush_incompatible(struct file *file, struct page *page); 408extern int nfs_flush_incompatible(struct file *file, struct page *page);
409extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); 409extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
410extern void nfs_writeback_done(struct rpc_task *task, void *data);
411extern void nfs_writedata_release(void *data);
412
413#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
414extern void nfs_commit_done(struct rpc_task *, void *data);
415extern void nfs_commit_release(void *data);
416#endif
417 410
418/* 411/*
419 * Try to write back everything synchronously (but check the 412 * Try to write back everything synchronously (but check the
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 6d6f69ec5675..277750cc70c0 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -714,7 +714,6 @@ struct nfs_write_data {
714#ifdef CONFIG_NFS_V4 714#ifdef CONFIG_NFS_V4
715 unsigned long timestamp; /* For lease renewal */ 715 unsigned long timestamp; /* For lease renewal */
716#endif 716#endif
717 void (*complete) (struct nfs_write_data *, int);
718 struct page *page_array[NFS_PAGEVEC_SIZE + 1]; 717 struct page *page_array[NFS_PAGEVEC_SIZE + 1];
719}; 718};
720 719
@@ -770,7 +769,9 @@ struct nfs_rpc_ops {
770 u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); 769 u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus);
771 void (*read_setup) (struct nfs_read_data *); 770 void (*read_setup) (struct nfs_read_data *);
772 void (*write_setup) (struct nfs_write_data *, int how); 771 void (*write_setup) (struct nfs_write_data *, int how);
772 int (*write_done) (struct rpc_task *, struct nfs_write_data *);
773 void (*commit_setup) (struct nfs_write_data *, int how); 773 void (*commit_setup) (struct nfs_write_data *, int how);
774 int (*commit_done) (struct rpc_task *, struct nfs_write_data *);
774 int (*file_open) (struct inode *, struct file *); 775 int (*file_open) (struct inode *, struct file *);
775 int (*file_release) (struct inode *, struct file *); 776 int (*file_release) (struct inode *, struct file *);
776 int (*lock)(struct file *, int, struct file_lock *); 777 int (*lock)(struct file *, int, struct file_lock *);