mirror of https://gitee.com/openkylin/libvirt.git
Replace LXC cgroup mount code with call to virCgroupIsolateMount
The LXC driver currently has code to detect cgroups mounts and then re-mount them inside the new root filesystem. Replace this fragile code with a call to virCgroupIsolateMount. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
1da631ecf3
commit
ff66b45e2b
|
@ -35,7 +35,6 @@
|
|||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <mntent.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
|
@ -1735,227 +1734,6 @@ static int lxcContainerSetupAllHostdevs(virDomainDefPtr vmDef,
|
|||
}
|
||||
|
||||
|
||||
struct lxcContainerCGroup {
|
||||
const char *dir;
|
||||
const char *linkDest;
|
||||
};
|
||||
|
||||
|
||||
static void lxcContainerCGroupFree(struct lxcContainerCGroup *mounts,
|
||||
size_t nmounts)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!mounts)
|
||||
return;
|
||||
|
||||
for (i = 0 ; i < nmounts ; i++) {
|
||||
VIR_FREE(mounts[i].dir);
|
||||
VIR_FREE(mounts[i].linkDest);
|
||||
}
|
||||
VIR_FREE(mounts);
|
||||
}
|
||||
|
||||
|
||||
static int lxcContainerIdentifyCGroups(struct lxcContainerCGroup **mountsret,
|
||||
size_t *nmountsret,
|
||||
char **root)
|
||||
{
|
||||
FILE *procmnt = NULL;
|
||||
struct mntent mntent;
|
||||
struct dirent *dent;
|
||||
char mntbuf[1024];
|
||||
int ret = -1;
|
||||
struct lxcContainerCGroup *mounts = NULL;
|
||||
size_t nmounts = 0;
|
||||
DIR *dh = NULL;
|
||||
char *path = NULL;
|
||||
|
||||
*mountsret = NULL;
|
||||
*nmountsret = 0;
|
||||
*root = NULL;
|
||||
|
||||
VIR_DEBUG("Finding cgroups mount points of type cgroup");
|
||||
|
||||
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 (STRNEQ(mntent.mnt_type, "cgroup"))
|
||||
continue;
|
||||
|
||||
if (!*root) {
|
||||
char *tmp;
|
||||
if (!(*root = strdup(mntent.mnt_dir))) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
tmp = strrchr(*root, '/');
|
||||
*tmp = '\0';
|
||||
} else if (!STRPREFIX(mntent.mnt_dir, *root)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Cgroup %s is not mounted under %s"),
|
||||
mntent.mnt_dir, *root);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Skip named mounts with no controller since they're
|
||||
* for application use only ie systemd */
|
||||
if (strstr(mntent.mnt_opts, "name="))
|
||||
continue;
|
||||
|
||||
if (VIR_EXPAND_N(mounts, nmounts, 1) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(mounts[nmounts-1].dir = strdup(mntent.mnt_dir))) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
VIR_DEBUG("Grabbed '%s'", mntent.mnt_dir);
|
||||
}
|
||||
|
||||
if (!*root) {
|
||||
VIR_DEBUG("No mounted cgroups found");
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Checking for symlinks in %s", *root);
|
||||
if (!(dh = opendir(*root))) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to read directory %s"),
|
||||
*root);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while ((dent = readdir(dh)) != NULL) {
|
||||
ssize_t rv;
|
||||
/* The cgroups links are just relative to the local
|
||||
* dir so we don't need a large buf */
|
||||
char linkbuf[100];
|
||||
|
||||
if (dent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
VIR_DEBUG("Checking entry %s", dent->d_name);
|
||||
if (virAsprintf(&path, "%s/%s", *root, dent->d_name) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((rv = readlink(path, linkbuf, sizeof(linkbuf)-1)) < 0) {
|
||||
if (errno != EINVAL) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to resolve link %s"),
|
||||
path);
|
||||
VIR_FREE(path);
|
||||
goto cleanup;
|
||||
}
|
||||
/* Ok not a link */
|
||||
VIR_FREE(path);
|
||||
} else {
|
||||
linkbuf[rv] = '\0';
|
||||
VIR_DEBUG("Got a link %s to %s", path, linkbuf);
|
||||
if (VIR_EXPAND_N(mounts, nmounts, 1) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(mounts[nmounts-1].linkDest = strdup(linkbuf))) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
mounts[nmounts-1].dir = path;
|
||||
path = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*mountsret = mounts;
|
||||
*nmountsret = nmounts;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
closedir(dh);
|
||||
endmntent(procmnt);
|
||||
VIR_FREE(path);
|
||||
|
||||
if (ret < 0) {
|
||||
lxcContainerCGroupFree(mounts, nmounts);
|
||||
VIR_FREE(*root);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int lxcContainerMountCGroups(struct lxcContainerCGroup *mounts,
|
||||
size_t nmounts,
|
||||
const char *root,
|
||||
char *sec_mount_options)
|
||||
{
|
||||
size_t i;
|
||||
char *opts = NULL;
|
||||
|
||||
VIR_DEBUG("Mounting cgroups at '%s'", root);
|
||||
|
||||
if (virFileMakePath(root) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to create directory %s"),
|
||||
root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virAsprintf(&opts,
|
||||
"mode=755,size=65536%s", sec_mount_options) < 0) {
|
||||
virReportOOMError();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
|
||||
VIR_FREE(opts);
|
||||
virReportSystemError(errno,
|
||||
_("Failed to mount %s on %s type %s"),
|
||||
"tmpfs", root, "tmpfs");
|
||||
return -1;
|
||||
}
|
||||
VIR_FREE(opts);
|
||||
|
||||
for (i = 0 ; i < nmounts ; i++) {
|
||||
if (mounts[i].linkDest) {
|
||||
VIR_DEBUG("Link mount point '%s' to '%s'",
|
||||
mounts[i].dir, mounts[i].linkDest);
|
||||
if (symlink(mounts[i].linkDest, mounts[i].dir) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to symlink directory %s to %s"),
|
||||
mounts[i].dir, mounts[i].linkDest);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
VIR_DEBUG("Create mount point '%s'", mounts[i].dir);
|
||||
if (virFileMakePath(mounts[i].dir) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to create directory %s"),
|
||||
mounts[i].dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount("cgroup", mounts[i].dir, "cgroup",
|
||||
0, mounts[i].dir + strlen(root) + 1) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Failed to mount cgroup on '%s'"),
|
||||
mounts[i].dir);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Got a FS mapped to /, we're going the pivot_root
|
||||
* approach to do a better-chroot-than-chroot
|
||||
* this is based on this thread http://lkml.org/lkml/2008/3/5/29
|
||||
|
@ -1966,10 +1744,9 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
|
|||
size_t nttyPaths,
|
||||
virSecurityManagerPtr securityDriver)
|
||||
{
|
||||
struct lxcContainerCGroup *mounts = NULL;
|
||||
size_t nmounts = 0;
|
||||
virCgroupPtr cgroup = NULL;
|
||||
int rc;
|
||||
int ret = -1;
|
||||
char *cgroupRoot = NULL;
|
||||
char *sec_mount_options;
|
||||
|
||||
if (!(sec_mount_options = virSecurityManagerGetMountOptions(securityDriver, vmDef)))
|
||||
|
@ -1977,8 +1754,11 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
|
|||
|
||||
/* Before pivoting we need to identify any
|
||||
* cgroups controllers that are mounted */
|
||||
if (lxcContainerIdentifyCGroups(&mounts, &nmounts, &cgroupRoot) < 0)
|
||||
if ((rc = virCgroupNewSelf(&cgroup)) != 0) {
|
||||
virReportSystemError(-rc, "%s",
|
||||
_("Cannot identify cgroup placement"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Ensure the root filesystem is mounted */
|
||||
if (lxcContainerPrepareRoot(vmDef, root) < 0)
|
||||
|
@ -2017,8 +1797,7 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
|
|||
|
||||
/* Now we can re-mount the cgroups controllers in the
|
||||
* same configuration as before */
|
||||
if (lxcContainerMountCGroups(mounts, nmounts,
|
||||
cgroupRoot, sec_mount_options) < 0)
|
||||
if (virCgroupIsolateMount(cgroup, "/.oldroot/", sec_mount_options) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Mounts /dev/pts */
|
||||
|
@ -2048,8 +1827,7 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
|
|||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
lxcContainerCGroupFree(mounts, nmounts);
|
||||
VIR_FREE(cgroupRoot);
|
||||
virCgroupFree(&cgroup);
|
||||
VIR_FREE(sec_mount_options);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue