[PATCH 1/4] cb_sequence: pnfs client support for minorversion1 callbacks

Benny Halevy bhalevy at panasas.com
Tue May 29 09:18:18 EDT 2007


Signed-off-by: Benny Halevy <bhalevy at panasas.com>
---
 fs/nfs/callback.h     |   12 ++++++++-
 fs/nfs/callback_xdr.c |   64 ++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 61 insertions(+), 15 deletions(-)

diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index aedc094..3bc2383 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -20,14 +20,24 @@ enum nfs4_callback_procnum {
 enum nfs4_callback_opnum {
 	OP_CB_GETATTR = 3,
 	OP_CB_RECALL  = 4,
+ /* Callback operations new to NFSv4.1 */
 	OP_CB_LAYOUTRECALL  = 5,
+	OP_CB_NOTIFY        = 6,
+	OP_CB_PUSH_DELEG    = 7,
+	OP_CB_RECALL_ANY    = 8,
+	OP_CB_RECALLABLE_OBJ_AVAIL = 9,
+	OP_CB_RECALL_SLOT   = 10,
+	OP_CB_SEQUENCE      = 11,
+	OP_CB_WANTS_CANCELLED = 12,
+	OP_CB_NOTIFY_LOCK   = 13,
 	OP_CB_ILLEGAL = 10044,
 };
 
 struct cb_compound_hdr_arg {
 	int taglen;
 	const char *tag;
-	unsigned int callback_ident;
+	unsigned int minorversion;
+	unsigned int callback_ident;	/* minorversion 0 only */
 	unsigned nops;
 };
 
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 9638750..f5c25ca 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -138,7 +138,6 @@ static unsigned decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
 static unsigned decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr)
 {
 	uint32_t *p;
-	unsigned int minor_version;
 	unsigned status;
 
 	status = decode_string(xdr, &hdr->taglen, &hdr->tag);
@@ -153,14 +152,15 @@ static unsigned decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compou
 	p = read_buf(xdr, 12);
 	if (unlikely(p == NULL))
 		return htonl(NFS4ERR_RESOURCE);
-	minor_version = ntohl(*p++);
+	hdr->minorversion = ntohl(*p++);
 	/* Check minor version is zero. */
-	if (minor_version != 0) {
+	if (hdr->minorversion == 0)
+		hdr->callback_ident = ntohl(*p++);
+	else if (hdr->minorversion != 1) {
 		printk(KERN_WARNING "%s: NFSv4 server callback with illegal minor version %u!\n",
-				__FUNCTION__, minor_version);
+				__FUNCTION__, hdr->minorversion);
 		return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
 	}
-	hdr->callback_ident = ntohl(*p++);
 	hdr->nops = ntohl(*p);
 	return 0;
 }
@@ -399,32 +399,59 @@ out:
 	return status;
 }
 
-static unsigned process_op(struct svc_rqst *rqstp,
+static unsigned 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 callback_op *op = &callback_ops[0];
-	unsigned int op_nr = OP_CB_ILLEGAL;
-	unsigned int status = 0;
+	unsigned int op_nr;
+	unsigned int status;
 	long maxlen;
 	unsigned res;
 
 	dprintk("%s: start\n", __FUNCTION__);
 	status = decode_op_hdr(xdr_in, &op_nr);
-	if (likely(status == 0)) {
+	if (unlikely(status))
+		goto out_illegal;
+
+#if defined(CONFIG_NFS_V4_1)
+	if (minorversion == 1) {
 		switch (op_nr) {
 			case OP_CB_GETATTR:
 			case OP_CB_RECALL:
 			case OP_CB_LAYOUTRECALL:
 				op = &callback_ops[op_nr];
 				break;
-			default:
-				op_nr = OP_CB_ILLEGAL;
+			case OP_CB_NOTIFY:
+			case OP_CB_PUSH_DELEG:
+			case OP_CB_RECALL_ANY:
+			case OP_CB_RECALLABLE_OBJ_AVAIL:
+			case OP_CB_RECALL_SLOT:
+			case OP_CB_SEQUENCE:
+			case OP_CB_WANTS_CANCELLED:
+			case OP_CB_NOTIFY_LOCK:
 				op = &callback_ops[0];
-				status = htonl(NFS4ERR_OP_ILLEGAL);
+				status = htonl(NFS4ERR_NOTSUPP);
+				break;
+			default:
+				goto out_illegal;
 		}
+
+		goto out;
+	}
+#endif /* defined(CONFIG_NFS_V4_1) */
+
+	switch (op_nr) {
+	case OP_CB_GETATTR:
+	case OP_CB_RECALL:
+		op = &callback_ops[op_nr];
+		break;
+	default:
+		goto out_illegal;
 	}
 
+out:
 	maxlen = xdr_out->end - xdr_out->p;
 	if (maxlen > 0 && maxlen < PAGE_SIZE) {
 		if (likely(status == 0 && op->decode_args != NULL))
@@ -441,6 +468,12 @@ static unsigned process_op(struct svc_rqst *rqstp,
 		status = op->encode_res(rqstp, xdr_out, resp);
 	dprintk("%s: done, status = %d\n", __FUNCTION__, status);
 	return status;
+
+out_illegal:
+	op_nr = OP_CB_ILLEGAL;
+	op = &callback_ops[0];
+	status = htonl(NFS4ERR_OP_ILLEGAL);
+	goto out;
 }
 
 /*
@@ -469,7 +502,8 @@ static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp
 	encode_compound_hdr_res(&xdr_out, &hdr_res);
 
 	for (;;) {
-		status = process_op(rqstp, &xdr_in, argp, &xdr_out, resp);
+		status = process_op(hdr_arg.minorversion, nops,
+		                    rqstp, &xdr_in, argp, &xdr_out, resp);
 		if (status != 0)
 			break;
 		if (nops == hdr_arg.nops)
@@ -483,7 +517,7 @@ static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp
 }
 
 /*
- * Define NFS4 callback COMPOUND ops.
+ * Define NFS4.[01] callback COMPOUND ops.
  */
 static struct callback_op callback_ops[] = {
 	[0] = {
@@ -500,6 +534,8 @@ static struct callback_op callback_ops[] = {
 		.decode_args = (callback_decode_arg_t)decode_recall_args,
 		.res_maxsize = CB_OP_RECALL_RES_MAXSZ,
 	},
+
+	/* NFSv4.1 callback operations */
 	[OP_CB_LAYOUTRECALL] = {
 		.process_op = (callback_process_op_t)nfs4_callback_pnfs_layoutrecall,
 		.decode_args = (callback_decode_arg_t)decode_pnfs_layoutrecall_args,
-- 
1.5.2.86.g99b5


--------------060104090809030008020508
Content-Type: text/plain;
 name*0="0002-cb_sequence-client-implementation-of-cb_sequence.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename*0="0002-cb_sequence-client-implementation-of-cb_sequence.patch"



More information about the pNFS mailing list