edecca
From 3d3a4186cbffd454c5f48af7ed7bd3e8934bbb2f Mon Sep 17 00:00:00 2001
edecca
Message-Id: <3d3a4186cbffd454c5f48af7ed7bd3e8934bbb2f@dist-git>
edecca
From: Michal Privoznik <mprivozn@redhat.com>
edecca
Date: Wed, 10 Oct 2018 17:25:56 +0200
edecca
Subject: [PATCH] virfile: Rework virFileIsSharedFixFUSE
edecca
edecca
RHEL-7.7: https://bugzilla.redhat.com/show_bug.cgi?id=1632711
edecca
RHEL-8.0: https://bugzilla.redhat.com/show_bug.cgi?id=1634782
edecca
RHEL-7.6.z: https://bugzilla.redhat.com/show_bug.cgi?id=1635705
edecca
edecca
There are couple of things wrong with the current implementation.
edecca
The first one is that in the first loop the code tries to build a
edecca
list of fuse.glusterfs mount points. Well, since the strings are
edecca
allocated in a temporary buffer and are not duplicated this
edecca
results in wrong decision made later in the code.
edecca
edecca
The second problem is that the code does not take into account
edecca
subtree mounts. For instance, if there's a fuse.gluster mounted
edecca
at /some/path and another FS mounted at /some/path/subdir the
edecca
code would not recognize this subdir mount.
edecca
edecca
Reported-by: Han Han <hhan@redhat.com>
edecca
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
edecca
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
edecca
(cherry picked from commit 1dbf6222dd5e1fedcbe335fc0852ef66e7a92901)
edecca
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
edecca
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
edecca
---
edecca
 src/util/virfile.c            | 61 ++++++++++++++---------------------
edecca
 tests/virfiledata/mounts3.txt |  2 ++
edecca
 tests/virfiletest.c           |  2 ++
edecca
 3 files changed, 29 insertions(+), 36 deletions(-)
edecca
edecca
diff --git a/src/util/virfile.c b/src/util/virfile.c
edecca
index 05ecf7bf21..e1dee7633a 100644
edecca
--- a/src/util/virfile.c
edecca
+++ b/src/util/virfile.c
edecca
@@ -3544,18 +3544,14 @@ static int
edecca
 virFileIsSharedFixFUSE(const char *path,
edecca
                        long long *f_type)
