From: "Daniel P. Berrange" <berrange(a)redhat.com>
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(a)redhat.com>
---
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