aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-04-09 19:54:50 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-04-09 19:54:50 -0400
commit2c61be0a9478258f77b66208a0c4b1f5f8161c3c (patch)
tree84654744fc5f43f1b21f8fa484aba0a15787d5df /fs
parenta6305ddb080fb483ca41ca56cacb6f96089f0c8e (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>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/write.c23
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; 850out:
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}