edecca
 {
edecca
-    char *dirpath = NULL;
edecca
-    const char **mounts = NULL;
edecca
-    size_t nmounts = 0;
edecca
-    char *p;
edecca
     FILE *f = NULL;
edecca
     struct mntent mb;
edecca
     char mntbuf[1024];
edecca
+    char *mntDir = NULL;
edecca
+    char *mntType = NULL;
edecca
+    size_t maxMatching = 0;
edecca
     int ret = -1;
edecca
 
edecca
-    if (VIR_STRDUP(dirpath, path) < 0)
edecca
-        return -1;
edecca
-
edecca
     if (!(f = setmntent(PROC_MOUNTS, "r"))) {
edecca
         virReportSystemError(errno,
edecca
                              _("Unable to open %s"),
edecca
@@ -3564,43 +3560,36 @@ virFileIsSharedFixFUSE(const char *path,
edecca
     }
edecca
 
edecca
     while (getmntent_r(f, &mb, mntbuf, sizeof(mntbuf))) {
edecca
-        if (STRNEQ("fuse.glusterfs", mb.mnt_type))
edecca
+        const char *p;
edecca
+        size_t len = strlen(mb.mnt_dir);
edecca
+
edecca
+        if (!(p = STRSKIP(path, mb.mnt_dir)))
edecca
             continue;
edecca
 
edecca
-        if (VIR_APPEND_ELEMENT_COPY(mounts, nmounts, mb.mnt_dir) < 0)
edecca
-            goto cleanup;
edecca
+        if (*(p - 1) != '/' && *p != '/' && *p != '\0')
edecca
+            continue;
edecca
+
edecca
+        if (len > maxMatching) {
edecca
+            maxMatching = len;
edecca
+            VIR_FREE(mntType);
edecca
+            VIR_FREE(mntDir);
edecca
+            if (VIR_STRDUP(mntDir, mb.mnt_dir) < 0 ||
edecca
+                VIR_STRDUP(mntType, mb.mnt_type) < 0)
edecca
+                goto cleanup;
edecca
+        }
edecca
     }
edecca
 
edecca
-    /* Add NULL sentinel so that this is a virStringList */
edecca
-    if (VIR_REALLOC_N(mounts, nmounts + 1) < 0)
edecca
-        goto cleanup;
edecca
-    mounts[nmounts] = NULL;
edecca
-
edecca
-    do {
edecca
-        if ((p = strrchr(dirpath, '/')) == NULL) {
edecca
-            virReportSystemError(EINVAL,
edecca
-                                 _("Invalid relative path '%s'"), path);
edecca
-            goto cleanup;
edecca
-        }
edecca
-
edecca
-        if (p == dirpath)
edecca
-            *(p+1) = '\0';
edecca
-        else
edecca
-            *p = '\0';
edecca
-
edecca
-        if (virStringListHasString(mounts, dirpath)) {
edecca
-            VIR_DEBUG("Found gluster FUSE mountpoint=%s for path=%s. "
edecca
-                      "Fixing shared FS type", dirpath, path);
edecca
-            *f_type = GFS2_MAGIC;
edecca
-            break;
edecca
-        }
edecca
-    } while (p != dirpath);
edecca
+    if (STREQ_NULLABLE(mntType, "fuse.glusterfs")) {
edecca
+        VIR_DEBUG("Found gluster FUSE mountpoint=%s for path=%s. "
edecca
+                  "Fixing shared FS type", mntDir, path);
edecca
+        *f_type = GFS2_MAGIC;
edecca
+    }
edecca
 
edecca
     ret = 0;
edecca
  cleanup:
edecca
+    VIR_FREE(mntType);
edecca
+    VIR_FREE(mntDir);
edecca
     endmntent(f);
edecca
-    VIR_FREE(mounts);
edecca
-    VIR_FREE(dirpath);
edecca
     return ret;
edecca
 }
edecca
 
edecca
diff --git a/tests/virfiledata/mounts3.txt b/tests/virfiledata/mounts3.txt
edecca
index 226f67dc00..134c6e8f81 100644
edecca
--- a/tests/virfiledata/mounts3.txt
edecca
+++ b/tests/virfiledata/mounts3.txt
edecca
@@ -31,3 +31,5 @@ hugetlbfs /hugepages2M hugetlbfs rw,relatime,mode=1777,pagesize=2M 0 0
edecca
 none /run/user/1000 tmpfs rw,relatime,mode=700,uid=1000 0 0
edecca
 host:/nfs /nfs nfs4 rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp6,timeo=600,retrans=2,sec=sys,clientaddr=::,local_lock=none,addr=:: 0 0
edecca
 dev /nfs/blah devtmpfs rw,nosuid,relatime,size=10240k,nr_inodes=4093060,mode=755 0 0
edecca
+host:/gv0 /gluster fuse.glusterfs rw 0 0
edecca
+root@host:/tmp/mkdir /gluster/sshfs fuse.sshfs rw 0 0
edecca
diff --git a/tests/virfiletest.c b/tests/virfiletest.c
edecca
index 80ea34bfa4..be4dbf8910 100644
edecca
--- a/tests/virfiletest.c
edecca
+++ b/tests/virfiletest.c
edecca
@@ -455,6 +455,8 @@ mymain(void)
edecca
     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts2.txt", "/run/user/501/gvfs/some/file", false);
edecca
     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/nfs/file", true);
edecca
     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/nfs/blah", false);
edecca
+    DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/file", true);
edecca
+    DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/sshfs/file", false);
edecca
 
edecca
     return ret != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
edecca
 }
edecca
-- 
edecca
2.19.1
edecca