summaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-11-15 15:03:33 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-12-01 17:21:46 -0500
commit586f1c39daf5c840c742b9be1ec236429f26dc13 (patch)
tree89ef5b3c8a2da81c51c16848525e74a1186b6810 /fs/nfs/nfs4proc.c
parentcf80516579ceb87b91205e68fb31d5affd5aea8d (diff)
downloadlinux-586f1c39daf5c840c742b9be1ec236429f26dc13.tar.bz2
NFSv4: Add encode/decode of the layoutreturn op in DELEGRETURN
Add XDR encoding for the layoutreturn op, and storage for the layoutreturn arguments to the DELEGRETURN compound. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9b9b0eabef9b..765af663257a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5608,11 +5608,15 @@ struct nfs4_delegreturndata {
struct nfs_fh fh;
nfs4_stateid stateid;
unsigned long timestamp;
+ struct {
+ struct nfs4_layoutreturn_args arg;
+ struct nfs4_layoutreturn_res res;
+ u32 roc_barrier;
+ bool roc;
+ } lr;
struct nfs_fattr fattr;
int rpc_status;
struct inode *inode;
- bool roc;
- u32 roc_barrier;
};
static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
@@ -5623,6 +5627,32 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
return;
trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status);
+
+ /* Handle Layoutreturn errors */
+ if (data->args.lr_args && task->tk_status != 0) {
+ switch(data->res.lr_ret) {
+ default:
+ data->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
+ break;
+ case 0:
+ data->args.lr_args = NULL;
+ data->res.lr_res = NULL;
+ break;
+ case -NFS4ERR_ADMIN_REVOKED:
+ case -NFS4ERR_DELEG_REVOKED:
+ case -NFS4ERR_EXPIRED:
+ case -NFS4ERR_BAD_STATEID:
+ case -NFS4ERR_OLD_STATEID:
+ case -NFS4ERR_UNKNOWN_LAYOUTTYPE:
+ case -NFS4ERR_WRONG_CRED:
+ data->args.lr_args = NULL;
+ data->res.lr_res = NULL;
+ data->res.lr_ret = 0;
+ rpc_restart_call_prepare(task);
+ return;
+ }
+ }
+
switch (task->tk_status) {
case 0:
renew_lease(data->res.server, data->timestamp);
@@ -5646,8 +5676,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
}
}
data->rpc_status = task->tk_status;
- if (data->roc && data->rpc_status == 0)
- pnfs_roc_set_barrier(data->inode, data->roc_barrier);
+ if (data->lr.roc && data->rpc_status == 0)
+ pnfs_roc_set_barrier(data->inode, data->lr.roc_barrier);
}
static void nfs4_delegreturn_release(void *calldata)
@@ -5656,7 +5686,7 @@ static void nfs4_delegreturn_release(void *calldata)
struct inode *inode = data->inode;
if (inode) {
- if (data->roc)
+ if (data->lr.roc)
pnfs_roc_release(inode);
nfs_iput_and_deactive(inode);
}
@@ -5669,11 +5699,12 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
d_data = (struct nfs4_delegreturndata *)data;
- if (nfs4_wait_on_layoutreturn(d_data->inode, task))
+ if (!d_data->args.lr_args &&
+ nfs4_wait_on_layoutreturn(d_data->inode, task))
return;
- if (d_data->roc)
- pnfs_roc_get_barrier(d_data->inode, &d_data->roc_barrier);
+ if (d_data->lr.roc)
+ pnfs_roc_get_barrier(d_data->inode, &d_data->lr.roc_barrier);
nfs4_setup_sequence(d_data->res.server,
&d_data->args.seq_args,
@@ -5720,12 +5751,13 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
nfs4_stateid_copy(&data->stateid, stateid);
data->res.fattr = &data->fattr;
data->res.server = server;
+ data->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
nfs_fattr_init(data->res.fattr);
data->timestamp = jiffies;
data->rpc_status = 0;
data->inode = nfs_igrab_and_active(inode);
if (data->inode)
- data->roc = nfs4_roc(inode);
+ data->lr.roc = nfs4_roc(inode);
task_setup_data.callback_data = data;
msg.rpc_argp = &data->args;