From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> Add a virCgroupIsolateMount method which looks at where the current process is place in the cgroups (eg /system/demo.lxc.libvirt) and then remounts the cgroups such that this sub-directory becomes the root directory from the current process' POV. Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- configure.ac | 2 +- include/libvirt/virterror.h | 1 + src/libvirt_private.syms | 1 + src/util/vircgroup.c | 127 ++++++++++++++++++++++++++++++++++++++++++++ src/util/vircgroup.h | 4 ++ src/util/virerror.c | 1 + 6 files changed, 135 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 11b332f..529d979 100644 --- a/configure.ac +++ b/configure.ac @@ -208,7 +208,7 @@ dnl Availability of various common headers (non-fatal if missing). AC_CHECK_HEADERS([pwd.h paths.h regex.h sys/un.h \ sys/poll.h syslog.h mntent.h net/ethernet.h linux/magic.h \ sys/un.h sys/syscall.h netinet/tcp.h ifaddrs.h libtasn1.h \ - sys/ucred.h]) + sys/ucred.h sys/mount.h]) dnl Check whether endian provides handy macros. AC_CHECK_DECLS([htole64], [], [], [[#include <endian.h>]]) diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 4cd9256..3864a31 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -116,6 +116,7 @@ typedef enum { VIR_FROM_LOCKSPACE = 51, /* Error from lockspace */ VIR_FROM_INITCTL = 52, /* Error from initctl device communication */ VIR_FROM_IDENTITY = 53, /* Error from identity code */ + VIR_FROM_CGROUP = 54, /* Error from cgroups */ # ifdef VIR_ENUM_SENTINELS VIR_ERR_DOMAIN_LAST diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 52c3bcb..8014ea1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1113,6 +1113,7 @@ virCgroupGetMemoryUsage; virCgroupGetMemSwapHardLimit; virCgroupGetMemSwapUsage; virCgroupHasController; +virCgroupIsolateMount; virCgroupKill; virCgroupKillPainfully; virCgroupKillRecursive; diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 14af16e..e8abc70 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -27,6 +27,9 @@ #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R # include <mntent.h> #endif +#if defined HAVE_SYS_MOUNT_H +# include <sys/mount.h> +#endif #include <fcntl.h> #include <string.h> #include <errno.h> @@ -42,6 +45,7 @@ #include "virutil.h" #include "viralloc.h" +#include "virerror.h" #include "virlog.h" #include "virfile.h" #include "virhash.h" @@ -49,6 +53,8 @@ #define CGROUP_MAX_VAL 512 +#define VIR_FROM_THIS VIR_FROM_CGROUP + VIR_ENUM_IMPL(virCgroupController, VIR_CGROUP_CONTROLLER_LAST, "cpu", "cpuacct", "cpuset", "memory", "devices", "freezer", "blkio"); @@ -2382,3 +2388,124 @@ int virCgroupKillPainfully(virCgroupPtr group ATTRIBUTE_UNUSED) return -ENOSYS; } #endif /* HAVE_KILL, HAVE_MNTENT_H, HAVE_GETMNTENT_R */ + +static char *virCgroupIdentifyRoot(virCgroupPtr group) +{ + char *ret = NULL; + size_t i; + + for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) { + char *tmp; + if (!group->controllers[i].mountPoint) + continue; + if (!(tmp = strrchr(group->controllers[i].mountPoint, '/'))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not find directory separator in %s"), + group->controllers[i].mountPoint); + return NULL; + } + + tmp[0] = '\0'; + ret = strdup(group->controllers[i].mountPoint); + tmp[0] = '/'; + if (!ret) { + virReportOOMError(); + return NULL; + } + return ret; + } + + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not find any mounted controllers")); + return NULL; +} + + +int virCgroupIsolateMount(virCgroupPtr group, const char *oldroot, + const char *mountopts) +{ + int ret = -1; + size_t i; + char *opts = NULL; + char *root = NULL; + + if (!(root = virCgroupIdentifyRoot(group))) + return -1; + + VIR_DEBUG("Mounting cgroups at '%s'", root); + + if (virFileMakePath(root) < 0) { + virReportSystemError(errno, + _("Unable to create directory %s"), + root); + goto cleanup; + } + + if (virAsprintf(&opts, + "mode=755,size=65536%s", mountopts) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) { + virReportSystemError(errno, + _("Failed to mount %s on %s type %s"), + "tmpfs", root, "tmpfs"); + goto cleanup; + } + + for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) { + if (!group->controllers[i].mountPoint) + continue; + + if (!virFileExists(group->controllers[i].mountPoint)) { + char *src; + if (virAsprintf(&src, "%s%s%s", + oldroot, + group->controllers[i].mountPoint, + group->controllers[i].placement) < 0) { + virReportOOMError(); + goto cleanup; + } + + VIR_DEBUG("Create mount point '%s'", group->controllers[i].mountPoint); + if (virFileMakePath(group->controllers[i].mountPoint) < 0) { + virReportSystemError(errno, + _("Unable to create directory %s"), + group->controllers[i].mountPoint); + VIR_FREE(src); + goto cleanup; + } + + if (mount(src, group->controllers[i].mountPoint, NULL, MS_BIND, NULL) < 0) { + virReportSystemError(errno, + _("Failed to bind cgroup '%s' on '%s'"), + src, group->controllers[i].mountPoint); + VIR_FREE(src); + goto cleanup; + } + + VIR_FREE(src); + } + + if (group->controllers[i].linkPoint) { + VIR_DEBUG("Link mount point '%s' to '%s'", + group->controllers[i].mountPoint, + group->controllers[i].linkPoint); + if (symlink(group->controllers[i].mountPoint, + group->controllers[i].linkPoint) < 0) { + virReportSystemError(errno, + _("Unable to symlink directory %s to %s"), + group->controllers[i].mountPoint, + group->controllers[i].linkPoint); + return -1; + } + } + } + ret = 0; + +cleanup: + VIR_FREE(root); + VIR_FREE(opts); + return ret; +} diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h index 936e09b..61e6f91 100644 --- a/src/util/vircgroup.h +++ b/src/util/vircgroup.h @@ -183,4 +183,8 @@ int virCgroupKill(virCgroupPtr group, int signum); int virCgroupKillRecursive(virCgroupPtr group, int signum); int virCgroupKillPainfully(virCgroupPtr group); +int virCgroupIsolateMount(virCgroupPtr group, + const char *oldroot, + const char *mountopts); + #endif /* __VIR_CGROUP_H__ */ diff --git a/src/util/virerror.c b/src/util/virerror.c index c30642a..8a329a9 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -119,6 +119,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST, "Lock Space", "Init control", "Identity", + "Cgroup", ) -- 1.8.1.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list