[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