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