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