From 767047377acee40f40237d2aca45cd94391cba37 Mon Sep 17 00:00:00 2001 From: Bipin Kunal Date: Mon, 27 Feb 2017 15:23:04 +0530 Subject: nfs: make subdir mounting work for Solaris 10 clients This fixes the segfault caused by solaris client in Gluster/NFS. Volname was not being parsed properly, Instead of volume name complete path was being used in nfs_mntpath_to_xlator(). Fixed it by striping volume name from complete path in nfs_mntpath_to_xlator(). Modified function name nfs3_funge_solaris_zerolen_fh() to nfs3_funge_webnfs_zerolen_fh() as zero-filled filehandle is specific to WebNFS. RFC : https://tools.ietf.org/html/rfc2055 Solaris uses WebNFS, the zero-filled FH is defined in the WebNFS spec. Logic was even added in fuction nfs3_funge_webnfs_zerolen_fh() to send subdir path in function glfs_resolve_at() instead of complete path for subdir mount. > Change-Id: I19aae3547b8910e7ed4974ee5385424cab3e834a > BUG: 1426667 > Signed-off-by: Bipin Kunal > Reviewed-on: https://review.gluster.org/16770 > Reviewed-by: Niels de Vos > Smoke: Gluster Build System > NetBSD-regression: NetBSD Build System > CentOS-regression: Gluster Build System > (cherry picked from commit 40e571339b3c19ab2a5b6a93bc46eadf2252d006) Change-Id: I21ebb1d104b6eb914af5f26a6906f161c132179c BUG: 1440228 Signed-off-by: Bipin Kunal Reviewed-on: https://review.gluster.org/17017 CentOS-regression: Gluster Build System Reviewed-by: Niels de Vos NetBSD-regression: NetBSD Build System Smoke: Gluster Build System --- api/src/glfs-resolve.c | 6 ++- xlators/nfs/server/src/nfs-common.c | 18 +++++-- xlators/nfs/server/src/nfs3.c | 96 +++++++++++++++++++++++++++---------- 3 files changed, 89 insertions(+), 31 deletions(-) diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c index f8b437bab0e..d495cd21413 100644 --- a/api/src/glfs-resolve.c +++ b/api/src/glfs-resolve.c @@ -385,6 +385,9 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, int ret = -1; struct iatt ciatt = {0, }; + DECLARE_OLD_THIS; + __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs); + path = gf_strdup (origpath); if (!path) { errno = ENOMEM; @@ -510,9 +513,10 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, } out: GF_FREE (path); + __GLFS_EXIT_FS; /* do NOT loc_wipe here as only last component might be missing */ - +invalid_fs: return ret; } diff --git a/xlators/nfs/server/src/nfs-common.c b/xlators/nfs/server/src/nfs-common.c index af37f6b264c..526918872d7 100644 --- a/xlators/nfs/server/src/nfs-common.c +++ b/xlators/nfs/server/src/nfs-common.c @@ -73,10 +73,11 @@ nfs_xlator_to_xlid (xlator_list_t *cl, xlator_t *xl) xlator_t * nfs_mntpath_to_xlator (xlator_list_t *cl, char *path) { - char *volname = NULL; - char *volptr = NULL; - size_t pathlen; + char *volname = NULL; + char *volptr = NULL; + size_t pathlen = -1; xlator_t *targetxl = NULL; + int i = 0; if ((!cl) || (!path)) return NULL; @@ -89,10 +90,17 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path) else volptr = &volname[0]; - if (pathlen && volname[pathlen - 1] == '/') - volname[pathlen - 1] = '\0'; + for (i = 0; i < pathlen; i++) { + if (volname[i] == '/') { + volname[i] = '\0'; + break; + } + } while (cl) { + gf_msg_trace (GF_NFS, 0, "Volptr: %s and cl->xlator->name: %s", + volptr, cl->xlator->name); + if (strcmp (volptr, cl->xlator->name) == 0) { targetxl = cl->xlator; break; diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index 64287c5b1bd..8b1d62b46ac 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -28,6 +28,7 @@ #include "xdr-rpc.h" #include "xdr-generic.h" #include "nfs-messages.h" +#include "glfs-internal.h" #include #include @@ -348,28 +349,68 @@ out: } -#define nfs3_funge_solaris_zerolen_fh(nfs3st, fhd, enam, nfsst, erl) \ - do { \ - xlator_t *fungexl = NULL; \ - uuid_t zero = {0, }; \ - fungexl =nfs_mntpath_to_xlator ((nfs3st)->exportslist,enam);\ - if (!fungexl) { \ - (nfsst) = NFS3ERR_NOENT; \ - goto erl; \ - } \ - \ - gf_uuid_copy ((fhd)->gfid, zero); \ - (fhd)->gfid[15] = 1; \ - (enam) = NULL; \ - if ((gf_nfs_dvm_off (nfs_state (nfs3st->nfsx)))) \ - (fhd)->exportid[15] = nfs_xlator_to_xlid ((nfs3st)->exportslist, fungexl); \ - else { \ - if(__nfs3_get_volume_id ((nfs3st), fungexl, (fhd)->exportid) < 0) { \ - (nfsst) = NFS3ERR_STALE; \ - goto erl; \ - } \ - } \ - } while (0) \ +static enum nfsstat3 +nfs3_funge_webnfs_zerolen_fh (struct nfs3_state *nfs3st, struct nfs3_fh *fhd, + char *name) +{ + xlator_t *fungexl = NULL; + glfs_t *fs = NULL; + loc_t loc = { 0, }; + enum nfsstat3 nfsstat = NFS3ERR_SERVERFAULT; + int ret = -1; + size_t namelen = -1; + + fungexl = nfs_mntpath_to_xlator (nfs3st->exportslist, name); + if (!fungexl) { + nfsstat = NFS3ERR_NOENT; + goto out; + } + + /* glfs_resolve_at copied from UDP MNT support */ + fs = glfs_new_from_ctx (fungexl->ctx); + if (!fs) { + nfsstat = NFS3ERR_NOENT; + goto out; + } + + /* strip volname/ from 'name' */ + namelen = strlen(name); + while (namelen != 0) { + name++; + if (name[0] == '/') { + break; + } + namelen--; + } + gf_msg_debug (GF_NFS, 0, "NAME :%s ", name); + + ret = glfs_resolve_at (fs, fungexl, NULL, name, &loc, NULL, 1, 0); + if (ret != 0) { + nfsstat = NFS3ERR_NOENT; + goto out; + } + + /* resolved subdir, copy gfid for the fh */ + gf_uuid_copy (fhd->gfid, loc.gfid); + loc_wipe (&loc); + + if (gf_nfs_dvm_off (nfs_state (nfs3st->nfsx))) + fhd->exportid[15] = nfs_xlator_to_xlid (nfs3st->exportslist, + fungexl); + else { + if (__nfs3_get_volume_id (nfs3st, fungexl, fhd->exportid) < 0) { + nfsstat = NFS3ERR_STALE; + goto out; + } + } + + nfsstat = NFS3_OK; +out: + if (fs) + glfs_free_from_ctx (fs); + + return nfsstat; +} #define nfs3_volume_started_check(nf3stt, vlm, rtval, erlbl) \ @@ -1495,9 +1536,14 @@ nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name) nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "LOOKUP", fh, name); nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret); - if (nfs3_solaris_zerolen_fh (fh, fhlen)) - nfs3_funge_solaris_zerolen_fh (nfs3, fh, name, stat, nfs3err); - else + if (nfs3_solaris_zerolen_fh (fh, fhlen)) { + stat = nfs3_funge_webnfs_zerolen_fh (nfs3, fh, name); + if (stat != NFS3_OK) + goto nfs3err; + + /* this fh means we're doing a mount, name is no more useful */ + name = NULL; + } else nfs3_validate_gluster_fh (fh, stat, nfs3err); nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret); nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err); -- cgit