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