From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list