2009-12-21 22:47:01

by Andy Adamson

[permalink] [raw]
Subject: [PATCH 0/2] nfsv4 back channel drc mininal implementation


nfs41: back channel drc minimal implementation
Patches against 2-6-33-rc1

For now the back channel ca_maxresponsesize_cached is 0 and there is no
backchannel DRC. Return NFS4ERR_REP_TOO_BIG_TO_CACHE when a cb_sequence
cachethis is true. When it is false, return NFS4ERR_RETRY_UNCACHED_REP as the
next operation error.

0001-nfs41-prepare-for-back-channel-drc.patch
0002-nfs41-back-channel-drc-minimal-implementation.patch

Tested:
CONFIG_NFS_V4_1
NFSv4.1 mount: Connectathon passes.

Hardcoded a pyNFS server to always replay a cb_recall. Tested with cachethis of
True and False. Then held a RO file open and performed a RW open from a different client to force a recall. This could be added to testclient.py


NFSv4.0 mount: Connectatahon passes.

-->Andy



2009-12-21 22:47:04

by Andy Adamson

[permalink] [raw]
Subject: [PATCH 1/2] nfs41: prepare for back channel drc

From: Andy Adamson <[email protected]>

Make all cb_sequence arguments available to verify_seqid which will make
replay decisions.

Signed-off-by: Andy Adamson <[email protected]>
---
fs/nfs/callback_proc.c | 19 +++++++++----------
1 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index defa9b4..7f92b6d 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -153,34 +153,34 @@ int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const n
* a single outstanding callback request at a time.
*/
static int
-validate_seqid(struct nfs4_slot_table *tbl, u32 slotid, u32 seqid)
+validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
{
struct nfs4_slot *slot;

dprintk("%s enter. slotid %d seqid %d\n",
- __func__, slotid, seqid);
+ __func__, args->csa_slotid, args->csa_sequenceid);

- if (slotid > NFS41_BC_MAX_CALLBACKS)
+ if (args->csa_slotid > NFS41_BC_MAX_CALLBACKS)
return htonl(NFS4ERR_BADSLOT);

- slot = tbl->slots + slotid;
+ slot = tbl->slots + args->csa_slotid;
dprintk("%s slot table seqid: %d\n", __func__, slot->seq_nr);

/* Normal */
- if (likely(seqid == slot->seq_nr + 1)) {
+ if (likely(args->csa_sequenceid == slot->seq_nr + 1)) {
slot->seq_nr++;
return htonl(NFS4_OK);
}

/* Replay */
- if (seqid == slot->seq_nr) {
+ if (args->csa_sequenceid == slot->seq_nr) {
dprintk("%s seqid %d is a replay - no DRC available\n",
- __func__, seqid);
+ __func__, args->csa_sequenceid);
return htonl(NFS4_OK);
}

/* Wraparound */
- if (seqid == 1 && (slot->seq_nr + 1) == 0) {
+ if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) {
slot->seq_nr = 1;
return htonl(NFS4_OK);
}
@@ -241,8 +241,7 @@ unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
if (clp == NULL)
goto out;

- status = validate_seqid(&clp->cl_session->bc_slot_table,
- args->csa_slotid, args->csa_sequenceid);
+ status = validate_seqid(&clp->cl_session->bc_slot_table, args);
if (status)
goto out_putclient;

--
1.6.0.6


2009-12-21 22:47:04

by Andy Adamson

[permalink] [raw]
Subject: [PATCH 2/2] nfs41: back channel drc minimal implementation

From: Andy Adamson <[email protected]>

For now the back channel ca_maxresponsesize_cached is 0 and there is no
backchannel DRC. Return NFS4ERR_REP_TOO_BIG_TO_CACHE when a cb_sequence
cachethis is true. When it is false, return NFS4ERR_RETRY_UNCACHED_REP as the
next operation error.

Remember the replay error accross compound operation processing.

Signed-off-by: Andy Adamson <[email protected]>
---
fs/nfs/callback_proc.c | 20 +++++++++++++++-----
fs/nfs/callback_xdr.c | 19 +++++++++++++++----
2 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 7f92b6d..c5e66fd 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -174,9 +174,15 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)

