On Fri, May 06, 2011 at 01:37:12PM -0400, Bryan Schumaker wrote: > On 05/06/2011 01:29 PM, J. Bruce Fields wrote: > > On Fri, May 06, 2011 at 12:49:53PM -0400, bjschuma@xxxxxxxxxx wrote: > >> From: Bryan Schumaker <bjschuma@xxxxxxxxxx> > >> > >> This patch adds in the xdr for doing a TEST_STATEID call with a > >> single stateid. RFC 5661 allows multiple stateids to be tested in a > >> single call, but only testing one keeps things simpler for now. > > > > These are among the mandatory 4.1 ops that we haven't implemented on > > the server yet. Anyone up for it? It's probably not difficult. > > I have some server patches that I think will work. I'm checking out > your linux.git tree from linux-nfs.org to make sure they still apply. OK, great. > Is there a branch that I should check against? Probably for-2.6.40. > > Also: how will it behave against a server that returns nfserr_notsupp? > > The FREE_STATEID won't be used, and the nfs v4.0 recovery functions will be called (these functions will be called after the FREE_STATEID anyway). Then it sounds like your patches cause no change in behavior in the case of a server that doesn't support the ops? --b. > > > > > --b. > > > >> > >> Signed-off-by: Bryan Schumaker <bjschuma@xxxxxxxxxx> > >> --- > >> fs/nfs/nfs4proc.c | 28 ++++++++++++++ > >> fs/nfs/nfs4xdr.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++ > >> include/linux/nfs4.h | 1 + > >> include/linux/nfs_xdr.h | 10 +++++ > >> 4 files changed, 130 insertions(+), 0 deletions(-) > >> > >> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c > >> index 69c0f3c..044c151 100644 > >> --- a/fs/nfs/nfs4proc.c > >> +++ b/fs/nfs/nfs4proc.c > >> @@ -5791,6 +5791,34 @@ out: > >> rpc_put_task(task); > >> return status; > >> } > >> +static int _nfs41_test_stateid(struct nfs_server *server, struct nfs4_state *state) > >> +{ > >> + int status; > >> + struct nfs41_test_stateid_args args = { > >> + .stateid = &state->stateid, > >> + }; > >> + struct nfs41_test_stateid_res res; > >> + struct rpc_message msg = { > >> + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID], > >> + .rpc_argp = &args, > >> + .rpc_resp = &res, > >> + }; > >> + args.seq_args.sa_session = res.seq_res.sr_session = NULL; > >> + status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 0, 1); > >> + return status; > >> +} > >> + > >> +static int nfs41_test_stateid(struct nfs_server *server, struct nfs4_state *state) > >> +{ > >> + struct nfs4_exception exception = { }; > >> + int err; > >> + do { > >> + err = nfs4_handle_exception(server, > >> + _nfs41_test_stateid(server, state), > >> + &exception); > >> + } while (exception.retry); > >> + return err; > >> +} > >> #endif /* CONFIG_NFS_V4_1 */ > >> > >> struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { > >> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c > >> index c3ccd2c..2746616 100644 > >> --- a/fs/nfs/nfs4xdr.c > >> +++ b/fs/nfs/nfs4xdr.c > >> @@ -338,6 +338,9 @@ static int nfs4_stat_to_errno(int); > >> 1 /* layoutupdate4 layout type */ + \ > >> 1 /* NULL filelayout layoutupdate4 payload */) > >> #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) > >> +#define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 8 + \ > >> + XDR_QUADLEN(NFS4_STATEID_SIZE)) > >> +#define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 8 + 4) > >> > >> #else /* CONFIG_NFS_V4_1 */ > >> #define encode_sequence_maxsz 0 > >> @@ -760,6 +763,12 @@ static int nfs4_stat_to_errno(int); > >> decode_putfh_maxsz + \ > >> decode_layoutcommit_maxsz + \ > >> decode_getattr_maxsz) > >> +#define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \ > >> + encode_sequence_maxsz + \ > >> + encode_test_stateid_maxsz) > >> +#define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \ > >> + decode_sequence_maxsz + \ > >> + decode_test_stateid_maxsz) > >> > >> > >> const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + > >> @@ -1889,6 +1898,20 @@ encode_layoutcommit(struct xdr_stream *xdr, > >> hdr->replen += decode_layoutcommit_maxsz; > >> return 0; > >> } > >> + > >> +static void encode_test_stateid(struct xdr_stream *xdr, > >> + struct nfs41_test_stateid_args *args, > >> + struct compound_hdr *hdr) > >> +{ > >> + __be32 *p; > >> + > >> + p = reserve_space(xdr, 8 + NFS4_STATEID_SIZE); > >> + *p++ = cpu_to_be32(OP_TEST_STATEID); > >> + *p++ = cpu_to_be32(1); > >> + xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); > >> + hdr->nops++; > >> + hdr->replen += decode_test_stateid_maxsz; > >> +} > >> #endif /* CONFIG_NFS_V4_1 */ > >> > >> /* > >> @@ -2722,6 +2745,23 @@ static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, > >> encode_nops(&hdr); > >> return 0; > >> } > >> + > >> +/* > >> + * Encode TEST_STATEID request > >> + */ > >> +static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req, > >> + struct xdr_stream *xdr, > >> + struct nfs41_test_stateid_args *args) > >> +{ > >> + struct compound_hdr hdr = { > >> + .minorversion = nfs4_xdr_minorversion(&args->seq_args), > >> + }; > >> + > >> + encode_compound_hdr(xdr, req, &hdr); > >> + encode_sequence(xdr, &args->seq_args, &hdr); > >> + encode_test_stateid(xdr, args, &hdr); > >> + encode_nops(&hdr); > >> +} > >> #endif /* CONFIG_NFS_V4_1 */ > >> > >> static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) > >> @@ -5231,6 +5271,35 @@ out_overflow: > >> print_overflow_msg(__func__, xdr); > >> return -EIO; > >> } > >> + > >> +static int decode_test_stateid(struct xdr_stream *xdr, > >> + struct nfs41_test_stateid_res *res) > >> +{ > >> + __be32 *p; > >> + int status; > >> + int num_res; > >> + > >> + status = decode_op_hdr(xdr, OP_TEST_STATEID); > >> + if (status) > >> + return status; > >> + > >> + p = xdr_inline_decode(xdr, 4); > >> + if (unlikely(!p)) > >> + goto out_overflow; > >> + num_res = be32_to_cpup(p++); > >> + if (num_res != 1) > >> + goto out; > >> + > >> + p = xdr_inline_decode(xdr, 4); > >> + if (unlikely(!p)) > >> + goto out_overflow; > >> + res->status = be32_to_cpup(p++); > >> + return res->status; > >> +out_overflow: > >> + print_overflow_msg(__func__, xdr); > >> +out: > >> + return -EIO; > >> +} > >> #endif /* CONFIG_NFS_V4_1 */ > >> > >> /* > >> @@ -6346,6 +6415,27 @@ static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, > >> out: > >> return status; > >> } > >> + > >> +/* > >> + * Decode TEST_STATEID response > >> + */ > >> +static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp, > >> + struct xdr_stream *xdr, > >> + struct nfs41_test_stateid_res *res) > >> +{ > >> + struct compound_hdr hdr; > >> + int status; > >> + > >> + status = decode_compound_hdr(xdr, &hdr); > >> + if (status) > >> + goto out; > >> + status = decode_sequence(xdr, &res->seq_res, rqstp); > >> + if (status) > >> + goto out; > >> + status = decode_test_stateid(xdr, res); > >> +out: > >> + return status; > >> +} > >> #endif /* CONFIG_NFS_V4_1 */ > >> > >> /** > >> @@ -6547,6 +6637,7 @@ struct rpc_procinfo nfs4_procedures[] = { > >> PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), > >> PROC(LAYOUTGET, enc_layoutget, dec_layoutget), > >> PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), > >> + PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), > >> #endif /* CONFIG_NFS_V4_1 */ > >> }; > >> > >> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h > >> index 178fafe..0df1eed 100644 > >> --- a/include/linux/nfs4.h > >> +++ b/include/linux/nfs4.h > >> @@ -562,6 +562,7 @@ enum { > >> NFSPROC4_CLNT_LAYOUTGET, > >> NFSPROC4_CLNT_GETDEVICEINFO, > >> NFSPROC4_CLNT_LAYOUTCOMMIT, > >> + NFSPROC4_CLNT_TEST_STATEID, > >> }; > >> > >> /* nfs41 types */ > >> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h > >> index 890dce2..36f50dc 100644 > >> --- a/include/linux/nfs_xdr.h > >> +++ b/include/linux/nfs_xdr.h > >> @@ -1062,6 +1062,16 @@ struct nfs41_reclaim_complete_args { > >> struct nfs41_reclaim_complete_res { > >> struct nfs4_sequence_res seq_res; > >> }; > >> + > >> +struct nfs41_test_stateid_args { > >> + nfs4_stateid *stateid; > >> + struct nfs4_sequence_args seq_args; > >> +}; > >> + > >> +struct nfs41_test_stateid_res { > >> + unsigned int status; > >> + struct nfs4_sequence_res seq_res; > >> +}; > >> #endif /* CONFIG_NFS_V4_1 */ > >> > >> struct nfs_page; > >> -- > >> 1.7.5.1 > >> > >> -- > >> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in > >> the body of a message to majordomo@xxxxxxxxxxxxxxx > >> More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html