aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 52ba7630794c..05afb7ba3bc4 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -226,6 +226,7 @@ struct nfs4_opendata {
226 struct nfs4_state_owner *owner; 226 struct nfs4_state_owner *owner;
227 struct iattr attrs; 227 struct iattr attrs;
228 unsigned long timestamp; 228 unsigned long timestamp;
229 unsigned int rpc_done : 1;
229 int rpc_status; 230 int rpc_status;
230 int cancelled; 231 int cancelled;
231}; 232};
@@ -620,6 +621,7 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
620 memcpy(data->o_res.stateid.data, data->c_res.stateid.data, 621 memcpy(data->o_res.stateid.data, data->c_res.stateid.data,
621 sizeof(data->o_res.stateid.data)); 622 sizeof(data->o_res.stateid.data));
622 renew_lease(data->o_res.server, data->timestamp); 623 renew_lease(data->o_res.server, data->timestamp);
624 data->rpc_done = 1;
623 } 625 }
624 nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status); 626 nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status);
625 nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid); 627 nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
@@ -634,7 +636,7 @@ static void nfs4_open_confirm_release(void *calldata)
634 if (data->cancelled == 0) 636 if (data->cancelled == 0)
635 goto out_free; 637 goto out_free;
636 /* In case of error, no cleanup! */ 638 /* In case of error, no cleanup! */
637 if (data->rpc_status != 0) 639 if (!data->rpc_done)
638 goto out_free; 640 goto out_free;
639 nfs_confirm_seqid(&data->owner->so_seqid, 0); 641 nfs_confirm_seqid(&data->owner->so_seqid, 0);
640 state = nfs4_opendata_to_nfs4_state(data); 642 state = nfs4_opendata_to_nfs4_state(data);
@@ -660,11 +662,8 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
660 int status; 662 int status;
661 663
662 kref_get(&data->kref); 664 kref_get(&data->kref);
663 /* 665 data->rpc_done = 0;
664 * If rpc_run_task() ends up calling ->rpc_release(), we 666 data->rpc_status = 0;
665 * want to ensure that it takes the 'error' code path.
666 */
667 data->rpc_status = -ENOMEM;
668 task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data); 667 task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
669 if (IS_ERR(task)) 668 if (IS_ERR(task))
670 return PTR_ERR(task); 669 return PTR_ERR(task);
@@ -725,6 +724,7 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
725 nfs_confirm_seqid(&data->owner->so_seqid, 0); 724 nfs_confirm_seqid(&data->owner->so_seqid, 0);
726 } 725 }
727 nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid); 726 nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid);
727 data->rpc_done = 1;
728} 728}
729 729
730static void nfs4_open_release(void *calldata) 730static void nfs4_open_release(void *calldata)
@@ -736,7 +736,7 @@ static void nfs4_open_release(void *calldata)
736 if (data->cancelled == 0) 736 if (data->cancelled == 0)
737 goto out_free; 737 goto out_free;
738 /* In case of error, no cleanup! */ 738 /* In case of error, no cleanup! */
739 if (data->rpc_status != 0) 739 if (data->rpc_status != 0 || !data->rpc_done)
740 goto out_free; 740 goto out_free;
741 /* In case we need an open_confirm, no cleanup! */ 741 /* In case we need an open_confirm, no cleanup! */
742 if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) 742 if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
@@ -768,11 +768,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
768 int status; 768 int status;
769 769
770 kref_get(&data->kref); 770 kref_get(&data->kref);
771 /* 771 data->rpc_done = 0;
772 * If rpc_run_task() ends up calling ->rpc_release(), we 772 data->rpc_status = 0;
773 * want to ensure that it takes the 'error' code path.
774 */
775 data->rpc_status = -ENOMEM;
776 data->cancelled = 0; 773 data->cancelled = 0;
777 task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data); 774 task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data);
778 if (IS_ERR(task)) 775 if (IS_ERR(task))
@@ -784,7 +781,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
784 } else 781 } else
785 status = data->rpc_status; 782 status = data->rpc_status;
786 rpc_put_task(task); 783 rpc_put_task(task);
787 if (status != 0) 784 if (status != 0 || !data->rpc_done)
788 return status; 785 return status;
789 786
790 if (o_arg->open_flags & O_CREAT) { 787 if (o_arg->open_flags & O_CREAT) {