/* Replay */
if (args->csa_sequenceid == slot->seq_nr) {
- dprintk("%s seqid %d is a replay - no DRC available\n",
+ dprintk("%s seqid %d is a replay\n",
__func__, args->csa_sequenceid);
- return htonl(NFS4_OK);
+ /* Signal process_op to set this error on next op */
+ if (args->csa_cachethis == 0)
+ return htonl(NFS4ERR_RETRY_UNCACHED_REP);
+
+ /* The ca_maxresponsesize_cached is 0 with no DRC */
+ else if (args->csa_cachethis == 1)
+ return htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE);
}

/* Wraparound */
@@ -255,9 +261,13 @@ unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
out_putclient:
nfs_put_client(clp);
out:
- dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
- res->csr_status = status;
- return res->csr_status;
+ if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP))
+ res->csr_status = 0;
+ else
+ res->csr_status = status;
+ dprintk("%s: exit with status = %d res->csr_status %d\n", __func__,
+ ntohl(status), ntohl(res->csr_status));
+ return status;
}

unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 8e1a251..0365f79 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -602,7 +602,7 @@ preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op)
static __be32 process_op(uint32_t minorversion, int nop,
struct svc_rqst *rqstp,
struct xdr_stream *xdr_in, void *argp,
- struct xdr_stream *xdr_out, void *resp)
+ struct xdr_stream *xdr_out, void *resp, int* drc_status)
{
struct callback_op *op = &callback_ops[0];
unsigned int op_nr = OP_CB_ILLEGAL;
@@ -624,6 +624,11 @@ static __be32 process_op(uint32_t minorversion, int nop,
preprocess_nfs4_op(op_nr, &op);
if (status == htonl(NFS4ERR_OP_ILLEGAL))
op_nr = OP_CB_ILLEGAL;
+
+ if (*drc_status) {
+ status = *drc_status;
+ goto encode_hdr;
+ }
out:
maxlen = xdr_out->end - xdr_out->p;
if (maxlen > 0 && maxlen < PAGE_SIZE) {
@@ -634,6 +639,12 @@ out:
} else
status = htonl(NFS4ERR_RESOURCE);

+ /* Only set by OP_CB_SEQUENCE processing */
+ if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP)) {
+ *drc_status = status;
+ status = 0;
+ }
+encode_hdr:
res = encode_op_hdr(xdr_out, op_nr, status);
if (status == 0)
status = res;
@@ -652,7 +663,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
struct cb_compound_hdr_res hdr_res = { NULL };
struct xdr_stream xdr_in, xdr_out;
__be32 *p;
- __be32 status;
+ __be32 status, drc_status = 0;
unsigned int nops = 0;

dprintk("%s: start\n", __func__);
@@ -672,8 +683,8 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
return rpc_system_err;

while (status == 0 && nops != hdr_arg.nops) {
- status = process_op(hdr_arg.minorversion, nops,
- rqstp, &xdr_in, argp, &xdr_out, resp);
+ status = process_op(hdr_arg.minorversion, nops, rqstp,
+ &xdr_in, argp, &xdr_out, resp, &drc_status);
nops++;
}

--
1.6.0.6


2009-12-22 01:10:23

by Labiaga, Ricardo

[permalink] [raw]
Subject: RE: [pnfs] [PATCH 2/2] nfs41: back channel drc minimal implementation

Don't forget to also update the comment at the top of validate_seqid()
since we will no longer process retransmissions.

- ricardo

