mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-21 10:52:22 +00:00
Add an API for re-mounting cgroups, to isolate the process location
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@redhat.com>
This commit is contained in:
parent
83336118db
commit
1da631ecf3
@ -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>]])
|
||||
|
||||
|
@ -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
|
||||
|
@ -1118,6 +1118,7 @@ virCgroupGetMemoryUsage;
|
||||
virCgroupGetMemSwapHardLimit;
|
||||
virCgroupGetMemSwapUsage;
|
||||
virCgroupHasController;
|
||||
virCgroupIsolateMount;
|
||||
virCgroupKill;
|
||||
virCgroupKillPainfully;
|
||||
virCgroupKillRecursive;
|
||||
|
@ -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");
|
||||
@ -2385,3 +2391,133 @@ int virCgroupKillPainfully(virCgroupPtr group ATTRIBUTE_UNUSED)
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif /* HAVE_KILL, HAVE_MNTENT_H, HAVE_GETMNTENT_R */
|
||||
|
||||
#ifdef __linux__
|
||||
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;
|
||||
}
|
||||
#else /* __linux__ */
|
||||
int virCgroupIsolateMount(virCgroupPtr group ATTRIBUTE_UNUSED,
|
||||
const char *oldroot ATTRIBUTE_UNUSED,
|
||||
const char *mountopts ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
@ -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__ */
|
||||
|
@ -119,6 +119,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
|
||||
"Lock Space",
|
||||
"Init control",
|
||||
"Identity",
|
||||
"Cgroup",
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user