diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-04-09 19:54:50 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-04-09 19:54:50 -0400 |
commit | 2c61be0a9478258f77b66208a0c4b1f5f8161c3c (patch) | |
tree | 84654744fc5f43f1b21f8fa484aba0a15787d5df | |
parent | a6305ddb080fb483ca41ca56cacb6f96089f0c8e (diff) |
NFS: Ensure that the WRITE and COMMIT RPC calls are always uninterruptible
We always want to ensure that WRITE and COMMIT completes, whether or not
the user presses ^C. Do this by making the call asynchronous, and allowing
the user to do an interruptible wait for rpc_task completion.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/write.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 40297c4f1ee0..de38d63aa920 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -781,7 +781,6 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
781 | int how) | 781 | int how) |
782 | { | 782 | { |
783 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 783 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
784 | int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | ||
785 | int priority = flush_task_priority(how); | 784 | int priority = flush_task_priority(how); |
786 | struct rpc_task *task; | 785 | struct rpc_task *task; |
787 | struct rpc_message msg = { | 786 | struct rpc_message msg = { |
@@ -796,9 +795,10 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
796 | .callback_ops = call_ops, | 795 | .callback_ops = call_ops, |
797 | .callback_data = data, | 796 | .callback_data = data, |
798 | .workqueue = nfsiod_workqueue, | 797 | .workqueue = nfsiod_workqueue, |
799 | .flags = flags, | 798 | .flags = RPC_TASK_ASYNC, |
800 | .priority = priority, | 799 | .priority = priority, |
801 | }; | 800 | }; |
801 | int ret = 0; | ||
802 | 802 | ||
803 | /* Set up the RPC argument and reply structs | 803 | /* Set up the RPC argument and reply structs |
804 | * NB: take care not to mess about with data->commit et al. */ | 804 | * NB: take care not to mess about with data->commit et al. */ |
@@ -837,10 +837,18 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
837 | (unsigned long long)data->args.offset); | 837 | (unsigned long long)data->args.offset); |
838 | 838 | ||
839 | task = rpc_run_task(&task_setup_data); | 839 | task = rpc_run_task(&task_setup_data); |
840 | if (IS_ERR(task)) | 840 | if (IS_ERR(task)) { |
841 | return PTR_ERR(task); | 841 | ret = PTR_ERR(task); |
842 | goto out; | ||
843 | } | ||
844 | if (how & FLUSH_SYNC) { | ||
845 | ret = rpc_wait_for_completion_task(task); | ||
846 | if (ret == 0) | ||
847 | ret = task->tk_status; | ||
848 | } | ||
842 | rpc_put_task(task); | 849 | rpc_put_task(task); |
843 | return 0; | 850 | out: |
851 | return ret; | ||
844 | } | 852 | } |
845 | 853 | ||
846 | /* If a nfs_flush_* function fails, it should remove reqs from @head and | 854 | /* If a nfs_flush_* function fails, it should remove reqs from @head and |
@@ -1210,7 +1218,6 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1210 | { | 1218 | { |
1211 | struct nfs_page *first = nfs_list_entry(head->next); | 1219 | struct nfs_page *first = nfs_list_entry(head->next); |
1212 | struct inode *inode = first->wb_context->path.dentry->d_inode; | 1220 | struct inode *inode = first->wb_context->path.dentry->d_inode; |
1213 | int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | ||
1214 | int priority = flush_task_priority(how); | 1221 | int priority = flush_task_priority(how); |
1215 | struct rpc_task *task; | 1222 | struct rpc_task *task; |
1216 | struct rpc_message msg = { | 1223 | struct rpc_message msg = { |
@@ -1225,7 +1232,7 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1225 | .callback_ops = &nfs_commit_ops, | 1232 | .callback_ops = &nfs_commit_ops, |
1226 | .callback_data = data, | 1233 | .callback_data = data, |
1227 | .workqueue = nfsiod_workqueue, | 1234 | .workqueue = nfsiod_workqueue, |
1228 | .flags = flags, | 1235 | .flags = RPC_TASK_ASYNC, |
1229 | .priority = priority, | 1236 | .priority = priority, |
1230 | }; | 1237 | }; |
1231 | 1238 | ||
@@ -1255,6 +1262,8 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1255 | task = rpc_run_task(&task_setup_data); | 1262 | task = rpc_run_task(&task_setup_data); |
1256 | if (IS_ERR(task)) | 1263 | if (IS_ERR(task)) |
1257 | return PTR_ERR(task); | 1264 | return PTR_ERR(task); |
1265 | if (how & FLUSH_SYNC) | ||
1266 | rpc_wait_for_completion_task(task); | ||
1258 | rpc_put_task(task); | 1267 | rpc_put_task(task); |
1259 | return 0; | 1268 | return 0; |
1260 | } | 1269 | } |