[libvirt] [PATCH] Unmount existing filesystems under user specified mounts in LXC

Daniel P. Berrange berrange at redhat.com
Mon Apr 8 15:12:11 UTC 2013


From: "Daniel P. Berrange" <berrange at redhat.com>

If the user requests a mount for /run, this may hide any existing
mounts that are lower down in /run. The result is that the
container still sees the mounts in /proc/mounts, but cannot
access them

sh-4.2# df
df: '/run/user/501/gvfs': No such file or directory
df: '/run/media/berrange/LIVE': No such file or directory
df: '/run/media/berrange/SecureDiskA1': No such file or directory
df: '/run/libvirt/lxc/sandbox': No such file or directory
Filesystem                      1K-blocks      Used Available Use% Mounted on
/dev/mapper/vg_t500wlan-lv_root 151476396 135390200   8384900  95% /
tmpfs                             1970888      3204   1967684   1% /run
/dev/sda1                          194241    155940     28061  85% /boot
devfs                                  64         0        64   0% /dev
tmpfs                                  64         0        64   0% /sys/fs/cgroup
tmpfs                             1970888      1200   1969688   1% /etc/libvirt-sandbox/scratch

Before mounting any filesystem at a particular location, we
must recursively unmount anything at or below the target mount
point

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/lxc/lxc_container.c | 218 ++++++++++++++++++++++++------------------------
 1 file changed, 111 insertions(+), 107 deletions(-)

diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index e59bfdf..30738bb 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -409,6 +409,113 @@ static int lxcContainerChildMountSort(const void *a, const void *b)
 # define MS_SLAVE                (1<<19)
 #endif
 
+static int lxcContainerGetSubtree(const char *prefix,
+                                  char ***mountsret,
+                                  size_t *nmountsret)
+{
+    FILE *procmnt;
+    struct mntent mntent;
+    char mntbuf[1024];
+    int ret = -1;
+    char **mounts = NULL;
+    size_t nmounts = 0;
+
+    VIR_DEBUG("prefix=%s", prefix);
+
+    *mountsret = NULL;
+    *nmountsret = 0;
+
+    if (!(procmnt = setmntent("/proc/mounts", "r"))) {
+        virReportSystemError(errno, "%s",
+                             _("Failed to read /proc/mounts"));
+        return -1;
+    }
+
+    while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
+        VIR_DEBUG("Got %s", mntent.mnt_dir);
+        if (!STRPREFIX(mntent.mnt_dir, prefix))
+            continue;
+
+        if (VIR_REALLOC_N(mounts, nmounts+1) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+        if (!(mounts[nmounts] = strdup(mntent.mnt_dir))) {
+            virReportOOMError();
+            goto cleanup;
+        }
+        nmounts++;
+        VIR_DEBUG("Grabbed %s", mntent.mnt_dir);
+    }
+
+    if (mounts)
+        qsort(mounts, nmounts, sizeof(mounts[0]),
+              lxcContainerChildMountSort);
+
+    ret = 0;
+cleanup:
+    *mountsret = mounts;
+    *nmountsret = nmounts;
+    endmntent(procmnt);
+    return ret;
+}
+
+static int lxcContainerUnmountSubtree(const char *prefix,
+                                      bool isOldRootFS)
+{
+    char **mounts = NULL;
+    size_t nmounts = 0;
+    size_t i;
+    int saveErrno;
+    const char *failedUmount = NULL;
+    int ret = -1;
+
+    VIR_DEBUG("Unmount subtreee from %s", prefix);
+
+    if (lxcContainerGetSubtree(prefix, &mounts, &nmounts) < 0)
+        goto cleanup;
+    for (i = 0 ; i < nmounts ; i++) {
+        VIR_DEBUG("Umount %s", mounts[i]);
+        if (umount(mounts[i]) < 0) {
+            char ebuf[1024];
+            failedUmount = mounts[i];
+            saveErrno = errno;
+            VIR_WARN("Failed to unmount '%s', trying to detach subtree '%s': %s",
+                     failedUmount, mounts[nmounts-1],
+                     virStrerror(errno, ebuf, sizeof(ebuf)));
+            break;
+        }
+    }
+
+    if (failedUmount) {
+        /* This detaches the subtree */
+        if (umount2(mounts[nmounts-1], MNT_DETACH) < 0) {
+            virReportSystemError(saveErrno,
+                                 _("Failed to unmount '%s' and could not detach subtree '%s'"),
+                                 failedUmount, mounts[nmounts-1]);
+            goto cleanup;
+        }
+        /* This unmounts the tmpfs on which the old root filesystem was hosted */
+        if (isOldRootFS &&
+            umount(mounts[nmounts-1]) < 0) {
+            virReportSystemError(saveErrno,
+                                 _("Failed to unmount '%s' and could not unmount old root '%s'"),
+                                 failedUmount, mounts[nmounts-1]);
+            goto cleanup;
+        }
+    }
+
+    ret = 0;
+
+cleanup:
+    for (i = 0 ; i < nmounts ; i++)
+        VIR_FREE(mounts[i]);
+    VIR_FREE(mounts);
+
+    return ret;
+}
+
+
 static int lxcContainerPrepareRoot(virDomainDefPtr def,
                                    virDomainFSDefPtr root)
 {
@@ -1254,6 +1361,10 @@ static int lxcContainerMountAllFS(virDomainDefPtr vmDef,
             STREQ(vmDef->fss[i]->dst, "/"))
             continue;
 
+        if (lxcContainerUnmountSubtree(vmDef->fss[i]->dst,
+                                       false) < 0)
+            return -1;
+
         if (lxcContainerMountFS(vmDef->fss[i], dstprefix, sec_mount_options) < 0)
             return -1;
     }
