mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 15:27:47 +00:00
vircgroup: extract v1 detect functions
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
This commit is contained in:
parent
47941ea7f5
commit
42a3fcc02b
@ -231,82 +231,6 @@ virCgroupPartitionEscape(char **path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
virCgroupResolveMountLink(const char *mntDir,
|
|
||||||
const char *typeStr,
|
|
||||||
virCgroupControllerPtr controller)
|
|
||||||
{
|
|
||||||
VIR_AUTOFREE(char *) linkSrc = NULL;
|
|
||||||
VIR_AUTOFREE(char *) tmp = NULL;
|
|
||||||
char *dirName;
|
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
if (VIR_STRDUP(tmp, mntDir) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
dirName = strrchr(tmp, '/');
|
|
||||||
if (!dirName) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("Missing '/' separator in cgroup mount '%s'"), tmp);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strchr(dirName + 1, ','))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
*dirName = '\0';
|
|
||||||
if (virAsprintf(&linkSrc, "%s/%s", tmp, typeStr) < 0)
|
|
||||||
return -1;
|
|
||||||
*dirName = '/';
|
|
||||||
|
|
||||||
if (lstat(linkSrc, &sb) < 0) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
VIR_WARN("Controller %s co-mounted at %s is missing symlink at %s",
|
|
||||||
typeStr, tmp, linkSrc);
|
|
||||||
} else {
|
|
||||||
virReportSystemError(errno, _("Cannot stat %s"), linkSrc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!S_ISLNK(sb.st_mode)) {
|
|
||||||
VIR_WARN("Expecting a symlink at %s for controller %s",
|
|
||||||
linkSrc, typeStr);
|
|
||||||
} else {
|
|
||||||
VIR_STEAL_PTR(controller->linkPoint, linkSrc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
virCgroupMountOptsMatchController(const char *mntOpts,
|
|
||||||
const char *typeStr)
|
|
||||||
{
|
|
||||||
const char *tmp = mntOpts;
|
|
||||||
int typeLen = strlen(typeStr);
|
|
||||||
|
|
||||||
while (tmp) {
|
|
||||||
const char *next = strchr(tmp, ',');
|
|
||||||
int len;
|
|
||||||
if (next) {
|
|
||||||
len = next - tmp;
|
|
||||||
next++;
|
|
||||||
} else {
|
|
||||||
len = strlen(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeLen == len && STREQLEN(typeStr, tmp, len))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
tmp = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process /proc/mounts figuring out what controllers are
|
* Process /proc/mounts figuring out what controllers are
|
||||||
* mounted and where
|
* mounted and where
|
||||||
@ -314,7 +238,6 @@ virCgroupMountOptsMatchController(const char *mntOpts,
|
|||||||
static int
|
static int
|
||||||
virCgroupDetectMounts(virCgroupPtr group)
|
virCgroupDetectMounts(virCgroupPtr group)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
FILE *mounts = NULL;
|
FILE *mounts = NULL;
|
||||||
struct mntent entry;
|
struct mntent entry;
|
||||||
char buf[CGROUP_MAX_VAL];
|
char buf[CGROUP_MAX_VAL];
|
||||||
@ -327,34 +250,11 @@ virCgroupDetectMounts(virCgroupPtr group)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
|
while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
|
||||||
if (STRNEQ(entry.mnt_type, "cgroup"))
|
if (group->backend->detectMounts(group,
|
||||||
continue;
|
entry.mnt_type,
|
||||||
|
entry.mnt_opts,
|
||||||
for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
|
entry.mnt_dir) < 0) {
|
||||||
const char *typestr = virCgroupControllerTypeToString(i);
|
|
||||||
|
|
||||||
if (virCgroupMountOptsMatchController(entry.mnt_opts, typestr)) {
|
|
||||||
/* Note that the lines in /proc/mounts have the same
|
|
||||||
* order than the mount operations, and that there may
|
|
||||||
* be duplicates due to bind mounts. This means
|
|
||||||
* that the same mount point may be processed more than
|
|
||||||
* once. We need to save the results of the last one,
|
|
||||||
* and we need to be careful to release the memory used
|
|
||||||
* by previous processing. */
|
|
||||||
virCgroupControllerPtr controller = &group->controllers[i];
|
|
||||||
|
|
||||||
VIR_FREE(controller->mountPoint);
|
|
||||||
VIR_FREE(controller->linkPoint);
|
|
||||||
if (VIR_STRDUP(controller->mountPoint, entry.mnt_dir) < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* If it is a co-mount it has a filename like "cpu,cpuacct"
|
|
||||||
* and we must identify the symlink path */
|
|
||||||
if (virCgroupResolveMountLink(entry.mnt_dir, typestr,
|
|
||||||
controller) < 0) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,7 +328,6 @@ virCgroupDetectPlacement(virCgroupPtr group,
|
|||||||
pid_t pid,
|
pid_t pid,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
FILE *mapping = NULL;
|
FILE *mapping = NULL;
|
||||||
char line[1024];
|
char line[1024];
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@ -468,30 +367,9 @@ virCgroupDetectPlacement(virCgroupPtr group,
|
|||||||
controllers++;
|
controllers++;
|
||||||
selfpath++;
|
selfpath++;
|
||||||
|
|
||||||
for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
|
if (group->backend->detectPlacement(group, path, controllers,
|
||||||
const char *typestr = virCgroupControllerTypeToString(i);
|
selfpath) < 0) {
|
||||||
|
|
||||||
if (virCgroupMountOptsMatchController(controllers, typestr) &&
|
|
||||||
group->controllers[i].mountPoint != NULL &&
|
|
||||||
group->controllers[i].placement == NULL) {
|
|
||||||
/*
|
|
||||||
* selfpath == "/" + path="" -> "/"
|
|
||||||
* selfpath == "/libvirt.service" + path == "" -> "/libvirt.service"
|
|
||||||
* selfpath == "/libvirt.service" + path == "foo" -> "/libvirt.service/foo"
|
|
||||||
*/
|
|
||||||
if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
|
|
||||||
if (VIR_STRDUP(group->controllers[i].placement,
|
|
||||||
selfpath) < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
|
||||||
if (virAsprintf(&group->controllers[i].placement,
|
|
||||||
"%s%s%s", selfpath,
|
|
||||||
(STREQ(selfpath, "/") ||
|
|
||||||
STREQ(path, "") ? "" : "/"),
|
|
||||||
path) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,18 @@ typedef int
|
|||||||
(*virCgroupCopyMountsCB)(virCgroupPtr group,
|
(*virCgroupCopyMountsCB)(virCgroupPtr group,
|
||||||
virCgroupPtr parent);
|
virCgroupPtr parent);
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(*virCgroupDetectMountsCB)(virCgroupPtr group,
|
||||||
|
const char *mntType,
|
||||||
|
const char *mntOpts,
|
||||||
|
const char *mntDir);
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(*virCgroupDetectPlacementCB)(virCgroupPtr group,
|
||||||
|
const char *path,
|
||||||
|
const char *controllers,
|
||||||
|
const char *selfpath);
|
||||||
|
|
||||||
struct _virCgroupBackend {
|
struct _virCgroupBackend {
|
||||||
virCgroupBackendType type;
|
virCgroupBackendType type;
|
||||||
|
|
||||||
@ -52,6 +64,8 @@ struct _virCgroupBackend {
|
|||||||
virCgroupAvailableCB available;
|
virCgroupAvailableCB available;
|
||||||
virCgroupValidateMachineGroupCB validateMachineGroup;
|
virCgroupValidateMachineGroupCB validateMachineGroup;
|
||||||
virCgroupCopyMountsCB copyMounts;
|
virCgroupCopyMountsCB copyMounts;
|
||||||
|
virCgroupDetectMountsCB detectMounts;
|
||||||
|
virCgroupDetectPlacementCB detectPlacement;
|
||||||
};
|
};
|
||||||
typedef struct _virCgroupBackend virCgroupBackend;
|
typedef struct _virCgroupBackend virCgroupBackend;
|
||||||
typedef virCgroupBackend *virCgroupBackendPtr;
|
typedef virCgroupBackend *virCgroupBackendPtr;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
|
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
|
||||||
# include <mntent.h>
|
# include <mntent.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include "virlog.h"
|
#include "virlog.h"
|
||||||
#include "virstring.h"
|
#include "virstring.h"
|
||||||
#include "virsystemd.h"
|
#include "virsystemd.h"
|
||||||
|
#include "virerror.h"
|
||||||
|
|
||||||
VIR_LOG_INIT("util.cgroup");
|
VIR_LOG_INIT("util.cgroup");
|
||||||
|
|
||||||
@ -180,12 +182,168 @@ virCgroupV1CopyMounts(virCgroupPtr group,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virCgroupV1ResolveMountLink(const char *mntDir,
|
||||||
|
const char *typeStr,
|
||||||
|
virCgroupControllerPtr controller)
|
||||||
|
{
|
||||||
|
VIR_AUTOFREE(char *) linkSrc = NULL;
|
||||||
|
VIR_AUTOFREE(char *) tmp = NULL;
|
||||||
|
char *dirName;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (VIR_STRDUP(tmp, mntDir) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dirName = strrchr(tmp, '/');
|
||||||
|
if (!dirName) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Missing '/' separator in cgroup mount '%s'"), tmp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strchr(dirName + 1, ','))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*dirName = '\0';
|
||||||
|
if (virAsprintf(&linkSrc, "%s/%s", tmp, typeStr) < 0)
|
||||||
|
return -1;
|
||||||
|
*dirName = '/';
|
||||||
|
|
||||||
|
if (lstat(linkSrc, &sb) < 0) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
VIR_WARN("Controller %s co-mounted at %s is missing symlink at %s",
|
||||||
|
typeStr, tmp, linkSrc);
|
||||||
|
} else {
|
||||||
|
virReportSystemError(errno, _("Cannot stat %s"), linkSrc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!S_ISLNK(sb.st_mode)) {
|
||||||
|
VIR_WARN("Expecting a symlink at %s for controller %s",
|
||||||
|
linkSrc, typeStr);
|
||||||
|
} else {
|
||||||
|
VIR_STEAL_PTR(controller->linkPoint, linkSrc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
virCgroupV1MountOptsMatchController(const char *mntOpts,
|
||||||
|
const char *typeStr)
|
||||||
|
{
|
||||||
|
const char *tmp = mntOpts;
|
||||||
|
int typeLen = strlen(typeStr);
|
||||||
|
|
||||||
|
while (tmp) {
|
||||||
|
const char *next = strchr(tmp, ',');
|
||||||
|
int len;
|
||||||
|
if (next) {
|
||||||
|
len = next - tmp;
|
||||||
|
next++;
|
||||||
|
} else {
|
||||||
|
len = strlen(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeLen == len && STREQLEN(typeStr, tmp, len))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
tmp = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virCgroupV1DetectMounts(virCgroupPtr group,
|
||||||
|
const char *mntType,
|
||||||
|
const char *mntOpts,
|
||||||
|
const char *mntDir)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (STRNEQ(mntType, "cgroup"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
|
||||||
|
const char *typestr = virCgroupV1ControllerTypeToString(i);
|
||||||
|
|
||||||
|
if (virCgroupV1MountOptsMatchController(mntOpts, typestr)) {
|
||||||
|
/* Note that the lines in /proc/mounts have the same
|
||||||
|
* order than the mount operations, and that there may
|
||||||
|
* be duplicates due to bind mounts. This means
|
||||||
|
* that the same mount point may be processed more than
|
||||||
|
* once. We need to save the results of the last one,
|
||||||
|
* and we need to be careful to release the memory used
|
||||||
|
* by previous processing. */
|
||||||
|
virCgroupControllerPtr controller = &group->controllers[i];
|
||||||
|
|
||||||
|
VIR_FREE(controller->mountPoint);
|
||||||
|
VIR_FREE(controller->linkPoint);
|
||||||
|
if (VIR_STRDUP(controller->mountPoint, mntDir) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* If it is a co-mount it has a filename like "cpu,cpuacct"
|
||||||
|
* and we must identify the symlink path */
|
||||||
|
if (virCgroupV1ResolveMountLink(mntDir, typestr, controller) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virCgroupV1DetectPlacement(virCgroupPtr group,
|
||||||
|
const char *path,
|
||||||
|
const char *controllers,
|
||||||
|
const char *selfpath)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
|
||||||
|
const char *typestr = virCgroupV1ControllerTypeToString(i);
|
||||||
|
|
||||||
|
if (virCgroupV1MountOptsMatchController(controllers, typestr) &&
|
||||||
|
group->controllers[i].mountPoint != NULL &&
|
||||||
|
group->controllers[i].placement == NULL) {
|
||||||
|
/*
|
||||||
|
* selfpath == "/" + path="" -> "/"
|
||||||
|
* selfpath == "/libvirt.service" + path == "" -> "/libvirt.service"
|
||||||
|
* selfpath == "/libvirt.service" + path == "foo" -> "/libvirt.service/foo"
|
||||||
|
*/
|
||||||
|
if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
|
||||||
|
if (VIR_STRDUP(group->controllers[i].placement,
|
||||||
|
selfpath) < 0)
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
if (virAsprintf(&group->controllers[i].placement,
|
||||||
|
"%s%s%s", selfpath,
|
||||||
|
(STREQ(selfpath, "/") ||
|
||||||
|
STREQ(path, "") ? "" : "/"),
|
||||||
|
path) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virCgroupBackend virCgroupV1Backend = {
|
virCgroupBackend virCgroupV1Backend = {
|
||||||
.type = VIR_CGROUP_BACKEND_TYPE_V1,
|
.type = VIR_CGROUP_BACKEND_TYPE_V1,
|
||||||
|
|
||||||
.available = virCgroupV1Available,
|
.available = virCgroupV1Available,
|
||||||
.validateMachineGroup = virCgroupV1ValidateMachineGroup,
|
.validateMachineGroup = virCgroupV1ValidateMachineGroup,
|
||||||
.copyMounts = virCgroupV1CopyMounts,
|
.copyMounts = virCgroupV1CopyMounts,
|
||||||
|
.detectMounts = virCgroupV1DetectMounts,
|
||||||
|
.detectPlacement = virCgroupV1DetectPlacement,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user