[pnfs] [PATCH 5/5] cb_sequence: nfsd initial implementation

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


Signed-off-by: Benny Halevy <bhalevy at panasas.com>
---
 fs/nfsd/nfs4callback.c     |  114 ++++++++++++++++++++++++++++++++++++++++----
 fs/nfsd/nfs4state.c        |    6 ++
 include/linux/nfsd/state.h |   13 +++++
 3 files changed, 124 insertions(+), 9 deletions(-)

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index eab3b32..fd4c506 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -63,12 +63,14 @@ static const struct rpc_call_ops nfs4_cb_null_ops;
 /* Index of predefined Linux callback client operations */
 
 enum {
-        NFSPROC4_CLNT_CB_NULL = 0,
+	NFSPROC4_CLNT_CB_NULL = 0,
 	NFSPROC4_CLNT_CB_RECALL,
+	NFSPROC4_CLNT_CB_SEQUENCE,
 };
 
 enum nfs_cb_opnum4 {
 	OP_CB_RECALL            = 4,
+	OP_CB_SEQUENCE          = 11,
 };
 
 #define NFS4_MAXTAGLEN		20
@@ -92,11 +94,29 @@ enum nfs_cb_opnum4 {
 #define NFS41_dec_cb_null_sz		0
 #define cb_compound41_enc_hdr_sz	3
 #define cb_compound41_dec_hdr_sz	(3 + (NFS4_MAXTAGLEN >> 2))
+#define sessionid_sz			(NFS4_MAX_SESSIONID_LEN >> 2)
+#define cb_sequence41_enc_sz		(sessionid_sz + 4 +              \
+					1 /* no referring calls list yet */)
+#define cb_sequence41_dec_sz		(op_dec_sz + sessionid_sz + 4)
 #define NFS41_enc_cb_recall_sz		(cb_compound41_enc_hdr_sz +     \
+					cb_sequence41_enc_sz +         \
 					1 + enc_stateid_sz +            \
 					enc_nfs4_fh_sz)
 #define NFS41_dec_cb_recall_sz		(cb_compound_dec_hdr_sz  +      \
+					cb_sequence41_dec_sz +          \
 					op_dec_sz)
+
+struct nfs41_rpc_args {
+	struct nfs4_callback     *args_callback;
+	void                     *args_op;
+	struct nfs41_cb_sequence *args_seq;
+};
+
+struct nfs41_rpc_res {
+	struct nfs4_callback     *res_callback;
+	void                     *res_op;
+	struct nfs41_cb_sequence *res_seq;
+};
 #endif /* defined(CONFIG_NFSD_V4_1) */
 
 /*
@@ -153,6 +173,10 @@ xdr_error:                                      \
 		return -EIO; \
 	} \
 } while (0)
+#define COPYMEM(x,nbytes) do {			\
+	memcpy((x), p, nbytes);			\
+	p += XDR_QUADLEN(nbytes);		\
+} while (0)
 
 struct nfs4_cb_compound_hdr {
 	/* args */
@@ -250,6 +274,25 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec)
 	return 0;
 }
 
