diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 23 |
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 | ||
730 | static void nfs4_open_release(void *calldata) | 730 | static 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) { |