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

Benny Halevy bhalevy at panasas.com
Thu May 31 14:08:28 EDT 2007


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

diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index 3b98754..263fc85 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -20,13 +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 29f9321..9b2fbde 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -132,7 +132,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);
@@ -147,14 +146,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;
 }
@@ -353,31 +353,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:
 				op = &callback_ops[op_nr];
 				break;
-			default:
-				op_nr = OP_CB_ILLEGAL;
+			case OP_CB_LAYOUTRECALL:
+			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))
@@ -394,6 +422,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;
 }
 
 /*
@@ -422,7 +456,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)
@@ -436,7 +471,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] = {
-- 
1.5.2.86.g99b5



More information about the pNFS mailing list