+#if defined(CONFIG_NFSD_V4_1)
+static int
+encode_cb_sequence(struct xdr_stream *xdr, struct nfs41_cb_sequence *args)
+{
+	u32 *p;
+
+	RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20);
+
+	WRITE32(OP_CB_SEQUENCE);
+	WRITEMEM(args->cbs_sessionid, NFS4_MAX_SESSIONID_LEN);
+	WRITE32(args->cbs_seqid);
+	WRITE32(args->cbs_slotid);
+	WRITE32(args->cbs_highest_slotid);
+	WRITE32(args->cbsa_cachethis);
+	WRITE32(0); /* FIXME: support referring_call_lists */
+	return 0;
+}
+#endif /* defined(CONFIG_NFSD_V4_1) */
+
 static int
 nfs4_xdr_enc_cb_null(struct rpc_rqst *req, u32 *p)
 {
@@ -288,9 +331,10 @@ encode_cb_compound41_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hd
 }
 
 nfs41_xdr_enc_cb_recall(struct rpc_rqst *req, u32 *p,
-                        struct nfs4_cb_recall *args)
+                        struct nfs41_rpc_args *rpc_args)
 {
 	struct xdr_stream xdr;
+	struct nfs4_cb_recall *args = rpc_args->args_op;
 	struct nfs4_cb_compound_hdr hdr = {
 		.ident = args->cbr_ident,
 		.nops   = 1,
@@ -298,6 +342,7 @@ nfs41_xdr_enc_cb_recall(struct rpc_rqst *req, u32 *p,
 
 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
 	encode_cb_compound41_hdr(&xdr, &hdr);
+	encode_cb_sequence(&xdr, rpc_args->args_seq);
 	return (encode_cb_recall(&xdr, args));
 }
 #endif /* defined(CONFIG_NFSD_V4_1) */
@@ -361,7 +406,22 @@ out:
 
 #if defined(CONFIG_NFSD_V4_1)
 static int
-nfs41_xdr_dec_cb_recall(struct rpc_rqst *rqstp, u32 *p)
+decode_cb_sequence(struct xdr_stream *xdr, struct nfs41_cb_sequence *res)
+{
+	u32 *p;
+
+	READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
+	COPYMEM(res->cbs_sessionid, NFS4_MAX_SESSIONID_LEN);
+	READ32(res->cbs_seqid);
+	READ32(res->cbs_slotid);
+	READ32(res->cbs_highest_slotid);
+	READ32(res->cbsr_target_highest_slotid);
+	return 0;
+}
+
+static int
+nfs41_xdr_dec_cb_recall(struct rpc_rqst *rqstp, u32 *p,
+                        struct nfs41_rpc_res *rpc_res)
 {
 	struct xdr_stream xdr;
 	struct nfs4_cb_compound_hdr hdr;
@@ -371,6 +431,9 @@ nfs41_xdr_dec_cb_recall(struct rpc_rqst *rqstp, u32 *p)
 	status = decode_cb_compound_hdr(&xdr, &hdr);
 	if (status)
 		goto out;
+	status = decode_cb_sequence(&xdr, rpc_res->res_seq);
+	if (status)
+		goto out;
 	status = decode_cb_op_hdr(&xdr, OP_CB_RECALL);
 out:
 	return status;
@@ -648,6 +711,32 @@ out_err:
 	dprintk("NFSD: warning: no callback path to client %.*s\n",
 		(int)clp->cl_name.len, clp->cl_name.data);
 }
+
+/* FIXME: cb_sequence should support referring call lists, cachethis, and multiple slots */
+static int
+nfs41_cb_sequence_setup(struct nfs4_client *clp, struct nfs41_cb_sequence *args)
+{
+	u32 *ptr = (u32 *)clp->cl_sessionid;
+	dprintk("%s: %u:%u:%u:%u\n", __FUNCTION__, ptr[0], ptr[1], ptr[2], ptr[3]);
+
+	mutex_lock(&clp->cl_cb_mutex);
+	memcpy(args->cbs_sessionid, clp->cl_sessionid, NFS4_MAX_SESSIONID_LEN);
+	args->cbs_seqid = ++clp->cl_cb_seq_nr;
+	args->cbs_slotid = 0;
+	args->cbs_highest_slotid = 0;
+	args->cbsa_cachethis = 0;
+	return 0;
+}
+
+static void
+nfs41_cb_sequence_done(struct nfs4_client *clp, struct nfs41_cb_sequence *res)
+{
+	u32 *ptr = (u32 *)res->cbs_sessionid;
+	dprintk("%s: %u:%u:%u:%u\n", __FUNCTION__, ptr[0], ptr[1], ptr[2], ptr[3]);
+
+	/* FIXME: support multiple callback slots */
+	mutex_unlock(&clp->cl_cb_mutex);
+}
 #endif
 
 static void
@@ -711,12 +800,23 @@ _nfsd41_cb_recall(struct nfs4_delegation *dp, struct rpc_message *msg)
 	struct nfs4_client *clp = dp->dl_client;
 	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
 	struct nfs4_cb_recall *cbr = &dp->dl_recall;
+	struct nfs41_cb_sequence seq;
+	struct nfs41_rpc_args args = {
+		.args_op = cbr,
+		.args_seq = &seq
+	};
+	struct nfs41_rpc_res res = {
+		.res_seq = &seq
+	};
 	int status;
 
+	nfs41_cb_sequence_setup(clp, &seq);
 	msg->rpc_proc = &nfs41_cb_procedures[NFSPROC4_CLNT_CB_RECALL];
-	msg->rpc_argp = cbr;
+	msg->rpc_argp = &args;
+	msg->rpc_resp = &res;
 
 	status = rpc_call_sync(clnt, msg, RPC_TASK_SOFT);
+	nfs41_cb_sequence_done(clp, &seq);
 
 	return status;
 }
@@ -732,11 +832,7 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
 	struct nfs4_client *clp = dp->dl_client;
 	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
 	struct nfs4_cb_recall *cbr = &dp->dl_recall;
-	struct rpc_message msg = {
-		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
-		.rpc_argp = cbr,
-	};
-	int retries = 1;
+	struct rpc_message msg;
 	int status = 0;
 
 	if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 8d71c1d..10ff791 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -504,6 +504,9 @@ alloc_client(struct xdr_netobj name)
 		if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) {
 			memcpy(clp->cl_name.data, name.data, name.len);
 			clp->cl_name.len = name.len;
+#if defined(CONFIG_NFSD_V4_1)
+			mutex_init(&clp->cl_cb_mutex);
+#endif
 		}
 		else {
 			kfree(clp);
@@ -523,6 +526,9 @@ free_client(struct nfs4_client *clp)
 	BUG_ON(!list_empty(&clp->cl_openowners));
 	if (clp->cl_cred.cr_group_info)
 		put_group_info(clp->cl_cred.cr_group_info);
+#if defined(CONFIG_NFSD_V4_1)
+	mutex_destroy(&clp->cl_cb_mutex);
+#endif
 	kfree(clp->cl_name.data);
 	kfree(clp);
 }
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index ec3c747..8c03076 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -183,6 +183,16 @@ struct current_session {
 	nfsd_sessionid_t	cs_sid;
 	struct nfs41_slot	*cs_slot;
 };
+
+struct nfs41_cb_sequence {
+	/* args/res */
+	char			cbs_sessionid[NFS4_MAX_SESSIONID_LEN];
+	u32			cbs_seqid;
+	u32			cbs_slotid;
+	u32			cbs_highest_slotid;
+	u32			cbsa_cachethis;			/* args only */
+	u32			cbsr_target_highest_slotid;	/* res only */
+};
 #endif
 
 #define HEXDIR_LEN     33 /* hex version of 16 byte md5 of cl_name plus '\0' */
@@ -225,6 +235,9 @@ struct nfs4_client {
 	 * For the v4.1 callback path setup
 	 */
 	struct svc_sock *	svsk;
+	/* FIXME: support multiple callback slots */
+	struct mutex		cl_cb_mutex;
+	u32			cl_cb_seq_nr;
 #endif
 };
 
-- 
1.5.2.86.g99b5



More information about the pNFS mailing list