2018-08-17 10:19:59 +02:00
/*
* vircgroupv1 . c : methods for cgroups v1 backend
*
* Copyright ( C ) 2010 - 2015 , 2018 Red Hat , Inc .
* Copyright IBM Corp . 2008
*
* 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
* License along with this library . If not , see
* < http : //www.gnu.org/licenses/>.
*/
# include <config.h>
2020-02-16 23:03:51 +01:00
# include <unistd.h>
vircgroupv1: fix build on non-linux OSes
Cgroups are linux specific and we need to make sure that the code is
compiled only on linux. On different OSes it fails the compilation:
../../src/util/vircgroupv1.c:65:19: error: variable has incomplete type 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:65:12: note: forward declaration of 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:74:12: error: implicit declaration of function 'getmntent_r' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
^
../../src/util/vircgroupv1.c:814:39: error: use of undeclared identifier 'MS_NOSUID'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:49: error: use of undeclared identifier 'MS_NODEV'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:58: error: use of undeclared identifier 'MS_NOEXEC'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:841:65: error: use of undeclared identifier 'MS_BIND'
if (mount(src, group->legacy[i].mountPoint, "none", MS_BIND,
^
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
2018-09-27 12:22:20 +02:00
# ifdef __linux__
2018-09-13 16:27:56 +02:00
# include <mntent.h>
vircgroupv1: fix build on non-linux OSes
Cgroups are linux specific and we need to make sure that the code is
compiled only on linux. On different OSes it fails the compilation:
../../src/util/vircgroupv1.c:65:19: error: variable has incomplete type 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:65:12: note: forward declaration of 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:74:12: error: implicit declaration of function 'getmntent_r' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
^
../../src/util/vircgroupv1.c:814:39: error: use of undeclared identifier 'MS_NOSUID'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:49: error: use of undeclared identifier 'MS_NODEV'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:58: error: use of undeclared identifier 'MS_NOEXEC'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:841:65: error: use of undeclared identifier 'MS_BIND'
if (mount(src, group->legacy[i].mountPoint, "none", MS_BIND,
^
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
2018-09-27 12:22:20 +02:00
# include <sys / stat.h>
2018-08-17 10:04:20 +02:00
# include <sys / mount.h>
vircgroupv1: fix build on non-linux OSes
Cgroups are linux specific and we need to make sure that the code is
compiled only on linux. On different OSes it fails the compilation:
../../src/util/vircgroupv1.c:65:19: error: variable has incomplete type 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:65:12: note: forward declaration of 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:74:12: error: implicit declaration of function 'getmntent_r' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
^
../../src/util/vircgroupv1.c:814:39: error: use of undeclared identifier 'MS_NOSUID'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:49: error: use of undeclared identifier 'MS_NODEV'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:58: error: use of undeclared identifier 'MS_NOEXEC'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:841:65: error: use of undeclared identifier 'MS_BIND'
if (mount(src, group->legacy[i].mountPoint, "none", MS_BIND,
^
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
2018-09-27 12:22:20 +02:00
# endif /* __linux__ */
2018-09-13 16:27:56 +02:00
2018-08-17 10:19:59 +02:00
# include "internal.h"
2018-12-13 14:53:50 +00:00
# define LIBVIRT_VIRCGROUPPRIV_H_ALLOW
2018-08-17 10:19:59 +02:00
# include "vircgrouppriv.h"
# include "vircgroup.h"
# include "vircgroupbackend.h"
# include "vircgroupv1.h"
2018-09-13 16:27:56 +02:00
# include "virfile.h"
2018-08-17 10:19:59 +02:00
# include "virlog.h"
2018-09-14 13:21:19 +02:00
# include "virstring.h"
# include "virsystemd.h"
2018-09-14 12:51:27 +02:00
# include "virerror.h"
2019-04-01 16:28:05 +02:00
# include "viralloc.h"
2021-01-06 12:56:11 +01:00
# include "virthread.h"
2018-08-17 10:19:59 +02:00
VIR_LOG_INIT ( " util.cgroup " ) ;
# define VIR_FROM_THIS VIR_FROM_CGROUP
VIR_ENUM_DECL ( virCgroupV1Controller ) ;
2019-03-16 14:20:32 -04:00
VIR_ENUM_IMPL ( virCgroupV1Controller ,
VIR_CGROUP_CONTROLLER_LAST ,
2018-08-17 10:19:59 +02:00
" cpu " , " cpuacct " , " cpuset " , " memory " , " devices " ,
" freezer " , " blkio " , " net_cls " , " perf_event " ,
2019-01-20 11:30:15 -05:00
" name=systemd " ,
) ;
2018-08-17 10:19:59 +02:00
vircgroupv1: fix build on non-linux OSes
Cgroups are linux specific and we need to make sure that the code is
compiled only on linux. On different OSes it fails the compilation:
../../src/util/vircgroupv1.c:65:19: error: variable has incomplete type 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:65:12: note: forward declaration of 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:74:12: error: implicit declaration of function 'getmntent_r' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
^
../../src/util/vircgroupv1.c:814:39: error: use of undeclared identifier 'MS_NOSUID'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:49: error: use of undeclared identifier 'MS_NODEV'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:58: error: use of undeclared identifier 'MS_NOEXEC'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:841:65: error: use of undeclared identifier 'MS_BIND'
if (mount(src, group->legacy[i].mountPoint, "none", MS_BIND,
^
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
2018-09-27 12:22:20 +02:00
# ifdef __linux__
2018-09-13 16:27:56 +02:00
/* We're looking for at least one 'cgroup' fs mount,
* which is * not * a named mount . */
static bool
virCgroupV1Available ( void )
{
bool ret = false ;
FILE * mounts = NULL ;
struct mntent entry ;
char buf [ CGROUP_MAX_VAL ] ;
if ( ! virFileExists ( " /proc/cgroups " ) )
return false ;
if ( ! ( mounts = fopen ( " /proc/mounts " , " r " ) ) )
return false ;
while ( getmntent_r ( mounts , & entry , buf , sizeof ( buf ) ) ! = NULL ) {
if ( STREQ ( entry . mnt_type , " cgroup " ) & & ! strstr ( entry . mnt_opts , " name= " ) ) {
ret = true ;
break ;
}
}
VIR_FORCE_FCLOSE ( mounts ) ;
return ret ;
}
2018-09-14 13:21:19 +02:00
static bool
2021-03-11 08:16:13 +01:00
virCgroupV1ValidateMachineGroup ( virCgroup * group ,
2018-09-14 13:21:19 +02:00
const char * name ,
const char * drivername ,
const char * machinename )
{
size_t i ;
2019-10-15 15:16:31 +02:00
g_autofree char * partname = NULL ;
g_autofree char * scopename_old = NULL ;
g_autofree char * scopename_new = NULL ;
g_autofree char * partmachinename = NULL ;
2018-09-14 13:21:19 +02:00
2019-10-22 15:26:14 +02:00
partname = g_strdup_printf ( " %s.libvirt-%s " , name , drivername ) ;
2018-09-14 13:21:19 +02:00
if ( virCgroupPartitionEscape ( & partname ) < 0 )
return false ;
2019-10-22 15:26:14 +02:00
partmachinename = g_strdup_printf ( " %s.libvirt-%s " ,
machinename , drivername ) ;
if ( virCgroupPartitionEscape ( & partmachinename ) < 0 )
2018-09-14 13:21:19 +02:00
return false ;
if ( ! ( scopename_old = virSystemdMakeScopeName ( name , drivername , true ) ) )
return false ;
if ( ! ( scopename_new = virSystemdMakeScopeName ( machinename ,
drivername , false ) ) )
return false ;
if ( virCgroupPartitionEscape ( & scopename_old ) < 0 )
return false ;
if ( virCgroupPartitionEscape ( & scopename_new ) < 0 )
return false ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
char * tmp ;
if ( i = = VIR_CGROUP_CONTROLLER_SYSTEMD )
continue ;
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . placement )
2018-09-14 13:21:19 +02:00
continue ;
2018-09-25 01:17:02 +02:00
tmp = strrchr ( group - > legacy [ i ] . placement , ' / ' ) ;
2018-09-14 13:21:19 +02:00
if ( ! tmp )
return false ;
if ( i = = VIR_CGROUP_CONTROLLER_CPU | |
i = = VIR_CGROUP_CONTROLLER_CPUACCT | |
i = = VIR_CGROUP_CONTROLLER_CPUSET ) {
if ( STREQ ( tmp , " /emulator " ) )
* tmp = ' \0 ' ;
2018-09-25 01:17:02 +02:00
tmp = strrchr ( group - > legacy [ i ] . placement , ' / ' ) ;
2018-09-14 13:21:19 +02:00
if ( ! tmp )
return false ;
}
tmp + + ;
if ( STRNEQ ( tmp , name ) & &
STRNEQ ( tmp , machinename ) & &
STRNEQ ( tmp , partname ) & &
STRNEQ ( tmp , partmachinename ) & &
STRNEQ ( tmp , scopename_old ) & &
STRNEQ ( tmp , scopename_new ) ) {
VIR_DEBUG ( " Name '%s' for controller '%s' does not match "
" '%s', '%s', '%s', '%s' or '%s' " ,
tmp , virCgroupV1ControllerTypeToString ( i ) ,
name , machinename , partname ,
scopename_old , scopename_new ) ;
return false ;
}
}
return true ;
}
2018-08-17 09:46:10 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1CopyMounts ( virCgroup * group ,
virCgroup * parent )
2018-08-17 09:46:10 +02:00
{
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
2018-09-25 01:17:02 +02:00
if ( ! parent - > legacy [ i ] . mountPoint )
2018-08-17 09:46:10 +02:00
continue ;
2019-10-20 13:49:46 +02:00
group - > legacy [ i ] . mountPoint = g_strdup ( parent - > legacy [ i ] . mountPoint ) ;
2018-08-17 09:46:10 +02:00
2019-10-20 13:49:46 +02:00
group - > legacy [ i ] . linkPoint = g_strdup ( parent - > legacy [ i ] . linkPoint ) ;
2018-08-17 09:46:10 +02:00
}
return 0 ;
}
2018-09-14 12:53:47 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1CopyPlacement ( virCgroup * group ,
2018-09-14 12:53:47 +02:00
const char * path ,
2021-03-11 08:16:13 +01:00
virCgroup * parent )
2018-09-14 12:53:47 +02:00
{
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
2020-11-02 23:06:19 +01:00
bool delim ;
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . mountPoint )
2018-09-14 12:53:47 +02:00
continue ;
if ( i = = VIR_CGROUP_CONTROLLER_SYSTEMD )
continue ;
2020-11-02 23:06:19 +01:00
delim = STREQ ( parent - > legacy [ i ] . placement , " / " ) | | STREQ ( path , " " ) ;
/*
* parent = = " / " + path = " " = > " / "
* parent = = " /libvirt.service " + path = = " " = > " /libvirt.service "
* parent = = " /libvirt.service " + path = = " foo " = > " /libvirt.service/foo "
*/
group - > legacy [ i ] . placement = g_strdup_printf ( " %s%s%s " ,
parent - > legacy [ i ] . placement ,
delim ? " " : " / " ,
path ) ;
2018-09-14 12:53:47 +02:00
}
return 0 ;
}
2018-09-14 12:51:27 +02:00
static int
virCgroupV1ResolveMountLink ( const char * mntDir ,
const char * typeStr ,
2021-03-11 08:16:13 +01:00
virCgroupV1Controller * controller )
2018-09-14 12:51:27 +02:00
{
2019-10-15 15:16:31 +02:00
g_autofree char * linkSrc = NULL ;
g_autofree char * tmp = NULL ;
2018-09-14 12:51:27 +02:00
char * dirName ;
2019-12-24 15:19:17 +00:00
GStatBuf sb ;
2018-09-14 12:51:27 +02:00
2019-10-20 13:49:46 +02:00
tmp = g_strdup ( mntDir ) ;
2018-09-14 12:51:27 +02:00
dirName = strrchr ( tmp , ' / ' ) ;
if ( ! dirName ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Missing '/' separator in cgroup mount '%1$s' " ) , tmp ) ;
2018-09-14 12:51:27 +02:00
return - 1 ;
}
if ( ! strchr ( dirName + 1 , ' , ' ) )
return 0 ;
* dirName = ' \0 ' ;
2019-10-22 15:26:14 +02:00
linkSrc = g_strdup_printf ( " %s/%s " , tmp , typeStr ) ;
2018-09-14 12:51:27 +02:00
* dirName = ' / ' ;
2019-12-24 15:19:17 +00:00
if ( g_lstat ( linkSrc , & sb ) < 0 ) {
2018-09-14 12:51:27 +02:00
if ( errno = = ENOENT ) {
VIR_WARN ( " Controller %s co-mounted at %s is missing symlink at %s " ,
typeStr , tmp , linkSrc ) ;
} else {
2023-03-09 15:11:50 +01:00
virReportSystemError ( errno , _ ( " Cannot stat %1$s " ) , linkSrc ) ;
2018-09-14 12:51:27 +02:00
return - 1 ;
}
} else {
if ( ! S_ISLNK ( sb . st_mode ) ) {
VIR_WARN ( " Expecting a symlink at %s for controller %s " ,
linkSrc , typeStr ) ;
} else {
2019-10-16 13:43:52 +02:00
controller - > linkPoint = g_steal_pointer ( & linkSrc ) ;
2018-09-14 12:51:27 +02:00
}
}
return 0 ;
}
static bool
virCgroupV1MountOptsMatchController ( const char * mntOpts ,
const char * typeStr )
{
const char * tmp = mntOpts ;
int typeLen = strlen ( typeStr ) ;
while ( tmp ) {
const char * next = strchr ( tmp , ' , ' ) ;
int len ;
if ( next ) {
len = next - tmp ;
next + + ;
} else {
len = strlen ( tmp ) ;
}
if ( typeLen = = len & & STREQLEN ( typeStr , tmp , len ) )
return true ;
tmp = next ;
}
return false ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1DetectMounts ( virCgroup * group ,
2018-09-14 12:51:27 +02:00
const char * mntType ,
const char * mntOpts ,
const char * mntDir )
{
size_t i ;
if ( STRNEQ ( mntType , " cgroup " ) )
return 0 ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
const char * typestr = virCgroupV1ControllerTypeToString ( i ) ;
if ( virCgroupV1MountOptsMatchController ( mntOpts , typestr ) ) {
/* Note that the lines in /proc/mounts have the same
* order than the mount operations , and that there may
* be duplicates due to bind mounts . This means
* that the same mount point may be processed more than
* once . We need to save the results of the last one ,
* and we need to be careful to release the memory used
* by previous processing . */
2021-03-11 08:16:13 +01:00
virCgroupV1Controller * controller = & group - > legacy [ i ] ;
2018-09-14 12:51:27 +02:00
VIR_FREE ( controller - > mountPoint ) ;
VIR_FREE ( controller - > linkPoint ) ;
2019-10-20 13:49:46 +02:00
controller - > mountPoint = g_strdup ( mntDir ) ;
2018-09-14 12:51:27 +02:00
/* If it is a co-mount it has a filename like "cpu,cpuacct"
* and we must identify the symlink path */
if ( virCgroupV1ResolveMountLink ( mntDir , typestr , controller ) < 0 )
return - 1 ;
}
}
return 0 ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1DetectPlacement ( virCgroup * group ,
2018-09-14 12:51:27 +02:00
const char * path ,
const char * controllers ,
const char * selfpath )
{
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
const char * typestr = virCgroupV1ControllerTypeToString ( i ) ;
2021-02-09 12:33:53 +01:00
g_autofree char * placement = NULL ;
char * tmp = NULL ;
2018-09-14 12:51:27 +02:00
2020-11-04 19:46:24 +01:00
if ( ! virCgroupV1MountOptsMatchController ( controllers , typestr ) )
continue ;
if ( ! group - > legacy [ i ] . mountPoint )
continue ;
if ( group - > legacy [ i ] . placement )
continue ;
2021-02-09 12:33:53 +01:00
/* On systemd we create a nested cgroup for some cgroup tasks
* but the placement should point to the root cgroup . */
placement = g_strdup ( selfpath ) ;
tmp = g_strrstr ( placement , " /libvirt " ) ;
if ( tmp )
* tmp = ' \0 ' ;
2020-11-04 19:46:24 +01:00
/*
* selfpath = = " / " + path = " " - > " / "
* selfpath = = " /libvirt.service " + path = = " " - > " /libvirt.service "
* selfpath = = " /libvirt.service " + path = = " foo " - > " /libvirt.service/foo "
*/
if ( i = = VIR_CGROUP_CONTROLLER_SYSTEMD ) {
2021-02-09 12:33:53 +01:00
group - > legacy [ i ] . placement = g_strdup ( placement ) ;
2020-11-04 19:46:24 +01:00
} else {
2021-02-09 12:33:53 +01:00
bool delim = STREQ ( placement , " / " ) | | STREQ ( path , " " ) ;
2020-11-04 19:46:24 +01:00
2021-02-09 12:33:53 +01:00
group - > legacy [ i ] . placement = g_strdup_printf ( " %s%s%s " , placement ,
2020-11-04 19:46:24 +01:00
delim ? " " : " / " ,
path ) ;
2018-09-14 12:51:27 +02:00
}
}
return 0 ;
}
2020-10-21 14:35:48 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetPlacement ( virCgroup * group ,
2020-10-21 14:35:48 +02:00
const char * path )
{
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
if ( ! group - > legacy [ i ] . mountPoint )
continue ;
if ( i = = VIR_CGROUP_CONTROLLER_SYSTEMD )
continue ;
group - > legacy [ i ] . placement = g_strdup ( path ) ;
}
return 0 ;
}
2018-08-24 15:15:23 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1ValidatePlacement ( virCgroup * group ,
2018-08-24 15:15:23 +02:00
pid_t pid )
{
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . mountPoint )
2018-08-24 15:15:23 +02:00
continue ;
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . placement ) {
2018-08-24 15:15:23 +02:00
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Could not find placement for v1 controller %1$s " ) ,
2022-05-25 18:20:40 -04:00
virCgroupV1ControllerTypeToString ( i ) ) ;
2018-08-24 15:15:23 +02:00
return - 1 ;
}
VIR_DEBUG ( " Detected mount/mapping %zu:%s at %s in %s for pid %lld " ,
i ,
virCgroupV1ControllerTypeToString ( i ) ,
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ,
group - > legacy [ i ] . placement ,
2018-08-24 15:15:23 +02:00
( long long ) pid ) ;
}
return 0 ;
}
2018-08-17 12:00:29 +02:00
static char *
2021-03-11 08:16:13 +01:00
virCgroupV1StealPlacement ( virCgroup * group )
2018-08-17 12:00:29 +02:00
{
2019-10-17 10:10:10 +02:00
return g_steal_pointer ( & group - > legacy [ VIR_CGROUP_CONTROLLER_SYSTEMD ] . placement ) ;
2018-08-17 12:00:29 +02:00
}
2018-09-25 01:12:22 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1DetectControllers ( virCgroup * group ,
2019-07-22 14:37:36 +02:00
int controllers ,
2021-03-11 08:16:13 +01:00
virCgroup * parent G_GNUC_UNUSED ,
2019-11-14 11:44:42 +01:00
int detected )
2018-09-25 01:12:22 +02:00
{
size_t i ;
size_t j ;
if ( controllers > = 0 ) {
VIR_DEBUG ( " Filtering controllers %d " , controllers ) ;
/* First mark requested but non-existing controllers to be ignored */
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
if ( ( ( 1 < < i ) & controllers ) ) {
2019-11-14 11:44:42 +01:00
int type = 1 < < i ;
if ( type & detected ) {
VIR_FREE ( group - > legacy [ i ] . mountPoint ) ;
VIR_FREE ( group - > legacy [ i ] . placement ) ;
}
2018-09-25 01:12:22 +02:00
/* Remove non-existent controllers */
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . mountPoint ) {
2018-09-25 01:12:22 +02:00
VIR_DEBUG ( " Requested controller '%s' not mounted, ignoring " ,
virCgroupV1ControllerTypeToString ( i ) ) ;
controllers & = ~ ( 1 < < i ) ;
}
}
}
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
VIR_DEBUG ( " Controller '%s' wanted=%s, mount='%s' " ,
virCgroupV1ControllerTypeToString ( i ) ,
( 1 < < i ) & controllers ? " yes " : " no " ,
2018-09-25 01:17:02 +02:00
NULLSTR ( group - > legacy [ i ] . mountPoint ) ) ;
2018-09-25 01:12:22 +02:00
if ( ! ( ( 1 < < i ) & controllers ) & &
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ) {
2018-09-25 01:12:22 +02:00
/* Check whether a request to disable a controller
* clashes with co - mounting of controllers */
for ( j = 0 ; j < VIR_CGROUP_CONTROLLER_LAST ; j + + ) {
if ( j = = i )
continue ;
if ( ! ( ( 1 < < j ) & controllers ) )
continue ;
2018-09-25 01:17:02 +02:00
if ( STREQ_NULLABLE ( group - > legacy [ i ] . mountPoint ,
group - > legacy [ j ] . mountPoint ) ) {
2018-09-25 01:12:22 +02:00
virReportSystemError ( EINVAL ,
2023-03-09 15:11:50 +01:00
_ ( " V1 controller '%1$s' is not wanted, but '%2$s' is co-mounted " ) ,
2018-09-25 01:12:22 +02:00
virCgroupV1ControllerTypeToString ( i ) ,
virCgroupV1ControllerTypeToString ( j ) ) ;
return - 1 ;
}
}
2018-09-25 01:17:02 +02:00
VIR_FREE ( group - > legacy [ i ] . mountPoint ) ;
2019-06-20 13:02:57 +02:00
VIR_FREE ( group - > legacy [ i ] . placement ) ;
2018-09-25 01:12:22 +02:00
}
}
} else {
VIR_DEBUG ( " Auto-detecting controllers " ) ;
controllers = 0 ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
2019-11-14 11:44:42 +01:00
int type = 1 < < i ;
if ( type & detected ) {
VIR_FREE ( group - > legacy [ i ] . mountPoint ) ;
VIR_FREE ( group - > legacy [ i ] . placement ) ;
}
2018-09-25 01:12:22 +02:00
VIR_DEBUG ( " Controller '%s' present=%s " ,
virCgroupV1ControllerTypeToString ( i ) ,
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ? " yes " : " no " ) ;
if ( group - > legacy [ i ] . mountPoint = = NULL )
2018-09-25 01:12:22 +02:00
continue ;
controllers | = ( 1 < < i ) ;
}
}
return controllers ;
}
2018-08-19 19:17:27 +02:00
static bool
2021-03-11 08:16:13 +01:00
virCgroupV1HasController ( virCgroup * group ,
2018-08-19 19:17:27 +02:00
int controller )
{
2018-09-25 01:17:02 +02:00
return group - > legacy [ controller ] . mountPoint ! = NULL ;
2018-08-19 19:17:27 +02:00
}
2018-08-19 19:20:25 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetAnyController ( virCgroup * group )
2018-08-19 19:20:25 +02:00
{
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
/* Reject any controller with a placement
* of ' / ' to avoid doing bad stuff to the root
* cgroup
*/
2018-09-25 01:17:02 +02:00
if ( group - > legacy [ i ] . mountPoint & &
group - > legacy [ i ] . placement & &
STRNEQ ( group - > legacy [ i ] . placement , " / " ) ) {
2018-08-19 19:20:25 +02:00
return i ;
}
}
return - 1 ;
}
2018-08-19 19:24:58 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1PathOfController ( virCgroup * group ,
2018-08-19 19:24:58 +02:00
int controller ,
const char * key ,
char * * path )
{
2018-09-25 01:17:02 +02:00
if ( group - > legacy [ controller ] . mountPoint = = NULL ) {
2018-08-19 19:24:58 +02:00
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " v1 controller '%1$s' is not mounted " ) ,
2018-08-19 19:24:58 +02:00
virCgroupV1ControllerTypeToString ( controller ) ) ;
return - 1 ;
}
2018-09-25 01:17:02 +02:00
if ( group - > legacy [ controller ] . placement = = NULL ) {
2018-08-19 19:24:58 +02:00
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " v1 controller '%1$s' is not enabled for group " ) ,
2018-08-19 19:24:58 +02:00
virCgroupV1ControllerTypeToString ( controller ) ) ;
return - 1 ;
}
2019-10-22 15:26:14 +02:00
* path = g_strdup_printf ( " %s%s/%s " , group - > legacy [ controller ] . mountPoint ,
group - > legacy [ controller ] . placement , NULLSTR_EMPTY ( key ) ) ;
2018-08-19 19:24:58 +02:00
return 0 ;
}
2018-09-18 16:11:47 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1CpuSetInherit ( virCgroup * parent ,
virCgroup * group )
2018-09-18 16:11:47 +02:00
{
size_t i ;
const char * inherit_values [ ] = {
" cpuset.cpus " ,
" cpuset.mems " ,
" cpuset.memory_migrate " ,
} ;
2020-10-14 10:29:45 +02:00
VIR_DEBUG ( " Setting up inheritance %s -> %s " ,
parent - > legacy [ VIR_CGROUP_CONTROLLER_CPUSET ] . placement ,
group - > legacy [ VIR_CGROUP_CONTROLLER_CPUSET ] . placement ) ;
2019-10-15 13:55:26 +02:00
for ( i = 0 ; i < G_N_ELEMENTS ( inherit_values ) ; i + + ) {
2019-10-15 15:16:31 +02:00
g_autofree char * value = NULL ;
2018-09-18 16:11:47 +02:00
if ( virCgroupGetValueStr ( parent ,
VIR_CGROUP_CONTROLLER_CPUSET ,
inherit_values [ i ] ,
& value ) < 0 )
return - 1 ;
VIR_DEBUG ( " Inherit %s = %s " , inherit_values [ i ] , value ) ;
if ( virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_CPUSET ,
inherit_values [ i ] ,
value ) < 0 )
return - 1 ;
}
return 0 ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetMemoryUseHierarchy ( virCgroup * group )
2018-09-18 16:11:47 +02:00
{
unsigned long long value ;
const char * filename = " memory.use_hierarchy " ;
if ( virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
filename , & value ) < 0 )
return - 1 ;
/* Setting twice causes error, so if already enabled, skip setting */
if ( value = = 1 )
return 0 ;
if ( virCgroupSetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
filename , 1 ) < 0 )
return - 1 ;
return 0 ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1MakeGroup ( virCgroup * parent ,
virCgroup * group ,
2018-09-18 16:11:47 +02:00
bool create ,
2020-11-04 19:55:44 +01:00
pid_t pid G_GNUC_UNUSED ,
2018-09-18 16:11:47 +02:00
unsigned int flags )
{
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
2019-10-15 15:16:31 +02:00
g_autofree char * path = NULL ;
2018-09-18 16:11:47 +02:00
/* We must never mkdir() in systemd's hierarchy */
if ( i = = VIR_CGROUP_CONTROLLER_SYSTEMD ) {
VIR_DEBUG ( " Not creating systemd controller group " ) ;
continue ;
}
/* Skip over controllers that aren't mounted */
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . mountPoint ) {
2018-09-18 16:11:47 +02:00
VIR_DEBUG ( " Skipping unmounted controller %s " ,
virCgroupV1ControllerTypeToString ( i ) ) ;
continue ;
}
if ( virCgroupV1PathOfController ( group , i , " " , & path ) < 0 )
return - 1 ;
VIR_DEBUG ( " Make controller %s " , path ) ;
if ( ! virFileExists ( path ) ) {
if ( ! create | |
mkdir ( path , 0755 ) < 0 ) {
if ( errno = = EEXIST )
continue ;
/* With a kernel that doesn't support multi-level directory
* for blkio controller , libvirt will fail and disable all
* other controllers even though they are available . So
* treat blkio as unmounted if mkdir fails . */
if ( i = = VIR_CGROUP_CONTROLLER_BLKIO ) {
VIR_DEBUG ( " Ignoring mkdir failure with blkio controller. Kernel probably too old " ) ;
2018-09-25 01:17:02 +02:00
VIR_FREE ( group - > legacy [ i ] . mountPoint ) ;
2018-09-18 16:11:47 +02:00
continue ;
} else {
virReportSystemError ( errno ,
2023-03-09 15:11:50 +01:00
_ ( " Failed to create v1 controller %1$s for group " ) ,
2018-09-18 16:11:47 +02:00
virCgroupV1ControllerTypeToString ( i ) ) ;
return - 1 ;
}
}
if ( i = = VIR_CGROUP_CONTROLLER_CPUSET & &
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ! = NULL & &
2018-09-18 16:11:47 +02:00
virCgroupV1CpuSetInherit ( parent , group ) < 0 ) {
return - 1 ;
}
/*
* Note that virCgroupV1SetMemoryUseHierarchy should always be
* called prior to creating subcgroups and attaching tasks .
*/
if ( ( flags & VIR_CGROUP_MEM_HIERACHY ) & &
i = = VIR_CGROUP_CONTROLLER_MEMORY & &
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ! = NULL & &
2018-09-18 16:11:47 +02:00
virCgroupV1SetMemoryUseHierarchy ( group ) < 0 ) {
return - 1 ;
}
}
}
VIR_DEBUG ( " Done making controllers for group " ) ;
return 0 ;
}
2021-02-09 12:31:13 +01:00
static bool
2021-03-11 08:16:13 +01:00
virCgroupV1Exists ( virCgroup * group )
2021-02-09 12:31:13 +01:00
{
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
g_autofree char * path = NULL ;
if ( i = = VIR_CGROUP_CONTROLLER_SYSTEMD )
continue ;
if ( ! group - > legacy [ i ] . mountPoint )
continue ;
if ( virCgroupV1PathOfController ( group , i , " " , & path ) < 0 )
return false ;
if ( ! virFileExists ( path ) ) {
return false ;
}
}
return true ;
}
2018-08-17 10:02:05 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1Remove ( virCgroup * group )
2018-08-17 10:02:05 +02:00
{
int rc = 0 ;
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
2019-10-15 15:16:31 +02:00
g_autofree char * grppath = NULL ;
2018-08-17 10:02:05 +02:00
/* Skip over controllers not mounted */
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . mountPoint )
2018-08-17 10:02:05 +02:00
continue ;
/* We must never rmdir() in systemd's hierarchy */
if ( i = = VIR_CGROUP_CONTROLLER_SYSTEMD )
continue ;
/* Don't delete the root group, if we accidentally
ended up in it for some reason */
2018-09-25 01:17:02 +02:00
if ( STREQ ( group - > legacy [ i ] . placement , " / " ) )
2018-08-17 10:02:05 +02:00
continue ;
if ( virCgroupV1PathOfController ( group ,
i ,
NULL ,
& grppath ) ! = 0 )
continue ;
VIR_DEBUG ( " Removing cgroup %s and all child cgroups " , grppath ) ;
rc = virCgroupRemoveRecursively ( grppath ) ;
}
return rc ;
}
2018-09-25 01:14:36 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1AddTask ( virCgroup * group ,
2018-09-25 01:14:36 +02:00
pid_t pid ,
unsigned int flags )
{
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
/* Skip over controllers not mounted */
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . mountPoint )
2018-09-25 01:14:36 +02:00
continue ;
/* We must never add tasks in systemd's hierarchy
* unless we ' re intentionally trying to move a
* task into a systemd machine scope */
if ( i = = VIR_CGROUP_CONTROLLER_SYSTEMD & &
! ( flags & VIR_CGROUP_TASK_SYSTEMD ) )
continue ;
if ( virCgroupSetValueI64 ( group , i , " tasks " , pid ) < 0 )
2019-10-21 15:19:04 -03:00
return - 1 ;
2018-09-25 01:14:36 +02:00
}
2019-10-21 15:19:04 -03:00
return 0 ;
2018-09-25 01:14:36 +02:00
}
2018-08-17 15:25:48 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1HasEmptyTasks ( virCgroup * cgroup ,
2018-08-17 15:25:48 +02:00
int controller )
{
int ret = - 1 ;
2019-10-15 15:16:31 +02:00
g_autofree char * content = NULL ;
2018-08-17 15:25:48 +02:00
if ( ! cgroup )
return - 1 ;
ret = virCgroupGetValueStr ( cgroup , controller , " tasks " , & content ) ;
if ( ret = = 0 & & content [ 0 ] = = ' \0 ' )
ret = 1 ;
return ret ;
}
2018-12-10 16:51:14 +08:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1KillRecursive ( virCgroup * group ,
2018-12-10 16:51:14 +08:00
int signum ,
2020-10-20 17:01:51 +02:00
GHashTable * pids )
2018-12-10 16:51:14 +08:00
{
2021-04-16 16:39:14 +02:00
return virCgroupKillRecursiveInternal ( group , signum , pids ,
2018-12-10 16:51:14 +08:00
" tasks " , false ) ;
}
2018-08-17 10:04:20 +02:00
static char *
2021-03-11 08:16:13 +01:00
virCgroupV1IdentifyRoot ( virCgroup * group )
2018-08-17 10:04:20 +02:00
{
char * ret = NULL ;
size_t i ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
char * tmp ;
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . mountPoint )
2018-08-17 10:04:20 +02:00
continue ;
2018-09-25 01:17:02 +02:00
if ( ! ( tmp = strrchr ( group - > legacy [ i ] . mountPoint , ' / ' ) ) ) {
2018-08-17 10:04:20 +02:00
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Could not find directory separator in %1$s " ) ,
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ) ;
2018-08-17 10:04:20 +02:00
return NULL ;
}
2019-10-24 19:41:34 +02:00
ret = g_strndup ( group - > legacy [ i ] . mountPoint ,
tmp - group - > legacy [ i ] . mountPoint ) ;
2018-08-17 10:04:20 +02:00
return ret ;
}
virReportError ( VIR_ERR_INTERNAL_ERROR , " %s " ,
_ ( " Could not find any mounted v1 controllers " ) ) ;
return NULL ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1BindMount ( virCgroup * group ,
2018-08-17 10:04:20 +02:00
const char * oldroot ,
const char * mountopts )
{
size_t i ;
2019-10-15 15:16:31 +02:00
g_autofree char * opts = NULL ;
g_autofree char * root = NULL ;
2018-08-17 10:04:20 +02:00
if ( ! ( root = virCgroupV1IdentifyRoot ( group ) ) )
return - 1 ;
VIR_DEBUG ( " Mounting cgroups at '%s' " , root ) ;
2021-02-26 09:37:10 +01:00
if ( g_mkdir_with_parents ( root , 0777 ) < 0 ) {
2018-08-17 10:04:20 +02:00
virReportSystemError ( errno ,
2023-03-09 15:11:50 +01:00
_ ( " Unable to create directory %1$s " ) ,
2018-08-17 10:04:20 +02:00
root ) ;
return - 1 ;
}
2019-10-22 15:26:14 +02:00
opts = g_strdup_printf ( " mode=755,size=65536%s " , mountopts ) ;
2018-08-17 10:04:20 +02:00
if ( mount ( " tmpfs " , root , " tmpfs " , MS_NOSUID | MS_NODEV | MS_NOEXEC , opts ) < 0 ) {
virReportSystemError ( errno ,
2023-03-09 15:11:50 +01:00
_ ( " Failed to mount %1$s on %2$s type %3$s " ) ,
2018-08-17 10:04:20 +02:00
" tmpfs " , root , " tmpfs " ) ;
return - 1 ;
}
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
2018-09-25 01:17:02 +02:00
if ( ! group - > legacy [ i ] . mountPoint )
2018-08-17 10:04:20 +02:00
continue ;
2018-09-25 01:17:02 +02:00
if ( ! virFileExists ( group - > legacy [ i ] . mountPoint ) ) {
2019-10-15 15:16:31 +02:00
g_autofree char * src = NULL ;
2019-10-22 15:26:14 +02:00
src = g_strdup_printf ( " %s%s " , oldroot , group - > legacy [ i ] . mountPoint ) ;
2018-08-17 10:04:20 +02:00
VIR_DEBUG ( " Create mount point '%s' " ,
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ) ;
2021-02-26 09:37:10 +01:00
if ( g_mkdir_with_parents ( group - > legacy [ i ] . mountPoint , 0777 ) < 0 ) {
2018-08-17 10:04:20 +02:00
virReportSystemError ( errno ,
2023-03-09 15:11:50 +01:00
_ ( " Unable to create directory %1$s " ) ,
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ) ;
2018-08-17 10:04:20 +02:00
return - 1 ;
}
2018-09-25 01:17:02 +02:00
if ( mount ( src , group - > legacy [ i ] . mountPoint , " none " , MS_BIND ,
2018-08-17 10:04:20 +02:00
NULL ) < 0 ) {
virReportSystemError ( errno ,
2023-03-09 15:11:50 +01:00
_ ( " Failed to bind cgroup '%1$s' on '%2$s' " ) ,
2018-09-25 01:17:02 +02:00
src , group - > legacy [ i ] . mountPoint ) ;
2018-08-17 10:04:20 +02:00
return - 1 ;
}
}
2018-09-25 01:17:02 +02:00
if ( group - > legacy [ i ] . linkPoint ) {
2018-08-17 10:04:20 +02:00
VIR_DEBUG ( " Link mount point '%s' to '%s' " ,
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ,
group - > legacy [ i ] . linkPoint ) ;
if ( symlink ( group - > legacy [ i ] . mountPoint ,
group - > legacy [ i ] . linkPoint ) < 0 ) {
2018-08-17 10:04:20 +02:00
virReportSystemError ( errno ,
2023-03-09 15:11:50 +01:00
_ ( " Unable to symlink directory %1$s to %2$s " ) ,
2018-09-25 01:17:02 +02:00
group - > legacy [ i ] . mountPoint ,
group - > legacy [ i ] . linkPoint ) ;
2018-08-17 10:04:20 +02:00
return - 1 ;
}
}
}
return 0 ;
}
2018-08-17 10:09:49 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetOwner ( virCgroup * cgroup ,
2018-08-17 10:09:49 +02:00
uid_t uid ,
gid_t gid ,
int controllers )
{
size_t i ;
int direrr ;
for ( i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i + + ) {
2019-10-15 15:16:31 +02:00
g_autofree char * base = NULL ;
2018-08-17 10:09:49 +02:00
struct dirent * de ;
2020-10-25 17:50:51 -04:00
g_autoptr ( DIR ) dh = NULL ;
2018-08-17 10:09:49 +02:00
if ( ! ( ( 1 < < i ) & controllers ) )
continue ;
2018-09-25 01:17:02 +02:00
if ( ! cgroup - > legacy [ i ] . mountPoint )
2018-08-17 10:09:49 +02:00
continue ;
2019-10-22 15:26:14 +02:00
base = g_strdup_printf ( " %s%s " , cgroup - > legacy [ i ] . mountPoint ,
cgroup - > legacy [ i ] . placement ) ;
2018-08-17 10:09:49 +02:00
if ( virDirOpen ( & dh , base ) < 0 )
2021-11-04 15:26:07 +01:00
return - 1 ;
2018-08-17 10:09:49 +02:00
while ( ( direrr = virDirRead ( dh , & de , base ) ) > 0 ) {
2019-10-15 15:16:31 +02:00
g_autofree char * entry = NULL ;
2018-08-17 10:09:49 +02:00
2019-10-22 15:26:14 +02:00
entry = g_strdup_printf ( " %s/%s " , base , de - > d_name ) ;
2018-08-17 10:09:49 +02:00
if ( chown ( entry , uid , gid ) < 0 ) {
virReportSystemError ( errno ,
2023-03-09 15:11:50 +01:00
_ ( " cannot chown '%1$s' to (%2$u, %3$u) " ) ,
2018-08-17 10:09:49 +02:00
entry , uid , gid ) ;
2021-11-04 15:26:07 +01:00
return - 1 ;
2018-08-17 10:09:49 +02:00
}
}
if ( direrr < 0 )
2021-11-04 15:26:07 +01:00
return - 1 ;
2018-08-17 10:09:49 +02:00
if ( chown ( base , uid , gid ) < 0 ) {
virReportSystemError ( errno ,
2023-03-09 15:11:50 +01:00
_ ( " cannot chown '%1$s' to (%2$u, %3$u) " ) ,
2018-08-17 10:09:49 +02:00
base , uid , gid ) ;
2021-11-04 15:26:07 +01:00
return - 1 ;
2018-08-17 10:09:49 +02:00
}
}
2021-11-04 15:26:07 +01:00
return 0 ;
2018-08-17 10:09:49 +02:00
}
2018-08-17 15:28:50 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetBlkioWeight ( virCgroup * group ,
2018-08-17 15:28:50 +02:00
unsigned int weight )
{
2019-10-15 15:16:31 +02:00
g_autofree char * path = NULL ;
2019-06-18 15:15:43 +02:00
if ( virCgroupV1PathOfController ( group , VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.bfq.weight " , & path ) < 0 ) {
return - 1 ;
}
if ( ! virFileExists ( path ) ) {
VIR_FREE ( path ) ;
if ( virCgroupV1PathOfController ( group , VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.weight " , & path ) < 0 ) {
return - 1 ;
}
}
if ( ! virFileExists ( path ) ) {
virReportError ( VIR_ERR_OPERATION_INVALID , " %s " ,
_ ( " blkio device weight is valid only for bfq or cfq scheduler " ) ) ;
return - 1 ;
}
2021-02-05 16:17:35 +01:00
if ( group - > unitName ) {
GVariant * value = g_variant_new ( " t " , weight ) ;
return virCgroupSetValueDBus ( group - > unitName , " BlockIOWeight " , value ) ;
} else {
g_autofree char * value = g_strdup_printf ( " %u " , weight ) ;
2019-06-18 15:15:43 +02:00
2021-02-05 16:17:35 +01:00
return virCgroupSetValueRaw ( path , value ) ;
}
2018-08-17 15:28:50 +02:00
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetBlkioWeight ( virCgroup * group ,
2018-08-17 15:28:50 +02:00
unsigned int * weight )
{
2019-10-15 15:16:31 +02:00
g_autofree char * path = NULL ;
g_autofree char * value = NULL ;
2019-06-18 15:15:43 +02:00
if ( virCgroupV1PathOfController ( group , VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.bfq.weight " , & path ) < 0 ) {
return - 1 ;
}
if ( ! virFileExists ( path ) ) {
VIR_FREE ( path ) ;
if ( virCgroupV1PathOfController ( group , VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.weight " , & path ) < 0 ) {
return - 1 ;
}
}
if ( ! virFileExists ( path ) ) {
virReportError ( VIR_ERR_OPERATION_INVALID , " %s " ,
_ ( " blkio device weight is valid only for bfq or cfq scheduler " ) ) ;
return - 1 ;
}
if ( virCgroupGetValueRaw ( path , & value ) < 0 )
return - 1 ;
if ( virStrToLong_ui ( value , NULL , 10 , weight ) < 0 ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Unable to parse '%1$s' as an integer " ) ,
2019-06-18 15:15:43 +02:00
value ) ;
return - 1 ;
}
return 0 ;
2018-08-17 15:28:50 +02:00
}
2023-04-12 14:46:04 +02:00
2018-08-17 15:29:39 +02:00
static int
2023-04-12 14:46:04 +02:00
virCgroupV1GetBlkioIoServicedOne ( virCgroup * group ,
const char * field ,
const char * devpath ,
long long * dataRead ,
long long * dataWrite )
2018-08-17 15:29:39 +02:00
{
2023-04-12 14:46:04 +02:00
g_autofree char * serviced = NULL ;
g_autofree char * filterWrite = NULL ;
g_autofree char * filterRead = NULL ;
unsigned long long tmpval ;
char * tmp ;
size_t len ;
2018-08-17 15:29:39 +02:00
2023-04-12 14:46:04 +02:00
* dataRead = 0 ;
* dataWrite = 0 ;
2018-08-17 15:29:39 +02:00
2023-04-12 14:46:04 +02:00
if ( virCgroupGetValueStr ( group , VIR_CGROUP_CONTROLLER_BLKIO , field , & serviced ) < 0 )
2018-08-17 15:29:39 +02:00
return - 1 ;
2023-04-12 14:46:04 +02:00
if ( devpath ) {
g_autofree char * devstr = NULL ;
2018-08-17 15:29:39 +02:00
2023-04-12 14:46:04 +02:00
if ( ! ( devstr = virCgroupGetBlockDevString ( devpath ) ) )
return - 1 ;
2018-08-17 15:29:39 +02:00
2023-04-12 14:46:04 +02:00
filterWrite = g_strdup_printf ( " %sWrite " , devstr ) ;
filterRead = g_strdup_printf ( " %sRead " , devstr ) ;
2018-08-17 15:29:39 +02:00
2023-04-12 14:46:04 +02:00
if ( ! strstr ( serviced , filterWrite ) | |
! strstr ( serviced , filterRead ) ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
_ ( " Cannot find blkio cgroup stats (%1$s) for block device '%2$s' (%3$s) " ) ,
field , devstr , devpath ) ;
return - 1 ;
2018-08-17 15:29:39 +02:00
}
2023-04-12 14:46:04 +02:00
} else {
filterWrite = g_strdup ( " Write " ) ;
filterRead = g_strdup ( " Read " ) ;
2018-08-17 15:29:39 +02:00
}
2023-04-12 14:46:04 +02:00
len = strlen ( filterRead ) ;
2018-08-17 15:29:39 +02:00
2023-04-12 14:46:04 +02:00
for ( tmp = strstr ( serviced , filterRead ) ; tmp ; tmp = strstr ( tmp , filterRead ) ) {
char * cur = tmp ;
tmp + = len ;
2018-08-17 15:29:39 +02:00
2023-04-12 14:46:04 +02:00
VIR_DEBUG ( " filter='%s' line='%.*s' " , filterRead , ( int ) ( strchr ( tmp , ' \n ' ) - tmp ) , tmp ) ;
2018-08-17 15:30:21 +02:00
2023-04-12 14:46:04 +02:00
if ( virStrToLong_ullp ( tmp , & tmp , 10 , & tmpval ) < 0 ) {
char * eol ;
2018-08-17 15:30:21 +02:00
2023-04-12 14:46:04 +02:00
if ( ( eol = strchr ( cur , ' \n ' ) ) )
* eol = ' \0 ' ;
2018-08-17 15:30:21 +02:00
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-04-12 14:46:04 +02:00
_ ( " Cannot parse blkio cgroup (%1$s) entry '%2$s' " ) ,
field , cur ) ;
2018-08-17 15:30:21 +02:00
return - 1 ;
}
2023-04-12 14:46:04 +02:00
if ( tmpval + * dataRead > LLONG_MAX ) {
virReportError ( VIR_ERR_OVERFLOW ,
_ ( " overflow in sum of statistic for blkio cgroup (%1$s) field '%2$s' " ) ,
field , filterRead ) ;
2018-08-17 15:30:21 +02:00
return - 1 ;
}
2023-04-12 14:46:04 +02:00
* dataRead + = tmpval ;
}
len = strlen ( filterWrite ) ;
for ( tmp = strstr ( serviced , filterWrite ) ; tmp ; tmp = strstr ( tmp , filterWrite ) ) {
char * cur = tmp ;
tmp + = len ;
VIR_DEBUG ( " filter='%s' line='%.*s' " , filterWrite , ( int ) ( strchr ( cur , ' \n ' ) - cur ) , cur ) ;
if ( virStrToLong_ullp ( tmp , & tmp , 10 , & tmpval ) < 0 ) {
char * eol ;
if ( ( eol = strchr ( cur , ' \n ' ) ) )
* eol = ' \0 ' ;
2018-08-17 15:30:21 +02:00
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-04-12 14:46:04 +02:00
_ ( " Cannot parse blkio cgroup ('%1$s') entry '%2$s' " ) ,
field , cur ) ;
2018-08-17 15:30:21 +02:00
return - 1 ;
}
2023-04-12 14:46:04 +02:00
if ( tmpval + * dataWrite > LLONG_MAX ) {
virReportError ( VIR_ERR_OVERFLOW ,
_ ( " overflow in sum of statistic for blkio cgroup (%1$s) field '%2$s' " ) ,
field , filterWrite ) ;
2018-08-17 15:30:21 +02:00
return - 1 ;
}
2023-04-12 14:46:04 +02:00
* dataWrite + = tmpval ;
2018-08-17 15:30:21 +02:00
}
return 0 ;
}
2023-04-12 14:46:04 +02:00
static int
virCgroupV1GetBlkioIoServicedInternal ( virCgroup * group ,
const char * devpath ,
long long * bytes_read ,
long long * bytes_write ,
long long * requests_read ,
long long * requests_write )
{
if ( virCgroupV1GetBlkioIoServicedOne ( group , " blkio.throttle.io_service_bytes " ,
devpath , bytes_read , bytes_write ) < 0 )
return - 1 ;
if ( virCgroupV1GetBlkioIoServicedOne ( group , " blkio.throttle.io_serviced " ,
devpath , requests_read , requests_write ) < 0 )
return - 1 ;
return 0 ;
}
static int
virCgroupV1GetBlkioIoServiced ( virCgroup * group ,
long long * bytes_read ,
long long * bytes_write ,
long long * requests_read ,
long long * requests_write )
{
return virCgroupV1GetBlkioIoServicedInternal ( group , NULL ,
bytes_read , bytes_write ,
requests_read , requests_write ) ;
}
static int
virCgroupV1GetBlkioIoDeviceServiced ( virCgroup * group ,
const char * path ,
long long * bytes_read ,
long long * bytes_write ,
long long * requests_read ,
long long * requests_write )
{
return virCgroupV1GetBlkioIoServicedInternal ( group , path ,
bytes_read , bytes_write ,
requests_read , requests_write ) ;
}
2018-09-24 12:20:19 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetBlkioDeviceWeight ( virCgroup * group ,
2019-06-18 15:15:43 +02:00
const char * devPath ,
2018-09-24 12:20:19 +02:00
unsigned int weight )
{
2019-10-15 15:16:31 +02:00
g_autofree char * path = NULL ;
2018-09-24 12:20:19 +02:00
2019-06-18 15:15:43 +02:00
if ( virCgroupV1PathOfController ( group , VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.weight_device " , & path ) < 0 ) {
return - 1 ;
}
if ( ! virFileExists ( path ) ) {
virReportError ( VIR_ERR_OPERATION_INVALID , " %s " ,
_ ( " blkio device weight is valid only for cfq scheduler " ) ) ;
return - 1 ;
}
2021-02-05 16:17:35 +01:00
if ( group - > unitName ) {
GVariant * value = NULL ;
value = g_variant_new_parsed ( " [(%s, uint64 %u)] " , path , weight ) ;
return virCgroupSetValueDBus ( group - > unitName , " BlockIODeviceWeight " , value ) ;
} else {
g_autofree char * str = NULL ;
g_autofree char * blkstr = NULL ;
if ( ! ( blkstr = virCgroupGetBlockDevString ( devPath ) ) )
return - 1 ;
str = g_strdup_printf ( " %s%d " , blkstr , weight ) ;
return virCgroupSetValueRaw ( path , str ) ;
}
2018-09-24 12:20:19 +02:00
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetBlkioDeviceWeight ( virCgroup * group ,
2019-06-18 15:15:43 +02:00
const char * devPath ,
2018-09-24 12:20:19 +02:00
unsigned int * weight )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
g_autofree char * value = NULL ;
g_autofree char * path = NULL ;
2018-09-24 12:20:19 +02:00
2019-06-18 15:15:43 +02:00
if ( virCgroupV1PathOfController ( group , VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.weight_device " , & path ) < 0 ) {
return - 1 ;
}
if ( ! virFileExists ( path ) ) {
virReportError ( VIR_ERR_OPERATION_INVALID , " %s " ,
_ ( " blkio device weight is valid only for cfq scheduler " ) ) ;
2019-06-18 15:24:41 +02:00
return - 1 ;
}
2019-06-18 15:15:43 +02:00
if ( virCgroupGetValueRaw ( path , & value ) < 0 )
return - 1 ;
if ( virCgroupGetValueForBlkDev ( value , devPath , & str ) < 0 )
2018-09-24 12:20:19 +02:00
return - 1 ;
if ( ! str ) {
* weight = 0 ;
} else if ( virStrToLong_ui ( str , NULL , 10 , weight ) < 0 ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Unable to parse '%1$s' as an integer " ) ,
2018-09-24 12:20:19 +02:00
str ) ;
return - 1 ;
}
return 0 ;
}
2018-09-24 12:20:31 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetBlkioDeviceReadIops ( virCgroup * group ,
2018-09-24 12:20:31 +02:00
const char * path ,
unsigned int riops )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
g_autofree char * blkstr = NULL ;
2018-09-24 12:20:31 +02:00
if ( ! ( blkstr = virCgroupGetBlockDevString ( path ) ) )
return - 1 ;
2019-10-22 15:26:14 +02:00
str = g_strdup_printf ( " %s%u " , blkstr , riops ) ;
2018-09-24 12:20:31 +02:00
return virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.throttle.read_iops_device " ,
str ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetBlkioDeviceReadIops ( virCgroup * group ,
2018-09-24 12:20:31 +02:00
const char * path ,
unsigned int * riops )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
g_autofree char * value = NULL ;
2018-09-24 12:20:31 +02:00
2019-06-18 15:24:41 +02:00
if ( virCgroupGetValueStr ( group ,
VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.throttle.read_iops_device " ,
& value ) < 0 ) {
return - 1 ;
}
if ( virCgroupGetValueForBlkDev ( value , path , & str ) < 0 )
2018-09-24 12:20:31 +02:00
return - 1 ;
if ( ! str ) {
* riops = 0 ;
} else if ( virStrToLong_ui ( str , NULL , 10 , riops ) < 0 ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Unable to parse '%1$s' as an integer " ) ,
2018-09-24 12:20:31 +02:00
str ) ;
return - 1 ;
}
return 0 ;
}
2018-09-24 12:20:50 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetBlkioDeviceWriteIops ( virCgroup * group ,
2018-09-24 12:20:50 +02:00
const char * path ,
unsigned int wiops )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
g_autofree char * blkstr = NULL ;
2018-09-24 12:20:50 +02:00
if ( ! ( blkstr = virCgroupGetBlockDevString ( path ) ) )
return - 1 ;
2019-10-22 15:26:14 +02:00
str = g_strdup_printf ( " %s%u " , blkstr , wiops ) ;
2018-09-24 12:20:50 +02:00
return virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.throttle.write_iops_device " ,
str ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetBlkioDeviceWriteIops ( virCgroup * group ,
2018-09-24 12:20:50 +02:00
const char * path ,
unsigned int * wiops )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
g_autofree char * value = NULL ;
2018-09-24 12:20:50 +02:00
2019-06-18 15:24:41 +02:00
if ( virCgroupGetValueStr ( group ,
VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.throttle.write_iops_device " ,
& value ) < 0 ) {
return - 1 ;
}
if ( virCgroupGetValueForBlkDev ( value , path , & str ) < 0 )
2018-09-24 12:20:50 +02:00
return - 1 ;
if ( ! str ) {
* wiops = 0 ;
} else if ( virStrToLong_ui ( str , NULL , 10 , wiops ) < 0 ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Unable to parse '%1$s' as an integer " ) ,
2018-09-24 12:20:50 +02:00
str ) ;
return - 1 ;
}
return 0 ;
}
2018-09-24 12:21:07 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetBlkioDeviceReadBps ( virCgroup * group ,
2018-09-24 12:21:07 +02:00
const char * path ,
unsigned long long rbps )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
g_autofree char * blkstr = NULL ;
2018-09-24 12:21:07 +02:00
if ( ! ( blkstr = virCgroupGetBlockDevString ( path ) ) )
return - 1 ;
2019-10-22 15:26:14 +02:00
str = g_strdup_printf ( " %s%llu " , blkstr , rbps ) ;
2018-09-24 12:21:07 +02:00
return virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.throttle.read_bps_device " ,
str ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetBlkioDeviceReadBps ( virCgroup * group ,
2018-09-24 12:21:07 +02:00
const char * path ,
unsigned long long * rbps )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
g_autofree char * value = NULL ;
2019-06-18 15:24:41 +02:00
if ( virCgroupGetValueStr ( group ,
VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.throttle.read_bps_device " ,
& value ) < 0 ) {
return - 1 ;
}
2018-09-24 12:21:07 +02:00
2019-06-18 15:24:41 +02:00
if ( virCgroupGetValueForBlkDev ( value , path , & str ) < 0 )
2018-09-24 12:21:07 +02:00
return - 1 ;
if ( ! str ) {
* rbps = 0 ;
} else if ( virStrToLong_ull ( str , NULL , 10 , rbps ) < 0 ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Unable to parse '%1$s' as an integer " ) ,
2018-09-24 12:21:07 +02:00
str ) ;
return - 1 ;
}
return 0 ;
}
2018-09-24 12:21:21 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetBlkioDeviceWriteBps ( virCgroup * group ,
2018-09-24 12:21:21 +02:00
const char * path ,
unsigned long long wbps )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
g_autofree char * blkstr = NULL ;
2018-09-24 12:21:21 +02:00
if ( ! ( blkstr = virCgroupGetBlockDevString ( path ) ) )
return - 1 ;
2019-10-22 15:26:14 +02:00
str = g_strdup_printf ( " %s%llu " , blkstr , wbps ) ;
2018-09-24 12:21:21 +02:00
return virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.throttle.write_bps_device " ,
str ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetBlkioDeviceWriteBps ( virCgroup * group ,
2018-09-24 12:21:21 +02:00
const char * path ,
unsigned long long * wbps )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
g_autofree char * value = NULL ;
2019-06-18 15:24:41 +02:00
if ( virCgroupGetValueStr ( group ,
VIR_CGROUP_CONTROLLER_BLKIO ,
" blkio.throttle.write_bps_device " ,
& value ) < 0 ) {
return - 1 ;
}
2018-09-24 12:21:21 +02:00
2019-06-18 15:24:41 +02:00
if ( virCgroupGetValueForBlkDev ( value , path , & str ) < 0 )
2018-09-24 12:21:21 +02:00
return - 1 ;
if ( ! str ) {
* wbps = 0 ;
} else if ( virStrToLong_ull ( str , NULL , 10 , wbps ) < 0 ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Unable to parse '%1$s' as an integer " ) ,
2018-09-24 12:21:21 +02:00
str ) ;
return - 1 ;
}
return 0 ;
}
2018-08-17 16:18:38 +02:00
/*
* Retrieve the " memory.limit_in_bytes " value from the memory controller
* root dir . This value cannot be modified by userspace and therefore
* is the maximum limit value supported by cgroups on the local system .
* Returns this value scaled to KB or falls back to the original
* VIR_DOMAIN_MEMORY_PARAM_UNLIMITED . Either way , remember the return
* value to avoid unnecessary cgroup filesystem access .
*/
static unsigned long long int virCgroupV1MemoryUnlimitedKB ;
static virOnceControl virCgroupV1MemoryOnce = VIR_ONCE_CONTROL_INITIALIZER ;
static void
virCgroupV1MemoryOnceInit ( void )
{
2020-10-09 16:09:46 +02:00
g_autoptr ( virCgroup ) group = NULL ;
2018-08-17 16:18:38 +02:00
unsigned long long int mem_unlimited = 0ULL ;
2020-10-15 17:05:17 +02:00
if ( virCgroupNew ( " / " , - 1 , & group ) < 0 )
2020-10-09 16:09:46 +02:00
return ;
2018-08-17 16:18:38 +02:00
if ( ! virCgroupV1HasController ( group , VIR_CGROUP_CONTROLLER_MEMORY ) )
2020-10-09 16:09:46 +02:00
return ;
2018-08-17 16:18:38 +02:00
ignore_value ( virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.limit_in_bytes " ,
& mem_unlimited ) ) ;
2020-10-09 16:09:46 +02:00
2018-08-17 16:18:38 +02:00
virCgroupV1MemoryUnlimitedKB = mem_unlimited > > 10 ;
}
static unsigned long long int
virCgroupV1GetMemoryUnlimitedKB ( void )
{
if ( virOnce ( & virCgroupV1MemoryOnce , virCgroupV1MemoryOnceInit ) < 0 )
VIR_DEBUG ( " Init failed, will fall back to defaults. " ) ;
if ( virCgroupV1MemoryUnlimitedKB )
return virCgroupV1MemoryUnlimitedKB ;
else
return VIR_DOMAIN_MEMORY_PARAM_UNLIMITED ;
}
2018-08-17 15:53:41 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetMemory ( virCgroup * group ,
2018-08-17 15:53:41 +02:00
unsigned long long kb )
{
unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED ;
if ( kb > maxkb ) {
virReportError ( VIR_ERR_INVALID_ARG ,
2023-03-09 15:11:50 +01:00
_ ( " Memory '%1$llu' must be less than %2$llu " ) ,
2018-08-17 15:53:41 +02:00
kb , maxkb ) ;
return - 1 ;
}
if ( kb = = maxkb )
return virCgroupSetValueI64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.limit_in_bytes " ,
- 1 ) ;
else
return virCgroupSetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.limit_in_bytes " ,
kb < < 10 ) ;
}
2018-08-17 15:55:47 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetMemoryStat ( virCgroup * group ,
2018-08-17 15:55:47 +02:00
unsigned long long * cache ,
unsigned long long * activeAnon ,
unsigned long long * inactiveAnon ,
unsigned long long * activeFile ,
unsigned long long * inactiveFile ,
unsigned long long * unevictable )
{
2020-11-23 16:09:40 -06:00
g_autofree char * stat = NULL ;
2018-08-17 15:55:47 +02:00
char * line = NULL ;
unsigned long long cacheVal = 0 ;
unsigned long long activeAnonVal = 0 ;
unsigned long long inactiveAnonVal = 0 ;
unsigned long long activeFileVal = 0 ;
unsigned long long inactiveFileVal = 0 ;
unsigned long long unevictableVal = 0 ;
if ( virCgroupGetValueStr ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.stat " ,
& stat ) < 0 ) {
return - 1 ;
}
line = stat ;
2018-11-07 18:40:24 -05:00
while ( * line ) {
2018-08-17 15:55:47 +02:00
char * newLine = strchr ( line , ' \n ' ) ;
char * valueStr = strchr ( line , ' ' ) ;
unsigned long long value ;
if ( newLine )
* newLine = ' \0 ' ;
if ( ! valueStr ) {
virReportError ( VIR_ERR_INTERNAL_ERROR , " %s " ,
_ ( " Cannot parse 'memory.stat' cgroup file. " ) ) ;
2021-11-04 15:26:07 +01:00
return - 1 ;
2018-08-17 15:55:47 +02:00
}
* valueStr = ' \0 ' ;
if ( virStrToLong_ull ( valueStr + 1 , NULL , 10 , & value ) < 0 )
2021-11-04 15:26:07 +01:00
return - 1 ;
2018-08-17 15:55:47 +02:00
if ( STREQ ( line , " cache " ) )
cacheVal = value > > 10 ;
else if ( STREQ ( line , " active_anon " ) )
activeAnonVal = value > > 10 ;
else if ( STREQ ( line , " inactive_anon " ) )
inactiveAnonVal = value > > 10 ;
else if ( STREQ ( line , " active_file " ) )
activeFileVal = value > > 10 ;
else if ( STREQ ( line , " inactive_file " ) )
inactiveFileVal = value > > 10 ;
else if ( STREQ ( line , " unevictable " ) )
unevictableVal = value > > 10 ;
2018-11-07 18:40:24 -05:00
if ( newLine )
line = newLine + 1 ;
else
break ;
2018-08-17 15:55:47 +02:00
}
* cache = cacheVal ;
* activeAnon = activeAnonVal ;
* inactiveAnon = inactiveAnonVal ;
* activeFile = activeFileVal ;
* inactiveFile = inactiveFileVal ;
* unevictable = unevictableVal ;
2021-11-04 15:26:07 +01:00
return 0 ;
2018-08-17 15:55:47 +02:00
}
2018-08-17 15:56:33 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetMemoryUsage ( virCgroup * group ,
2018-08-17 15:56:33 +02:00
unsigned long * kb )
{
long long unsigned int usage_in_bytes ;
int ret ;
ret = virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.usage_in_bytes " , & usage_in_bytes ) ;
if ( ret = = 0 )
* kb = ( unsigned long ) usage_in_bytes > > 10 ;
return ret ;
}
2018-08-17 16:18:38 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetMemoryHardLimit ( virCgroup * group ,
2018-08-17 16:18:38 +02:00
unsigned long long kb )
{
return virCgroupV1SetMemory ( group , kb ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetMemoryHardLimit ( virCgroup * group ,
2018-08-17 16:18:38 +02:00
unsigned long long * kb )
{
long long unsigned int limit_in_bytes ;
if ( virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.limit_in_bytes " , & limit_in_bytes ) < 0 )
return - 1 ;
* kb = limit_in_bytes > > 10 ;
if ( * kb > = virCgroupV1GetMemoryUnlimitedKB ( ) )
* kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED ;
return 0 ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetMemorySoftLimit ( virCgroup * group ,
2018-08-17 16:18:38 +02:00
unsigned long long kb )
{
unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED ;
if ( kb > maxkb ) {
virReportError ( VIR_ERR_INVALID_ARG ,
2023-03-09 15:11:50 +01:00
_ ( " Memory '%1$llu' must be less than %2$llu " ) ,
2018-08-17 16:18:38 +02:00
kb , maxkb ) ;
return - 1 ;
}
if ( kb = = maxkb )
return virCgroupSetValueI64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.soft_limit_in_bytes " ,
- 1 ) ;
else
return virCgroupSetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.soft_limit_in_bytes " ,
kb < < 10 ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetMemorySoftLimit ( virCgroup * group ,
2018-08-17 16:18:38 +02:00
unsigned long long * kb )
{
long long unsigned int limit_in_bytes ;
if ( virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.soft_limit_in_bytes " , & limit_in_bytes ) < 0 )
return - 1 ;
* kb = limit_in_bytes > > 10 ;
if ( * kb > = virCgroupV1GetMemoryUnlimitedKB ( ) )
* kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED ;
return 0 ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetMemSwapHardLimit ( virCgroup * group ,
2018-08-17 16:18:38 +02:00
unsigned long long kb )
{
unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED ;
if ( kb > maxkb ) {
virReportError ( VIR_ERR_INVALID_ARG ,
2023-03-09 15:11:50 +01:00
_ ( " Memory '%1$llu' must be less than %2$llu " ) ,
2018-08-17 16:18:38 +02:00
kb , maxkb ) ;
return - 1 ;
}
if ( kb = = maxkb )
return virCgroupSetValueI64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.memsw.limit_in_bytes " ,
- 1 ) ;
else
return virCgroupSetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.memsw.limit_in_bytes " ,
kb < < 10 ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetMemSwapHardLimit ( virCgroup * group ,
2018-08-17 16:18:38 +02:00
unsigned long long * kb )
{
long long unsigned int limit_in_bytes ;
if ( virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.memsw.limit_in_bytes " , & limit_in_bytes ) < 0 )
return - 1 ;
* kb = limit_in_bytes > > 10 ;
if ( * kb > = virCgroupV1GetMemoryUnlimitedKB ( ) )
* kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED ;
return 0 ;
}
2018-08-17 16:19:08 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetMemSwapUsage ( virCgroup * group ,
2018-08-17 16:19:08 +02:00
unsigned long long * kb )
{
long long unsigned int usage_in_bytes ;
int ret ;
ret = virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_MEMORY ,
" memory.memsw.usage_in_bytes " , & usage_in_bytes ) ;
if ( ret = = 0 )
* kb = usage_in_bytes > > 10 ;
return ret ;
}
2018-09-05 20:08:48 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1AllowDevice ( virCgroup * group ,
2018-09-05 20:08:48 +02:00
char type ,
int major ,
int minor ,
int perms )
{
2019-10-15 15:16:31 +02:00
g_autofree char * devstr = NULL ;
g_autofree char * majorstr = NULL ;
g_autofree char * minorstr = NULL ;
2018-09-05 20:08:48 +02:00
2019-10-20 13:49:46 +02:00
if ( major < 0 )
majorstr = g_strdup ( " * " ) ;
2019-10-22 15:26:14 +02:00
else
majorstr = g_strdup_printf ( " %i " , major ) ;
2018-09-05 20:08:48 +02:00
2019-10-20 13:49:46 +02:00
if ( minor < 0 )
minorstr = g_strdup ( " * " ) ;
2019-10-22 15:26:14 +02:00
else
minorstr = g_strdup_printf ( " %i " , minor ) ;
2018-09-05 20:08:48 +02:00
2019-10-22 15:26:14 +02:00
devstr = g_strdup_printf ( " %c %s:%s %s " , type , majorstr , minorstr ,
virCgroupGetDevicePermsString ( perms ) ) ;
2018-09-05 20:08:48 +02:00
if ( virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_DEVICES ,
" devices.allow " ,
devstr ) < 0 )
return - 1 ;
return 0 ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1DenyDevice ( virCgroup * group ,
2018-09-05 20:08:48 +02:00
char type ,
int major ,
int minor ,
int perms )
{
2019-10-15 15:16:31 +02:00
g_autofree char * devstr = NULL ;
g_autofree char * majorstr = NULL ;
g_autofree char * minorstr = NULL ;
2018-09-05 20:08:48 +02:00
2019-10-20 13:49:46 +02:00
if ( major < 0 )
majorstr = g_strdup ( " * " ) ;
2019-10-22 15:26:14 +02:00
else
majorstr = g_strdup_printf ( " %i " , major ) ;
2018-09-05 20:08:48 +02:00
2019-10-20 13:49:46 +02:00
if ( minor < 0 )
minorstr = g_strdup ( " * " ) ;
2019-10-22 15:26:14 +02:00
else
minorstr = g_strdup_printf ( " %i " , minor ) ;
2018-09-05 20:08:48 +02:00
2019-10-22 15:26:14 +02:00
devstr = g_strdup_printf ( " %c %s:%s %s " , type , majorstr , minorstr ,
virCgroupGetDevicePermsString ( perms ) ) ;
2018-09-05 20:08:48 +02:00
if ( virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_DEVICES ,
" devices.deny " ,
devstr ) < 0 )
return - 1 ;
return 0 ;
}
2018-09-05 20:10:02 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1AllowAllDevices ( virCgroup * group ,
2018-09-05 20:10:02 +02:00
int perms )
{
if ( virCgroupV1AllowDevice ( group , ' b ' , - 1 , - 1 , perms ) < 0 )
2019-10-21 15:19:04 -03:00
return - 1 ;
2018-09-05 20:10:02 +02:00
if ( virCgroupV1AllowDevice ( group , ' c ' , - 1 , - 1 , perms ) < 0 )
2019-10-21 15:19:04 -03:00
return - 1 ;
2018-09-05 20:10:02 +02:00
2019-10-21 15:19:04 -03:00
return 0 ;
2018-09-05 20:10:02 +02:00
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1DenyAllDevices ( virCgroup * group )
2018-09-05 20:10:02 +02:00
{
return virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_DEVICES ,
" devices.deny " ,
" a " ) ;
}
2018-09-05 20:11:38 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetCpuShares ( virCgroup * group ,
2018-09-05 20:11:38 +02:00
unsigned long long shares )
{
2021-03-03 14:10:15 +01:00
if ( shares < VIR_CGROUP_CPU_SHARES_MIN | |
shares > VIR_CGROUP_CPU_SHARES_MAX ) {
virReportError ( VIR_ERR_INVALID_ARG ,
2023-03-09 15:11:50 +01:00
_ ( " shares '%1$llu' must be in range [%2$llu, %3$llu] " ) ,
2021-03-03 14:10:15 +01:00
shares ,
VIR_CGROUP_CPU_SHARES_MIN ,
VIR_CGROUP_CPU_SHARES_MAX ) ;
return - 1 ;
}
2021-02-05 16:17:35 +01:00
if ( group - > unitName ) {
GVariant * value = g_variant_new ( " t " , shares ) ;
return virCgroupSetValueDBus ( group - > unitName , " CPUShares " , value ) ;
} else {
return virCgroupSetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_CPU ,
" cpu.shares " , shares ) ;
}
2018-09-05 20:11:38 +02:00
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetCpuShares ( virCgroup * group ,
2018-09-05 20:11:38 +02:00
unsigned long long * shares )
{
return virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_CPU ,
" cpu.shares " , shares ) ;
}
2018-08-17 16:22:30 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetCpuCfsPeriod ( virCgroup * group ,
2018-08-17 16:22:30 +02:00
unsigned long long cfs_period )
{
2020-11-25 11:54:01 +01:00
if ( cfs_period < VIR_CGROUP_CPU_PERIOD_MIN | |
cfs_period > VIR_CGROUP_CPU_PERIOD_MAX ) {
2018-08-17 16:22:30 +02:00
virReportError ( VIR_ERR_INVALID_ARG ,
2023-03-09 15:11:50 +01:00
_ ( " cfs_period '%1$llu' must be in range (%2$llu, %3$llu) " ) ,
2020-11-25 11:54:01 +01:00
cfs_period ,
VIR_CGROUP_CPU_PERIOD_MIN ,
VIR_CGROUP_CPU_PERIOD_MAX ) ;
2018-08-17 16:22:30 +02:00
return - 1 ;
}
return virCgroupSetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_CPU ,
" cpu.cfs_period_us " , cfs_period ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetCpuCfsPeriod ( virCgroup * group ,
2018-08-17 16:22:30 +02:00
unsigned long long * cfs_period )
{
return virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_CPU ,
" cpu.cfs_period_us " , cfs_period ) ;
}
2018-08-17 16:22:56 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetCpuCfsQuota ( virCgroup * group ,
2018-08-17 16:22:56 +02:00
long long cfs_quota )
{
if ( cfs_quota > = 0 & &
2020-11-25 11:54:01 +01:00
( cfs_quota < VIR_CGROUP_CPU_QUOTA_MIN | |
cfs_quota > VIR_CGROUP_CPU_QUOTA_MAX ) ) {
2018-08-17 16:22:56 +02:00
virReportError ( VIR_ERR_INVALID_ARG ,
2023-03-09 15:11:50 +01:00
_ ( " cfs_quota '%1$lld' must be in range (%2$llu, %3$llu) " ) ,
2020-11-25 11:54:01 +01:00
cfs_quota ,
VIR_CGROUP_CPU_QUOTA_MIN ,
VIR_CGROUP_CPU_QUOTA_MAX ) ;
2018-08-17 16:22:56 +02:00
return - 1 ;
}
return virCgroupSetValueI64 ( group ,
VIR_CGROUP_CONTROLLER_CPU ,
" cpu.cfs_quota_us " , cfs_quota ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetCpuCfsQuota ( virCgroup * group ,
2018-08-17 16:22:56 +02:00
long long * cfs_quota )
{
return virCgroupGetValueI64 ( group ,
VIR_CGROUP_CONTROLLER_CPU ,
" cpu.cfs_quota_us " , cfs_quota ) ;
}
2018-08-17 16:23:14 +02:00
static bool
2021-03-11 08:16:13 +01:00
virCgroupV1SupportsCpuBW ( virCgroup * cgroup )
2018-08-17 16:23:14 +02:00
{
2019-10-15 15:16:31 +02:00
g_autofree char * path = NULL ;
2018-08-17 16:23:14 +02:00
if ( ! cgroup )
return false ;
if ( virCgroupV1PathOfController ( cgroup , VIR_CGROUP_CONTROLLER_CPU ,
" cpu.cfs_period_us " , & path ) < 0 ) {
virResetLastError ( ) ;
return false ;
}
return virFileExists ( path ) ;
}
2018-08-20 09:57:51 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetCpuacctUsage ( virCgroup * group ,
2018-08-20 09:57:51 +02:00
unsigned long long * usage )
{
return virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_CPUACCT ,
" cpuacct.usage " , usage ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetCpuacctPercpuUsage ( virCgroup * group ,
2018-08-20 09:57:51 +02:00
char * * usage )
{
return virCgroupGetValueStr ( group , VIR_CGROUP_CONTROLLER_CPUACCT ,
" cpuacct.usage_percpu " , usage ) ;
}
2018-08-20 09:58:33 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetCpuacctStat ( virCgroup * group ,
2018-08-20 09:58:33 +02:00
unsigned long long * user ,
unsigned long long * sys )
{
2019-10-15 15:16:31 +02:00
g_autofree char * str = NULL ;
2018-08-20 09:58:33 +02:00
char * p ;
static double scale = - 1.0 ;
if ( virCgroupGetValueStr ( group , VIR_CGROUP_CONTROLLER_CPUACCT ,
" cpuacct.stat " , & str ) < 0 )
return - 1 ;
if ( ! ( p = STRSKIP ( str , " user " ) ) | |
virStrToLong_ull ( p , & p , 10 , user ) < 0 ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Cannot parse user stat '%1$s' " ) ,
2018-08-20 09:58:33 +02:00
p ) ;
return - 1 ;
}
if ( ! ( p = STRSKIP ( p , " \n system " ) ) | |
virStrToLong_ull ( p , NULL , 10 , sys ) < 0 ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2023-03-09 15:11:50 +01:00
_ ( " Cannot parse sys stat '%1$s' " ) ,
2018-08-20 09:58:33 +02:00
p ) ;
return - 1 ;
}
/* times reported are in system ticks (generally 100 Hz), but that
* rate can theoretically vary between machines . Scale things
* into approximate nanoseconds . */
if ( scale < 0 ) {
long ticks_per_sec = sysconf ( _SC_CLK_TCK ) ;
if ( ticks_per_sec = = - 1 ) {
virReportSystemError ( errno , " %s " ,
_ ( " Cannot determine system clock HZ " ) ) ;
return - 1 ;
}
scale = 1000000000.0 / ticks_per_sec ;
}
* user * = scale ;
* sys * = scale ;
return 0 ;
}
2018-08-16 18:22:08 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetFreezerState ( virCgroup * group ,
2018-08-16 18:22:08 +02:00
const char * state )
{
return virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_FREEZER ,
" freezer.state " , state ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetFreezerState ( virCgroup * group ,
2018-08-16 18:22:08 +02:00
char * * state )
{
return virCgroupGetValueStr ( group ,
VIR_CGROUP_CONTROLLER_FREEZER ,
" freezer.state " , state ) ;
}
2018-08-20 10:00:04 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetCpusetMems ( virCgroup * group ,
2018-08-20 10:00:04 +02:00
const char * mems )
{
return virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_CPUSET ,
" cpuset.mems " ,
mems ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetCpusetMems ( virCgroup * group ,
2018-08-20 10:00:04 +02:00
char * * mems )
{
return virCgroupGetValueStr ( group ,
VIR_CGROUP_CONTROLLER_CPUSET ,
" cpuset.mems " ,
mems ) ;
}
2018-08-20 10:00:57 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetCpusetMemoryMigrate ( virCgroup * group ,
2018-08-20 10:00:57 +02:00
bool migrate )
{
return virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_CPUSET ,
" cpuset.memory_migrate " ,
migrate ? " 1 " : " 0 " ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetCpusetMemoryMigrate ( virCgroup * group ,
2018-08-20 10:00:57 +02:00
bool * migrate )
{
unsigned long long value = 0 ;
int ret = virCgroupGetValueU64 ( group ,
VIR_CGROUP_CONTROLLER_CPUSET ,
" cpuset.memory_migrate " ,
& value ) ;
* migrate = ! ! value ;
return ret ;
}
2018-08-20 10:01:10 +02:00
static int
2021-03-11 08:16:13 +01:00
virCgroupV1SetCpusetCpus ( virCgroup * group ,
2018-08-20 10:01:10 +02:00
const char * cpus )
{
return virCgroupSetValueStr ( group ,
VIR_CGROUP_CONTROLLER_CPUSET ,
" cpuset.cpus " ,
cpus ) ;
}
static int
2021-03-11 08:16:13 +01:00
virCgroupV1GetCpusetCpus ( virCgroup * group ,
2018-08-20 10:01:10 +02:00
char * * cpus )
{
return virCgroupGetValueStr ( group ,
VIR_CGROUP_CONTROLLER_CPUSET ,
" cpuset.cpus " ,
cpus ) ;
}
2018-08-17 10:19:59 +02:00
virCgroupBackend virCgroupV1Backend = {
. type = VIR_CGROUP_BACKEND_TYPE_V1 ,
2018-09-13 16:27:56 +02:00
. available = virCgroupV1Available ,
2018-09-14 13:21:19 +02:00
. validateMachineGroup = virCgroupV1ValidateMachineGroup ,
2018-08-17 09:46:10 +02:00
. copyMounts = virCgroupV1CopyMounts ,
2018-09-14 12:53:47 +02:00
. copyPlacement = virCgroupV1CopyPlacement ,
2018-09-14 12:51:27 +02:00
. detectMounts = virCgroupV1DetectMounts ,
. detectPlacement = virCgroupV1DetectPlacement ,
2020-10-21 14:35:48 +02:00
. setPlacement = virCgroupV1SetPlacement ,
2018-08-24 15:15:23 +02:00
. validatePlacement = virCgroupV1ValidatePlacement ,
2018-08-17 12:00:29 +02:00
. stealPlacement = virCgroupV1StealPlacement ,
2018-09-25 01:12:22 +02:00
. detectControllers = virCgroupV1DetectControllers ,
2018-08-19 19:17:27 +02:00
. hasController = virCgroupV1HasController ,
2018-08-19 19:20:25 +02:00
. getAnyController = virCgroupV1GetAnyController ,
2018-08-19 19:24:58 +02:00
. pathOfController = virCgroupV1PathOfController ,
2018-09-18 16:11:47 +02:00
. makeGroup = virCgroupV1MakeGroup ,
2021-02-09 12:31:13 +01:00
. exists = virCgroupV1Exists ,
2018-08-17 10:02:05 +02:00
. remove = virCgroupV1Remove ,
2018-09-25 01:14:36 +02:00
. addTask = virCgroupV1AddTask ,
2018-08-17 15:25:48 +02:00
. hasEmptyTasks = virCgroupV1HasEmptyTasks ,
2018-12-10 16:51:14 +08:00
. killRecursive = virCgroupV1KillRecursive ,
2018-08-17 10:04:20 +02:00
. bindMount = virCgroupV1BindMount ,
2018-08-17 10:09:49 +02:00
. setOwner = virCgroupV1SetOwner ,
2018-08-17 15:28:50 +02:00
. setBlkioWeight = virCgroupV1SetBlkioWeight ,
. getBlkioWeight = virCgroupV1GetBlkioWeight ,
2018-08-17 15:29:39 +02:00
. getBlkioIoServiced = virCgroupV1GetBlkioIoServiced ,
2018-08-17 15:30:21 +02:00
. getBlkioIoDeviceServiced = virCgroupV1GetBlkioIoDeviceServiced ,
2018-09-24 12:20:19 +02:00
. setBlkioDeviceWeight = virCgroupV1SetBlkioDeviceWeight ,
. getBlkioDeviceWeight = virCgroupV1GetBlkioDeviceWeight ,
2018-09-24 12:20:31 +02:00
. setBlkioDeviceReadIops = virCgroupV1SetBlkioDeviceReadIops ,
. getBlkioDeviceReadIops = virCgroupV1GetBlkioDeviceReadIops ,
2018-09-24 12:20:50 +02:00
. setBlkioDeviceWriteIops = virCgroupV1SetBlkioDeviceWriteIops ,
. getBlkioDeviceWriteIops = virCgroupV1GetBlkioDeviceWriteIops ,
2018-09-24 12:21:07 +02:00
. setBlkioDeviceReadBps = virCgroupV1SetBlkioDeviceReadBps ,
. getBlkioDeviceReadBps = virCgroupV1GetBlkioDeviceReadBps ,
2018-09-24 12:21:21 +02:00
. setBlkioDeviceWriteBps = virCgroupV1SetBlkioDeviceWriteBps ,
. getBlkioDeviceWriteBps = virCgroupV1GetBlkioDeviceWriteBps ,
2018-08-17 15:53:41 +02:00
. setMemory = virCgroupV1SetMemory ,
2018-08-17 15:55:47 +02:00
. getMemoryStat = virCgroupV1GetMemoryStat ,
2018-08-17 15:56:33 +02:00
. getMemoryUsage = virCgroupV1GetMemoryUsage ,
2018-08-17 16:18:38 +02:00
. setMemoryHardLimit = virCgroupV1SetMemoryHardLimit ,
. getMemoryHardLimit = virCgroupV1GetMemoryHardLimit ,
. setMemorySoftLimit = virCgroupV1SetMemorySoftLimit ,
. getMemorySoftLimit = virCgroupV1GetMemorySoftLimit ,
. setMemSwapHardLimit = virCgroupV1SetMemSwapHardLimit ,
. getMemSwapHardLimit = virCgroupV1GetMemSwapHardLimit ,
2018-08-17 16:19:08 +02:00
. getMemSwapUsage = virCgroupV1GetMemSwapUsage ,
2018-09-05 20:08:48 +02:00
. allowDevice = virCgroupV1AllowDevice ,
. denyDevice = virCgroupV1DenyDevice ,
2018-09-05 20:10:02 +02:00
. allowAllDevices = virCgroupV1AllowAllDevices ,
. denyAllDevices = virCgroupV1DenyAllDevices ,
2018-09-05 20:11:38 +02:00
. setCpuShares = virCgroupV1SetCpuShares ,
. getCpuShares = virCgroupV1GetCpuShares ,
2018-08-17 16:22:30 +02:00
. setCpuCfsPeriod = virCgroupV1SetCpuCfsPeriod ,
. getCpuCfsPeriod = virCgroupV1GetCpuCfsPeriod ,
2018-08-17 16:22:56 +02:00
. setCpuCfsQuota = virCgroupV1SetCpuCfsQuota ,
. getCpuCfsQuota = virCgroupV1GetCpuCfsQuota ,
2018-08-17 16:23:14 +02:00
. supportsCpuBW = virCgroupV1SupportsCpuBW ,
2018-08-20 09:57:51 +02:00
. getCpuacctUsage = virCgroupV1GetCpuacctUsage ,
. getCpuacctPercpuUsage = virCgroupV1GetCpuacctPercpuUsage ,
2018-08-20 09:58:33 +02:00
. getCpuacctStat = virCgroupV1GetCpuacctStat ,
2018-08-16 18:22:08 +02:00
. setFreezerState = virCgroupV1SetFreezerState ,
. getFreezerState = virCgroupV1GetFreezerState ,
2018-08-20 10:00:04 +02:00
. setCpusetMems = virCgroupV1SetCpusetMems ,
. getCpusetMems = virCgroupV1GetCpusetMems ,
2018-08-20 10:00:57 +02:00
. setCpusetMemoryMigrate = virCgroupV1SetCpusetMemoryMigrate ,
. getCpusetMemoryMigrate = virCgroupV1GetCpusetMemoryMigrate ,
2018-08-20 10:01:10 +02:00
. setCpusetCpus = virCgroupV1SetCpusetCpus ,
. getCpusetCpus = virCgroupV1GetCpusetCpus ,
2018-08-17 10:19:59 +02:00
} ;
void
virCgroupV1Register ( void )
{
virCgroupBackendRegister ( & virCgroupV1Backend ) ;
}
vircgroupv1: fix build on non-linux OSes
Cgroups are linux specific and we need to make sure that the code is
compiled only on linux. On different OSes it fails the compilation:
../../src/util/vircgroupv1.c:65:19: error: variable has incomplete type 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:65:12: note: forward declaration of 'struct mntent'
struct mntent entry;
^
../../src/util/vircgroupv1.c:74:12: error: implicit declaration of function 'getmntent_r' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
^
../../src/util/vircgroupv1.c:814:39: error: use of undeclared identifier 'MS_NOSUID'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:49: error: use of undeclared identifier 'MS_NODEV'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:814:58: error: use of undeclared identifier 'MS_NOEXEC'
if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
^
../../src/util/vircgroupv1.c:841:65: error: use of undeclared identifier 'MS_BIND'
if (mount(src, group->legacy[i].mountPoint, "none", MS_BIND,
^
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
2018-09-27 12:22:20 +02:00
# else /* !__linux__ */
void
virCgroupV1Register ( void )
{
VIR_INFO ( " Control groups not supported on this platform " ) ;
}
# endif /* !__linux__ */