[sheepdog] [PATCH 03/12] sheep/nfs: add mount protocol stub

Liu Yuan namei.unix at gmail.com
Tue Jan 28 21:19:03 CET 2014


This is a preparation patch

Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
 sheep/Makefile.am |   2 +-
 sheep/nfs/mount.c |  42 +++++++++++++++++++
 sheep/nfs/nfs.h   |  99 ++++++++++++++++++++++++++++++++++++++++++++
 sheep/nfs/nfsd.c  |  75 +++++++++++++++++++++++++++++----
 sheep/nfs/xdr.c   | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 330 insertions(+), 10 deletions(-)
 create mode 100644 sheep/nfs/mount.c

diff --git a/sheep/Makefile.am b/sheep/Makefile.am
index b964f5f..82e3af9 100644
--- a/sheep/Makefile.am
+++ b/sheep/Makefile.am
@@ -35,7 +35,7 @@ sheep_SOURCES		+= http/http.c http/kv.c http/s3.c http/swift.c \
 endif
 
 if BUILD_NFS
-sheep_SOURCES		+= nfs/nfsd.c nfs/nfs.c nfs/xdr.c
+sheep_SOURCES		+= nfs/nfsd.c nfs/nfs.c nfs/xdr.c nfs/mount.c
 endif
 
 if BUILD_COROSYNC
diff --git a/sheep/nfs/mount.c b/sheep/nfs/mount.c
new file mode 100644
index 0000000..8f454cf
--- /dev/null
+++ b/sheep/nfs/mount.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 Taobao Inc.
+ *
+ * Liu Yuan <namei.unix at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <nfs://www.gnu.org/licenses/>.
+ */
+
+#include "sheep_priv.h"
+#include "nfs.h"
+
+void *mount3_null(struct svc_req *req, struct nfs_arg *arg)
+{
+	return NULL;
+}
+
+void *mount3_mnt(struct svc_req *req, struct nfs_arg *arg)
+{
+	return NULL;
+}
+
+void *mount3_dump(struct svc_req *req, struct nfs_arg *arg)
+{
+	return NULL;
+}
+void *mount3_umnt(struct svc_req *req, struct nfs_arg *arg)
+{
+	return NULL;
+}
+void *mount3_umntall(struct svc_req *req, struct nfs_arg *arg)
+{
+	return NULL;
+}
+void *mount3_export(struct svc_req *req, struct nfs_arg *arg)
+{
+	return NULL;
+}
diff --git a/sheep/nfs/nfs.h b/sheep/nfs/nfs.h
index c4bc703..1a0e501 100644
--- a/sheep/nfs/nfs.h
+++ b/sheep/nfs/nfs.h
@@ -946,6 +946,8 @@ typedef struct COMMIT3res COMMIT3res;
 #define NFSPROC3_PATHCONF 20
 #define NFSPROC3_COMMIT 21
 