> -----Original Message-----
> From: Adamson, Andy
> Sent: Monday, December 21, 2009 2:46 PM
> To: Myklebust, Trond
> Cc: Adamson, Andy; [email protected]; [email protected]
> Subject: [pnfs] [PATCH 2/2] nfs41: back channel drc minimal
implementation
>
> From: Andy Adamson <[email protected]>
>
> For now the back channel ca_maxresponsesize_cached is 0 and there is
no
> backchannel DRC. Return NFS4ERR_REP_TOO_BIG_TO_CACHE when a
cb_sequence
> cachethis is true. When it is false, return
NFS4ERR_RETRY_UNCACHED_REP as
> the
> next operation error.
>
> Remember the replay error accross compound operation processing.
>
> Signed-off-by: Andy Adamson <[email protected]>
> ---
> fs/nfs/callback_proc.c | 20 +++++++++++++++-----
> fs/nfs/callback_xdr.c | 19 +++++++++++++++----
> 2 files changed, 30 insertions(+), 9 deletions(-)
>
> diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
> index 7f92b6d..c5e66fd 100644
> --- a/fs/nfs/callback_proc.c
> +++ b/fs/nfs/callback_proc.c
> @@ -174,9 +174,15 @@ validate_seqid(struct nfs4_slot_table *tbl,
struct
> cb_sequenceargs * args)
>
> /* Replay */
> if (args->csa_sequenceid == slot->seq_nr) {
> - dprintk("%s seqid %d is a replay - no DRC available\n",
> + dprintk("%s seqid %d is a replay\n",
> __func__, args->csa_sequenceid);
> - return htonl(NFS4_OK);
> + /* Signal process_op to set this error on next op */
> + if (args->csa_cachethis == 0)
> + return htonl(NFS4ERR_RETRY_UNCACHED_REP);
> +
> + /* The ca_maxresponsesize_cached is 0 with no DRC */
> + else if (args->csa_cachethis == 1)
> + return htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE);
> }
>
> /* Wraparound */
> @@ -255,9 +261,13 @@ unsigned nfs4_callback_sequence(struct
> cb_sequenceargs *args,
> out_putclient:
> nfs_put_client(clp);
> out:
> - dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
> - res->csr_status = status;
> - return res->csr_status;
> + if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP))
> + res->csr_status = 0;
> + else
> + res->csr_status = status;
> + dprintk("%s: exit with status = %d res->csr_status %d\n",
__func__,
> + ntohl(status), ntohl(res->csr_status));
> + return status;
> }
>
> unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void
> *dummy)
> diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
> index 8e1a251..0365f79 100644
> --- a/fs/nfs/callback_xdr.c
> +++ b/fs/nfs/callback_xdr.c
> @@ -602,7 +602,7 @@ preprocess_nfs4_op(unsigned int op_nr, struct
> callback_op **op)
> static __be32 process_op(uint32_t minorversion, int nop,
> struct svc_rqst *rqstp,
> struct xdr_stream *xdr_in, void *argp,
> - struct xdr_stream *xdr_out, void *resp)
> + struct xdr_stream *xdr_out, void *resp, int* drc_status)
> {
> struct callback_op *op = &callback_ops[0];
> unsigned int op_nr = OP_CB_ILLEGAL;
> @@ -624,6 +624,11 @@ static __be32 process_op(uint32_t minorversion,
int
> nop,
> preprocess_nfs4_op(op_nr, &op);
> if (status == htonl(NFS4ERR_OP_ILLEGAL))
> op_nr = OP_CB_ILLEGAL;
> +
> + if (*drc_status) {
> + status = *drc_status;
> + goto encode_hdr;
> + }
> out:
> maxlen = xdr_out->end - xdr_out->p;
> if (maxlen > 0 && maxlen < PAGE_SIZE) {
> @@ -634,6 +639,12 @@ out:
> } else
> status = htonl(NFS4ERR_RESOURCE);
>
> + /* Only set by OP_CB_SEQUENCE processing */
> + if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP)) {
> + *drc_status = status;
> + status = 0;
> + }
> +encode_hdr:
> res = encode_op_hdr(xdr_out, op_nr, status);
> if (status == 0)
> status = res;
> @@ -652,7 +663,7 @@ static __be32 nfs4_callback_compound(struct
svc_rqst
> *rqstp, void *argp, void *r
> struct cb_compound_hdr_res hdr_res = { NULL };
> struct xdr_stream xdr_in, xdr_out;
> __be32 *p;
> - __be32 status;
> + __be32 status, drc_status = 0;
> unsigned int nops = 0;
>
> dprintk("%s: start\n", __func__);
> @@ -672,8 +683,8 @@ static __be32 nfs4_callback_compound(struct
svc_rqst
> *rqstp, void *argp, void *r
> return rpc_system_err;
>
> while (status == 0 && nops != hdr_arg.nops) {
> - status = process_op(hdr_arg.minorversion, nops,
> - rqstp, &xdr_in, argp, &xdr_out,
resp);
> + status = process_op(hdr_arg.minorversion, nops, rqstp,
> + &xdr_in, argp, &xdr_out, resp,
&drc_status);
> nops++;
> }
>
> --
> 1.6.0.6
>
> _______________________________________________
> pNFS mailing list
> [email protected]
> http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs