From 99ea01aa92109f0fa5b35f47e7d04dce11baa654 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Tue, 8 May 2012 15:15:31 +0530 Subject: nfs/mount: Support MOUNT protocol on UDP. Needed for NLM on solaris clients. Change-Id: I3f5c35d06827fb267a7dae53d949c61567a945d0 BUG: 799287 Signed-off-by: Krishna Srinivas Reviewed-on: http://review.gluster.com/3337 Tested-by: Gluster Build System Reviewed-by: Rajesh Amaravathi Reviewed-by: Anand Avati --- rpc/xdr/src/mount3udp.x | 34 +++++ xlators/mgmt/glusterd/src/glusterd-volgen.c | 1 + xlators/nfs/server/src/Makefile.am | 2 +- xlators/nfs/server/src/mount3.c | 91 ++++++++++++- xlators/nfs/server/src/mount3udp_svc.c | 201 ++++++++++++++++++++++++++++ xlators/nfs/server/src/nfs-mem-types.h | 10 +- xlators/nfs/server/src/nfs.c | 26 ++++ xlators/nfs/server/src/nfs.h | 1 + xlators/nfs/server/src/nfs3-fh.c | 12 ++ xlators/nfs/server/src/nfs3-fh.h | 4 + 10 files changed, 376 insertions(+), 6 deletions(-) create mode 100644 rpc/xdr/src/mount3udp.x create mode 100644 xlators/nfs/server/src/mount3udp_svc.c diff --git a/rpc/xdr/src/mount3udp.x b/rpc/xdr/src/mount3udp.x new file mode 100644 index 000000000..90b5b741a --- /dev/null +++ b/rpc/xdr/src/mount3udp.x @@ -0,0 +1,34 @@ +/* + Copyright (c) 2012 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +/* This is used by rpcgen to auto generate the rpc stubs. + * mount3udp_svc.c is heavily modified though + */ + +const MNTUDPPATHLEN = 1024; + +typedef string mntudpdirpath; + +program MOUNTUDP_PROGRAM { + version MOUNTUDP_V3 { + void MOUNTUDPPROC3_NULL(void) = 0; + mountres3 MOUNTUDPPROC3_MNT (mntudpdirpath) = 1; + mountstat3 MOUNTUDPPROC3_UMNT (mntudpdirpath) = 3; + } = 3; +} = 100005; diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 0d82f1624..ae38d5b14 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -217,6 +217,7 @@ static struct volopt_map_entry glusterd_volopt_map[] = { {"nfs.export-dir", "nfs/server", "!nfs3.*.export-dir", NULL, DOC, 0}, {"nfs.disable", "nfs/server", "!nfs-disable", NULL, DOC, 0}, {"nfs.nlm", "nfs/server", "nfs.nlm", NULL, GLOBAL_DOC, 0}, + {"nfs.mount-udp", "nfs/server", "nfs.mount-udp", NULL, GLOBAL_DOC, 0}, {VKEY_FEATURES_QUOTA, "features/marker", "quota", "off", NO_DOC, OPT_FLAG_FORCE}, {VKEY_FEATURES_LIMIT_USAGE, "features/quota", "limit-set", NULL, NO_DOC, 0}, diff --git a/xlators/nfs/server/src/Makefile.am b/xlators/nfs/server/src/Makefile.am index b5fd8586d..ef3b67297 100644 --- a/xlators/nfs/server/src/Makefile.am +++ b/xlators/nfs/server/src/Makefile.am @@ -4,7 +4,7 @@ nfsrpclibdir = $(top_srcdir)/rpc/rpc-lib/src server_la_LDFLAGS = -module -avoidversion server_la_SOURCES = nfs.c nfs-common.c nfs-fops.c nfs-inodes.c \ nfs-generics.c mount3.c nfs3-fh.c nfs3.c nfs3-helpers.c nlm4.c \ - nlmcbk_svc.c + nlmcbk_svc.c mount3udp_svc.c server_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la noinst_HEADERS = nfs.h nfs-common.h nfs-fops.h nfs-inodes.h nfs-generics.h \ diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index d088b3c53..93b086476 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -47,6 +47,9 @@ typedef ssize_t (*mnt3_serializer) (struct iovec outmsg, void *args); +extern void * +mount3udp_thread (void *argv); + /* Generic reply function for MOUNTv3 specific replies. */ int @@ -1406,6 +1409,87 @@ err: return ret; } +/* just declaring, definition is way down below */ +rpcsvc_program_t mnt3prog; + +/* nfs3_rootfh used by mount3udp thread needs to access mount3prog.private + * directly as we don't have nfs xlator pointer to dereference it. But thats OK + */ + +struct nfs3_fh * +nfs3_rootfh (char* path) +{ + struct mount3_state *ms = NULL; + struct nfs3_fh *fh = NULL; + struct mnt3_export *exp = NULL; + inode_t *inode = NULL; + char *tmp = NULL; + + ms = mnt3prog.private; + exp = mnt3_mntpath_to_export (ms, path); + if (exp == NULL) + goto err; + + tmp = (char *)path; + tmp = strchr (tmp, '/'); + if (tmp == NULL) + tmp = "/"; + + inode = inode_from_path (exp->vol->itable, tmp); + if (inode == NULL) + goto err; + + fh = GF_CALLOC (1, sizeof(*fh), gf_nfs_mt_nfs3_fh); + if (fh == NULL) + goto err; + nfs3_build_fh (inode, exp->volumeid, fh); + +err: + if (inode) + inode_unref (inode); + return fh; +} + +int +mount3udp_add_mountlist (char *host, dirpath *expname) +{ + struct mountentry *me = NULL; + struct mount3_state *ms = NULL; + char *export = NULL; + + ms = mnt3prog.private; + me = GF_CALLOC (1, sizeof (*me), gf_nfs_mt_mountentry); + if (!me) + return -1; + export = (char *)expname; + while (*export == '/') + export++; + + strcpy (me->exname, export); + strcpy (me->hostname, host); + INIT_LIST_HEAD (&me->mlist); + LOCK (&ms->mountlock); + { + list_add_tail (&me->mlist, &ms->mountlist); + } + UNLOCK (&ms->mountlock); + return 0; +} + +int +mount3udp_delete_mountlist (char *hostname, dirpath *expname) +{ + struct mount3_state *ms = NULL; + char *export = NULL; + + ms = mnt3prog.private; + export = (char *)expname; + while (*export == '/') + export++; + __mnt3svc_umount (ms, export, hostname); + return 0; +} + struct mnt3_export * mnt3_init_export_ent (struct mount3_state *ms, xlator_t *xl, char *exportpath, @@ -1785,6 +1869,7 @@ rpcsvc_program_t mnt3prog = { }; + rpcsvc_program_t * mnt3svc_init (xlator_t *nfsx) { @@ -1793,6 +1878,7 @@ mnt3svc_init (xlator_t *nfsx) dict_t *options = NULL; char *portstr = NULL; int ret = -1; + pthread_t udp_thread; if (!nfsx || !nfsx->private) return NULL; @@ -1842,6 +1928,9 @@ mnt3svc_init (xlator_t *nfsx) goto err; } + if (nfs->mount_udp) { + pthread_create (&udp_thread, NULL, mount3udp_thread, NULL); + } return &mnt3prog; err: return NULL; @@ -1930,5 +2019,3 @@ mnt1svc_init (xlator_t *nfsx) err: return NULL; } - - diff --git a/xlators/nfs/server/src/mount3udp_svc.c b/xlators/nfs/server/src/mount3udp_svc.c new file mode 100644 index 000000000..2c370a74a --- /dev/null +++ b/xlators/nfs/server/src/mount3udp_svc.c @@ -0,0 +1,201 @@ +/* + Copyright (c) 2012 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + + +#include "xdr-nfs3.h" +#include "logging.h" +#include "mem-pool.h" +#include "nfs-mem-types.h" +#include "mount3.h" +#include +#include +#include +#include +#include +#include +#include + + +extern struct nfs3_fh* nfs3_rootfh (char *dp); +extern mountres3 mnt3svc_set_mountres3 (mountstat3 stat, struct nfs3_fh *fh, + int *authflavor, u_int aflen); +extern int +mount3udp_add_mountlist (char *host, dirpath *expname); + +extern int +mount3udp_delete_mountlist (char *host, dirpath *expname); + + +/* only this thread will use this, no locking needed */ +char mnthost[INET_ADDRSTRLEN+1]; + +mountres3 * +mountudpproc3_mnt_3_svc(dirpath **dpp, struct svc_req *req) +{ + struct mountres3 *res = NULL; + int *autharr = NULL; + struct nfs3_fh *fh = NULL; + char *tmp = NULL; + + tmp = (char *)*dpp; + while (*tmp == '/') + tmp++; + fh = nfs3_rootfh (tmp); + if (fh == NULL) { + gf_log (GF_MNT, GF_LOG_DEBUG, "unable to get fh for %s", tmp); + goto err; + } + + res = GF_CALLOC (1, sizeof(*res), gf_nfs_mt_mountres3); + if (res == NULL) { + gf_log (GF_MNT, GF_LOG_ERROR, "unable to allocate memory"); + goto err; + } + autharr = GF_CALLOC (1, sizeof(*autharr), gf_nfs_mt_int); + if (autharr == NULL) { + gf_log (GF_MNT, GF_LOG_ERROR, "unable to allocate memory"); + goto err; + } + autharr[0] = AUTH_UNIX; + *res = mnt3svc_set_mountres3 (MNT3_OK, fh, autharr, 1); + mount3udp_add_mountlist (mnthost, *dpp); + return res; + + err: + if (fh) + GF_FREE (fh); + if (res) + GF_FREE (res); + if (autharr) + GF_FREE (autharr); + return NULL; +} + +mountstat3 * +mountudpproc3_umnt_3_svc(dirpath **dp, struct svc_req *req) +{ + mountstat3 *stat = NULL; + + stat = GF_CALLOC (1, sizeof(mountstat3), gf_nfs_mt_mountstat3); + if (stat == NULL) { + gf_log (GF_MNT, GF_LOG_ERROR, "unable to allocate memory"); + return NULL; + } + *stat = MNT3_OK; + mount3udp_delete_mountlist (mnthost, *dp); + return stat; +} + +static void +mountudp_program_3(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + dirpath mountudpproc3_mnt_3_arg; + } argument; + char *result = NULL; + xdrproc_t _xdr_argument = NULL, _xdr_result = NULL; + char *(*local)(char *, struct svc_req *) = NULL; + mountres3 *res = NULL; + struct sockaddr_in *sin = NULL; + + sin = svc_getcaller (transp); + inet_ntop (AF_INET, &sin->sin_addr, mnthost, INET_ADDRSTRLEN+1); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, + (char *)NULL); + return; + + case MOUNT3_MNT: + _xdr_argument = (xdrproc_t) xdr_dirpath; + _xdr_result = (xdrproc_t) xdr_mountres3; + local = (char *(*)(char *, + struct svc_req *)) mountudpproc3_mnt_3_svc; + break; + + case MOUNT3_UMNT: + _xdr_argument = (xdrproc_t) xdr_dirpath; + _xdr_result = (xdrproc_t) xdr_mountstat3; + local = (char *(*)(char *, + struct svc_req *)) mountudpproc3_umnt_3_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, + (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + result = (*local)((char *)&argument, rqstp); + if (result == NULL) { + gf_log (GF_MNT, GF_LOG_DEBUG, "PROC returned error"); + svcerr_systemerr (transp); + } + if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, + result)) { + gf_log (GF_MNT, GF_LOG_ERROR, "svc_sendreply returned error"); + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, + (caddr_t) &argument)) { + gf_log (GF_MNT, GF_LOG_ERROR, "unable to free arguments"); + } + if (result == NULL) + return; + /* free the result */ + switch (rqstp->rq_proc) { + case MOUNT3_MNT: + res = (mountres3 *) result; + GF_FREE (res->mountres3_u.mountinfo.fhandle.fhandle3_val); + GF_FREE (res->mountres3_u.mountinfo.auth_flavors.auth_flavors_val); + GF_FREE (res); + break; + + case MOUNT3_UMNT: + GF_FREE (result); + break; + } + return; +} + +void * +mount3udp_thread (void *argv) +{ + register SVCXPRT *transp = NULL; + + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) { + gf_log (GF_MNT, GF_LOG_ERROR, "svcudp_create error"); + return NULL; + } + if (!svc_register(transp, MOUNT_PROGRAM, MOUNT_V3, + mountudp_program_3, IPPROTO_UDP)) { + gf_log (GF_MNT, GF_LOG_ERROR, "svc_register error"); + return NULL; + } + + svc_run (); + gf_log (GF_MNT, GF_LOG_ERROR, "svc_run returned"); + return NULL; +} diff --git a/xlators/nfs/server/src/nfs-mem-types.h b/xlators/nfs/server/src/nfs-mem-types.h index 1a3b25281..d9edc95b9 100644 --- a/xlators/nfs/server/src/nfs-mem-types.h +++ b/xlators/nfs/server/src/nfs-mem-types.h @@ -37,15 +37,19 @@ enum gf_nfs_mem_types_ { gf_nfs_mt_entry3, gf_nfs_mt_entryp3, gf_nfs_mt_nfs3_fd_entry, + gf_nfs_mt_nfs3_fh, gf_nfs_mt_nfs_initer_list, gf_nfs_mt_xlator_t, gf_nfs_mt_list_head, gf_nfs_mt_mnt3_resolve, gf_nfs_mt_mnt3_export, + gf_nfs_mt_int, + gf_nfs_mt_mountres3, + gf_nfs_mt_mountstat3, gf_nfs_mt_inode_q, - gf_nfs_mt_nlm4_state, - gf_nfs_mt_nlm4_cm, - gf_nfs_mt_nlm4_fde, + gf_nfs_mt_nlm4_state, + gf_nfs_mt_nlm4_cm, + gf_nfs_mt_nlm4_fde, gf_nfs_mt_nlm4_nlmclnt, gf_nfs_mt_nlm4_share, gf_nfs_mt_end diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c index a48e11499..6e9a274d9 100644 --- a/xlators/nfs/server/src/nfs.c +++ b/xlators/nfs/server/src/nfs.c @@ -651,6 +651,25 @@ nfs_init_state (xlator_t *this) } } + nfs->mount_udp = 0; + if (dict_get(this->options, "nfs.mount-udp")) { + ret = dict_get_str (this->options, "nfs.mount-udp", &optstr); + if (ret == -1) { + gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict"); + goto free_foppool; + } + + ret = gf_string2boolean (optstr, &boolt); + if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool " + "string"); + goto free_foppool; + } + + if (boolt == _gf_true) + nfs->mount_udp = 1; + } + /* support both options rpc-auth.ports.insecure and * rpc-auth-allow-insecure for backward compatibility */ @@ -1187,6 +1206,13 @@ struct volume_options options[] = { " Set it to 'on' to re-enable it. Default value: 'on'" }, + { .key = {"nfs.mount-udp"}, + .type = GF_OPTION_TYPE_BOOL, + .description = "set the option to 'on' to enable mountd on UDP. " + "Needed by Solaris NFS clients if NLM support is" + "needed" + }, + { .key = {NULL} }, }; diff --git a/xlators/nfs/server/src/nfs.h b/xlators/nfs/server/src/nfs.h index 0c9721244..4c6d039f8 100644 --- a/xlators/nfs/server/src/nfs.h +++ b/xlators/nfs/server/src/nfs.h @@ -86,6 +86,7 @@ struct nfs_state { unsigned int override_portnum; int allow_insecure; int enable_nlm; + int mount_udp; struct rpc_clnt *rpc_clnt; }; diff --git a/xlators/nfs/server/src/nfs3-fh.c b/xlators/nfs/server/src/nfs3-fh.c index 9aea88137..f41c3f2f1 100644 --- a/xlators/nfs/server/src/nfs3-fh.c +++ b/xlators/nfs/server/src/nfs3-fh.c @@ -229,6 +229,18 @@ done: return 0; } +int +nfs3_build_fh (inode_t *inode, uuid_t exportid, struct nfs3_fh *newfh) +{ + if (!newfh || !inode) + return -1; + + newfh->ident[0] = GF_NFSFH_IDENT0; + newfh->ident[1] = GF_NFSFH_IDENT1; + uuid_copy (newfh->gfid, inode->gfid); + uuid_copy (newfh->exportid, exportid); + return 0; +} int nfs3_fh_build_child_fh (struct nfs3_fh *parent, struct iatt *newstat, diff --git a/xlators/nfs/server/src/nfs3-fh.h b/xlators/nfs/server/src/nfs3-fh.h index e7c0625ee..3be043ed3 100644 --- a/xlators/nfs/server/src/nfs3-fh.h +++ b/xlators/nfs/server/src/nfs3-fh.h @@ -115,4 +115,8 @@ nfs3_fh_build_parent_fh (struct nfs3_fh *child, struct iatt *newstat, extern struct nfs3_fh nfs3_fh_build_uuid_root_fh (uuid_t volumeid); + +extern int +nfs3_build_fh (inode_t *inode, uuid_t exportid, struct nfs3_fh *newfh); + #endif -- cgit