NFSv4: Add encode/decode of the layoutreturn op in CLOSE
Add XDR encoding for the layoutreturn op, and storage for the layoutreturn arguments to the CLOSE compound. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
This commit is contained in:
parent
d8434d4c54
commit
cf80516579
@ -3035,10 +3035,14 @@ struct nfs4_closedata {
|
|||||||
struct nfs4_state *state;
|
struct nfs4_state *state;
|
||||||
struct nfs_closeargs arg;
|
struct nfs_closeargs arg;
|
||||||
struct nfs_closeres res;
|
struct nfs_closeres res;
|
||||||
|
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;
|
||||||
unsigned long timestamp;
|
unsigned long timestamp;
|
||||||
bool roc;
|
|
||||||
u32 roc_barrier;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void nfs4_free_closedata(void *data)
|
static void nfs4_free_closedata(void *data)
|
||||||
@ -3047,7 +3051,7 @@ static void nfs4_free_closedata(void *data)
|
|||||||
struct nfs4_state_owner *sp = calldata->state->owner;
|
struct nfs4_state_owner *sp = calldata->state->owner;
|
||||||
struct super_block *sb = calldata->state->inode->i_sb;
|
struct super_block *sb = calldata->state->inode->i_sb;
|
||||||
|
|
||||||
if (calldata->roc)
|
if (calldata->lr.roc)
|
||||||
pnfs_roc_release(calldata->state->inode);
|
pnfs_roc_release(calldata->state->inode);
|
||||||
nfs4_put_open_state(calldata->state);
|
nfs4_put_open_state(calldata->state);
|
||||||
nfs_free_seqid(calldata->arg.seqid);
|
nfs_free_seqid(calldata->arg.seqid);
|
||||||
@ -3067,15 +3071,41 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
|
|||||||
if (!nfs4_sequence_done(task, &calldata->res.seq_res))
|
if (!nfs4_sequence_done(task, &calldata->res.seq_res))
|
||||||
return;
|
return;
|
||||||
trace_nfs4_close(state, &calldata->arg, &calldata->res, task->tk_status);
|
trace_nfs4_close(state, &calldata->arg, &calldata->res, task->tk_status);
|
||||||
|
|
||||||
|
/* Handle Layoutreturn errors */
|
||||||
|
if (calldata->arg.lr_args && task->tk_status != 0) {
|
||||||
|
switch (calldata->res.lr_ret) {
|
||||||
|
default:
|
||||||
|
calldata->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
calldata->arg.lr_args = NULL;
|
||||||
|
calldata->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:
|
||||||
|
calldata->arg.lr_args = NULL;
|
||||||
|
calldata->res.lr_res = NULL;
|
||||||
|
calldata->res.lr_ret = 0;
|
||||||
|
rpc_restart_call_prepare(task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* hmm. we are done with the inode, and in the process of freeing
|
/* hmm. we are done with the inode, and in the process of freeing
|
||||||
* the state_owner. we keep this around to process errors
|
* the state_owner. we keep this around to process errors
|
||||||
*/
|
*/
|
||||||
switch (task->tk_status) {
|
switch (task->tk_status) {
|
||||||
case 0:
|
case 0:
|
||||||
res_stateid = &calldata->res.stateid;
|
res_stateid = &calldata->res.stateid;
|
||||||
if (calldata->roc)
|
if (calldata->lr.roc)
|
||||||
pnfs_roc_set_barrier(state->inode,
|
pnfs_roc_set_barrier(state->inode,
|
||||||
calldata->roc_barrier);
|
calldata->lr.roc_barrier);
|
||||||
renew_lease(server, calldata->timestamp);
|
renew_lease(server, calldata->timestamp);
|
||||||
break;
|
break;
|
||||||
case -NFS4ERR_ADMIN_REVOKED:
|
case -NFS4ERR_ADMIN_REVOKED:
|
||||||
@ -3151,7 +3181,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
|
|||||||
goto out_no_action;
|
goto out_no_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nfs4_wait_on_layoutreturn(inode, task)) {
|
if (!calldata->arg.lr_args && nfs4_wait_on_layoutreturn(inode, task)) {
|
||||||
nfs_release_seqid(calldata->arg.seqid);
|
nfs_release_seqid(calldata->arg.seqid);
|
||||||
goto out_wait;
|
goto out_wait;
|
||||||
}
|
}
|
||||||
@ -3165,8 +3195,8 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
|
|||||||
else
|
else
|
||||||
calldata->arg.bitmask = NULL;
|
calldata->arg.bitmask = NULL;
|
||||||
}
|
}
|
||||||
if (calldata->roc)
|
if (calldata->lr.roc)
|
||||||
pnfs_roc_get_barrier(inode, &calldata->roc_barrier);
|
pnfs_roc_get_barrier(inode, &calldata->lr.roc_barrier);
|
||||||
|
|
||||||
calldata->arg.share_access =
|
calldata->arg.share_access =
|
||||||
nfs4_map_atomic_open_share(NFS_SERVER(inode),
|
nfs4_map_atomic_open_share(NFS_SERVER(inode),
|
||||||
@ -3250,7 +3280,8 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait)
|
|||||||
calldata->res.fattr = &calldata->fattr;
|
calldata->res.fattr = &calldata->fattr;
|
||||||
calldata->res.seqid = calldata->arg.seqid;
|
calldata->res.seqid = calldata->arg.seqid;
|
||||||
calldata->res.server = server;
|
calldata->res.server = server;
|
||||||
calldata->roc = nfs4_roc(state->inode);
|
calldata->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
|
||||||
|
calldata->lr.roc = nfs4_roc(state->inode);
|
||||||
nfs_sb_active(calldata->inode->i_sb);
|
nfs_sb_active(calldata->inode->i_sb);
|
||||||
|
|
||||||
msg.rpc_argp = &calldata->arg;
|
msg.rpc_argp = &calldata->arg;
|
||||||
|
@ -415,6 +415,8 @@ static int nfs4_stat_to_errno(int);
|
|||||||
#else /* CONFIG_NFS_V4_1 */
|
#else /* CONFIG_NFS_V4_1 */
|
||||||
#define encode_sequence_maxsz 0
|
#define encode_sequence_maxsz 0
|
||||||
#define decode_sequence_maxsz 0
|
#define decode_sequence_maxsz 0
|
||||||
|
#define encode_layoutreturn_maxsz 0
|
||||||
|
#define decode_layoutreturn_maxsz 0
|
||||||
#endif /* CONFIG_NFS_V4_1 */
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
|
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
|
||||||
@ -508,11 +510,13 @@ static int nfs4_stat_to_errno(int);
|
|||||||
#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
|
#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
|
||||||
encode_sequence_maxsz + \
|
encode_sequence_maxsz + \
|
||||||
encode_putfh_maxsz + \
|
encode_putfh_maxsz + \
|
||||||
|
encode_layoutreturn_maxsz + \
|
||||||
encode_close_maxsz + \
|
encode_close_maxsz + \
|
||||||
encode_getattr_maxsz)
|
encode_getattr_maxsz)
|
||||||
#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
|
#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
|
||||||
decode_sequence_maxsz + \
|
decode_sequence_maxsz + \
|
||||||
decode_putfh_maxsz + \
|
decode_putfh_maxsz + \
|
||||||
|
decode_layoutreturn_maxsz + \
|
||||||
decode_close_maxsz + \
|
decode_close_maxsz + \
|
||||||
decode_getattr_maxsz)
|
decode_getattr_maxsz)
|
||||||
#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
|
#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
|
||||||
@ -2061,6 +2065,13 @@ static void encode_free_stateid(struct xdr_stream *xdr,
|
|||||||
encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr);
|
encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr);
|
||||||
encode_nfs4_stateid(xdr, &args->stateid);
|
encode_nfs4_stateid(xdr, &args->stateid);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline void
|
||||||
|
encode_layoutreturn(struct xdr_stream *xdr,
|
||||||
|
const struct nfs4_layoutreturn_args *args,
|
||||||
|
struct compound_hdr *hdr)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif /* CONFIG_NFS_V4_1 */
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2248,6 +2259,8 @@ static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr,
|
|||||||
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->fh, &hdr);
|
encode_putfh(xdr, args->fh, &hdr);
|
||||||
|
if (args->lr_args)
|
||||||
|
encode_layoutreturn(xdr, args->lr_args, &hdr);
|
||||||
encode_close(xdr, args, &hdr);
|
encode_close(xdr, args, &hdr);
|
||||||
if (args->bitmask != NULL)
|
if (args->bitmask != NULL)
|
||||||
encode_getfattr(xdr, args->bitmask, &hdr);
|
encode_getfattr(xdr, args->bitmask, &hdr);
|
||||||
@ -6088,6 +6101,13 @@ static int decode_free_stateid(struct xdr_stream *xdr,
|
|||||||
res->status = decode_op_hdr(xdr, OP_FREE_STATEID);
|
res->status = decode_op_hdr(xdr, OP_FREE_STATEID);
|
||||||
return res->status;
|
return res->status;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline
|
||||||
|
int decode_layoutreturn(struct xdr_stream *xdr,
|
||||||
|
struct nfs4_layoutreturn_res *res)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* CONFIG_NFS_V4_1 */
|
#endif /* CONFIG_NFS_V4_1 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6440,6 +6460,12 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
|
|||||||
status = decode_putfh(xdr);
|
status = decode_putfh(xdr);
|
||||||
if (status)
|
if (status)
|
||||||
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_close(xdr, res);
|
status = decode_close(xdr, res);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -469,6 +469,7 @@ struct nfs_closeargs {
|
|||||||
fmode_t fmode;
|
fmode_t fmode;
|
||||||
u32 share_access;
|
u32 share_access;
|
||||||
const u32 * bitmask;
|
const u32 * bitmask;
|
||||||
|
struct nfs4_layoutreturn_args *lr_args;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nfs_closeres {
|
struct nfs_closeres {
|
||||||
@ -477,6 +478,8 @@ struct nfs_closeres {
|
|||||||
struct nfs_fattr * fattr;
|
struct nfs_fattr * fattr;
|
||||||
struct nfs_seqid * seqid;
|
struct nfs_seqid * seqid;
|
||||||
const struct nfs_server *server;
|
const struct nfs_server *server;
|
||||||
|
struct nfs4_layoutreturn_res *lr_res;
|
||||||
|
int lr_ret;
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* * Arguments to the lock,lockt, and locku call.
|
* * Arguments to the lock,lockt, and locku call.
|
||||||
|
Loading…
Reference in New Issue
Block a user