[pnfs] [PATCH 4/4] cb_sequence: nfsd callback initial implementation

Benny Halevy bhalevy at panasas.com
Tue May 29 14:19:13 EDT 2007


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

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 2438308..73b818d 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -63,14 +63,16 @@ 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_LAYOUT,
+	NFSPROC4_CLNT_CB_SEQUENCE,
 };
 
 enum nfs_cb_opnum4 {
 	OP_CB_RECALL            = 4,
 	OP_CB_LAYOUT            = 5,
+	OP_CB_SEQUENCE          = 11,
 };
 
 #define NFS4_MAXTAGLEN		20
@@ -94,16 +96,36 @@ 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)
 #define NFS41_enc_cb_layout_sz		(cb_compound_enc_hdr_sz +       \
+					cb_sequence41_enc_sz +          \
 					1 + 3 +                         \
 					enc_nfs4_fh_sz + 4)
 #define NFS41_dec_cb_layout_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) */
 
 /*
@@ -164,6 +186,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 */
@@ -302,6 +328,25 @@ encode_cb_layout(struct xdr_stream *xdr, struct nfs4_layoutrecall *clr)
 }
 #endif /* CONFIG_PNFS */
 
+#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)
 {
@@ -341,9 +386,10 @@ encode_cb_compound41_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hd
 
 static int
 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,
@@ -351,15 +397,17 @@ 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));
 }
 
 #ifdef CONFIG_PNFS
 static int
 nfs41_xdr_enc_cb_layout(struct rpc_rqst *req, u32 *p,
-                        struct nfs4_layoutrecall *args)
+                        struct nfs41_rpc_args *rpc_args)
 {
 	struct xdr_stream xdr;
+	struct nfs4_layoutrecall *args = rpc_args->args_op;
 	struct nfs4_cb_compound_hdr hdr = {
 		.ident = 0,
 		.nops   = 1,
@@ -367,6 +415,7 @@ nfs41_xdr_enc_cb_layout(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_layout(&xdr, args));
 }
 #endif /* CONFIG_PNFS */
@@ -431,7 +480,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;
@@ -441,6 +505,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;
@@ -448,7 +515,8 @@ out:
 
 #ifdef CONFIG_PNFS
 static int
-nfs41_xdr_dec_cb_layout(struct rpc_rqst *rqstp, u32 *p)
+nfs41_xdr_dec_cb_layout(struct rpc_rqst *rqstp, u32 *p,
+                        struct nfs41_rpc_res *rpc_res)
 {
 	struct xdr_stream xdr;
 	struct nfs4_cb_compound_hdr hdr;
@@ -458,6 +526,9 @@ nfs41_xdr_dec_cb_layout(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_LAYOUT);
 out:
 	return status;
@@ -739,6 +810,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
@@ -802,12 +899,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;
 }
@@ -823,11 +931,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)
@@ -874,9 +978,18 @@ nfsd4_cb_layout(struct nfs4_layoutrecall *clr)
 {
 	struct nfs4_client *clp = clr->clr_client;
 	struct rpc_clnt *clnt = NULL;
+	struct nfs41_cb_sequence seq;
+	struct nfs41_rpc_args args = {
+		.args_op = clr,
+		.args_seq = &seq
+	};
+	struct nfs41_rpc_res res = {
+		.res_seq = &seq
+	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs41_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
-		.rpc_argp = clr,
+		.rpc_argp = &args,
+		.rpc_resp = &res
 	};
 
 	if (clp)
@@ -892,7 +1005,9 @@ nfsd4_cb_layout(struct nfs4_layoutrecall *clr)
 		goto out;
 	}
 
+	nfs41_cb_sequence_setup(clp, &seq);
 	clr->clr_status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+	nfs41_cb_sequence_done(clp, &seq);
 
 	put_rpccred(msg.rpc_cred);
 
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 12a89d6..e7b71dd 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -521,6 +521,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);
@@ -540,6 +543,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 f15a975..7ed3863 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -182,6 +182,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' */
@@ -227,6 +237,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