aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-05-03 14:40:01 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-05-06 17:24:22 -0400
commit7c1d5fae4a87d3cf3e9ffd68bcdbaf6529013009 (patch)
treef547ba7b4d1ff5bcbd732e1ce29e7420b01543ef /fs/nfs
parent9b1d75b75505cff4468ceba0da51a1ba47e15ea2 (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.c98
-rw-r--r--fs/nfs/nfs4xdr.c2
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
6786static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) 6786struct 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
6792static 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
6801static 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
6814static void nfs41_free_stateid_release(void *calldata)
6815{
6816 kfree(calldata);
6817}
6818
6819const 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
6825static 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 */
6817static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) 6867static 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
6830static bool nfs41_match_stateid(const nfs4_stateid *s1, 6882static 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