This is a preparation patch Signed-off-by: Liu Yuan <[email protected]> --- 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 <[email protected]> + * + * 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 -- sheepdog mailing list [email protected] http://lists.wpkg.org/mailman/listinfo/sheepdog