+typedef char *dirpath;
+
 struct nfs_arg {
 	union {
 		GETATTR3args getattr;
@@ -969,6 +971,9 @@ struct nfs_arg {
 		FSINFO3args fsinfo;
 		PATHCONF3args pathconf;
 		COMMIT3args commit;
+		/* mount */
+		dirpath mnt;
+		dirpath umnt;
 	};
 };
 
@@ -1131,4 +1136,98 @@ extern bool_t xdr_commit_res(XDR *, COMMIT3res*);
 extern bool_t xdr_null_args(XDR *xdrs, void *);
 extern bool_t xdr_null_res(XDR *xdrs, void *);
 
+/* Mount Protocol */
+
+#define MNTPATHLEN 1024
+#define MNTNAMLEN 255
+#define FHSIZE 32
+#define FHSIZE3 64
+
+typedef struct {
+	u_int fhandle3_len;
+	char *fhandle3_val;
+} fhandle3;
+
+enum mountstat3 {
+	MNT3_OK = 0,
+	MNT3ERR_PERM = 1,
+	MNT3ERR_NOENT = 2,
+	MNT3ERR_IO = 5,
+	MNT3ERR_ACCES = 13,
+	MNT3ERR_NOTDIR = 20,
+	MNT3ERR_INVAL = 22,
+	MNT3ERR_NAMETOOLONG = 63,
+	MNT3ERR_NOTSUPP = 10004,
+	MNT3ERR_SERVERFAULT = 10006,
+};
+typedef enum mountstat3 mountstat3;
+
+struct mountres3_ok {
+	fhandle3 fhandle;
+	struct {
+		u_int auth_flavors_len;
+		int *auth_flavors_val;
+	} auth_flavors;
+};
+typedef struct mountres3_ok mountres3_ok;
+
+struct mountres3 {
+	mountstat3 fhs_status;
+	union {
+		mountres3_ok mountinfo;
+	} mountres3_u;
+};
+typedef struct mountres3 mountres3;
+
+typedef struct mountbody *mountlist;
+
+struct mountbody {
+	char *ml_hostname;
+	dirpath ml_directory;
+	mountlist ml_next;
+};
+typedef struct mountbody mountbody;
+
+typedef struct groupnode *groups;
+
+struct groupnode {
+	char *gr_name;
+	groups gr_next;
+};
+typedef struct groupnode groupnode;
+
+typedef struct exportnode *exports;
+
+struct exportnode {
+	dirpath ex_dir;
+	groups ex_groups;
+	exports ex_next;
+};
+typedef struct exportnode exportnode;
+
+#define MOUNT_PROGRAM 100005
+#define MOUNT_V3 3
+
+extern void *mount3_null(struct svc_req *, struct nfs_arg *);
+extern void *mount3_mnt(struct svc_req *, struct nfs_arg *);
+extern void *mount3_dump(struct svc_req *, struct nfs_arg *);
+extern void *mount3_umnt(struct svc_req *, struct nfs_arg *);
+extern void *mount3_umntall(struct svc_req *, struct nfs_arg *);
+extern void *mount3_export(struct svc_req *, struct nfs_arg *);
+
+/* the xdr functions */
+
+extern bool_t xdr_fhandle3(XDR *, fhandle3*);
+extern bool_t xdr_mountstat3(XDR *, mountstat3*);
+extern bool_t xdr_mountres3_ok(XDR *, mountres3_ok*);
+extern bool_t xdr_mountres3(XDR *, mountres3*);
+extern bool_t xdr_dirpath(XDR *, dirpath*);
+extern bool_t xdr_name(XDR *, char **);
+extern bool_t xdr_mountlist(XDR *, mountlist*);
+extern bool_t xdr_mountbody(XDR *, mountbody*);
+extern bool_t xdr_groups(XDR *, groups*);
+extern bool_t xdr_groupnode(XDR *, groupnode*);
+extern bool_t xdr_exports(XDR *, exports*);
+extern bool_t xdr_exportnode(XDR *, exportnode*);
+
 #endif /* !_NFS_H */
diff --git a/sheep/nfs/nfsd.c b/sheep/nfs/nfsd.c
index 11af50a..a1394c5 100644
--- a/sheep/nfs/nfsd.c
+++ b/sheep/nfs/nfsd.c
@@ -22,6 +22,7 @@ struct svc_handler {
 	xdrproc_t    decoder; /* XDR decode args */
 	xdrproc_t    encoder; /* XDR encode result */
 	unsigned int count;	 /* call count */
+	const char *name;       /* handler name */
 };
 
 #define NFS_HANDLER(name)			\
@@ -30,6 +31,7 @@ struct svc_handler {
 	(xdrproc_t) xdr_##name##_args,		\
 	(xdrproc_t) xdr_##name##_res,		\
 	0,					\
+	"nfs3."#name,				\
 }
 
 static struct svc_handler nfs3_handlers[] = {
@@ -57,28 +59,57 @@ static struct svc_handler nfs3_handlers[] = {
 	NFS_HANDLER(commit),
 };
 
-static void nfs3_dispatcher(struct svc_req *reg, SVCXPRT *transp)
+#define MOUNT_HANDLER(name, arg, res)		\
+{						\
+	(svc_func)  mount3_##name,		\
+	(xdrproc_t) xdr_##arg,			\
+	(xdrproc_t) xdr_##res,			\
+	0,					\
+	"mount3."#name,				\
+}
+
+static struct svc_handler mount3_handlers[] = {
+	MOUNT_HANDLER(null, null_args, null_res),
+	MOUNT_HANDLER(mnt, dirpath, mountres3),
+	MOUNT_HANDLER(dump, null_args, mountlist),
+	MOUNT_HANDLER(umnt, dirpath, null_res),
+	MOUNT_HANDLER(umntall, null_args, null_res),
+	MOUNT_HANDLER(export, null_args, exports),
+};
+
+static void svc_dispatcher(struct svc_req *reg, SVCXPRT *transp)
 {
 	struct nfs_arg arg = {};
-	int proc = reg->rq_proc;
+	int prog = reg->rq_prog, vers = reg->rq_vers, proc = reg->rq_proc;
+	struct svc_handler *handlers;
 	void *result;
 
-	sd_debug("%d", proc);
+	if (prog == NFS_PROGRAM && vers == NFS_V3)
+		handlers = nfs3_handlers;
+	else if (prog == MOUNT_PROGRAM && vers == MOUNT_V3)
+		handlers = mount3_handlers;
+	else {
+		sd_err("invalid protocol %d, version %d", prog, vers);
+		return;
+	}
+
+	sd_debug("%s", handlers[proc].name);
 
-	if (!svc_getargs(transp, nfs3_handlers[proc].decoder, (caddr_t)&arg)) {
+	if (!svc_getargs(transp, handlers[proc].decoder, (caddr_t)&arg)) {
 		sd_err("svc_getargs failed");
 		svcerr_decode(transp);
 		return;
 	}
 
-	result = nfs3_handlers[proc].func(reg, &arg);
-	if (result && !svc_sendreply(transp, nfs3_handlers[proc].encoder,
+	handlers[proc].count++;
+	result = handlers[proc].func(reg, &arg);
+	if (result && !svc_sendreply(transp, handlers[proc].encoder,
 				     result)) {
 		sd_err("svc_sendreply failed");
 		svcerr_systemerr(transp);
 	}
 
-	if (!svc_freeargs(transp, nfs3_handlers[proc].decoder, (caddr_t)&arg))
+	if (!svc_freeargs(transp, handlers[proc].decoder, (caddr_t)&arg))
 		panic("unable to free arguments");
 
 	return;
@@ -89,6 +120,7 @@ static int nfs_init_transport(void)
 	SVCXPRT *nfs_trans = NULL;
 
 	pmap_unset(NFS_PROGRAM, NFS_V3);
+	pmap_unset(MOUNT_PROGRAM, MOUNT_V3);
 
 	nfs_trans = svcudp_create(RPC_ANYSOCK);
 	if (!nfs_trans) {
@@ -96,7 +128,7 @@ static int nfs_init_transport(void)
 		return -1;
 	}
 
-	if (!svc_register(nfs_trans, NFS_PROGRAM, NFS_V3, nfs3_dispatcher,
+	if (!svc_register(nfs_trans, NFS_PROGRAM, NFS_V3, svc_dispatcher,
 			  IPPROTO_UDP)) {
 		sd_err("svc_register udp, failed");
 		return -1;
@@ -109,13 +141,38 @@ static int nfs_init_transport(void)
 		return -1;
 	}
 
-	if (!svc_register(nfs_trans, NFS_PROGRAM, NFS_V3, nfs3_dispatcher,
+	if (!svc_register(nfs_trans, NFS_PROGRAM, NFS_V3, svc_dispatcher,
 			  IPPROTO_TCP)) {
 		sd_err("svc_register tcp, failed");
 		return -1;
 	}
 	sd_info("nfs service listen at %d, proto tcp", nfs_trans->xp_port);
 
+	nfs_trans = svcudp_create(RPC_ANYSOCK);
+	if (!nfs_trans) {
+		sd_err("svcudp_create for mount failed");
+		return -1;
+	}
+
+	if (!svc_register(nfs_trans, MOUNT_PROGRAM, MOUNT_V3, svc_dispatcher,
+			  IPPROTO_UDP)) {
+		sd_err("svc_register udp for mount failed");
+		return -1;
+	}
+	sd_info("mount service listen at %d, proto udp", nfs_trans->xp_port);
+
+	nfs_trans = svctcp_create(RPC_ANYSOCK, 0, 0);
+	if (!nfs_trans) {
+		sd_err("svctcp_create for mount failed");
+		return -1;
+	}
+
+	if (!svc_register(nfs_trans, MOUNT_PROGRAM, MOUNT_V3, svc_dispatcher,
+			  IPPROTO_TCP)) {
+		sd_err("svc_register tcp for mount failed");
+		return -1;
+	}
+	sd_info("mount service listen at %d, proto tcp", nfs_trans->xp_port);
 	return 0;
 }
 
diff --git a/sheep/nfs/xdr.c b/sheep/nfs/xdr.c
index 15f9902..7f9b0f4 100644
--- a/sheep/nfs/xdr.c
+++ b/sheep/nfs/xdr.c
@@ -1659,3 +1659,125 @@ bool_t xdr_null_res(XDR *xdrs, void *ignore)
 {
 	return xdr_void();
 }
+
+bool_t
+xdr_fhandle3(XDR *xdrs, fhandle3 *objp)
+{
+	if (!xdr_bytes(xdrs, (char **)&objp->fhandle3_val,
+		       (u_int *)&objp->fhandle3_len, FHSIZE3))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_mountstat3(XDR *xdrs, mountstat3 *objp)
+{
+	if (!xdr_enum(xdrs, (enum_t *) objp))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp)
+{
+	if (!xdr_fhandle3(xdrs, &objp->fhandle))
+		return FALSE;
+	if (!xdr_array(xdrs, (char **)&objp->auth_flavors.auth_flavors_val,
+		       (u_int *)&objp->auth_flavors.auth_flavors_len, ~0,
+		       sizeof(int), (xdrproc_t) xdr_int))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_mountres3(XDR *xdrs, mountres3 *objp)
+{
+	if (!xdr_mountstat3(xdrs, &objp->fhs_status))
+		return FALSE;
+	switch (objp->fhs_status) {
+	case 0:
+		if (!xdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo))
+			return FALSE;
+		break;
+	default:
+		break;
+	}
+	return TRUE;
+}
+
+bool_t
+xdr_dirpath(XDR *xdrs, dirpath *objp)
+{
+	if (!xdr_string(xdrs, objp, MNTPATHLEN))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_name(XDR *xdrs, char **objp)
+{
+	if (!xdr_string(xdrs, objp, MNTNAMLEN))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_mountlist(XDR *xdrs, mountlist *objp)
+{
+	if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody),
+			 (xdrproc_t) xdr_mountbody))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_mountbody(XDR *xdrs, mountbody *objp)
+{
+	if (!xdr_name(xdrs, &objp->ml_hostname))
+		return FALSE;
+	if (!xdr_dirpath(xdrs, &objp->ml_directory))
+		return FALSE;
+	if (!xdr_mountlist(xdrs, &objp->ml_next))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_groups(XDR *xdrs, groups *objp)
+{
+	if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode),
+			 (xdrproc_t) xdr_groupnode))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_groupnode(XDR *xdrs, groupnode *objp)
+{
+	if (!xdr_name(xdrs, &objp->gr_name))
+		return FALSE;
+	if (!xdr_groups(xdrs, &objp->gr_next))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_exports(XDR *xdrs, exports *objp)
+{
+	if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode),
+			 (xdrproc_t) xdr_exportnode))
+		return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_exportnode(XDR *xdrs, exportnode *objp)
+{
+	if (!xdr_dirpath(xdrs, &objp->ex_dir))
+		return FALSE;
+	if (!xdr_groups(xdrs, &objp->ex_groups))
+		return FALSE;
+	if (!xdr_exports(xdrs, &objp->ex_next))
+		return FALSE;
+	return TRUE;
+}
-- 
1.8.1.2




More information about the sheepdog mailing list