Commit 586f1c39 authored by Trond Myklebust's avatar Trond Myklebust

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: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent cf805165
...@@ -5608,11 +5608,15 @@ struct nfs4_delegreturndata { ...@@ -5608,11 +5608,15 @@ struct nfs4_delegreturndata {
struct nfs_fh fh; struct nfs_fh fh;
nfs4_stateid stateid; nfs4_stateid stateid;
unsigned long timestamp; unsigned long timestamp;
struct {
struct nfs4_layoutreturn_args arg;
struct nfs4_layoutreturn_res res;
u32 roc_barrier;
bool roc;
} lr;
struct nfs_fattr fattr; struct nfs_fattr fattr;
int rpc_status; int rpc_status;
struct inode *inode; struct inode *inode;
bool roc;
u32 roc_barrier;
}; };
static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) 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) ...@@ -5623,6 +5627,32 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
return; return;
trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status); 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) { switch (task->tk_status) {
case 0: case 0:
renew_lease(data->res.server, data->timestamp); renew_lease(data->res.server, data->timestamp);
...@@ -5646,8 +5676,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) ...@@ -5646,8 +5676,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
} }
} }
data->rpc_status = task->tk_status; data->rpc_status = task->tk_status;
if (data->roc && data->rpc_status == 0) if (data->lr.roc && data->rpc_status == 0)
pnfs_roc_set_barrier(data->inode, data->roc_barrier); pnfs_roc_set_barrier(data->inode, data->lr.roc_barrier);
} }
static void nfs4_delegreturn_release(void *calldata) static void nfs4_delegreturn_release(void *calldata)
...@@ -5656,7 +5686,7 @@ static void nfs4_delegreturn_release(void *calldata) ...@@ -5656,7 +5686,7 @@ static void nfs4_delegreturn_release(void *calldata)
struct inode *inode = data->inode; struct inode *inode = data->inode;
if (inode) { if (inode) {
if (data->roc) if (data->lr.roc)
pnfs_roc_release(inode); pnfs_roc_release(inode);
nfs_iput_and_deactive(inode); nfs_iput_and_deactive(inode);
} }
...@@ -5669,11 +5699,12 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) ...@@ -5669,11 +5699,12 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
d_data = (struct nfs4_delegreturndata *)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; return;
if (d_data->roc) if (d_data->lr.roc)
pnfs_roc_get_barrier(d_data->inode, &d_data->roc_barrier); pnfs_roc_get_barrier(d_data->inode, &d_data->lr.roc_barrier);
nfs4_setup_sequence(d_data->res.server, nfs4_setup_sequence(d_data->res.server,
&d_data->args.seq_args, &d_data->args.seq_args,
...@@ -5720,12 +5751,13 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co ...@@ -5720,12 +5751,13 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
nfs4_stateid_copy(&data->stateid, stateid); nfs4_stateid_copy(&data->stateid, stateid);
data->res.fattr = &data->fattr; data->res.fattr = &data->fattr;
data->res.server = server; data->res.server = server;
data->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
nfs_fattr_init(data->res.fattr); nfs_fattr_init(data->res.fattr);
data->timestamp = jiffies; data->timestamp = jiffies;
data->rpc_status = 0; data->rpc_status = 0;
data->inode = nfs_igrab_and_active(inode); data->inode = nfs_igrab_and_active(inode);
if (data->inode) if (data->inode)
data->roc = nfs4_roc(inode); data->lr.roc = nfs4_roc(inode);
task_setup_data.callback_data = data; task_setup_data.callback_data = data;
msg.rpc_argp = &data->args; msg.rpc_argp = &data->args;
......
...@@ -710,11 +710,13 @@ static int nfs4_stat_to_errno(int); ...@@ -710,11 +710,13 @@ static int nfs4_stat_to_errno(int);
#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \ encode_sequence_maxsz + \
encode_putfh_maxsz + \ encode_putfh_maxsz + \
encode_layoutreturn_maxsz + \
encode_delegreturn_maxsz + \ encode_delegreturn_maxsz + \
encode_getattr_maxsz) encode_getattr_maxsz)
#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \ decode_sequence_maxsz + \
decode_putfh_maxsz + \ decode_putfh_maxsz + \
decode_layoutreturn_maxsz + \
decode_delegreturn_maxsz + \ decode_delegreturn_maxsz + \
decode_getattr_maxsz) decode_getattr_maxsz)
#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
...@@ -2683,6 +2685,8 @@ static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, ...@@ -2683,6 +2685,8 @@ static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req,
encode_compound_hdr(xdr, req, &hdr); encode_compound_hdr(xdr, req, &hdr);
encode_sequence(xdr, &args->seq_args, &hdr); encode_sequence(xdr, &args->seq_args, &hdr);
encode_putfh(xdr, args->fhandle, &hdr); encode_putfh(xdr, args->fhandle, &hdr);
if (args->lr_args)
encode_layoutreturn(xdr, args->lr_args, &hdr);
encode_getfattr(xdr, args->bitmask, &hdr); encode_getfattr(xdr, args->bitmask, &hdr);
encode_delegreturn(xdr, args->stateid, &hdr); encode_delegreturn(xdr, args->stateid, &hdr);
encode_nops(&hdr); encode_nops(&hdr);
...@@ -6942,6 +6946,12 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, ...@@ -6942,6 +6946,12 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp,
status = decode_putfh(xdr); status = decode_putfh(xdr);
if (status != 0) if (status != 0)
goto out; goto out;
if (res->lr_res) {
status = decode_layoutreturn(xdr, res->lr_res);
res->lr_ret = status;
if (status)
goto out;
}
status = decode_getfattr(xdr, res->fattr, res->server); status = decode_getfattr(xdr, res->fattr, res->server);
if (status != 0) if (status != 0)
goto out; goto out;
......
...@@ -552,12 +552,15 @@ struct nfs4_delegreturnargs { ...@@ -552,12 +552,15 @@ struct nfs4_delegreturnargs {
const struct nfs_fh *fhandle; const struct nfs_fh *fhandle;
const nfs4_stateid *stateid; const nfs4_stateid *stateid;
const u32 * bitmask; const u32 * bitmask;
struct nfs4_layoutreturn_args *lr_args;
}; };
struct nfs4_delegreturnres { struct nfs4_delegreturnres {
struct nfs4_sequence_res seq_res; struct nfs4_sequence_res seq_res;
struct nfs_fattr * fattr; struct nfs_fattr * fattr;
struct nfs_server *server; struct nfs_server *server;
struct nfs4_layoutreturn_res *lr_res;
int lr_ret;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment