diff options
-rw-r--r-- | fs/nfs/nfs3proc.c | 66 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 54 | ||||
-rw-r--r-- | fs/nfs/proc.c | 24 | ||||
-rw-r--r-- | fs/nfs/write.c | 92 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 7 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 3 |
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 | ||
852 | static void nfs3_write_done(struct rpc_task *task, void *calldata) | 852 | static 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 | ||
863 | static const struct rpc_call_ops nfs3_write_ops = { | 861 | static 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 | |||
868 | static void | ||
869 | nfs3_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 | ||
899 | static void nfs3_commit_done(struct rpc_task *task, void *calldata) | 881 | static 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 | ||
910 | static const struct rpc_call_ops nfs3_commit_ops = { | 890 | static 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 | |||
915 | static void | ||
916 | nfs3_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 | ||
936 | static int | 902 | static 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 | ||
2391 | static void nfs4_write_done(struct rpc_task *task, void *calldata) | 2391 | static 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 | ||
2408 | static const struct rpc_call_ops nfs4_write_ops = { | 2406 | static 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 | |||
2413 | static void | ||
2414 | nfs4_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 | ||
2449 | static void nfs4_commit_done(struct rpc_task *task, void *calldata) | 2435 | static 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 | ||
2464 | static const struct rpc_call_ops nfs4_commit_ops = { | 2448 | static 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 | |||
2469 | static void | ||
2470 | nfs4_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 | ||
657 | static void nfs_write_done(struct rpc_task *task, void *calldata) | 657 | static 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 | ||
666 | static const struct rpc_call_ops nfs_write_ops = { | 664 | static 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 | |||
671 | static void | ||
672 | nfs_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 | ||
695 | static void | 680 | static 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); |
80 | static void nfs_writeback_done_partial(struct nfs_write_data *, int); | 80 | static int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *); |
81 | static void nfs_writeback_done_full(struct nfs_write_data *, int); | ||
82 | static int nfs_wait_on_write_congestion(struct address_space *, int); | 81 | static int nfs_wait_on_write_congestion(struct address_space *, int); |
83 | static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int); | 82 | static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int); |
84 | static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, | 83 | static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, |
85 | unsigned int npages, int how); | 84 | unsigned int npages, int how); |
85 | static const struct rpc_call_ops nfs_write_partial_ops; | ||
86 | static const struct rpc_call_ops nfs_write_full_ops; | ||
87 | static const struct rpc_call_ops nfs_commit_ops; | ||
86 | 88 | ||
87 | static kmem_cache_t *nfs_wdata_cachep; | 89 | static kmem_cache_t *nfs_wdata_cachep; |
88 | mempool_t *nfs_wdata_mempool; | 90 | mempool_t *nfs_wdata_mempool; |
@@ -872,10 +874,12 @@ static inline int flush_task_priority(int how) | |||
872 | */ | 874 | */ |
873 | static void nfs_write_rpcsetup(struct nfs_page *req, | 875 | static 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 | */ |
1069 | static void nfs_writeback_done_partial(struct nfs_write_data *data, int status) | 1076 | static 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 | ||
1116 | static 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 | */ |
1112 | static void nfs_writeback_done_full(struct nfs_write_data *data, int status) | 1128 | static 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 | ||
1177 | static 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 | */ |
1160 | void nfs_writeback_done(struct rpc_task *task, void *calldata) | 1186 | static 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 | */ |
1241 | static void nfs_commit_rpcsetup(struct list_head *head, | 1267 | static 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 | */ |
1306 | void nfs_commit_done(struct rpc_task *task, void *calldata) | 1337 | static 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 | |||
1384 | static 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 | ||
1350 | static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, | 1390 | static 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); | |||
407 | extern int nfs_writepages(struct address_space *, struct writeback_control *); | 407 | extern int nfs_writepages(struct address_space *, struct writeback_control *); |
408 | extern int nfs_flush_incompatible(struct file *file, struct page *page); | 408 | extern int nfs_flush_incompatible(struct file *file, struct page *page); |
409 | extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); | 409 | extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); |
410 | extern void nfs_writeback_done(struct rpc_task *task, void *data); | ||
411 | extern void nfs_writedata_release(void *data); | ||
412 | |||
413 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | ||
414 | extern void nfs_commit_done(struct rpc_task *, void *data); | ||
415 | extern 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 *); |