Blob Blame History Raw
From 241f3c35d613657deb1d8fa41061a9c4faf00424 Mon Sep 17 00:00:00 2001
From: Bipin Kunal <bkunal@redhat.com>
Date: Mon, 27 Feb 2017 15:23:04 +0530
Subject: [PATCH 376/393] nfs: make subdir mounting work for Solaris 10 clients

	Backport of: https://review.gluster.org/#/c/16770/

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.

BUG: 1372283
Change-Id: I1c1efbd951f4e8b0cb04a0adad4629d2ed9c10e1
Signed-off-by: Bipin Kunal <bkunal@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/103007
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
---
 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 f8b437b..d495cd2 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 af37f6b..5269188 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 64287c5..8b1d62b 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 <sys/socket.h>
 #include <sys/uio.h>
@@ -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);
-- 
1.8.3.1