@@ -1624,113 +1735,6 @@ static int lxcContainerSetupAllHostdevs(virDomainDefPtr vmDef,
 }
 
 
-static int lxcContainerGetSubtree(const char *prefix,
-                                  char ***mountsret,
-                                  size_t *nmountsret)
-{
-    FILE *procmnt;
-    struct mntent mntent;
-    char mntbuf[1024];
-    int ret = -1;
-    char **mounts = NULL;
-    size_t nmounts = 0;
-
-    VIR_DEBUG("prefix=%s", prefix);
-
-    *mountsret = NULL;
-    *nmountsret = 0;
-
-    if (!(procmnt = setmntent("/proc/mounts", "r"))) {
-        virReportSystemError(errno, "%s",
-                             _("Failed to read /proc/mounts"));
-        return -1;
-    }
-
-    while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
-        VIR_DEBUG("Got %s", mntent.mnt_dir);
-        if (!STRPREFIX(mntent.mnt_dir, prefix))
-            continue;
-
-        if (VIR_REALLOC_N(mounts, nmounts+1) < 0) {
-            virReportOOMError();
-            goto cleanup;
-        }
-        if (!(mounts[nmounts] = strdup(mntent.mnt_dir))) {
-            virReportOOMError();
-            goto cleanup;
-        }
-        nmounts++;
-        VIR_DEBUG("Grabbed %s", mntent.mnt_dir);
-    }
-
-    if (mounts)
-        qsort(mounts, nmounts, sizeof(mounts[0]),
-              lxcContainerChildMountSort);
-
-    ret = 0;
-cleanup:
-    *mountsret = mounts;
-    *nmountsret = nmounts;
-    endmntent(procmnt);
-    return ret;
-}
-
-static int lxcContainerUnmountSubtree(const char *prefix,
-                                      bool isOldRootFS)
-{
-    char **mounts = NULL;
-    size_t nmounts = 0;
-    size_t i;
-    int saveErrno;
-    const char *failedUmount = NULL;
-    int ret = -1;
-
-    VIR_DEBUG("Unmount subtreee from %s", prefix);
-
-    if (lxcContainerGetSubtree(prefix, &mounts, &nmounts) < 0)
-        goto cleanup;
-    for (i = 0 ; i < nmounts ; i++) {
-        VIR_DEBUG("Umount %s", mounts[i]);
-        if (umount(mounts[i]) < 0) {
-            char ebuf[1024];
-            failedUmount = mounts[i];
-            saveErrno = errno;
-            VIR_WARN("Failed to unmount '%s', trying to detach subtree '%s': %s",
-                     failedUmount, mounts[nmounts-1],
-                     virStrerror(errno, ebuf, sizeof(ebuf)));
-            break;
-        }
-    }
-
-    if (failedUmount) {
-        /* This detaches the subtree */
-        if (umount2(mounts[nmounts-1], MNT_DETACH) < 0) {
-            virReportSystemError(saveErrno,
-                                 _("Failed to unmount '%s' and could not detach subtree '%s'"),
-                                 failedUmount, mounts[nmounts-1]);
-            goto cleanup;
-        }
-        /* This unmounts the tmpfs on which the old root filesystem was hosted */
-        if (isOldRootFS &&
-            umount(mounts[nmounts-1]) < 0) {
-            virReportSystemError(saveErrno,
-                                 _("Failed to unmount '%s' and could not unmount old root '%s'"),
-                                 failedUmount, mounts[nmounts-1]);
-            goto cleanup;
-        }
-    }
-
-    ret = 0;
-
-cleanup:
-    for (i = 0 ; i < nmounts ; i++)
-        VIR_FREE(mounts[i]);
-    VIR_FREE(mounts);
-
-    return ret;
-}
-
-
 struct lxcContainerCGroup {
     const char *dir;
     const char *linkDest;
-- 
1.8.1.4




More information about the libvir-list mailing list