diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-05-03 14:40:01 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-05-06 17:24:22 -0400 |
commit | 7c1d5fae4a87d3cf3e9ffd68bcdbaf6529013009 (patch) | |
tree | f547ba7b4d1ff5bcbd732e1ce29e7420b01543ef /fs/nfs | |
parent | 9b1d75b75505cff4468ceba0da51a1ba47e15ea2 (diff) |
NFSv4: Convert nfs41_free_stateid to use an asynchronous RPC call
The main reason for doing this is will be to allow for an asynchronous
RPC mode that we can use for freeing lock stateids as per section
8.2.4 of RFC5661.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 98 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 2 |
2 files changed, 76 insertions, 24 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index dc1da2adc459..1f3c6118c8ce 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -6783,26 +6783,76 @@ static int nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6783 | return err; | 6783 | return err; |
6784 | } | 6784 | } |
6785 | 6785 | ||
6786 | static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 6786 | struct nfs_free_stateid_data { |
6787 | { | 6787 | struct nfs_server *server; |
6788 | struct nfs41_free_stateid_args args = { | 6788 | struct nfs41_free_stateid_args args; |
6789 | .stateid = stateid, | ||
6790 | }; | ||
6791 | struct nfs41_free_stateid_res res; | 6789 | struct nfs41_free_stateid_res res; |
6790 | }; | ||
6791 | |||
6792 | static void nfs41_free_stateid_prepare(struct rpc_task *task, void *calldata) | ||
6793 | { | ||
6794 | struct nfs_free_stateid_data *data = calldata; | ||
6795 | nfs41_setup_sequence(nfs4_get_session(data->server), | ||
6796 | &data->args.seq_args, | ||
6797 | &data->res.seq_res, | ||
6798 | task); | ||
6799 | } | ||
6800 | |||
6801 | static void nfs41_free_stateid_done(struct rpc_task *task, void *calldata) | ||
6802 | { | ||
6803 | struct nfs_free_stateid_data *data = calldata; | ||
6804 | |||
6805 | nfs41_sequence_done(task, &data->res.seq_res); | ||
6806 | |||
6807 | switch (task->tk_status) { | ||
6808 | case -NFS4ERR_DELAY: | ||
6809 | if (nfs4_async_handle_error(task, data->server, NULL) == -EAGAIN) | ||
6810 | rpc_restart_call_prepare(task); | ||
6811 | } | ||
6812 | } | ||
6813 | |||
6814 | static void nfs41_free_stateid_release(void *calldata) | ||
6815 | { | ||
6816 | kfree(calldata); | ||
6817 | } | ||
6818 | |||
6819 | const struct rpc_call_ops nfs41_free_stateid_ops = { | ||
6820 | .rpc_call_prepare = nfs41_free_stateid_prepare, | ||
6821 | .rpc_call_done = nfs41_free_stateid_done, | ||
6822 | .rpc_release = nfs41_free_stateid_release, | ||
6823 | }; | ||
6824 | |||
6825 | static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | ||
6826 | nfs4_stateid *stateid, | ||
6827 | bool privileged) | ||
6828 | { | ||
6792 | struct rpc_message msg = { | 6829 | struct rpc_message msg = { |
6793 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID], | 6830 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID], |
6794 | .rpc_argp = &args, | ||
6795 | .rpc_resp = &res, | ||
6796 | }; | 6831 | }; |
6797 | int status; | 6832 | struct rpc_task_setup task_setup = { |
6833 | .rpc_client = server->client, | ||
6834 | .rpc_message = &msg, | ||
6835 | .callback_ops = &nfs41_free_stateid_ops, | ||
6836 | .flags = RPC_TASK_ASYNC, | ||
6837 | }; | ||
6838 | struct nfs_free_stateid_data *data; | ||
6798 | 6839 | ||
6799 | dprintk("NFS call free_stateid %p\n", stateid); | 6840 | dprintk("NFS call free_stateid %p\n", stateid); |
6800 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); | 6841 | data = kmalloc(sizeof(*data), GFP_NOFS); |
6801 | nfs4_set_sequence_privileged(&args.seq_args); | 6842 | if (!data) |
6802 | status = nfs4_call_sync_sequence(server->client, server, &msg, | 6843 | return ERR_PTR(-ENOMEM); |
6803 | &args.seq_args, &res.seq_res); | 6844 | data->server = server; |
6804 | dprintk("NFS reply free_stateid: %d\n", status); | 6845 | nfs4_stateid_copy(&data->args.stateid, stateid); |
6805 | return status; | 6846 | |
6847 | task_setup.callback_data = data; | ||
6848 | |||
6849 | msg.rpc_argp = &data->args; | ||
6850 | msg.rpc_resp = &data->res; | ||
6851 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); | ||
6852 | if (privileged) | ||
6853 | nfs4_set_sequence_privileged(&data->args.seq_args); | ||
6854 | |||
6855 | return rpc_run_task(&task_setup); | ||
6806 | } | 6856 | } |
6807 | 6857 | ||
6808 | /** | 6858 | /** |
@@ -6816,15 +6866,17 @@ static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6816 | */ | 6866 | */ |
6817 | static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 6867 | static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) |
6818 | { | 6868 | { |
6819 | struct nfs4_exception exception = { }; | 6869 | struct rpc_task *task; |
6820 | int err; | 6870 | int ret; |
6821 | do { | 6871 | |
6822 | err = _nfs4_free_stateid(server, stateid); | 6872 | task = _nfs41_free_stateid(server, stateid, true); |
6823 | if (err != -NFS4ERR_DELAY) | 6873 | if (IS_ERR(task)) |
6824 | break; | 6874 | return PTR_ERR(task); |
6825 | nfs4_handle_exception(server, err, &exception); | 6875 | ret = rpc_wait_for_completion_task(task); |
6826 | } while (exception.retry); | 6876 | if (!ret) |
6827 | return err; | 6877 | ret = task->tk_status; |
6878 | rpc_put_task(task); | ||
6879 | return ret; | ||
6828 | } | 6880 | } |
6829 | 6881 | ||
6830 | static bool nfs41_match_stateid(const nfs4_stateid *s1, | 6882 | static bool nfs41_match_stateid(const nfs4_stateid *s1, |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 3c79c5878c6d..4be8d135ed61 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -2003,7 +2003,7 @@ static void encode_free_stateid(struct xdr_stream *xdr, | |||
2003 | struct compound_hdr *hdr) | 2003 | struct compound_hdr *hdr) |
2004 | { | 2004 | { |
2005 | encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr); | 2005 | encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr); |
2006 | encode_nfs4_stateid(xdr, args->stateid); | 2006 | encode_nfs4_stateid(xdr, &args->stateid); |
2007 | } | 2007 | } |
2008 | #endif /* CONFIG_NFS_V4_1 */ | 2008 | #endif /* CONFIG_NFS_V4_1 */ |
2009 | 2009 | ||