aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-03 03:55:18 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-06 14:58:44 -0500
commitfe650407a86823bcafbfbee96c7bc6a1b5cd1c76 (patch)
tree38e899d40fabba538bb558c0dcc3d38f830beadb /fs
parenta5d16a4d090bd2af86e648ed9bb205903fcf1e86 (diff)
NFSv4: Make DELEGRETURN an interruptible operation.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4proc.c68
1 files changed, 60 insertions, 8 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 718fcc722556..f060e6538edc 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2885,19 +2885,71 @@ nfs4_proc_setclientid_confirm(struct nfs4_client *clp)
2885 return status; 2885 return status;
2886} 2886}
2887 2887
2888static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) 2888struct nfs4_delegreturndata {
2889 struct nfs4_delegreturnargs args;
2890 struct nfs_fh fh;
2891 nfs4_stateid stateid;
2892 struct rpc_cred *cred;
2893 int rpc_status;
2894};
2895
2896static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata)
2889{ 2897{
2890 struct nfs4_delegreturnargs args = { 2898 struct nfs4_delegreturndata *data = calldata;
2891 .fhandle = NFS_FH(inode),
2892 .stateid = stateid,
2893 };
2894 struct rpc_message msg = { 2899 struct rpc_message msg = {
2895 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN], 2900 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
2896 .rpc_argp = &args, 2901 .rpc_argp = &data->args,
2897 .rpc_cred = cred, 2902 .rpc_cred = data->cred,
2898 }; 2903 };
2904 rpc_call_setup(task, &msg, 0);
2905}
2899 2906
2900 return rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 2907static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
2908{
2909 struct nfs4_delegreturndata *data = calldata;
2910 data->rpc_status = task->tk_status;
2911}
2912
2913static void nfs4_delegreturn_release(void *calldata)
2914{
2915 struct nfs4_delegreturndata *data = calldata;
2916
2917 put_rpccred(data->cred);
2918 kfree(calldata);
2919}
2920
2921const static struct rpc_call_ops nfs4_delegreturn_ops = {
2922 .rpc_call_prepare = nfs4_delegreturn_prepare,
2923 .rpc_call_done = nfs4_delegreturn_done,
2924 .rpc_release = nfs4_delegreturn_release,
2925};
2926
2927static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
2928{
2929 struct nfs4_delegreturndata *data;
2930 struct rpc_task *task;
2931 int status;
2932
2933 data = kmalloc(sizeof(*data), GFP_KERNEL);
2934 if (data == NULL)
2935 return -ENOMEM;
2936 data->args.fhandle = &data->fh;
2937 data->args.stateid = &data->stateid;
2938 nfs_copy_fh(&data->fh, NFS_FH(inode));
2939 memcpy(&data->stateid, stateid, sizeof(data->stateid));
2940 data->cred = get_rpccred(cred);
2941 data->rpc_status = 0;
2942
2943 task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data);
2944 if (IS_ERR(task)) {
2945 nfs4_delegreturn_release(data);
2946 return PTR_ERR(task);
2947 }
2948 status = nfs4_wait_for_completion_rpc_task(task);
2949 if (status == 0)
2950 status = data->rpc_status;
2951 rpc_release_task(task);
2952 return status;
2901} 2953}
2902 2954
2903int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) 2955int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)