diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-01-03 03:55:18 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-01-06 14:58:44 -0500 |
commit | fe650407a86823bcafbfbee96c7bc6a1b5cd1c76 (patch) | |
tree | 38e899d40fabba538bb558c0dcc3d38f830beadb | |
parent | a5d16a4d090bd2af86e648ed9bb205903fcf1e86 (diff) |
NFSv4: Make DELEGRETURN an interruptible operation.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/nfs4proc.c | 68 |
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 | ||
2888 | static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) | 2888 | struct 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 | |||
2896 | static 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); | 2907 | static 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 | |||
2913 | static void nfs4_delegreturn_release(void *calldata) | ||
2914 | { | ||
2915 | struct nfs4_delegreturndata *data = calldata; | ||
2916 | |||
2917 | put_rpccred(data->cred); | ||
2918 | kfree(calldata); | ||
2919 | } | ||
2920 | |||
2921 | const 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 | |||
2927 | static 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 | ||
2903 | int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) | 2955 | int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) |