2008-10-03 17:58:02 +00:00
|
|
|
/*
|
2012-12-03 15:03:47 +00:00
|
|
|
* vircgroup.c: methods for managing control cgroups
|
2008-10-03 17:58:02 +00:00
|
|
|
*
|
2015-03-11 10:15:29 +00:00
|
|
|
* Copyright (C) 2010-2015 Red Hat, Inc.
|
2008-10-03 17:58:02 +00:00
|
|
|
* Copyright IBM Corp. 2008
|
|
|
|
*
|
2012-07-27 09:39:53 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-27 09:39:53 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-10-03 17:58:02 +00:00
|
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
|
2018-09-27 10:19:17 +00:00
|
|
|
#ifdef __linux__
|
2010-03-09 18:22:22 +00:00
|
|
|
# include <mntent.h>
|
2013-04-05 11:48:47 +00:00
|
|
|
# include <sys/mount.h>
|
2018-09-27 10:19:17 +00:00
|
|
|
# include <fcntl.h>
|
|
|
|
# include <sys/stat.h>
|
2016-04-14 13:11:45 +00:00
|
|
|
|
2018-09-27 10:19:17 +00:00
|
|
|
# ifdef MAJOR_IN_MKDEV
|
|
|
|
# include <sys/mkdev.h>
|
|
|
|
# elif MAJOR_IN_SYSMACROS
|
|
|
|
# include <sys/sysmacros.h>
|
|
|
|
# endif
|
2016-04-14 13:11:45 +00:00
|
|
|
|
2018-09-27 10:19:17 +00:00
|
|
|
# include <sys/types.h>
|
|
|
|
# include <signal.h>
|
|
|
|
# include <dirent.h>
|
|
|
|
# include <unistd.h>
|
|
|
|
#endif /* __linux__ */
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2018-12-13 14:53:50 +00:00
|
|
|
#define LIBVIRT_VIRCGROUPPRIV_H_ALLOW
|
2013-03-28 14:32:23 +00:00
|
|
|
#include "vircgrouppriv.h"
|
|
|
|
|
2012-12-13 17:44:57 +00:00
|
|
|
#include "virutil.h"
|
2018-07-30 09:04:26 +00:00
|
|
|
#include "viralloc.h"
|
2018-09-13 14:27:56 +00:00
|
|
|
#include "vircgroupbackend.h"
|
2013-04-05 11:48:47 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2012-01-25 16:13:59 +00:00
|
|
|
#include "virhash.h"
|
2012-01-18 16:10:43 +00:00
|
|
|
#include "virhashcode.h"
|
2013-04-26 09:23:51 +00:00
|
|
|
#include "virstring.h"
|
2013-07-22 15:34:51 +00:00
|
|
|
#include "virsystemd.h"
|
2014-02-14 17:49:01 +00:00
|
|
|
#include "virtypedparam.h"
|
2016-04-13 17:53:02 +00:00
|
|
|
#include "virhostcpu.h"
|
2016-12-06 12:03:29 +00:00
|
|
|
#include "virthread.h"
|
2014-02-14 17:49:02 +00:00
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("util.cgroup");
|
|
|
|
|
2013-04-05 11:48:47 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_CGROUP
|
|
|
|
|
2014-02-14 17:49:01 +00:00
|
|
|
#define CGROUP_NB_TOTAL_CPU_STAT_PARAM 3
|
2014-02-14 17:49:02 +00:00
|
|
|
#define CGROUP_NB_PER_CPU_STAT_PARAM 1
|
2014-02-14 17:49:01 +00:00
|
|
|
|
2019-03-16 18:20:32 +00:00
|
|
|
VIR_ENUM_IMPL(virCgroupController,
|
|
|
|
VIR_CGROUP_CONTROLLER_LAST,
|
2009-09-21 14:31:22 +00:00
|
|
|
"cpu", "cpuacct", "cpuset", "memory", "devices",
|
2013-07-25 18:13:44 +00:00
|
|
|
"freezer", "blkio", "net_cls", "perf_event",
|
2019-01-20 16:30:15 +00:00
|
|
|
"name=systemd",
|
|
|
|
);
|
2009-07-09 13:10:41 +00:00
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2014-07-08 15:34:56 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetDevicePermsString:
|
|
|
|
*
|
|
|
|
* @perms: Bitwise or of VIR_CGROUP_DEVICE permission bits
|
|
|
|
*
|
|
|
|
* Returns string corresponding to the appropriate bits set.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
virCgroupGetDevicePermsString(int perms)
|
|
|
|
{
|
|
|
|
if (perms & VIR_CGROUP_DEVICE_READ) {
|
|
|
|
if (perms & VIR_CGROUP_DEVICE_WRITE) {
|
|
|
|
if (perms & VIR_CGROUP_DEVICE_MKNOD)
|
|
|
|
return "rwm";
|
|
|
|
else
|
|
|
|
return "rw";
|
|
|
|
} else {
|
|
|
|
if (perms & VIR_CGROUP_DEVICE_MKNOD)
|
|
|
|
return "rm";
|
|
|
|
else
|
|
|
|
return "r";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (perms & VIR_CGROUP_DEVICE_WRITE) {
|
|
|
|
if (perms & VIR_CGROUP_DEVICE_MKNOD)
|
|
|
|
return "wm";
|
|
|
|
else
|
|
|
|
return "w";
|
|
|
|
} else {
|
|
|
|
if (perms & VIR_CGROUP_DEVICE_MKNOD)
|
|
|
|
return "m";
|
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-27 10:16:57 +00:00
|
|
|
#ifdef __linux__
|
2013-08-12 19:52:06 +00:00
|
|
|
bool
|
|
|
|
virCgroupAvailable(void)
|
2013-07-04 15:49:24 +00:00
|
|
|
{
|
2018-09-13 14:27:56 +00:00
|
|
|
size_t i;
|
|
|
|
virCgroupBackendPtr *backends = virCgroupBackendGetAll();
|
2013-07-04 15:49:24 +00:00
|
|
|
|
2018-09-13 14:27:56 +00:00
|
|
|
if (!backends)
|
2013-07-04 15:49:24 +00:00
|
|
|
return false;
|
|
|
|
|
2018-09-13 14:27:56 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (backends[i] && backends[i]->available())
|
|
|
|
return true;
|
2013-07-04 15:49:24 +00:00
|
|
|
}
|
|
|
|
|
2018-09-13 14:27:56 +00:00
|
|
|
return false;
|
2013-07-04 15:49:24 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 21:01:30 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virCgroupPartitionNeedsEscaping(const char *path)
|
|
|
|
{
|
|
|
|
FILE *fp = NULL;
|
|
|
|
int ret = 0;
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) line = NULL;
|
2013-08-12 21:01:30 +00:00
|
|
|
size_t buflen;
|
|
|
|
|
|
|
|
/* If it starts with 'cgroup.' or a '_' of any
|
|
|
|
* of the controller names from /proc/cgroups,
|
|
|
|
* then we must prefix a '_'
|
|
|
|
*/
|
|
|
|
if (STRPREFIX(path, "cgroup."))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (path[0] == '_' ||
|
|
|
|
path[0] == '.')
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (!(fp = fopen("/proc/cgroups", "r"))) {
|
|
|
|
/* The API contract is that we return ENXIO
|
|
|
|
* if cgroups are not available on a host */
|
|
|
|
if (errno == ENOENT)
|
|
|
|
errno = ENXIO;
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Cannot open /proc/cgroups"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Data looks like this:
|
|
|
|
* #subsys_name hierarchy num_cgroups enabled
|
|
|
|
* cpuset 2 4 1
|
|
|
|
* cpu 3 48 1
|
|
|
|
* cpuacct 3 48 1
|
|
|
|
* memory 4 4 1
|
|
|
|
* devices 5 4 1
|
|
|
|
* freezer 6 4 1
|
|
|
|
* net_cls 7 1 1
|
|
|
|
*/
|
|
|
|
while (getline(&line, &buflen, fp) > 0) {
|
|
|
|
char *tmp;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
if (STRPREFIX(line, "#subsys_name"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
tmp = strchrnul(line, ' ');
|
|
|
|
*tmp = '\0';
|
|
|
|
len = tmp - line;
|
|
|
|
|
|
|
|
if (STRPREFIX(path, line) &&
|
|
|
|
path[len] == '.') {
|
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ferror(fp)) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Error while reading /proc/cgroups"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-08-12 21:01:30 +00:00
|
|
|
VIR_FORCE_FCLOSE(fp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-14 11:21:19 +00:00
|
|
|
int
|
2013-08-12 21:01:30 +00:00
|
|
|
virCgroupPartitionEscape(char **path)
|
|
|
|
{
|
|
|
|
int rc;
|
2016-06-14 06:02:30 +00:00
|
|
|
char *newstr = NULL;
|
2013-08-12 21:01:30 +00:00
|
|
|
|
|
|
|
if ((rc = virCgroupPartitionNeedsEscaping(*path)) <= 0)
|
|
|
|
return rc;
|
|
|
|
|
2016-06-14 06:02:30 +00:00
|
|
|
if (virAsprintf(&newstr, "_%s", *path) < 0)
|
2013-08-12 21:01:30 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-06-14 06:02:30 +00:00
|
|
|
VIR_FREE(*path);
|
|
|
|
*path = newstr;
|
|
|
|
|
2013-08-12 21:01:30 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2013-07-29 14:55:05 +00:00
|
|
|
|
|
|
|
|
2009-07-09 13:10:41 +00:00
|
|
|
/*
|
|
|
|
* Process /proc/mounts figuring out what controllers are
|
|
|
|
* mounted and where
|
|
|
|
*/
|
2018-09-14 11:17:07 +00:00
|
|
|
static int
|
2018-09-14 10:38:54 +00:00
|
|
|
virCgroupDetectMounts(virCgroupPtr group)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2009-03-16 10:41:37 +00:00
|
|
|
FILE *mounts = NULL;
|
2008-10-03 17:58:02 +00:00
|
|
|
struct mntent entry;
|
|
|
|
char buf[CGROUP_MAX_VAL];
|
2017-07-11 08:46:52 +00:00
|
|
|
int ret = -1;
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2018-09-14 10:38:54 +00:00
|
|
|
mounts = fopen("/proc/mounts", "r");
|
2008-10-03 17:58:02 +00:00
|
|
|
if (mounts == NULL) {
|
2018-09-14 10:38:54 +00:00
|
|
|
virReportSystemError(errno, "%s", _("Unable to open /proc/mounts"));
|
2013-07-04 15:49:24 +00:00
|
|
|
return -1;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
|
2018-09-28 17:53:05 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (group->backends[i] &&
|
|
|
|
group->backends[i]->detectMounts(group,
|
|
|
|
entry.mnt_type,
|
|
|
|
entry.mnt_opts,
|
|
|
|
entry.mnt_dir) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-07-09 13:10:41 +00:00
|
|
|
}
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 08:46:52 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
2010-11-17 02:13:29 +00:00
|
|
|
VIR_FORCE_FCLOSE(mounts);
|
2017-07-11 08:46:52 +00:00
|
|
|
return ret;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 13:10:41 +00:00
|
|
|
|
|
|
|
/*
|
2013-03-22 11:11:34 +00:00
|
|
|
* virCgroupDetectPlacement:
|
|
|
|
* @group: the group to process
|
|
|
|
* @path: the relative path to append, not starting with '/'
|
|
|
|
*
|
2009-07-09 13:10:41 +00:00
|
|
|
* Process /proc/self/cgroup figuring out what cgroup
|
|
|
|
* sub-path the current process is assigned to. ie not
|
2013-03-22 11:11:34 +00:00
|
|
|
* necessarily in the root. The contents of this file
|
|
|
|
* looks like
|
|
|
|
*
|
|
|
|
* 9:perf_event:/
|
|
|
|
* 8:blkio:/
|
|
|
|
* 7:net_cls:/
|
|
|
|
* 6:freezer:/
|
|
|
|
* 5:devices:/
|
|
|
|
* 4:memory:/
|
|
|
|
* 3:cpuacct,cpu:/
|
|
|
|
* 2:cpuset:/
|
|
|
|
* 1:name=systemd:/user/berrange/2
|
|
|
|
*
|
|
|
|
* It then appends @path to each detected path.
|
2008-10-03 17:58:02 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
static int
|
|
|
|
virCgroupDetectPlacement(virCgroupPtr group,
|
|
|
|
pid_t pid,
|
|
|
|
const char *path)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2009-07-09 13:10:41 +00:00
|
|
|
FILE *mapping = NULL;
|
|
|
|
char line[1024];
|
2013-07-04 15:49:24 +00:00
|
|
|
int ret = -1;
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) procfile = NULL;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-07-25 18:13:44 +00:00
|
|
|
VIR_DEBUG("Detecting placement for pid %lld path %s",
|
2016-10-06 14:54:41 +00:00
|
|
|
(long long) pid, path);
|
2013-07-19 10:13:05 +00:00
|
|
|
if (pid == -1) {
|
|
|
|
if (VIR_STRDUP(procfile, "/proc/self/cgroup") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
2016-10-06 14:54:41 +00:00
|
|
|
if (virAsprintf(&procfile, "/proc/%lld/cgroup",
|
|
|
|
(long long) pid) < 0)
|
2013-07-19 10:13:05 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
mapping = fopen(procfile, "r");
|
2009-07-09 13:10:41 +00:00
|
|
|
if (mapping == NULL) {
|
2013-07-19 10:13:05 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Unable to open '%s'"),
|
|
|
|
procfile);
|
|
|
|
goto cleanup;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 13:10:41 +00:00
|
|
|
while (fgets(line, sizeof(line), mapping) != NULL) {
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
2009-07-09 13:10:41 +00:00
|
|
|
char *controllers = strchr(line, ':');
|
2013-03-22 11:11:34 +00:00
|
|
|
char *selfpath = controllers ? strchr(controllers + 1, ':') : NULL;
|
|
|
|
char *nl = selfpath ? strchr(selfpath, '\n') : NULL;
|
2009-07-09 13:10:41 +00:00
|
|
|
|
2013-03-22 11:11:34 +00:00
|
|
|
if (!controllers || !selfpath)
|
2009-07-09 13:10:41 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (nl)
|
|
|
|
*nl = '\0';
|
|
|
|
|
2013-03-22 11:11:34 +00:00
|
|
|
*selfpath = '\0';
|
2009-07-09 13:10:41 +00:00
|
|
|
controllers++;
|
2013-03-22 11:11:34 +00:00
|
|
|
selfpath++;
|
2009-07-09 13:10:41 +00:00
|
|
|
|
2018-09-28 17:53:05 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (group->backends[i] &&
|
|
|
|
group->backends[i]->detectPlacement(group, path, controllers,
|
|
|
|
selfpath) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-07-09 13:10:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
ret = 0;
|
2009-07-09 13:10:41 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2010-11-17 02:13:29 +00:00
|
|
|
VIR_FORCE_FCLOSE(mapping);
|
2013-07-04 15:49:24 +00:00
|
|
|
return ret;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2018-08-15 14:14:12 +00:00
|
|
|
static int
|
|
|
|
virCgroupDetect(virCgroupPtr group,
|
|
|
|
pid_t pid,
|
|
|
|
int controllers,
|
|
|
|
const char *path,
|
|
|
|
virCgroupPtr parent)
|
|
|
|
{
|
2018-09-12 11:47:21 +00:00
|
|
|
size_t i;
|
2018-09-28 17:53:05 +00:00
|
|
|
bool backendAvailable = false;
|
|
|
|
int controllersAvailable = 0;
|
2018-09-12 11:47:21 +00:00
|
|
|
virCgroupBackendPtr *backends = virCgroupBackendGetAll();
|
2018-08-15 14:14:12 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("group=%p controllers=%d path=%s parent=%p",
|
|
|
|
group, controllers, path, parent);
|
|
|
|
|
2018-09-12 11:47:21 +00:00
|
|
|
if (!backends)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (backends[i] && backends[i]->available()) {
|
2018-09-28 17:53:05 +00:00
|
|
|
group->backends[i] = backends[i];
|
|
|
|
backendAvailable = true;
|
2018-09-12 11:47:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-28 17:53:05 +00:00
|
|
|
if (!backendAvailable) {
|
2018-09-12 11:47:21 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("no cgroup backend available"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-08-15 14:14:12 +00:00
|
|
|
if (parent) {
|
2018-09-28 17:53:05 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (group->backends[i] &&
|
|
|
|
group->backends[i]->copyMounts(group, parent) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2018-08-15 14:14:12 +00:00
|
|
|
} else {
|
|
|
|
if (virCgroupDetectMounts(group) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-07-25 18:13:44 +00:00
|
|
|
/* In some cases we can copy part of the placement info
|
|
|
|
* based on the parent cgroup...
|
|
|
|
*/
|
2018-09-28 17:53:05 +00:00
|
|
|
if (parent || path[0] == '/') {
|
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (group->backends[i] &&
|
|
|
|
group->backends[i]->copyPlacement(group, path, parent) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-07-25 18:13:44 +00:00
|
|
|
|
|
|
|
/* ... but use /proc/cgroups to fill in the rest */
|
|
|
|
if (virCgroupDetectPlacement(group, pid, path) < 0)
|
|
|
|
return -1;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
/* Check that for every mounted controller, we found our placement */
|
2018-09-28 17:53:05 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (group->backends[i] &&
|
|
|
|
group->backends[i]->validatePlacement(group, pid) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2019-06-20 11:02:57 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (group->backends[i]) {
|
2019-07-22 12:37:36 +00:00
|
|
|
int rc = group->backends[i]->detectControllers(group, controllers, parent);
|
2019-06-20 11:02:57 +00:00
|
|
|
if (rc < 0)
|
|
|
|
return -1;
|
|
|
|
controllersAvailable |= rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check that at least 1 controller is available */
|
|
|
|
if (controllersAvailable == 0) {
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("At least one cgroup controller is required"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
return 0;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 13:10:41 +00:00
|
|
|
|
2018-08-17 13:30:21 +00:00
|
|
|
char *
|
2015-08-03 12:44:14 +00:00
|
|
|
virCgroupGetBlockDevString(const char *path)
|
|
|
|
{
|
|
|
|
char *ret = NULL;
|
|
|
|
struct stat sb;
|
|
|
|
|
|
|
|
if (stat(path, &sb) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Path '%s' is not accessible"),
|
|
|
|
path);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!S_ISBLK(sb.st_mode)) {
|
|
|
|
virReportSystemError(EINVAL,
|
|
|
|
_("Path '%s' must be a block device"),
|
|
|
|
path);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Automatically append space after the string since all callers
|
|
|
|
* use it anyway */
|
|
|
|
if (virAsprintf(&ret, "%d:%d ", major(sb.st_rdev), minor(sb.st_rdev)) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-18 14:11:47 +00:00
|
|
|
int
|
2019-06-18 13:01:39 +00:00
|
|
|
virCgroupSetValueRaw(const char *path,
|
2013-08-12 19:52:06 +00:00
|
|
|
const char *value)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2019-06-18 13:01:39 +00:00
|
|
|
char *tmp;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2019-06-18 13:01:39 +00:00
|
|
|
VIR_DEBUG("Set value '%s' to '%s'", path, value);
|
|
|
|
if (virFileWriteStr(path, value, 0) < 0) {
|
2013-10-11 13:41:23 +00:00
|
|
|
if (errno == EINVAL &&
|
2019-06-18 13:01:39 +00:00
|
|
|
(tmp = strrchr(path, '/'))) {
|
2013-10-11 13:41:23 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Invalid value '%s' for '%s'"),
|
|
|
|
value, tmp + 1);
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2013-10-11 13:41:23 +00:00
|
|
|
}
|
2013-07-08 10:08:46 +00:00
|
|
|
virReportSystemError(errno,
|
2019-06-18 13:01:39 +00:00
|
|
|
_("Unable to write to '%s'"), path);
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2018-07-24 15:52:10 +00:00
|
|
|
return 0;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2018-09-18 14:11:47 +00:00
|
|
|
int
|
2019-06-18 13:01:39 +00:00
|
|
|
virCgroupGetValueRaw(const char *path,
|
2013-08-12 19:52:06 +00:00
|
|
|
char **value)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2018-07-24 15:52:10 +00:00
|
|
|
int rc;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2009-07-09 13:10:06 +00:00
|
|
|
*value = NULL;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2019-06-18 13:01:39 +00:00
|
|
|
VIR_DEBUG("Get value %s", path);
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2019-06-18 13:01:39 +00:00
|
|
|
if ((rc = virFileReadAll(path, 1024*1024, value)) < 0) {
|
2013-07-08 10:08:46 +00:00
|
|
|
virReportSystemError(errno,
|
2019-06-18 13:01:39 +00:00
|
|
|
_("Unable to read from '%s'"), path);
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
/* Terminated with '\n' has sometimes harmful effects to the caller */
|
|
|
|
if (rc > 0 && (*value)[rc - 1] == '\n')
|
|
|
|
(*value)[rc - 1] = '\0';
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2018-07-24 15:52:10 +00:00
|
|
|
return 0;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2019-06-18 13:01:39 +00:00
|
|
|
int
|
|
|
|
virCgroupSetValueStr(virCgroupPtr group,
|
|
|
|
int controller,
|
|
|
|
const char *key,
|
|
|
|
const char *value)
|
|
|
|
{
|
|
|
|
VIR_AUTOFREE(char *) keypath = NULL;
|
|
|
|
|
|
|
|
if (virCgroupPathOfController(group, controller, key, &keypath) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return virCgroupSetValueRaw(keypath, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetValueStr(virCgroupPtr group,
|
|
|
|
int controller,
|
|
|
|
const char *key,
|
|
|
|
char **value)
|
|
|
|
{
|
|
|
|
VIR_AUTOFREE(char *) keypath = NULL;
|
|
|
|
|
|
|
|
if (virCgroupPathOfController(group, controller, key, &keypath) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return virCgroupGetValueRaw(keypath, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-24 10:20:19 +00:00
|
|
|
int
|
2019-06-18 13:24:41 +00:00
|
|
|
virCgroupGetValueForBlkDev(const char *str,
|
2015-08-03 13:10:20 +00:00
|
|
|
const char *path,
|
|
|
|
char **value)
|
|
|
|
{
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) prefix = NULL;
|
2018-07-30 09:03:16 +00:00
|
|
|
char **lines = NULL;
|
|
|
|
int ret = -1;
|
2015-08-03 13:10:20 +00:00
|
|
|
|
|
|
|
if (!(prefix = virCgroupGetBlockDevString(path)))
|
2018-07-30 09:03:16 +00:00
|
|
|
goto error;
|
2015-08-03 13:10:20 +00:00
|
|
|
|
|
|
|
if (!(lines = virStringSplit(str, "\n", -1)))
|
2018-07-30 09:03:16 +00:00
|
|
|
goto error;
|
2015-08-03 13:10:20 +00:00
|
|
|
|
2016-11-25 08:18:35 +00:00
|
|
|
if (VIR_STRDUP(*value, virStringListGetFirstWithPrefix(lines, prefix)) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto error;
|
2015-08-03 13:10:20 +00:00
|
|
|
|
2018-07-30 09:03:16 +00:00
|
|
|
ret = 0;
|
|
|
|
error:
|
|
|
|
virStringListFree(lines);
|
|
|
|
return ret;
|
2015-08-03 13:10:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-18 14:11:47 +00:00
|
|
|
int
|
2013-08-12 19:52:06 +00:00
|
|
|
virCgroupSetValueU64(virCgroupPtr group,
|
|
|
|
int controller,
|
|
|
|
const char *key,
|
|
|
|
unsigned long long int value)
|
2009-07-09 13:10:06 +00:00
|
|
|
{
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) strval = NULL;
|
2009-07-09 13:10:06 +00:00
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
if (virAsprintf(&strval, "%llu", value) < 0)
|
|
|
|
return -1;
|
2009-07-09 13:10:06 +00:00
|
|
|
|
2018-07-24 15:52:10 +00:00
|
|
|
return virCgroupSetValueStr(group, controller, key, strval);
|
2009-07-09 13:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-24 23:14:36 +00:00
|
|
|
int
|
2013-08-12 19:52:06 +00:00
|
|
|
virCgroupSetValueI64(virCgroupPtr group,
|
|
|
|
int controller,
|
|
|
|
const char *key,
|
|
|
|
long long int value)
|
2008-10-08 16:28:48 +00:00
|
|
|
{
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) strval = NULL;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
if (virAsprintf(&strval, "%lld", value) < 0)
|
|
|
|
return -1;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2018-07-24 15:52:10 +00:00
|
|
|
return virCgroupSetValueStr(group, controller, key, strval);
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2018-08-17 14:22:56 +00:00
|
|
|
int
|
2013-08-12 19:52:06 +00:00
|
|
|
virCgroupGetValueI64(virCgroupPtr group,
|
|
|
|
int controller,
|
|
|
|
const char *key,
|
|
|
|
long long int *value)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) strval = NULL;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
if (virCgroupGetValueStr(group, controller, key, &strval) < 0)
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
if (virStrToLong_ll(strval, NULL, 10, value) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to parse '%s' as an integer"),
|
|
|
|
strval);
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2013-07-08 10:08:46 +00:00
|
|
|
}
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2018-07-24 15:52:10 +00:00
|
|
|
return 0;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2018-09-18 14:11:47 +00:00
|
|
|
int
|
2013-08-12 19:52:06 +00:00
|
|
|
virCgroupGetValueU64(virCgroupPtr group,
|
|
|
|
int controller,
|
|
|
|
const char *key,
|
|
|
|
unsigned long long int *value)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) strval = NULL;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
if (virCgroupGetValueStr(group, controller, key, &strval) < 0)
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
if (virStrToLong_ull(strval, NULL, 10, value) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to parse '%s' as an integer"),
|
|
|
|
strval);
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2013-07-08 10:08:46 +00:00
|
|
|
}
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2018-07-24 15:52:10 +00:00
|
|
|
return 0;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
static int
|
|
|
|
virCgroupMakeGroup(virCgroupPtr parent,
|
|
|
|
virCgroupPtr group,
|
|
|
|
bool create,
|
|
|
|
unsigned int flags)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (group->backends[i] &&
|
|
|
|
group->backends[i]->makeGroup(parent, group, create, flags) < 0) {
|
|
|
|
virCgroupRemove(group);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2018-07-24 15:52:10 +00:00
|
|
|
return 0;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 13:10:41 +00:00
|
|
|
|
2013-03-22 11:11:34 +00:00
|
|
|
/**
|
|
|
|
* virCgroupNew:
|
|
|
|
* @path: path for the new group
|
|
|
|
* @parent: parent group, or NULL
|
|
|
|
* @controllers: bitmask of controllers to activate
|
|
|
|
*
|
|
|
|
* Create a new cgroup storing it in @group.
|
|
|
|
*
|
|
|
|
* If @path starts with a '/' it is treated as an
|
|
|
|
* absolute path, and @parent is ignored. Otherwise
|
|
|
|
* it is treated as being relative to @parent. If
|
|
|
|
* @parent is NULL, then the placement of the current
|
|
|
|
* process is used.
|
|
|
|
*
|
2013-07-04 15:49:24 +00:00
|
|
|
* Returns 0 on success, -1 on error
|
2013-03-22 11:11:34 +00:00
|
|
|
*/
|
2018-08-17 14:18:38 +00:00
|
|
|
int
|
2013-08-12 19:52:06 +00:00
|
|
|
virCgroupNew(pid_t pid,
|
|
|
|
const char *path,
|
|
|
|
virCgroupPtr parent,
|
|
|
|
int controllers,
|
|
|
|
virCgroupPtr *group)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2015-03-27 10:29:25 +00:00
|
|
|
VIR_DEBUG("pid=%lld path=%s parent=%p controllers=%d group=%p",
|
|
|
|
(long long) pid, path, parent, controllers, group);
|
2009-07-09 13:10:41 +00:00
|
|
|
*group = NULL;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
if (VIR_ALLOC((*group)) < 0)
|
|
|
|
goto error;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-03-22 11:11:34 +00:00
|
|
|
if (path[0] == '/' || !parent) {
|
2013-07-04 15:49:24 +00:00
|
|
|
if (VIR_STRDUP((*group)->path, path) < 0)
|
|
|
|
goto error;
|
2013-03-22 11:11:34 +00:00
|
|
|
} else {
|
|
|
|
if (virAsprintf(&(*group)->path, "%s%s%s",
|
|
|
|
parent->path,
|
|
|
|
STREQ(parent->path, "") ? "" : "/",
|
2013-07-04 15:49:24 +00:00
|
|
|
path) < 0)
|
|
|
|
goto error;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2013-07-19 10:13:05 +00:00
|
|
|
if (virCgroupDetect(*group, pid, controllers, path, parent) < 0)
|
2013-07-04 15:49:24 +00:00
|
|
|
goto error;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
error:
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(group);
|
2009-07-09 13:10:41 +00:00
|
|
|
*group = NULL;
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
return -1;
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
2009-07-10 10:40:04 +00:00
|
|
|
|
2013-03-21 13:27:13 +00:00
|
|
|
|
2018-09-28 17:53:05 +00:00
|
|
|
static int
|
|
|
|
virCgroupAddTaskInternal(virCgroupPtr group,
|
|
|
|
pid_t pid,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (group->backends[i] &&
|
|
|
|
group->backends[i]->addTask(group, pid, flags) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-05 15:26:00 +00:00
|
|
|
/**
|
2018-09-11 13:03:22 +00:00
|
|
|
* virCgroupAddProcess:
|
2017-01-05 15:26:00 +00:00
|
|
|
*
|
2018-09-11 13:03:22 +00:00
|
|
|
* @group: The cgroup to add a process to
|
|
|
|
* @pid: The pid of the process to add
|
2017-01-05 15:26:00 +00:00
|
|
|
*
|
2018-09-11 13:03:22 +00:00
|
|
|
* Will add the process to all controllers, except the
|
2017-01-05 15:26:00 +00:00
|
|
|
* systemd unit controller.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
2018-09-11 13:03:22 +00:00
|
|
|
virCgroupAddProcess(virCgroupPtr group, pid_t pid)
|
2017-01-05 15:26:00 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
return virCgroupAddTaskInternal(group, pid, VIR_CGROUP_TASK_PROCESS);
|
2017-01-05 15:26:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-09-11 13:03:22 +00:00
|
|
|
* virCgroupAddMachineProcess:
|
2017-01-05 15:26:00 +00:00
|
|
|
*
|
2018-09-11 13:03:22 +00:00
|
|
|
* @group: The cgroup to add a process to
|
|
|
|
* @pid: The pid of the process to add
|
2017-01-05 15:26:00 +00:00
|
|
|
*
|
2018-09-11 13:03:22 +00:00
|
|
|
* Will add the process to all controllers, including the
|
2017-01-05 15:26:00 +00:00
|
|
|
* systemd unit controller.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
2018-09-11 13:03:22 +00:00
|
|
|
virCgroupAddMachineProcess(virCgroupPtr group, pid_t pid)
|
2017-01-05 15:26:00 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
return virCgroupAddTaskInternal(group, pid,
|
|
|
|
VIR_CGROUP_TASK_PROCESS |
|
|
|
|
VIR_CGROUP_TASK_SYSTEMD);
|
2017-01-05 15:26:00 +00:00
|
|
|
}
|
|
|
|
|
2018-09-24 22:54:04 +00:00
|
|
|
/**
|
|
|
|
* virCgroupAddThread:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to add a thread to
|
|
|
|
* @pid: The pid of the thread to add
|
|
|
|
*
|
|
|
|
* Will add the thread to all controllers, except the
|
|
|
|
* systemd unit controller.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupAddThread(virCgroupPtr group,
|
|
|
|
pid_t pid)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
return virCgroupAddTaskInternal(group, pid, VIR_CGROUP_TASK_THREAD);
|
2018-09-24 22:54:04 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virCgroupSetPartitionSuffix(const char *path, char **res)
|
2013-04-26 09:23:51 +00:00
|
|
|
{
|
2018-07-30 09:03:16 +00:00
|
|
|
char **tokens;
|
2013-04-26 09:23:51 +00:00
|
|
|
size_t i;
|
2018-07-30 09:03:16 +00:00
|
|
|
int ret = -1;
|
2013-04-26 09:23:51 +00:00
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
if (!(tokens = virStringSplit(path, "/", 0)))
|
2018-07-30 09:03:16 +00:00
|
|
|
return ret;
|
2013-04-26 09:23:51 +00:00
|
|
|
|
2013-05-21 07:58:16 +00:00
|
|
|
for (i = 0; tokens[i] != NULL; i++) {
|
2013-04-26 09:23:51 +00:00
|
|
|
/* Whitelist the 3 top level fixed dirs
|
|
|
|
* NB i == 0 is "", since we have leading '/'
|
|
|
|
*/
|
|
|
|
if (i == 1 &&
|
|
|
|
(STREQ(tokens[i], "machine") ||
|
|
|
|
STREQ(tokens[i], "system") ||
|
|
|
|
STREQ(tokens[i], "user"))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* If there is no suffix set already, then
|
|
|
|
* add ".partition"
|
|
|
|
*/
|
|
|
|
if (STRNEQ(tokens[i], "") &&
|
|
|
|
!strchr(tokens[i], '.')) {
|
|
|
|
if (VIR_REALLOC_N(tokens[i],
|
2013-07-04 15:49:24 +00:00
|
|
|
strlen(tokens[i]) + strlen(".partition") + 1) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2013-04-26 09:23:51 +00:00
|
|
|
strcat(tokens[i], ".partition");
|
|
|
|
}
|
2013-04-26 09:50:24 +00:00
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
if (virCgroupPartitionEscape(&(tokens[i])) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2013-04-26 09:23:51 +00:00
|
|
|
}
|
|
|
|
|
2016-11-25 08:18:35 +00:00
|
|
|
if (!(*res = virStringListJoin((const char **)tokens, "/")))
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2013-04-26 09:23:51 +00:00
|
|
|
|
2018-07-30 09:03:16 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virStringListFree(tokens);
|
|
|
|
return ret;
|
2013-04-26 09:23:51 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2013-03-28 18:08:39 +00:00
|
|
|
/**
|
|
|
|
* virCgroupNewPartition:
|
|
|
|
* @path: path for the partition
|
|
|
|
* @create: true to create the cgroup tree
|
|
|
|
* @controllers: mask of controllers to create
|
|
|
|
*
|
|
|
|
* Creates a new cgroup to represent the resource
|
2015-03-27 10:24:16 +00:00
|
|
|
* partition path identified by @path.
|
2013-03-28 18:08:39 +00:00
|
|
|
*
|
2013-07-04 15:49:24 +00:00
|
|
|
* Returns 0 on success, -1 on failure
|
2013-03-28 18:08:39 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupNewPartition(const char *path,
|
|
|
|
bool create,
|
|
|
|
int controllers,
|
|
|
|
virCgroupPtr *group)
|
2013-03-28 18:08:39 +00:00
|
|
|
{
|
2018-07-30 09:03:16 +00:00
|
|
|
int ret = -1;
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) parentPath = NULL;
|
|
|
|
VIR_AUTOFREE(char *) newPath = NULL;
|
2018-07-30 09:03:16 +00:00
|
|
|
virCgroupPtr parent = NULL;
|
2013-03-28 18:08:39 +00:00
|
|
|
VIR_DEBUG("path=%s create=%d controllers=%x",
|
|
|
|
path, create, controllers);
|
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
if (path[0] != '/') {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Partition path '%s' must start with '/'"),
|
|
|
|
path);
|
|
|
|
return -1;
|
|
|
|
}
|
2013-03-28 18:08:39 +00:00
|
|
|
|
2013-12-06 03:38:14 +00:00
|
|
|
if (virCgroupSetPartitionSuffix(path, &newPath) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2013-04-26 09:23:51 +00:00
|
|
|
|
2018-07-30 09:03:16 +00:00
|
|
|
if (virCgroupNew(-1, newPath, NULL, controllers, group) < 0)
|
|
|
|
goto cleanup;
|
2013-03-28 18:08:39 +00:00
|
|
|
|
2013-12-06 03:38:14 +00:00
|
|
|
if (STRNEQ(newPath, "/")) {
|
2013-03-28 18:08:39 +00:00
|
|
|
char *tmp;
|
2013-12-06 03:38:14 +00:00
|
|
|
if (VIR_STRDUP(parentPath, newPath) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2013-03-28 18:08:39 +00:00
|
|
|
|
|
|
|
tmp = strrchr(parentPath, '/');
|
|
|
|
tmp++;
|
|
|
|
*tmp = '\0';
|
|
|
|
|
2013-07-19 10:13:05 +00:00
|
|
|
if (virCgroupNew(-1, parentPath, NULL, controllers, &parent) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2013-03-28 18:08:39 +00:00
|
|
|
|
2018-08-17 13:00:44 +00:00
|
|
|
if (virCgroupMakeGroup(parent, *group, create, VIR_CGROUP_NONE) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2013-03-28 18:08:39 +00:00
|
|
|
}
|
|
|
|
|
2018-07-30 09:03:16 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
if (ret != 0)
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(group);
|
|
|
|
virCgroupFree(&parent);
|
2018-07-30 09:03:16 +00:00
|
|
|
return ret;
|
2013-03-28 18:08:39 +00:00
|
|
|
}
|
|
|
|
|
2008-10-03 17:58:02 +00:00
|
|
|
|
2012-11-12 07:02:26 +00:00
|
|
|
/**
|
2013-03-28 16:33:22 +00:00
|
|
|
* virCgroupNewSelf:
|
2012-11-12 07:02:26 +00:00
|
|
|
*
|
|
|
|
* @group: Pointer to returned virCgroupPtr
|
|
|
|
*
|
2013-03-21 11:53:14 +00:00
|
|
|
* Obtain a cgroup representing the config of the
|
|
|
|
* current process
|
|
|
|
*
|
2013-07-04 15:49:24 +00:00
|
|
|
* Returns 0 on success, or -1 on error
|
2012-11-12 07:02:26 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupNewSelf(virCgroupPtr *group)
|
2012-11-12 07:02:26 +00:00
|
|
|
{
|
2013-07-24 16:31:25 +00:00
|
|
|
return virCgroupNewDetect(-1, -1, group);
|
2012-11-12 07:02:26 +00:00
|
|
|
}
|
2013-07-19 10:13:05 +00:00
|
|
|
|
2009-07-10 10:40:04 +00:00
|
|
|
|
2013-03-28 18:08:39 +00:00
|
|
|
/**
|
|
|
|
* virCgroupNewDomainPartition:
|
|
|
|
*
|
|
|
|
* @partition: partition holding the domain
|
|
|
|
* @driver: name of the driver
|
|
|
|
* @name: name of the domain
|
|
|
|
* @group: Pointer to returned virCgroupPtr
|
|
|
|
*
|
2013-07-04 15:49:24 +00:00
|
|
|
* Returns 0 on success, or -1 on error
|
2013-03-28 18:08:39 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupNewDomainPartition(virCgroupPtr partition,
|
|
|
|
const char *driver,
|
|
|
|
const char *name,
|
|
|
|
bool create,
|
|
|
|
virCgroupPtr *group)
|
2013-03-28 18:08:39 +00:00
|
|
|
{
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *)grpname = NULL;
|
2013-03-28 18:08:39 +00:00
|
|
|
|
2013-04-26 08:52:47 +00:00
|
|
|
if (virAsprintf(&grpname, "%s.libvirt-%s",
|
2013-03-28 18:08:39 +00:00
|
|
|
name, driver) < 0)
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2013-03-28 18:08:39 +00:00
|
|
|
|
2013-07-04 15:49:24 +00:00
|
|
|
if (virCgroupPartitionEscape(&grpname) < 0)
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2013-04-26 09:50:24 +00:00
|
|
|
|
2013-07-19 10:13:05 +00:00
|
|
|
if (virCgroupNew(-1, grpname, partition, -1, group) < 0)
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2013-07-04 15:49:24 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a cgroup with memory.use_hierarchy enabled to
|
|
|
|
* surely account memory usage of lxc with ns subsystem
|
|
|
|
* enabled. (To be exact, memory and ns subsystems are
|
|
|
|
* enabled at the same time.)
|
|
|
|
*
|
|
|
|
* The reason why doing it here, not a upper group, say
|
|
|
|
* a group for driver, is to avoid overhead to track
|
|
|
|
* cumulative usage that we don't need.
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
if (virCgroupMakeGroup(partition, *group, create,
|
|
|
|
VIR_CGROUP_MEM_HIERACHY) < 0) {
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(group);
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2013-03-28 18:08:39 +00:00
|
|
|
}
|
|
|
|
|
2018-07-24 15:52:10 +00:00
|
|
|
return 0;
|
2013-03-28 18:08:39 +00:00
|
|
|
}
|
2009-07-10 10:40:04 +00:00
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2015-04-07 12:28:05 +00:00
|
|
|
/**
|
|
|
|
* virCgroupNewThread:
|
|
|
|
*
|
|
|
|
* @domain: group for the domain
|
|
|
|
* @name: enum to generate the name for the new thread
|
|
|
|
* @id: id of the vcpu or iothread
|
|
|
|
* @create: true to create if not already existing
|
|
|
|
* @group: Pointer to returned virCgroupPtr
|
|
|
|
*
|
|
|
|
* Returns 0 on success, or -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupNewThread(virCgroupPtr domain,
|
|
|
|
virCgroupThreadName nameval,
|
|
|
|
int id,
|
|
|
|
bool create,
|
|
|
|
virCgroupPtr *group)
|
|
|
|
{
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) name = NULL;
|
2015-04-07 12:28:05 +00:00
|
|
|
int controllers;
|
|
|
|
|
|
|
|
switch (nameval) {
|
|
|
|
case VIR_CGROUP_THREAD_VCPU:
|
|
|
|
if (virAsprintf(&name, "vcpu%d", id) < 0)
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2015-04-07 12:28:05 +00:00
|
|
|
break;
|
|
|
|
case VIR_CGROUP_THREAD_EMULATOR:
|
|
|
|
if (VIR_STRDUP(name, "emulator") < 0)
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2015-04-07 12:28:05 +00:00
|
|
|
break;
|
|
|
|
case VIR_CGROUP_THREAD_IOTHREAD:
|
|
|
|
if (virAsprintf(&name, "iothread%d", id) < 0)
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2015-04-07 12:28:05 +00:00
|
|
|
break;
|
|
|
|
case VIR_CGROUP_THREAD_LAST:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected name value %d"), nameval);
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2015-04-07 12:28:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
controllers = ((1 << VIR_CGROUP_CONTROLLER_CPU) |
|
|
|
|
(1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
|
|
|
|
(1 << VIR_CGROUP_CONTROLLER_CPUSET));
|
|
|
|
|
|
|
|
if (virCgroupNew(-1, name, domain, controllers, group) < 0)
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2015-04-07 12:28:05 +00:00
|
|
|
|
2018-09-18 15:49:19 +00:00
|
|
|
if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_THREAD) < 0) {
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(group);
|
2018-07-24 15:52:10 +00:00
|
|
|
return -1;
|
2015-04-07 12:28:05 +00:00
|
|
|
}
|
|
|
|
|
2018-07-24 15:52:10 +00:00
|
|
|
return 0;
|
2015-04-07 12:28:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupNewDetect(pid_t pid,
|
|
|
|
int controllers,
|
|
|
|
virCgroupPtr *group)
|
2013-07-19 10:13:05 +00:00
|
|
|
{
|
2013-07-24 16:31:25 +00:00
|
|
|
return virCgroupNew(pid, "", NULL, controllers, group);
|
2013-07-19 10:13:05 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2013-07-24 16:36:42 +00:00
|
|
|
/*
|
|
|
|
* Returns 0 on success (but @group may be NULL), -1 on fatal error
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupNewDetectMachine(const char *name,
|
|
|
|
const char *drivername,
|
|
|
|
pid_t pid,
|
|
|
|
int controllers,
|
2017-07-21 13:51:03 +00:00
|
|
|
char *machinename,
|
2013-08-12 19:52:06 +00:00
|
|
|
virCgroupPtr *group)
|
2013-07-24 16:36:42 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
|
|
|
|
2013-07-24 16:31:25 +00:00
|
|
|
if (virCgroupNewDetect(pid, controllers, group) < 0) {
|
2013-07-24 16:36:42 +00:00
|
|
|
if (virCgroupNewIgnoreError())
|
|
|
|
return 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-09-28 17:53:05 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if ((*group)->backends[i] &&
|
|
|
|
!(*group)->backends[i]->validateMachineGroup(*group, name,
|
|
|
|
drivername,
|
|
|
|
machinename)) {
|
|
|
|
VIR_DEBUG("Failed to validate machine name for '%s' driver '%s'",
|
|
|
|
name, drivername);
|
|
|
|
virCgroupFree(group);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-07-24 16:36:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2018-07-31 10:09:40 +00:00
|
|
|
static int
|
|
|
|
virCgroupEnableMissingControllers(char *path,
|
|
|
|
pid_t pidleader,
|
|
|
|
int controllers,
|
|
|
|
virCgroupPtr *group)
|
|
|
|
{
|
|
|
|
virCgroupPtr parent = NULL;
|
|
|
|
char *offset = path;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (virCgroupNew(pidleader,
|
2018-09-10 13:43:42 +00:00
|
|
|
"/",
|
2018-07-31 10:09:40 +00:00
|
|
|
NULL,
|
|
|
|
controllers,
|
|
|
|
&parent) < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
virCgroupPtr tmp;
|
|
|
|
char *t = strchr(offset + 1, '/');
|
|
|
|
if (t)
|
|
|
|
*t = '\0';
|
|
|
|
|
|
|
|
if (virCgroupNew(pidleader,
|
|
|
|
path,
|
|
|
|
parent,
|
|
|
|
controllers,
|
|
|
|
&tmp) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-06-27 12:54:54 +00:00
|
|
|
if (virCgroupMakeGroup(parent, tmp, true, VIR_CGROUP_SYSTEMD) < 0) {
|
2018-07-31 10:09:40 +00:00
|
|
|
virCgroupFree(&tmp);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (t) {
|
|
|
|
*t = '/';
|
|
|
|
offset = t;
|
|
|
|
virCgroupFree(&parent);
|
|
|
|
parent = tmp;
|
|
|
|
} else {
|
|
|
|
*group = tmp;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virCgroupFree(&parent);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-22 15:34:51 +00:00
|
|
|
/*
|
|
|
|
* Returns 0 on success, -1 on fatal error, -2 on systemd not available
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virCgroupNewMachineSystemd(const char *name,
|
|
|
|
const char *drivername,
|
|
|
|
const unsigned char *uuid,
|
|
|
|
const char *rootdir,
|
|
|
|
pid_t pidleader,
|
|
|
|
bool isContainer,
|
2014-11-11 17:38:43 +00:00
|
|
|
size_t nnicindexes,
|
|
|
|
int *nicindexes,
|
2013-07-22 15:34:51 +00:00
|
|
|
const char *partition,
|
|
|
|
int controllers,
|
2019-05-22 23:12:14 +00:00
|
|
|
unsigned int maxthreads,
|
2013-07-22 15:34:51 +00:00
|
|
|
virCgroupPtr *group)
|
2013-07-18 15:55:37 +00:00
|
|
|
{
|
2013-07-22 15:34:51 +00:00
|
|
|
int rv;
|
2018-07-31 10:09:40 +00:00
|
|
|
virCgroupPtr init;
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) path = NULL;
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
2013-07-22 15:34:51 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Trying to setup machine '%s' via systemd", name);
|
|
|
|
if ((rv = virSystemdCreateMachine(name,
|
|
|
|
drivername,
|
|
|
|
uuid,
|
|
|
|
rootdir,
|
|
|
|
pidleader,
|
|
|
|
isContainer,
|
2014-11-11 17:38:43 +00:00
|
|
|
nnicindexes,
|
|
|
|
nicindexes,
|
2019-05-22 23:12:14 +00:00
|
|
|
partition,
|
|
|
|
maxthreads)) < 0)
|
2013-07-22 15:34:51 +00:00
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (controllers != -1)
|
|
|
|
controllers |= (1 << VIR_CGROUP_CONTROLLER_SYSTEMD);
|
|
|
|
|
|
|
|
VIR_DEBUG("Detecting systemd placement");
|
|
|
|
if (virCgroupNewDetect(pidleader,
|
|
|
|
controllers,
|
|
|
|
&init) < 0)
|
|
|
|
return -1;
|
2013-07-18 15:55:37 +00:00
|
|
|
|
2018-09-28 17:53:05 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (init->backends[i] &&
|
|
|
|
(path = init->backends[i]->stealPlacement(init))) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(&init);
|
2013-07-22 15:34:51 +00:00
|
|
|
|
|
|
|
if (!path || STREQ(path, "/") || path[0] != '/') {
|
|
|
|
VIR_DEBUG("Systemd didn't setup its controller");
|
2018-07-31 10:09:40 +00:00
|
|
|
return -2;
|
2013-07-22 15:34:51 +00:00
|
|
|
}
|
|
|
|
|
2018-07-31 10:09:40 +00:00
|
|
|
if (virCgroupEnableMissingControllers(path, pidleader,
|
|
|
|
controllers, group) < 0) {
|
2018-09-27 14:11:19 +00:00
|
|
|
return -1;
|
2013-07-22 15:34:51 +00:00
|
|
|
}
|
|
|
|
|
2018-09-27 14:11:19 +00:00
|
|
|
if (virCgroupAddProcess(*group, pidleader) < 0) {
|
|
|
|
virErrorPtr saved = virSaveLastError();
|
|
|
|
virCgroupRemove(*group);
|
|
|
|
virCgroupFree(group);
|
|
|
|
if (saved) {
|
|
|
|
virSetError(saved);
|
|
|
|
virFreeError(saved);
|
|
|
|
}
|
2018-09-10 12:46:24 +00:00
|
|
|
}
|
|
|
|
|
2018-09-27 14:11:19 +00:00
|
|
|
return 0;
|
2013-07-22 15:34:51 +00:00
|
|
|
}
|
2013-07-18 15:55:37 +00:00
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2014-09-25 11:32:58 +00:00
|
|
|
/*
|
|
|
|
* Returns 0 on success, -1 on fatal error
|
|
|
|
*/
|
2016-02-01 15:50:54 +00:00
|
|
|
int virCgroupTerminateMachine(const char *name)
|
2014-09-25 11:32:58 +00:00
|
|
|
{
|
2016-02-01 15:50:54 +00:00
|
|
|
return virSystemdTerminateMachine(name);
|
2014-09-25 11:32:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-22 15:34:51 +00:00
|
|
|
static int
|
|
|
|
virCgroupNewMachineManual(const char *name,
|
|
|
|
const char *drivername,
|
2016-01-14 16:00:25 +00:00
|
|
|
pid_t pidleader,
|
2013-07-22 15:34:51 +00:00
|
|
|
const char *partition,
|
|
|
|
int controllers,
|
|
|
|
virCgroupPtr *group)
|
|
|
|
{
|
2018-07-30 09:03:16 +00:00
|
|
|
virCgroupPtr parent = NULL;
|
|
|
|
int ret = -1;
|
2013-07-22 15:34:51 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Fallback to non-systemd setup");
|
2013-07-18 15:55:37 +00:00
|
|
|
if (virCgroupNewPartition(partition,
|
|
|
|
STREQ(partition, "/machine"),
|
|
|
|
controllers,
|
|
|
|
&parent) < 0) {
|
|
|
|
if (virCgroupNewIgnoreError())
|
2018-07-30 09:03:16 +00:00
|
|
|
goto done;
|
2013-07-18 15:55:37 +00:00
|
|
|
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2013-07-18 15:55:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virCgroupNewDomainPartition(parent,
|
|
|
|
drivername,
|
|
|
|
name,
|
|
|
|
true,
|
|
|
|
group) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2013-07-18 15:55:37 +00:00
|
|
|
|
2018-09-11 13:03:22 +00:00
|
|
|
if (virCgroupAddProcess(*group, pidleader) < 0) {
|
2016-01-14 16:00:25 +00:00
|
|
|
virErrorPtr saved = virSaveLastError();
|
|
|
|
virCgroupRemove(*group);
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(group);
|
2016-01-14 16:00:25 +00:00
|
|
|
if (saved) {
|
|
|
|
virSetError(saved);
|
|
|
|
virFreeError(saved);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-30 09:03:16 +00:00
|
|
|
done:
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(&parent);
|
2018-07-30 09:03:16 +00:00
|
|
|
return ret;
|
2013-07-18 15:55:37 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupNewMachine(const char *name,
|
|
|
|
const char *drivername,
|
|
|
|
const unsigned char *uuid,
|
|
|
|
const char *rootdir,
|
|
|
|
pid_t pidleader,
|
|
|
|
bool isContainer,
|
2014-11-11 17:38:43 +00:00
|
|
|
size_t nnicindexes,
|
|
|
|
int *nicindexes,
|
2013-08-12 19:52:06 +00:00
|
|
|
const char *partition,
|
|
|
|
int controllers,
|
2019-05-22 23:12:14 +00:00
|
|
|
unsigned int maxthreads,
|
2013-08-12 19:52:06 +00:00
|
|
|
virCgroupPtr *group)
|
2013-07-22 15:34:51 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
*group = NULL;
|
|
|
|
|
|
|
|
if ((rv = virCgroupNewMachineSystemd(name,
|
|
|
|
drivername,
|
|
|
|
uuid,
|
|
|
|
rootdir,
|
|
|
|
pidleader,
|
|
|
|
isContainer,
|
2014-11-11 17:38:43 +00:00
|
|
|
nnicindexes,
|
|
|
|
nicindexes,
|
2013-07-22 15:34:51 +00:00
|
|
|
partition,
|
|
|
|
controllers,
|
2019-05-22 23:12:14 +00:00
|
|
|
maxthreads,
|
2013-07-22 15:34:51 +00:00
|
|
|
group)) == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (rv == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return virCgroupNewMachineManual(name,
|
|
|
|
drivername,
|
2016-01-14 16:00:25 +00:00
|
|
|
pidleader,
|
2013-07-22 15:34:51 +00:00
|
|
|
partition,
|
|
|
|
controllers,
|
|
|
|
group);
|
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
virCgroupNewIgnoreError(void)
|
2013-07-04 15:49:24 +00:00
|
|
|
{
|
|
|
|
if (virLastErrorIsSystemErrno(ENXIO) ||
|
|
|
|
virLastErrorIsSystemErrno(EPERM) ||
|
|
|
|
virLastErrorIsSystemErrno(EACCES)) {
|
|
|
|
virResetLastError();
|
|
|
|
VIR_DEBUG("No cgroups present/configured/accessible, ignoring error");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2013-08-12 21:20:59 +00:00
|
|
|
/**
|
|
|
|
* virCgroupHasController: query whether a cgroup controller is present
|
|
|
|
*
|
|
|
|
* @cgroup: The group structure to be queried, or NULL
|
|
|
|
* @controller: cgroup subsystem id
|
|
|
|
*
|
|
|
|
* Returns true if a cgroup controller is mounted and is associated
|
|
|
|
* with this cgroup object.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
virCgroupHasController(virCgroupPtr cgroup, int controller)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
|
|
|
|
2013-08-12 21:20:59 +00:00
|
|
|
if (!cgroup)
|
|
|
|
return false;
|
|
|
|
if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST)
|
|
|
|
return false;
|
2018-08-19 17:17:27 +00:00
|
|
|
|
2018-09-28 17:53:05 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (cgroup->backends[i] &&
|
|
|
|
cgroup->backends[i]->hasController(cgroup, controller)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2013-08-12 21:20:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupPathOfController(virCgroupPtr group,
|
2018-08-15 15:21:47 +00:00
|
|
|
unsigned int controller,
|
2013-08-12 21:20:59 +00:00
|
|
|
const char *key,
|
|
|
|
char **path)
|
|
|
|
{
|
2018-08-15 15:21:47 +00:00
|
|
|
if (controller >= VIR_CGROUP_CONTROLLER_LAST) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Invalid controller id '%d'"), controller);
|
2013-08-12 21:20:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, controller, pathOfController, -1,
|
|
|
|
controller, key, path);
|
2013-08-12 21:20:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-14 17:48:59 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetBlkioIoServiced:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get throughput for
|
|
|
|
* @bytes_read: Pointer to returned bytes read
|
|
|
|
* @bytes_write: Pointer to returned bytes written
|
|
|
|
* @requests_read: Pointer to returned read io ops
|
|
|
|
* @requests_write: Pointer to returned write io ops
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioIoServiced(virCgroupPtr group,
|
|
|
|
long long *bytes_read,
|
|
|
|
long long *bytes_write,
|
|
|
|
long long *requests_read,
|
|
|
|
long long *requests_write)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
getBlkioIoServiced, -1,
|
2018-08-17 13:29:39 +00:00
|
|
|
bytes_read, bytes_write,
|
|
|
|
requests_read, requests_write);
|
2014-02-14 17:48:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupGetBlkioIoDeviceServiced:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get throughput for
|
|
|
|
* @path: The device to get throughput for
|
|
|
|
* @bytes_read: Pointer to returned bytes read
|
|
|
|
* @bytes_write: Pointer to returned bytes written
|
|
|
|
* @requests_read: Pointer to returned read io ops
|
|
|
|
* @requests_write: Pointer to returned write io ops
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
long long *bytes_read,
|
|
|
|
long long *bytes_write,
|
|
|
|
long long *requests_read,
|
|
|
|
long long *requests_write)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
getBlkioIoDeviceServiced, -1,
|
2018-08-17 13:30:21 +00:00
|
|
|
path, bytes_read, bytes_write,
|
|
|
|
requests_read, requests_write);
|
2014-02-14 17:48:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-08 06:56:39 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetBlkioWeight:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to change io weight for
|
|
|
|
* @weight: The Weight for this cgroup
|
|
|
|
*
|
2013-07-08 10:08:46 +00:00
|
|
|
* Returns: 0 on success, -1 on error
|
2011-02-08 06:56:39 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight)
|
2011-02-08 06:56:39 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
setBlkioWeight, -1, weight);
|
2011-02-08 06:56:39 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2011-02-08 06:56:39 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetBlkioWeight:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get weight for
|
|
|
|
* @Weight: Pointer to returned weight
|
|
|
|
*
|
2013-07-08 10:08:46 +00:00
|
|
|
* Returns: 0 on success, -1 on error
|
2011-02-08 06:56:39 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight)
|
2011-02-08 06:56:39 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
getBlkioWeight, -1, weight);
|
2011-02-08 06:56:39 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 08:29:50 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetBlkioDeviceReadIops:
|
|
|
|
* @group: The cgroup to change block io setting for
|
|
|
|
* @path: The path of device
|
|
|
|
* @riops: The new device read iops throttle, or 0 to clear
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceReadIops(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned int riops)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
setBlkioDeviceReadIops, -1, path, riops);
|
2013-12-11 08:29:50 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2011-11-08 11:00:34 +00:00
|
|
|
/**
|
2013-12-11 08:29:50 +00:00
|
|
|
* virCgroupSetBlkioDeviceWriteIops:
|
|
|
|
* @group: The cgroup to change block io setting for
|
|
|
|
* @path: The path of device
|
|
|
|
* @wiops: The new device write iops throttle, or 0 to clear
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned int wiops)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
setBlkioDeviceWriteIops, -1, path, wiops);
|
2013-12-11 08:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupSetBlkioDeviceReadBps:
|
|
|
|
* @group: The cgroup to change block io setting for
|
|
|
|
* @path: The path of device
|
|
|
|
* @rbps: The new device read bps throttle, or 0 to clear
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceReadBps(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned long long rbps)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
setBlkioDeviceReadBps, -1, path, rbps);
|
2013-12-11 08:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupSetBlkioDeviceWriteBps:
|
|
|
|
* @group: The cgroup to change block io setting for
|
|
|
|
* @path: The path of device
|
|
|
|
* @wbps: The new device write bps throttle, or 0 to clear
|
2011-11-08 11:00:34 +00:00
|
|
|
*
|
2013-12-11 08:29:50 +00:00
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned long long wbps)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
setBlkioDeviceWriteBps, -1, path, wbps);
|
2013-12-11 08:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupSetBlkioDeviceWeight:
|
|
|
|
* @group: The cgroup to change block io setting for
|
|
|
|
* @path: The path of device
|
2013-10-11 13:41:23 +00:00
|
|
|
* @weight: The new device weight (100-1000),
|
|
|
|
* (10-1000) after kernel 2.6.39, or 0 to clear
|
2011-11-08 11:00:34 +00:00
|
|
|
*
|
2013-07-08 10:08:46 +00:00
|
|
|
* Returns: 0 on success, -1 on error
|
2011-11-08 11:00:34 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned int weight)
|
2011-11-08 11:00:34 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
setBlkioDeviceWeight, -1, path, weight);
|
2011-11-08 11:00:34 +00:00
|
|
|
}
|
2013-08-11 12:04:28 +00:00
|
|
|
|
2015-08-03 13:10:20 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetBlkioDeviceReadIops:
|
|
|
|
* @group: The cgroup to gather block io setting for
|
|
|
|
* @path: The path of device
|
|
|
|
* @riops: Returned device read iops throttle, 0 if there is none
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceReadIops(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned int *riops)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
getBlkioDeviceReadIops, -1, path, riops);
|
2015-08-03 13:10:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupGetBlkioDeviceWriteIops:
|
|
|
|
* @group: The cgroup to gather block io setting for
|
|
|
|
* @path: The path of device
|
|
|
|
* @wiops: Returned device write iops throttle, 0 if there is none
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceWriteIops(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned int *wiops)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
getBlkioDeviceWriteIops, -1, path, wiops);
|
2015-08-03 13:10:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupGetBlkioDeviceReadBps:
|
|
|
|
* @group: The cgroup to gather block io setting for
|
|
|
|
* @path: The path of device
|
|
|
|
* @rbps: Returned device read bps throttle, 0 if there is none
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceReadBps(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned long long *rbps)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
getBlkioDeviceReadBps, -1, path, rbps);
|
2015-08-03 13:10:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupGetBlkioDeviceWriteBps:
|
|
|
|
* @group: The cgroup to gather block io setting for
|
|
|
|
* @path: The path of device
|
|
|
|
* @wbps: Returned device write bps throttle, 0 if there is none
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceWriteBps(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned long long *wbps)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
getBlkioDeviceWriteBps, -1, path, wbps);
|
2015-08-03 13:10:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupGetBlkioDeviceWeight:
|
|
|
|
* @group: The cgroup to gather block io setting for
|
|
|
|
* @path: The path of device
|
|
|
|
* @weight: Returned device weight, 0 if there is none
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceWeight(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
unsigned int *weight)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
|
|
|
|
getBlkioDeviceWeight, -1, path, weight);
|
2015-08-03 13:10:20 +00:00
|
|
|
}
|
|
|
|
|
2011-11-08 11:00:34 +00:00
|
|
|
|
2008-10-03 17:58:02 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetMemory:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to change memory for
|
|
|
|
* @kb: The memory amount in kilobytes
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetMemory(virCgroupPtr group, unsigned long long kb)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
setMemory, -1, kb);
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2018-07-20 12:47:11 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetMemoryStat:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to change memory for
|
|
|
|
* @cache: page cache memory in KiB
|
|
|
|
* @activeAnon: anonymous and swap cache memory in KiB
|
|
|
|
* @inactiveAnon: anonymous and swap cache memory in KiB
|
|
|
|
* @activeFile: file-backed memory in KiB
|
|
|
|
* @inactiveFile: file-backed memory in KiB
|
|
|
|
* @unevictable: memory that cannot be reclaimed KiB
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetMemoryStat(virCgroupPtr group,
|
|
|
|
unsigned long long *cache,
|
|
|
|
unsigned long long *activeAnon,
|
|
|
|
unsigned long long *inactiveAnon,
|
|
|
|
unsigned long long *activeFile,
|
|
|
|
unsigned long long *inactiveFile,
|
|
|
|
unsigned long long *unevictable)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
getMemoryStat, -1, cache,
|
2018-08-17 13:55:47 +00:00
|
|
|
activeAnon, inactiveAnon,
|
|
|
|
activeFile, inactiveFile,
|
|
|
|
unevictable);
|
2018-07-20 12:47:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-07 13:26:23 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetMemoryUsage:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to change memory for
|
|
|
|
* @kb: Pointer to returned used memory in kilobytes
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb)
|
2009-10-07 13:26:23 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
getMemoryUsage, -1, kb);
|
2009-10-07 13:26:23 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2010-10-12 14:50:53 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetMemoryHardLimit:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to change memory hard limit for
|
|
|
|
* @kb: The memory amount in kilobytes
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb)
|
2010-10-12 14:50:53 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
setMemoryHardLimit, -1, kb);
|
2010-10-12 14:50:53 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2010-10-12 14:50:53 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetMemoryHardLimit:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get the memory hard limit for
|
|
|
|
* @kb: The memory amount in kilobytes
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb)
|
2010-10-12 14:50:53 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
getMemoryHardLimit, -1, kb);
|
2010-10-12 14:50:53 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2010-10-12 14:50:53 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetMemorySoftLimit:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to change memory soft limit for
|
|
|
|
* @kb: The memory amount in kilobytes
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long long kb)
|
2010-10-12 14:50:53 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
setMemorySoftLimit, -1, kb);
|
2010-10-12 14:50:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupGetMemorySoftLimit:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get the memory soft limit for
|
|
|
|
* @kb: The memory amount in kilobytes
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb)
|
2010-10-12 14:50:53 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
getMemorySoftLimit, -1, kb);
|
2010-10-12 14:50:53 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2010-10-12 14:50:53 +00:00
|
|
|
/**
|
2011-03-16 05:07:12 +00:00
|
|
|
* virCgroupSetMemSwapHardLimit:
|
2010-10-12 14:50:53 +00:00
|
|
|
*
|
2011-03-16 05:07:12 +00:00
|
|
|
* @group: The cgroup to change mem+swap hard limit for
|
|
|
|
* @kb: The mem+swap amount in kilobytes
|
2010-10-12 14:50:53 +00:00
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb)
|
2010-10-12 14:50:53 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
setMemSwapHardLimit, -1, kb);
|
2010-10-12 14:50:53 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2010-10-12 14:50:53 +00:00
|
|
|
/**
|
2011-03-16 05:07:12 +00:00
|
|
|
* virCgroupGetMemSwapHardLimit:
|
2010-10-12 14:50:53 +00:00
|
|
|
*
|
2011-03-16 05:07:12 +00:00
|
|
|
* @group: The cgroup to get mem+swap hard limit for
|
|
|
|
* @kb: The mem+swap amount in kilobytes
|
2010-10-12 14:50:53 +00:00
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb)
|
2010-10-12 14:50:53 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
getMemSwapHardLimit, -1, kb);
|
2010-10-12 14:50:53 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2012-11-12 07:02:25 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetMemSwapUsage:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get mem+swap usage for
|
|
|
|
* @kb: The mem+swap amount in kilobytes
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb)
|
2012-11-12 07:02:25 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
|
|
|
|
getMemSwapUsage, -1, kb);
|
2012-11-12 07:02:25 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2011-12-20 08:34:58 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetCpusetMems:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to set cpuset.mems for
|
|
|
|
* @mems: the numa nodes to set
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetCpusetMems(virCgroupPtr group, const char *mems)
|
2011-12-20 08:34:58 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
|
|
|
|
setCpusetMems, -1, mems);
|
2011-12-20 08:34:58 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2011-12-20 08:34:58 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetCpusetMems:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get cpuset.mems for
|
|
|
|
* @mems: the numa nodes to get
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupGetCpusetMems(virCgroupPtr group, char **mems)
|
2011-12-20 08:34:58 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
|
|
|
|
getCpusetMems, -1, mems);
|
2011-12-20 08:34:58 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2015-03-11 10:15:29 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetCpusetMemoryMigrate:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to set cpuset.memory_migrate for
|
|
|
|
* @migrate: Whether to migrate the memory on change or not
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupSetCpusetMemoryMigrate(virCgroupPtr group, bool migrate)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
|
|
|
|
setCpusetMemoryMigrate, -1, migrate);
|
2015-03-11 10:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupGetCpusetMemoryMigrate:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get cpuset.memory_migrate for
|
|
|
|
* @migrate: Migration setting
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetCpusetMemoryMigrate(virCgroupPtr group, bool *migrate)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
|
|
|
|
getCpusetMemoryMigrate, -1, migrate);
|
2015-03-11 10:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-21 09:18:30 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetCpusetCpus:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to set cpuset.cpus for
|
|
|
|
* @cpus: the cpus to set
|
|
|
|
*
|
2016-11-15 14:00:08 +00:00
|
|
|
* Returns: 0 on success
|
2012-08-21 09:18:30 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus)
|
2012-08-21 09:18:30 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
|
|
|
|
setCpusetCpus, -1, cpus);
|
2012-08-21 09:18:30 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2012-08-21 09:18:30 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetCpusetCpus:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get cpuset.cpus for
|
|
|
|
* @cpus: the cpus to get
|
|
|
|
*
|
2016-11-15 14:00:08 +00:00
|
|
|
* Returns: 0 on success
|
2012-08-21 09:18:30 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus)
|
2012-08-21 09:18:30 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
|
|
|
|
getCpusetCpus, -1, cpus);
|
2012-08-21 09:18:30 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2008-10-03 17:58:02 +00:00
|
|
|
/**
|
|
|
|
* virCgroupDenyAllDevices:
|
|
|
|
*
|
2011-03-09 03:13:18 +00:00
|
|
|
* @group: The cgroup to deny all permissions, for all devices
|
2008-10-03 17:58:02 +00:00
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupDenyAllDevices(virCgroupPtr group)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
|
|
|
|
denyAllDevices, -1);
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
|
|
|
|
2014-07-18 08:02:29 +00:00
|
|
|
/**
|
|
|
|
* virCgroupAllowAllDevices:
|
|
|
|
*
|
2018-12-04 17:08:14 +00:00
|
|
|
* Allows the permission for all devices by setting lines similar
|
2014-07-18 08:02:29 +00:00
|
|
|
* to these ones (obviously the 'm' permission is an example):
|
|
|
|
*
|
|
|
|
* 'b *:* m'
|
|
|
|
* 'c *:* m'
|
|
|
|
*
|
|
|
|
* @group: The cgroup to allow devices for
|
|
|
|
* @perms: Bitwise or of VIR_CGROUP_DEVICE permission bits to allow
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupAllowAllDevices(virCgroupPtr group, int perms)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
|
|
|
|
allowAllDevices, -1, perms);
|
2014-07-18 08:02:29 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2008-10-03 17:58:02 +00:00
|
|
|
/**
|
|
|
|
* virCgroupAllowDevice:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to allow a device for
|
|
|
|
* @type: The device type (i.e., 'c' or 'b')
|
2014-07-18 08:02:29 +00:00
|
|
|
* @major: The major number of the device, a negative value means '*'
|
|
|
|
* @minor: The minor number of the device, a negative value means '*'
|
2011-03-09 03:13:18 +00:00
|
|
|
* @perms: Bitwise or of VIR_CGROUP_DEVICE permission bits to allow
|
2008-10-03 17:58:02 +00:00
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupAllowDevice(virCgroupPtr group, char type, int major, int minor,
|
|
|
|
int perms)
|
2008-10-03 17:58:02 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
|
|
|
|
allowDevice, -1, type, major, minor, perms);
|
2008-10-03 17:58:02 +00:00
|
|
|
}
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2009-07-09 13:11:49 +00:00
|
|
|
/**
|
|
|
|
* virCgroupAllowDevicePath:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to allow the device for
|
|
|
|
* @path: the device to allow
|
2011-03-09 03:13:18 +00:00
|
|
|
* @perms: Bitwise or of VIR_CGROUP_DEVICE permission bits to allow
|
2016-02-16 13:43:41 +00:00
|
|
|
* @ignoreEacces: Ignore lack of permission (mostly for NFS mounts)
|
2009-07-09 13:11:49 +00:00
|
|
|
*
|
|
|
|
* Queries the type of device and its major/minor number, and
|
|
|
|
* adds that to the cgroup ACL
|
|
|
|
*
|
2016-02-16 13:43:41 +00:00
|
|
|
* Returns: 0 on success, 1 if path exists but is not a device or is not
|
2018-12-04 17:08:14 +00:00
|
|
|
* accessible, or * -1 on error
|
2009-07-09 13:11:49 +00:00
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
2016-02-16 13:43:41 +00:00
|
|
|
virCgroupAllowDevicePath(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
int perms,
|
|
|
|
bool ignoreEacces)
|
2009-07-09 13:11:49 +00:00
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
if (stat(path, &sb) < 0) {
|
2016-02-16 13:43:41 +00:00
|
|
|
if (errno == EACCES && ignoreEacces)
|
|
|
|
return 1;
|
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Path '%s' is not accessible"),
|
|
|
|
path);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-07-09 13:11:49 +00:00
|
|
|
|
|
|
|
if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode))
|
2011-02-17 00:05:54 +00:00
|
|
|
return 1;
|
2009-07-09 13:11:49 +00:00
|
|
|
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
|
|
|
|
allowDevice, -1,
|
2018-09-05 18:08:48 +00:00
|
|
|
S_ISCHR(sb.st_mode) ? 'c' : 'b',
|
|
|
|
major(sb.st_rdev),
|
|
|
|
minor(sb.st_rdev),
|
|
|
|
perms);
|
2009-07-09 13:11:49 +00:00
|
|
|
}
|
2009-10-07 10:18:31 +00:00
|
|
|
|
2009-07-09 13:11:49 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupDenyDevice:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to deny a device for
|
|
|
|
* @type: The device type (i.e., 'c' or 'b')
|
2016-02-16 13:01:25 +00:00
|
|
|
* @major: The major number of the device, a negative value means '*'
|
|
|
|
* @minor: The minor number of the device, a negative value means '*'
|
2011-03-09 03:13:18 +00:00
|
|
|
* @perms: Bitwise or of VIR_CGROUP_DEVICE permission bits to deny
|
2009-07-09 13:11:49 +00:00
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupDenyDevice(virCgroupPtr group, char type, int major, int minor,
|
|
|
|
int perms)
|
2009-07-09 13:11:49 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
|
|
|
|
denyDevice, -1, type, major, minor, perms);
|
2009-07-09 13:11:49 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2016-02-16 13:43:41 +00:00
|
|
|
/**
|
|
|
|
* virCgroupDenyDevicePath:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to deny the device for
|
|
|
|
* @path: the device to deny
|
|
|
|
* @perms: Bitwise or of VIR_CGROUP_DEVICE permission bits to allow
|
|
|
|
* @ignoreEacces: Ignore lack of permission (mostly for NFS mounts)
|
|
|
|
*
|
|
|
|
* Queries the type of device and its major/minor number, and
|
|
|
|
* removes it from the cgroup ACL
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, 1 if path exists but is not a device or is not
|
|
|
|
* accessible, or -1 on error.
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
2016-02-16 13:43:41 +00:00
|
|
|
virCgroupDenyDevicePath(virCgroupPtr group,
|
|
|
|
const char *path,
|
|
|
|
int perms,
|
|
|
|
bool ignoreEacces)
|
2009-07-09 13:11:49 +00:00
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
if (stat(path, &sb) < 0) {
|
2016-02-16 13:43:41 +00:00
|
|
|
if (errno == EACCES && ignoreEacces)
|
|
|
|
return 1;
|
|
|
|
|
2013-07-08 10:08:46 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Path '%s' is not accessible"),
|
|
|
|
path);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-07-09 13:11:49 +00:00
|
|
|
|
|
|
|
if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode))
|
2011-02-17 00:05:54 +00:00
|
|
|
return 1;
|
2009-07-09 13:11:49 +00:00
|
|
|
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
|
|
|
|
denyDevice, -1,
|
2018-09-05 18:08:48 +00:00
|
|
|
S_ISCHR(sb.st_mode) ? 'c' : 'b',
|
|
|
|
major(sb.st_rdev),
|
|
|
|
minor(sb.st_rdev),
|
|
|
|
perms);
|
2009-07-09 13:11:49 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2014-04-03 15:53:43 +00:00
|
|
|
/* This function gets the sums of cpu time consumed by all vcpus.
|
|
|
|
* For example, if there are 4 physical cpus, and 2 vcpus in a domain,
|
|
|
|
* then for each vcpu, the cpuacct.usage_percpu looks like this:
|
|
|
|
* t0 t1 t2 t3
|
|
|
|
* and we have 2 groups of such data:
|
|
|
|
* v\p 0 1 2 3
|
|
|
|
* 0 t00 t01 t02 t03
|
|
|
|
* 1 t10 t11 t12 t13
|
|
|
|
* for each pcpu, the sum is cpu time consumed by all vcpus.
|
|
|
|
* s0 = t00 + t10
|
|
|
|
* s1 = t01 + t11
|
|
|
|
* s2 = t02 + t12
|
|
|
|
* s3 = t03 + t13
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virCgroupGetPercpuVcpuSum(virCgroupPtr group,
|
2015-12-14 14:10:22 +00:00
|
|
|
virBitmapPtr guestvcpus,
|
2014-04-03 15:53:43 +00:00
|
|
|
unsigned long long *sum_cpu_time,
|
2015-01-22 10:54:50 +00:00
|
|
|
size_t nsum,
|
|
|
|
virBitmapPtr cpumap)
|
2014-04-03 15:53:43 +00:00
|
|
|
{
|
2018-07-30 09:03:16 +00:00
|
|
|
int ret = -1;
|
2015-12-14 14:10:22 +00:00
|
|
|
ssize_t i = -1;
|
2018-07-30 09:03:16 +00:00
|
|
|
virCgroupPtr group_vcpu = NULL;
|
2014-04-03 15:53:43 +00:00
|
|
|
|
2015-12-14 14:10:22 +00:00
|
|
|
while ((i = virBitmapNextSetBit(guestvcpus, i)) >= 0) {
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) buf = NULL;
|
2014-04-03 15:53:43 +00:00
|
|
|
char *pos;
|
|
|
|
unsigned long long tmp;
|
2015-01-22 10:54:50 +00:00
|
|
|
ssize_t j;
|
2014-04-03 15:53:43 +00:00
|
|
|
|
2015-04-07 12:53:35 +00:00
|
|
|
if (virCgroupNewThread(group, VIR_CGROUP_THREAD_VCPU, i,
|
|
|
|
false, &group_vcpu) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2014-04-03 15:53:43 +00:00
|
|
|
|
|
|
|
if (virCgroupGetCpuacctPercpuUsage(group_vcpu, &buf) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2014-04-03 15:53:43 +00:00
|
|
|
|
|
|
|
pos = buf;
|
2015-01-22 10:54:50 +00:00
|
|
|
for (j = virBitmapNextSetBit(cpumap, -1);
|
|
|
|
j >= 0 && j < nsum;
|
|
|
|
j = virBitmapNextSetBit(cpumap, j)) {
|
2014-04-03 15:53:43 +00:00
|
|
|
if (virStrToLong_ull(pos, &pos, 10, &tmp) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("cpuacct parse error"));
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2014-04-03 15:53:43 +00:00
|
|
|
}
|
|
|
|
sum_cpu_time[j] += tmp;
|
|
|
|
}
|
2018-07-30 09:03:16 +00:00
|
|
|
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(&group_vcpu);
|
2014-04-03 15:53:43 +00:00
|
|
|
}
|
|
|
|
|
2018-07-30 09:03:16 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(&group_vcpu);
|
2018-07-30 09:03:16 +00:00
|
|
|
return ret;
|
2014-04-03 15:53:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-07 06:39:34 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetPercpuStats:
|
|
|
|
* @cgroup: cgroup data structure
|
|
|
|
* @params: typed parameter array where data is returned
|
|
|
|
* @nparams: cardinality of @params
|
|
|
|
* @start_cpu: offset of physical CPU to get data for
|
|
|
|
* @ncpus: number of physical CPUs to get data for
|
|
|
|
* @nvcpupids: number of vCPU threads for a domain (actual number of vcpus)
|
|
|
|
*
|
|
|
|
* This function is the worker that retrieves data in the appropriate format
|
|
|
|
* for the terribly designed 'virDomainGetCPUStats' API. Sharing semantics with
|
|
|
|
* the API, this function has two modes of operation depending on magic settings
|
|
|
|
* of the input arguments. Please refer to docs of 'virDomainGetCPUStats' for
|
|
|
|
* the usage patterns of the similarly named arguments.
|
|
|
|
*
|
|
|
|
* @nvcpupids determines the count of active vcpu threads for the vm. If the
|
|
|
|
* threads could not be detected the percpu data is skipped.
|
|
|
|
*
|
|
|
|
* Please DON'T use this function anywhere else.
|
|
|
|
*/
|
2014-02-14 17:49:02 +00:00
|
|
|
int
|
|
|
|
virCgroupGetPercpuStats(virCgroupPtr group,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
unsigned int nparams,
|
|
|
|
int start_cpu,
|
2014-04-03 15:53:43 +00:00
|
|
|
unsigned int ncpus,
|
2015-12-14 14:10:22 +00:00
|
|
|
virBitmapPtr guestvcpus)
|
2014-02-14 17:49:02 +00:00
|
|
|
{
|
2018-07-30 09:03:16 +00:00
|
|
|
int ret = -1;
|
2014-02-14 17:49:02 +00:00
|
|
|
size_t i;
|
2014-04-03 17:53:13 +00:00
|
|
|
int need_cpus, total_cpus;
|
2014-02-14 17:49:02 +00:00
|
|
|
char *pos;
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) buf = NULL;
|
|
|
|
VIR_AUTOFREE(unsigned long long *) sum_cpu_time = NULL;
|
2014-02-14 17:49:02 +00:00
|
|
|
virTypedParameterPtr ent;
|
|
|
|
int param_idx;
|
|
|
|
unsigned long long cpu_time;
|
2018-07-30 09:03:16 +00:00
|
|
|
virBitmapPtr cpumap = NULL;
|
2014-02-14 17:49:02 +00:00
|
|
|
|
|
|
|
/* return the number of supported params */
|
2014-04-03 15:53:43 +00:00
|
|
|
if (nparams == 0 && ncpus != 0) {
|
2015-12-14 14:10:22 +00:00
|
|
|
if (!guestvcpus)
|
2014-04-03 15:53:43 +00:00
|
|
|
return CGROUP_NB_PER_CPU_STAT_PARAM;
|
|
|
|
else
|
|
|
|
return CGROUP_NB_PER_CPU_STAT_PARAM + 1;
|
|
|
|
}
|
2014-02-14 17:49:02 +00:00
|
|
|
|
|
|
|
/* To parse account file, we need to know how many cpus are present. */
|
2016-04-13 17:16:16 +00:00
|
|
|
if (!(cpumap = virHostCPUGetPresentBitmap()))
|
2015-12-07 06:39:34 +00:00
|
|
|
return -1;
|
2014-02-14 17:49:02 +00:00
|
|
|
|
2015-01-22 10:54:50 +00:00
|
|
|
total_cpus = virBitmapSize(cpumap);
|
|
|
|
|
2015-12-07 06:39:34 +00:00
|
|
|
/* return total number of cpus */
|
2018-07-30 09:03:16 +00:00
|
|
|
if (ncpus == 0) {
|
|
|
|
ret = total_cpus;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-02-14 17:49:02 +00:00
|
|
|
|
2014-04-03 17:38:54 +00:00
|
|
|
if (start_cpu >= total_cpus) {
|
2014-02-14 17:49:02 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("start_cpu %d larger than maximum of %d"),
|
2014-04-03 17:38:54 +00:00
|
|
|
start_cpu, total_cpus - 1);
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2014-02-14 17:49:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* we get percpu cputime accounting info. */
|
|
|
|
if (virCgroupGetCpuacctPercpuUsage(group, &buf))
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2014-02-14 17:49:02 +00:00
|
|
|
pos = buf;
|
|
|
|
|
|
|
|
/* return percpu cputime in index 0 */
|
|
|
|
param_idx = 0;
|
|
|
|
|
|
|
|
/* number of cpus to compute */
|
2014-04-03 17:23:25 +00:00
|
|
|
need_cpus = MIN(total_cpus, start_cpu + ncpus);
|
2014-02-14 17:49:02 +00:00
|
|
|
|
2014-04-03 17:23:25 +00:00
|
|
|
for (i = 0; i < need_cpus; i++) {
|
2015-03-11 15:41:57 +00:00
|
|
|
if (!virBitmapIsBitSet(cpumap, i)) {
|
2015-01-22 10:54:50 +00:00
|
|
|
cpu_time = 0;
|
|
|
|
} else if (virStrToLong_ull(pos, &pos, 10, &cpu_time) < 0) {
|
2014-02-14 17:49:02 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("cpuacct parse error"));
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2014-02-14 17:49:02 +00:00
|
|
|
}
|
|
|
|
if (i < start_cpu)
|
|
|
|
continue;
|
|
|
|
ent = ¶ms[(i - start_cpu) * nparams + param_idx];
|
|
|
|
if (virTypedParameterAssign(ent, VIR_DOMAIN_CPU_STATS_CPUTIME,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, cpu_time) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2014-02-14 17:49:02 +00:00
|
|
|
}
|
|
|
|
|
2014-04-03 15:53:43 +00:00
|
|
|
/* return percpu vcputime in index 1 */
|
2015-12-07 06:39:34 +00:00
|
|
|
param_idx = 1;
|
2014-04-03 15:53:43 +00:00
|
|
|
|
2015-12-14 14:10:22 +00:00
|
|
|
if (guestvcpus && param_idx < nparams) {
|
2015-12-07 06:39:34 +00:00
|
|
|
if (VIR_ALLOC_N(sum_cpu_time, need_cpus) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2015-12-14 14:10:22 +00:00
|
|
|
if (virCgroupGetPercpuVcpuSum(group, guestvcpus, sum_cpu_time,
|
|
|
|
need_cpus, cpumap) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2015-12-07 06:39:34 +00:00
|
|
|
|
|
|
|
for (i = start_cpu; i < need_cpus; i++) {
|
2018-09-19 08:38:14 +00:00
|
|
|
int idx = (i - start_cpu) * nparams + param_idx;
|
|
|
|
if (virTypedParameterAssign(¶ms[idx],
|
2015-12-07 06:39:34 +00:00
|
|
|
VIR_DOMAIN_CPU_STATS_VCPUTIME,
|
|
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
|
|
sum_cpu_time[i]) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
goto cleanup;
|
2015-12-07 06:39:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
param_idx++;
|
2014-04-03 15:53:43 +00:00
|
|
|
}
|
|
|
|
|
2018-07-30 09:03:16 +00:00
|
|
|
ret = param_idx;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virBitmapFree(cpumap);
|
|
|
|
return ret;
|
2014-02-14 17:49:02 +00:00
|
|
|
}
|
|
|
|
|
2014-02-14 17:49:01 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetDomainTotalCpuStats(virCgroupPtr group,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
unsigned long long cpu_time;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (nparams == 0) /* return supported number of params */
|
|
|
|
return CGROUP_NB_TOTAL_CPU_STAT_PARAM;
|
|
|
|
/* entry 0 is cputime */
|
|
|
|
ret = virCgroupGetCpuacctUsage(group, &cpu_time);
|
|
|
|
if (ret < 0) {
|
|
|
|
virReportSystemError(-ret, "%s", _("unable to get cpu account"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_CPU_STATS_CPUTIME,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, cpu_time) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (nparams > 1) {
|
|
|
|
unsigned long long user;
|
|
|
|
unsigned long long sys;
|
|
|
|
|
|
|
|
ret = virCgroupGetCpuacctStat(group, &user, &sys);
|
|
|
|
if (ret < 0) {
|
|
|
|
virReportSystemError(-ret, "%s", _("unable to get cpu account"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virTypedParameterAssign(¶ms[1],
|
|
|
|
VIR_DOMAIN_CPU_STATS_USERTIME,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, user) < 0)
|
|
|
|
return -1;
|
|
|
|
if (nparams > 2 &&
|
|
|
|
virTypedParameterAssign(¶ms[2],
|
|
|
|
VIR_DOMAIN_CPU_STATS_SYSTEMTIME,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, sys) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (nparams > CGROUP_NB_TOTAL_CPU_STAT_PARAM)
|
|
|
|
nparams = CGROUP_NB_TOTAL_CPU_STAT_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nparams;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetCpuShares(virCgroupPtr group, unsigned long long shares)
|
2008-10-08 16:28:48 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
|
|
|
|
setCpuShares, -1, shares);
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares)
|
2008-10-08 16:28:48 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
|
|
|
|
getCpuShares, -1, shares);
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
2009-03-06 14:44:04 +00:00
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2011-07-21 07:21:05 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetCpuCfsPeriod:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to change cpu.cfs_period_us for
|
|
|
|
* @cfs_period: The bandwidth period in usecs
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetCpuCfsPeriod(virCgroupPtr group, unsigned long long cfs_period)
|
2011-07-21 07:21:05 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
|
|
|
|
setCpuCfsPeriod, -1, cfs_period);
|
2011-07-21 07:21:05 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2011-07-21 07:21:05 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetCpuCfsPeriod:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get cpu.cfs_period_us for
|
|
|
|
* @cfs_period: Pointer to the returned bandwidth period in usecs
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupGetCpuCfsPeriod(virCgroupPtr group, unsigned long long *cfs_period)
|
2011-07-21 07:21:05 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
|
|
|
|
getCpuCfsPeriod, -1, cfs_period);
|
2011-07-21 07:21:05 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2011-07-21 07:21:05 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSetCpuCfsQuota:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to change cpu.cfs_quota_us for
|
|
|
|
* @cfs_quota: the cpu bandwidth (in usecs) that this tg will be allowed to
|
|
|
|
* consume over period
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupSetCpuCfsQuota(virCgroupPtr group, long long cfs_quota)
|
2011-07-21 07:21:05 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
|
|
|
|
setCpuCfsQuota, -1, cfs_quota);
|
2011-07-21 07:21:05 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpuacctPercpuUsage(virCgroupPtr group, char **usage)
|
2012-03-02 02:54:23 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUACCT,
|
|
|
|
getCpuacctPercpuUsage, -1, usage);
|
2012-03-02 02:54:23 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2018-08-17 08:02:05 +00:00
|
|
|
int
|
2013-08-12 21:20:59 +00:00
|
|
|
virCgroupRemoveRecursively(char *grppath)
|
|
|
|
{
|
|
|
|
DIR *grpdir;
|
|
|
|
struct dirent *ent;
|
|
|
|
int rc = 0;
|
2014-04-25 20:45:49 +00:00
|
|
|
int direrr;
|
2013-08-12 21:20:59 +00:00
|
|
|
|
2016-06-21 14:52:37 +00:00
|
|
|
if (virDirOpenQuiet(&grpdir, grppath) < 0) {
|
2013-08-12 21:20:59 +00:00
|
|
|
if (errno == ENOENT)
|
|
|
|
return 0;
|
|
|
|
rc = -errno;
|
|
|
|
VIR_ERROR(_("Unable to open %s (%d)"), grppath, errno);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2014-04-25 20:45:49 +00:00
|
|
|
/* This is best-effort cleanup: we want to log failures with just
|
|
|
|
* VIR_ERROR instead of normal virReportError */
|
|
|
|
while ((direrr = virDirRead(grpdir, &ent, NULL)) > 0) {
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) path = NULL;
|
2013-08-12 21:20:59 +00:00
|
|
|
|
|
|
|
if (ent->d_type != DT_DIR) continue;
|
|
|
|
|
|
|
|
if (virAsprintf(&path, "%s/%s", grppath, ent->d_name) == -1) {
|
|
|
|
rc = -ENOMEM;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rc = virCgroupRemoveRecursively(path);
|
|
|
|
if (rc != 0)
|
|
|
|
break;
|
|
|
|
}
|
2014-04-25 20:45:49 +00:00
|
|
|
if (direrr < 0) {
|
|
|
|
rc = -errno;
|
|
|
|
VIR_ERROR(_("Failed to readdir for %s (%d)"), grppath, errno);
|
|
|
|
}
|
|
|
|
|
2016-06-21 10:40:29 +00:00
|
|
|
VIR_DIR_CLOSE(grpdir);
|
2013-08-12 21:20:59 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Removing cgroup %s", grppath);
|
|
|
|
if (rmdir(grppath) != 0 && errno != ENOENT) {
|
|
|
|
rc = -errno;
|
|
|
|
VIR_ERROR(_("Unable to remove %s (%d)"), grppath, errno);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virCgroupRemove:
|
|
|
|
*
|
|
|
|
* @group: The group to be removed
|
|
|
|
*
|
|
|
|
* It first removes all child groups recursively
|
|
|
|
* in depth first order and then removes @group
|
|
|
|
* because the presence of the child groups
|
|
|
|
* prevents removing @group.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupRemove(virCgroupPtr group)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
2019-07-19 03:19:38 +00:00
|
|
|
if (group->backends[i]) {
|
|
|
|
int rc = group->backends[i]->remove(group);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
2018-09-28 17:53:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2013-08-12 21:20:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-19 14:43:04 +00:00
|
|
|
/*
|
|
|
|
* Returns 1 if some PIDs are killed, 0 if none are killed, or -1 on error
|
|
|
|
*/
|
2013-08-12 19:52:06 +00:00
|
|
|
static int
|
2018-12-10 08:51:14 +00:00
|
|
|
virCgroupKillInternal(virCgroupPtr group,
|
|
|
|
int signum,
|
|
|
|
virHashTablePtr pids,
|
|
|
|
int controller,
|
|
|
|
const char *taskFile)
|
2011-02-22 17:33:59 +00:00
|
|
|
{
|
2013-07-19 14:43:04 +00:00
|
|
|
int ret = -1;
|
2013-05-24 10:14:02 +00:00
|
|
|
bool killedAny = false;
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) keypath = NULL;
|
2011-02-22 17:33:59 +00:00
|
|
|
bool done = false;
|
cgroup: avoid leaking a file
Clang detected a dead store to rc. It turns out that in fixing this,
I also found a FILE* leak.
This is a subtle change in behavior, although unlikely to hit. The
pidfile is a kernel file, so we've probably got more serious problems
under foot if we fail to parse one. However, the previous behavior
was that even if one pid file failed to parse, we tried others,
whereas now we give up on the first failure. Either way, though,
the function returns -1, so the caller will know that something is
going wrong, and that not all pids were necessarily reaped. Besides,
there were other instances already in the code where failure in the
inner loop aborted the outer loop.
* src/util/cgroup.c (virCgroupKillInternal): Abort rather than
resuming loop on fscanf failure, and cleanup file on error.
2011-05-03 21:46:06 +00:00
|
|
|
FILE *fp = NULL;
|
|
|
|
VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
|
|
|
|
group, group->path, signum, pids);
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2018-12-10 08:51:14 +00:00
|
|
|
if (virCgroupPathOfController(group, controller, taskFile, &keypath) < 0)
|
2013-07-19 14:43:04 +00:00
|
|
|
return -1;
|
2011-02-22 17:33:59 +00:00
|
|
|
|
|
|
|
/* PIDs may be forking as we kill them, so loop
|
|
|
|
* until there are no new PIDs found
|
|
|
|
*/
|
|
|
|
while (!done) {
|
|
|
|
done = true;
|
|
|
|
if (!(fp = fopen(keypath, "r"))) {
|
2013-07-26 15:02:22 +00:00
|
|
|
if (errno == ENOENT) {
|
|
|
|
VIR_DEBUG("No file %s, assuming done", keypath);
|
|
|
|
killedAny = false;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2013-07-19 14:43:04 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to read %s"),
|
|
|
|
keypath);
|
2011-02-22 17:33:59 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
while (!feof(fp)) {
|
2016-10-06 14:54:41 +00:00
|
|
|
long pid_value;
|
|
|
|
if (fscanf(fp, "%ld", &pid_value) != 1) {
|
2011-02-22 17:33:59 +00:00
|
|
|
if (feof(fp))
|
|
|
|
break;
|
2013-07-19 14:43:04 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to read %s"),
|
|
|
|
keypath);
|
cgroup: avoid leaking a file
Clang detected a dead store to rc. It turns out that in fixing this,
I also found a FILE* leak.
This is a subtle change in behavior, although unlikely to hit. The
pidfile is a kernel file, so we've probably got more serious problems
under foot if we fail to parse one. However, the previous behavior
was that even if one pid file failed to parse, we tried others,
whereas now we give up on the first failure. Either way, though,
the function returns -1, so the caller will know that something is
going wrong, and that not all pids were necessarily reaped. Besides,
there were other instances already in the code where failure in the
inner loop aborted the outer loop.
* src/util/cgroup.c (virCgroupKillInternal): Abort rather than
resuming loop on fscanf failure, and cleanup file on error.
2011-05-03 21:46:06 +00:00
|
|
|
goto cleanup;
|
2011-02-22 17:33:59 +00:00
|
|
|
}
|
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-10 23:08:11 +00:00
|
|
|
if (virHashLookup(pids, (void*)pid_value))
|
2011-02-22 17:33:59 +00:00
|
|
|
continue;
|
|
|
|
|
2016-10-06 14:54:41 +00:00
|
|
|
VIR_DEBUG("pid=%ld", pid_value);
|
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-10 23:08:11 +00:00
|
|
|
/* Cgroups is a Linux concept, so this cast is safe. */
|
|
|
|
if (kill((pid_t)pid_value, signum) < 0) {
|
2011-02-22 17:33:59 +00:00
|
|
|
if (errno != ESRCH) {
|
2013-07-19 14:43:04 +00:00
|
|
|
virReportSystemError(errno,
|
2016-10-06 14:54:41 +00:00
|
|
|
_("Failed to kill process %ld"),
|
2013-07-19 14:43:04 +00:00
|
|
|
pid_value);
|
2011-02-22 17:33:59 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
/* Leave RC == 0 since we didn't kill one */
|
|
|
|
} else {
|
2013-05-24 10:14:02 +00:00
|
|
|
killedAny = true;
|
2011-02-22 17:33:59 +00:00
|
|
|
done = false;
|
|
|
|
}
|
|
|
|
|
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-10 23:08:11 +00:00
|
|
|
ignore_value(virHashAddEntry(pids, (void*)pid_value, (void*)1));
|
2011-02-22 17:33:59 +00:00
|
|
|
}
|
|
|
|
VIR_FORCE_FCLOSE(fp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-26 15:02:22 +00:00
|
|
|
done:
|
2013-07-19 14:43:04 +00:00
|
|
|
ret = killedAny ? 1 : 0;
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
cgroup: avoid leaking a file
Clang detected a dead store to rc. It turns out that in fixing this,
I also found a FILE* leak.
This is a subtle change in behavior, although unlikely to hit. The
pidfile is a kernel file, so we've probably got more serious problems
under foot if we fail to parse one. However, the previous behavior
was that even if one pid file failed to parse, we tried others,
whereas now we give up on the first failure. Either way, though,
the function returns -1, so the caller will know that something is
going wrong, and that not all pids were necessarily reaped. Besides,
there were other instances already in the code where failure in the
inner loop aborted the outer loop.
* src/util/cgroup.c (virCgroupKillInternal): Abort rather than
resuming loop on fscanf failure, and cleanup file on error.
2011-05-03 21:46:06 +00:00
|
|
|
VIR_FORCE_FCLOSE(fp);
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2013-07-19 14:43:04 +00:00
|
|
|
return ret;
|
2011-02-22 17:33:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
static uint32_t
|
|
|
|
virCgroupPidCode(const void *name, uint32_t seed)
|
2011-02-22 17:33:59 +00:00
|
|
|
{
|
2016-10-06 14:54:41 +00:00
|
|
|
long pid_value = (long)(intptr_t)name;
|
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-10 23:08:11 +00:00
|
|
|
return virHashCodeGen(&pid_value, sizeof(pid_value), seed);
|
2011-02-22 17:33:59 +00:00
|
|
|
}
|
2013-08-12 19:52:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
virCgroupPidEqual(const void *namea, const void *nameb)
|
2011-02-22 17:33:59 +00:00
|
|
|
{
|
|
|
|
return namea == nameb;
|
|
|
|
}
|
2013-08-12 19:52:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
virCgroupPidCopy(const void *name)
|
2011-02-22 17:33:59 +00:00
|
|
|
{
|
|
|
|
return (void*)name;
|
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2018-12-10 08:51:14 +00:00
|
|
|
int
|
2013-08-12 19:52:06 +00:00
|
|
|
virCgroupKillRecursiveInternal(virCgroupPtr group,
|
|
|
|
int signum,
|
|
|
|
virHashTablePtr pids,
|
2018-12-10 08:51:14 +00:00
|
|
|
int controller,
|
|
|
|
const char *taskFile,
|
2013-08-12 19:52:06 +00:00
|
|
|
bool dormdir)
|
2011-02-22 17:33:59 +00:00
|
|
|
{
|
2013-07-19 14:43:04 +00:00
|
|
|
int ret = -1;
|
2011-02-22 17:33:59 +00:00
|
|
|
int rc;
|
2013-07-19 14:43:04 +00:00
|
|
|
bool killedAny = false;
|
2018-07-24 15:52:10 +00:00
|
|
|
VIR_AUTOFREE(char *) keypath = NULL;
|
2014-05-13 08:01:16 +00:00
|
|
|
DIR *dp = NULL;
|
2018-07-30 09:03:16 +00:00
|
|
|
virCgroupPtr subgroup = NULL;
|
2011-02-22 17:33:59 +00:00
|
|
|
struct dirent *ent;
|
2014-04-25 20:45:49 +00:00
|
|
|
int direrr;
|
2013-08-12 19:52:06 +00:00
|
|
|
VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
|
|
|
|
group, group->path, signum, pids);
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2018-12-10 08:51:14 +00:00
|
|
|
if (virCgroupPathOfController(group, controller, "", &keypath) < 0)
|
2013-07-19 14:43:04 +00:00
|
|
|
return -1;
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2018-12-10 08:51:14 +00:00
|
|
|
if ((rc = virCgroupKillInternal(group, signum, pids,
|
|
|
|
controller, taskFile)) < 0) {
|
2014-05-13 08:01:16 +00:00
|
|
|
goto cleanup;
|
2018-12-10 08:51:14 +00:00
|
|
|
}
|
2013-07-19 14:43:04 +00:00
|
|
|
if (rc == 1)
|
|
|
|
killedAny = true;
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2013-07-26 15:02:22 +00:00
|
|
|
VIR_DEBUG("Iterate over children of %s (killedAny=%d)", keypath, killedAny);
|
2016-06-21 14:47:24 +00:00
|
|
|
if ((rc = virDirOpenIfExists(&dp, keypath)) < 0)
|
2014-05-13 08:01:16 +00:00
|
|
|
goto cleanup;
|
2016-06-21 14:47:24 +00:00
|
|
|
|
|
|
|
if (rc == 0) {
|
|
|
|
VIR_DEBUG("Path %s does not exist, assuming done", keypath);
|
|
|
|
killedAny = false;
|
|
|
|
goto done;
|
2011-02-22 17:33:59 +00:00
|
|
|
}
|
|
|
|
|
2014-04-25 20:45:49 +00:00
|
|
|
while ((direrr = virDirRead(dp, &ent, keypath)) > 0) {
|
2011-02-22 17:33:59 +00:00
|
|
|
if (ent->d_type != DT_DIR)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
VIR_DEBUG("Process subdir %s", ent->d_name);
|
|
|
|
|
2013-07-19 10:13:05 +00:00
|
|
|
if (virCgroupNew(-1, ent->d_name, group, -1, &subgroup) < 0)
|
2011-02-22 17:33:59 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids,
|
2018-12-10 08:51:14 +00:00
|
|
|
controller, taskFile, true)) < 0)
|
2011-02-22 17:33:59 +00:00
|
|
|
goto cleanup;
|
|
|
|
if (rc == 1)
|
2013-07-19 14:43:04 +00:00
|
|
|
killedAny = true;
|
2011-02-22 17:33:59 +00:00
|
|
|
|
|
|
|
if (dormdir)
|
|
|
|
virCgroupRemove(subgroup);
|
2018-07-30 09:03:16 +00:00
|
|
|
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(&subgroup);
|
2011-02-22 17:33:59 +00:00
|
|
|
}
|
2014-04-25 20:45:49 +00:00
|
|
|
if (direrr < 0)
|
|
|
|
goto cleanup;
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2013-07-26 15:02:22 +00:00
|
|
|
done:
|
2013-07-19 14:43:04 +00:00
|
|
|
ret = killedAny ? 1 : 0;
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(&subgroup);
|
2016-06-21 10:40:29 +00:00
|
|
|
VIR_DIR_CLOSE(dp);
|
2013-07-19 14:43:04 +00:00
|
|
|
return ret;
|
2011-02-22 17:33:59 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupKillRecursive(virCgroupPtr group, int signum)
|
2011-02-22 17:33:59 +00:00
|
|
|
{
|
2018-12-10 08:51:14 +00:00
|
|
|
int ret = 0;
|
|
|
|
int rc;
|
|
|
|
size_t i;
|
2019-01-24 16:20:58 +00:00
|
|
|
bool backendAvailable = false;
|
2018-12-10 08:51:14 +00:00
|
|
|
virCgroupBackendPtr *backends = virCgroupBackendGetAll();
|
2018-07-30 09:03:16 +00:00
|
|
|
virHashTablePtr pids = virHashCreateFull(100,
|
|
|
|
NULL,
|
|
|
|
virCgroupPidCode,
|
|
|
|
virCgroupPidEqual,
|
|
|
|
virCgroupPidCopy,
|
|
|
|
NULL);
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2018-12-10 08:51:14 +00:00
|
|
|
VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
|
2018-07-30 09:03:16 +00:00
|
|
|
|
2018-12-10 08:51:14 +00:00
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
2019-01-24 16:20:58 +00:00
|
|
|
if (backends && backends[i] && backends[i]->available()) {
|
|
|
|
backendAvailable = true;
|
2018-12-10 08:51:14 +00:00
|
|
|
rc = backends[i]->killRecursive(group, signum, pids);
|
|
|
|
if (rc < 0) {
|
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (rc > 0)
|
|
|
|
ret = rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-24 16:20:58 +00:00
|
|
|
if (!backends || !backendAvailable) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("no cgroup backend available"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-12-10 08:51:14 +00:00
|
|
|
cleanup:
|
|
|
|
virHashFree(pids);
|
2018-07-30 09:03:16 +00:00
|
|
|
return ret;
|
2011-02-22 17:33:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
|
|
|
virCgroupKillPainfully(virCgroupPtr group)
|
2011-02-22 17:33:59 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-07-19 14:43:04 +00:00
|
|
|
int ret;
|
2011-02-22 17:33:59 +00:00
|
|
|
VIR_DEBUG("cgroup=%p path=%s", group, group->path);
|
2013-05-21 07:58:16 +00:00
|
|
|
for (i = 0; i < 15; i++) {
|
2011-02-22 17:33:59 +00:00
|
|
|
int signum;
|
|
|
|
if (i == 0)
|
|
|
|
signum = SIGTERM;
|
|
|
|
else if (i == 8)
|
|
|
|
signum = SIGKILL;
|
|
|
|
else
|
2012-10-11 16:31:20 +00:00
|
|
|
signum = 0; /* Just check for existence */
|
2011-02-22 17:33:59 +00:00
|
|
|
|
2013-07-19 14:43:04 +00:00
|
|
|
ret = virCgroupKillRecursive(group, signum);
|
|
|
|
VIR_DEBUG("Iteration %zu rc=%d", i, ret);
|
|
|
|
/* If ret == -1 we hit error, if 0 we ran out of PIDs */
|
|
|
|
if (ret <= 0)
|
2011-02-22 17:33:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
usleep(200 * 1000);
|
|
|
|
}
|
2013-07-19 14:43:04 +00:00
|
|
|
VIR_DEBUG("Complete %d", ret);
|
|
|
|
return ret;
|
2011-02-22 17:33:59 +00:00
|
|
|
}
|
2011-02-28 14:13:58 +00:00
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
|
2013-08-12 17:47:13 +00:00
|
|
|
/**
|
|
|
|
* virCgroupGetCpuCfsQuota:
|
|
|
|
*
|
|
|
|
* @group: The cgroup to get cpu.cfs_quota_us for
|
|
|
|
* @cfs_quota: Pointer to the returned cpu bandwidth (in usecs) that this tg
|
|
|
|
* will be allowed to consume over period
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virCgroupGetCpuCfsQuota(virCgroupPtr group, long long *cfs_quota)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
|
|
|
|
getCpuCfsQuota, -1, cfs_quota);
|
2013-08-12 17:47:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUACCT,
|
|
|
|
getCpuacctUsage, -1, usage);
|
2013-08-12 17:47:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
|
|
|
|
unsigned long long *sys)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUACCT,
|
|
|
|
getCpuacctStat, -1, user, sys);
|
2013-08-12 17:47:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetFreezerState(virCgroupPtr group, const char *state)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_FREEZER,
|
|
|
|
setFreezerState, -1, state);
|
2013-08-12 17:47:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetFreezerState(virCgroupPtr group, char **state)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_FREEZER,
|
|
|
|
getFreezerState, -1, state);
|
2013-08-12 17:47:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
2016-01-22 16:07:18 +00:00
|
|
|
virCgroupBindMount(virCgroupPtr group, const char *oldroot,
|
|
|
|
const char *mountopts)
|
2013-04-05 11:48:47 +00:00
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (group->backends[i] &&
|
|
|
|
group->backends[i]->bindMount(group, oldroot, mountopts) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2013-04-05 11:48:47 +00:00
|
|
|
}
|
2013-08-12 20:02:26 +00:00
|
|
|
|
|
|
|
|
2014-02-24 12:23:33 +00:00
|
|
|
int virCgroupSetOwner(virCgroupPtr cgroup,
|
|
|
|
uid_t uid,
|
|
|
|
gid_t gid,
|
|
|
|
int controllers)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (cgroup->backends[i] &&
|
|
|
|
cgroup->backends[i]->setOwner(cgroup, uid, gid, controllers) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2014-02-24 12:23:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-13 14:03:14 +00:00
|
|
|
/**
|
|
|
|
* virCgroupSupportsCpuBW():
|
|
|
|
* Check whether the host supports CFS bandwidth.
|
|
|
|
*
|
|
|
|
* Return true when CFS bandwidth is supported,
|
|
|
|
* false when CFS bandwidth is not supported.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
virCgroupSupportsCpuBW(virCgroupPtr cgroup)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
VIR_CGROUP_BACKEND_CALL(cgroup, VIR_CGROUP_CONTROLLER_CPU,
|
|
|
|
supportsCpuBW, false);
|
2013-09-13 14:03:14 +00:00
|
|
|
}
|
|
|
|
|
2014-12-13 08:56:00 +00:00
|
|
|
int
|
|
|
|
virCgroupHasEmptyTasks(virCgroupPtr cgroup, int controller)
|
|
|
|
{
|
2018-09-28 17:53:05 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
|
|
|
|
if (cgroup->backends[i]) {
|
|
|
|
int rc = cgroup->backends[i]->hasEmptyTasks(cgroup, controller);
|
|
|
|
if (rc <= 0)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
2014-12-13 08:56:00 +00:00
|
|
|
}
|
2013-09-13 14:03:14 +00:00
|
|
|
|
2015-03-31 09:39:13 +00:00
|
|
|
bool
|
|
|
|
virCgroupControllerAvailable(int controller)
|
|
|
|
{
|
2018-07-30 09:03:16 +00:00
|
|
|
virCgroupPtr cgroup;
|
|
|
|
bool ret = false;
|
2015-03-31 09:39:13 +00:00
|
|
|
|
|
|
|
if (virCgroupNewSelf(&cgroup) < 0)
|
2018-07-30 09:03:16 +00:00
|
|
|
return ret;
|
2015-03-31 09:39:13 +00:00
|
|
|
|
2018-07-30 09:03:16 +00:00
|
|
|
ret = virCgroupHasController(cgroup, controller);
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(&cgroup);
|
2018-07-30 09:03:16 +00:00
|
|
|
return ret;
|
2015-03-31 09:39:13 +00:00
|
|
|
}
|
|
|
|
|
2018-09-27 10:16:57 +00:00
|
|
|
#else /* !__linux__ */
|
2013-08-12 20:02:26 +00:00
|
|
|
|
2013-08-11 12:04:27 +00:00
|
|
|
bool
|
|
|
|
virCgroupAvailable(void)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:28 +00:00
|
|
|
int
|
|
|
|
virCgroupNewPartition(const char *path ATTRIBUTE_UNUSED,
|
|
|
|
bool create ATTRIBUTE_UNUSED,
|
|
|
|
int controllers ATTRIBUTE_UNUSED,
|
|
|
|
virCgroupPtr *group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupNewSelf(virCgroupPtr *group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupNewDomainPartition(virCgroupPtr partition ATTRIBUTE_UNUSED,
|
|
|
|
const char *driver ATTRIBUTE_UNUSED,
|
|
|
|
const char *name ATTRIBUTE_UNUSED,
|
|
|
|
bool create ATTRIBUTE_UNUSED,
|
|
|
|
virCgroupPtr *group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-07 12:28:05 +00:00
|
|
|
int
|
|
|
|
virCgroupNewThread(virCgroupPtr domain ATTRIBUTE_UNUSED,
|
|
|
|
virCgroupThreadName nameval ATTRIBUTE_UNUSED,
|
|
|
|
int id ATTRIBUTE_UNUSED,
|
|
|
|
bool create ATTRIBUTE_UNUSED,
|
|
|
|
virCgroupPtr *group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:28 +00:00
|
|
|
int
|
|
|
|
virCgroupNewDetect(pid_t pid ATTRIBUTE_UNUSED,
|
|
|
|
int controllers ATTRIBUTE_UNUSED,
|
|
|
|
virCgroupPtr *group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:27 +00:00
|
|
|
int
|
|
|
|
virCgroupNewDetectMachine(const char *name ATTRIBUTE_UNUSED,
|
|
|
|
const char *drivername ATTRIBUTE_UNUSED,
|
|
|
|
pid_t pid ATTRIBUTE_UNUSED,
|
|
|
|
int controllers ATTRIBUTE_UNUSED,
|
2017-07-21 13:51:03 +00:00
|
|
|
char *machinename ATTRIBUTE_UNUSED,
|
2013-08-11 12:04:27 +00:00
|
|
|
virCgroupPtr *group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-10-02 09:05:50 +00:00
|
|
|
|
2016-02-01 15:50:54 +00:00
|
|
|
int virCgroupTerminateMachine(const char *name ATTRIBUTE_UNUSED)
|
2014-10-02 09:05:50 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:29 +00:00
|
|
|
int
|
|
|
|
virCgroupNewMachine(const char *name ATTRIBUTE_UNUSED,
|
|
|
|
const char *drivername ATTRIBUTE_UNUSED,
|
|
|
|
const unsigned char *uuid ATTRIBUTE_UNUSED,
|
|
|
|
const char *rootdir ATTRIBUTE_UNUSED,
|
|
|
|
pid_t pidleader ATTRIBUTE_UNUSED,
|
|
|
|
bool isContainer ATTRIBUTE_UNUSED,
|
2015-01-20 09:00:59 +00:00
|
|
|
size_t nnicindexes ATTRIBUTE_UNUSED,
|
|
|
|
int *nicindexes ATTRIBUTE_UNUSED,
|
2013-08-11 12:04:29 +00:00
|
|
|
const char *partition ATTRIBUTE_UNUSED,
|
|
|
|
int controllers ATTRIBUTE_UNUSED,
|
2019-07-25 07:51:50 +00:00
|
|
|
unsigned int maxthreads ATTRIBUTE_UNUSED,
|
2013-08-11 12:04:29 +00:00
|
|
|
virCgroupPtr *group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
virCgroupNewIgnoreError(void)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("No cgroups present/configured/accessible, ignoring error");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-08-11 12:04:27 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
virCgroupHasController(virCgroupPtr cgroup ATTRIBUTE_UNUSED,
|
|
|
|
int controller ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:28 +00:00
|
|
|
int
|
|
|
|
virCgroupPathOfController(virCgroupPtr group ATTRIBUTE_UNUSED,
|
2018-08-15 15:21:47 +00:00
|
|
|
unsigned int controller ATTRIBUTE_UNUSED,
|
2013-08-11 12:04:28 +00:00
|
|
|
const char *key ATTRIBUTE_UNUSED,
|
|
|
|
char **path ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:29 +00:00
|
|
|
int
|
2018-09-11 13:03:22 +00:00
|
|
|
virCgroupAddProcess(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
pid_t pid ATTRIBUTE_UNUSED)
|
2013-08-11 12:04:29 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-09 14:27:34 +00:00
|
|
|
int
|
2018-09-11 13:03:22 +00:00
|
|
|
virCgroupAddMachineProcess(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
pid_t pid ATTRIBUTE_UNUSED)
|
2017-01-09 14:27:34 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-24 22:54:04 +00:00
|
|
|
int
|
|
|
|
virCgroupAddThread(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
pid_t pid ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-14 17:48:59 +00:00
|
|
|
int
|
|
|
|
virCgroupGetBlkioIoServiced(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
long long *bytes_read ATTRIBUTE_UNUSED,
|
|
|
|
long long *bytes_write ATTRIBUTE_UNUSED,
|
|
|
|
long long *requests_read ATTRIBUTE_UNUSED,
|
|
|
|
long long *requests_write ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
long long *bytes_read ATTRIBUTE_UNUSED,
|
|
|
|
long long *bytes_write ATTRIBUTE_UNUSED,
|
|
|
|
long long *requests_read ATTRIBUTE_UNUSED,
|
|
|
|
long long *requests_write ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:29 +00:00
|
|
|
int
|
|
|
|
virCgroupSetBlkioWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int weight ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int *weight ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:28 +00:00
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int weight ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-12-11 08:29:50 +00:00
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceReadIops(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int riops ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int wiops ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceReadBps(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long rbps ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long wbps ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-08-03 13:10:20 +00:00
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
2015-08-20 06:42:56 +00:00
|
|
|
unsigned int *weight ATTRIBUTE_UNUSED)
|
2015-08-03 13:10:20 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceReadIops(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
2015-08-20 06:42:56 +00:00
|
|
|
unsigned int *riops ATTRIBUTE_UNUSED)
|
2015-08-03 13:10:20 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceWriteIops(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
2015-08-20 06:42:56 +00:00
|
|
|
unsigned int *wiops ATTRIBUTE_UNUSED)
|
2015-08-03 13:10:20 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceReadBps(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
2015-08-20 06:42:56 +00:00
|
|
|
unsigned long long *rbps ATTRIBUTE_UNUSED)
|
2015-08-03 13:10:20 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetBlkioDeviceWriteBps(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
2015-08-20 06:42:56 +00:00
|
|
|
unsigned long long *wbps ATTRIBUTE_UNUSED)
|
2015-08-03 13:10:20 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
2013-08-11 12:04:28 +00:00
|
|
|
|
2013-08-11 12:04:29 +00:00
|
|
|
int
|
|
|
|
virCgroupSetMemory(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long kb ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-13 14:03:03 +00:00
|
|
|
int
|
|
|
|
virCgroupGetMemoryStat(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *cache ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *activeAnon ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *inactiveAnon ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *activeFile ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *inactiveFile ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *unevictable ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:29 +00:00
|
|
|
int
|
|
|
|
virCgroupGetMemoryUsage(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long *kb ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetMemoryHardLimit(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long kb ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetMemoryHardLimit(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *kb ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetMemorySoftLimit(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long kb ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetMemorySoftLimit(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *kb ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetMemSwapHardLimit(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long kb ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetMemSwapHardLimit(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *kb ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetMemSwapUsage(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *kb ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetCpusetMems(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *mems ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpusetMems(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
char **mems ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-03-27 16:13:56 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetCpusetMemoryMigrate(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
bool migrate ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpusetMemoryMigrate(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
bool *migrate ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-08-11 12:04:29 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetCpusetCpus(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *cpus ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpusetCpus(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
char **cpus ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-07-18 08:02:29 +00:00
|
|
|
int
|
|
|
|
virCgroupAllowAllDevices(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
int perms ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
2013-08-11 12:04:29 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupDenyAllDevices(virCgroupPtr group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupAllowDevice(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
char type ATTRIBUTE_UNUSED,
|
|
|
|
int major ATTRIBUTE_UNUSED,
|
|
|
|
int minor ATTRIBUTE_UNUSED,
|
|
|
|
int perms ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:28 +00:00
|
|
|
int
|
|
|
|
virCgroupAllowDevicePath(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
2016-02-16 13:43:41 +00:00
|
|
|
int perms ATTRIBUTE_UNUSED,
|
|
|
|
bool ignoreEaccess ATTRIBUTE_UNUSED)
|
2013-08-11 12:04:28 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:29 +00:00
|
|
|
int
|
|
|
|
virCgroupDenyDevice(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
char type ATTRIBUTE_UNUSED,
|
|
|
|
int major ATTRIBUTE_UNUSED,
|
|
|
|
int minor ATTRIBUTE_UNUSED,
|
|
|
|
int perms ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:28 +00:00
|
|
|
int
|
|
|
|
virCgroupDenyDevicePath(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
2016-02-17 13:25:35 +00:00
|
|
|
int perms ATTRIBUTE_UNUSED,
|
|
|
|
bool ignoreEacces ATTRIBUTE_UNUSED)
|
2013-08-11 12:04:28 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-11 12:04:29 +00:00
|
|
|
int
|
|
|
|
virCgroupSetCpuShares(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long shares ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpuShares(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *shares ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetCpuCfsPeriod(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long cfs_period ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpuCfsPeriod(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *cfs_period ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetCpuCfsQuota(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
long long cfs_quota ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupRemove(virCgroupPtr group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 20:02:26 +00:00
|
|
|
int
|
|
|
|
virCgroupKillRecursive(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
int signum ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupKillPainfully(virCgroupPtr group ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 17:47:13 +00:00
|
|
|
int
|
|
|
|
virCgroupGetCpuCfsQuota(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
long long *cfs_quota ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpuacctUsage(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *usage ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpuacctPercpuUsage(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
char **usage ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetCpuacctStat(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *user ATTRIBUTE_UNUSED,
|
|
|
|
unsigned long long *sys ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-21 08:10:48 +00:00
|
|
|
int
|
|
|
|
virCgroupGetDomainTotalCpuStats(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
virTypedParameterPtr params ATTRIBUTE_UNUSED,
|
|
|
|
int nparams ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 17:47:13 +00:00
|
|
|
int
|
|
|
|
virCgroupSetFreezerState(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *state ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetFreezerState(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
char **state ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 19:52:06 +00:00
|
|
|
int
|
2016-01-26 16:37:29 +00:00
|
|
|
virCgroupBindMount(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
const char *oldroot ATTRIBUTE_UNUSED,
|
|
|
|
const char *mountopts ATTRIBUTE_UNUSED)
|
2013-04-05 11:48:47 +00:00
|
|
|
{
|
2013-07-08 10:08:46 +00:00
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
2013-04-05 11:48:47 +00:00
|
|
|
}
|
2013-08-12 20:02:26 +00:00
|
|
|
|
2013-09-13 14:03:14 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
virCgroupSupportsCpuBW(virCgroupPtr cgroup ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("Control groups not supported on this platform");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-26 00:18:54 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupGetPercpuStats(virCgroupPtr group ATTRIBUTE_UNUSED,
|
|
|
|
virTypedParameterPtr params ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int nparams ATTRIBUTE_UNUSED,
|
|
|
|
int start_cpu ATTRIBUTE_UNUSED,
|
2014-04-09 14:47:26 +00:00
|
|
|
unsigned int ncpus ATTRIBUTE_UNUSED,
|
2016-02-08 13:06:30 +00:00
|
|
|
virBitmapPtr guestvcpus ATTRIBUTE_UNUSED)
|
2014-02-26 00:18:54 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virCgroupSetOwner(virCgroupPtr cgroup ATTRIBUTE_UNUSED,
|
|
|
|
uid_t uid ATTRIBUTE_UNUSED,
|
|
|
|
gid_t gid ATTRIBUTE_UNUSED,
|
|
|
|
int controllers ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-12-13 08:56:00 +00:00
|
|
|
int
|
|
|
|
virCgroupHasEmptyTasks(virCgroupPtr cgroup ATTRIBUTE_UNUSED,
|
|
|
|
int controller ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Control groups not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-03-31 09:39:13 +00:00
|
|
|
bool
|
|
|
|
virCgroupControllerAvailable(int controller ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-27 10:16:57 +00:00
|
|
|
#endif /* !__linux__ */
|
2016-08-04 21:36:38 +00:00
|
|
|
|
|
|
|
|
2019-04-24 13:26:12 +00:00
|
|
|
/**
|
|
|
|
* virCgroupFree:
|
|
|
|
*
|
|
|
|
* @group: The group structure to free
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virCgroupFree(virCgroupPtr *group)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (*group == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
|
|
|
|
VIR_FREE((*group)->legacy[i].mountPoint);
|
|
|
|
VIR_FREE((*group)->legacy[i].linkPoint);
|
|
|
|
VIR_FREE((*group)->legacy[i].placement);
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE((*group)->unified.mountPoint);
|
|
|
|
VIR_FREE((*group)->unified.placement);
|
|
|
|
|
|
|
|
VIR_FREE((*group)->path);
|
|
|
|
VIR_FREE(*group);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-04 21:36:38 +00:00
|
|
|
int
|
|
|
|
virCgroupDelThread(virCgroupPtr cgroup,
|
|
|
|
virCgroupThreadName nameval,
|
|
|
|
int idx)
|
|
|
|
{
|
2018-07-30 09:03:16 +00:00
|
|
|
virCgroupPtr new_cgroup = NULL;
|
2016-08-04 21:36:38 +00:00
|
|
|
|
|
|
|
if (cgroup) {
|
|
|
|
if (virCgroupNewThread(cgroup, nameval, idx, false, &new_cgroup) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Remove the offlined cgroup */
|
|
|
|
virCgroupRemove(new_cgroup);
|
2018-07-30 09:06:31 +00:00
|
|
|
virCgroupFree(&new_cgroup);
|
2016-08-04 21:36:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|