You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
(16) |
May
(148) |
Jun
(82) |
Jul
(179) |
Aug
(412) |
Sep
(138) |
Oct
(33) |
Nov
(112) |
Dec
(146) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(117) |
Feb
(203) |
Mar
(98) |
Apr
(122) |
May
(196) |
Jun
(216) |
Jul
(109) |
Aug
(38) |
Sep
(25) |
Oct
(97) |
Nov
(78) |
Dec
(95) |
2010 |
Jan
(51) |
Feb
(37) |
Mar
(192) |
Apr
(34) |
May
(47) |
Jun
(57) |
Jul
(104) |
Aug
(102) |
Sep
(87) |
Oct
(86) |
Nov
(144) |
Dec
(104) |
2011 |
Jan
(40) |
Feb
(42) |
Mar
(58) |
Apr
(59) |
May
(155) |
Jun
(98) |
Jul
(49) |
Aug
(160) |
Sep
(46) |
Oct
(14) |
Nov
(57) |
Dec
(37) |
2012 |
Jan
|
Feb
(20) |
Mar
|
Apr
(13) |
May
(36) |
Jun
(63) |
Jul
(35) |
Aug
(11) |
Sep
(15) |
Oct
(26) |
Nov
(29) |
Dec
(17) |
2013 |
Jan
(12) |
Feb
(49) |
Mar
(55) |
Apr
(3) |
May
(20) |
Jun
(21) |
Jul
(22) |
Aug
(49) |
Sep
(123) |
Oct
(112) |
Nov
(16) |
Dec
(1) |
2014 |
Jan
|
Feb
(9) |
Mar
(3) |
Apr
(12) |
May
(21) |
Jun
(26) |
Jul
(39) |
Aug
(4) |
Sep
(15) |
Oct
(6) |
Nov
(1) |
Dec
(12) |
2015 |
Jan
(2) |
Feb
(1) |
Mar
(2) |
Apr
|
May
|
Jun
(1) |
Jul
(1) |
Aug
(7) |
Sep
|
Oct
|
Nov
|
Dec
(4) |
2016 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
2017 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2018 |
Jan
|
Feb
|
Mar
|
Apr
(5) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2019 |
Jan
(11) |
Feb
(1) |
Mar
|
Apr
(1) |
May
(12) |
Jun
(45) |
Jul
(16) |
Aug
|
Sep
(28) |
Oct
(21) |
Nov
(38) |
Dec
(14) |
2020 |
Jan
(50) |
Feb
(12) |
Mar
|
Apr
|
May
(22) |
Jun
(11) |
Jul
(13) |
Aug
|
Sep
(8) |
Oct
(22) |
Nov
(18) |
Dec
(12) |
2021 |
Jan
|
Feb
(60) |
Mar
(51) |
Apr
(45) |
May
(12) |
Jun
(32) |
Jul
(14) |
Aug
|
Sep
|
Oct
|
Nov
(16) |
Dec
|
2022 |
Jan
|
Feb
|
Mar
(1) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: R. D. <rdi...@ya...> - 2022-04-19 19:22:09
|
Hi all: I am looking for a wrapper script like this: run-on-temporary-cgroup.sh cmd arg1 ... argn. The tool should create a temporary cgroup, run the process inside, and return the same exit code as the user command. I may want to limit the amount of memory the cgroup is allowed to consume. But more importantly, I want the tool to return when all processes in the cgroup (the user command an any children) have already terminated. This is apparently not so easy to achieve without cgroups. Those requirements are similar to what systemd-run does, but I need an alternative which does not depend on systemd. Even if you have systemd, systemd-run is rather convenient, but it is somewhat heavy weight and it has issues with some signals (like SIGTERM), and with escaping/quoting, depending on the mode (--scope vs --wait). I looked at libcgroup, and cgexec comes close, but it is described as follows: Use command line tool "cgexec" to launch the task in right cgroup. To use "cgexec" to place the task in right cgroup: [...] So it does not look like it would automatically create a temporary cgroup, and delete it at the end. Or am I missing something? Otherwise, I could write my own script, but I do not know much about cgroups yet. How could I approach this task? Can you create a cgroup without being root? Is there an example script somewhere to get started? Thanks in advance, rdiez |
From: Tom H. <tom...@or...> - 2022-03-11 15:26:42
|
The libcgroup team has released libcgroup v2.0.1. * https://github.com/libcgroup/libcgroup/releases/tag/v2.0.1 The libcgroup v2.0.1 release is backwards compatible with previous v2.x releases and is a drop-in replacement; no recompilation of applications is required. As with the v2.0 release, cgroup v1 and cgroup v2 are both fully supported. Thanks so much to all of you who have helped make this release possible! This release added five new libcgroup contributors - Anthony G. Basile, Ingo van Lil, Kamalesh Babulal, Ross Burton, and Tomasz Kłoczko. Changes in the v2.0.1 release include: * Allow reading/writing from cgroup.* files in cgroup v2 * Add support for cgroup v2's cgroup.threads file * Fix issue where libcgroup/pam wasn't working properly when cgrulesengd is disabled * Fix a bug where the cgroup version wasn't initialized in a named cgroup v1 hierarchy * Various automake bug fixes * Build PAM module as unversioned DSO * Fix build issues with musl libc * Fix potential TOCTOU race in cgroup_get_procs() Regards, Tom Hromatka |
From: Tom H. <tom...@or...> - 2021-11-09 16:36:13
|
Add support for all of the cgcreate flags. Signed-off-by: Tom Hromatka <tom...@or...> --- ftests/cgroup.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/ftests/cgroup.py b/ftests/cgroup.py index 06ca45693ae9..8b8451ef55fb 100644 --- a/ftests/cgroup.py +++ b/ftests/cgroup.py @@ -124,9 +124,10 @@ class Cgroup(object): return os.path.join(consts.LIBCG_MOUNT_POINT, 'src/daemon/{}'.format(cmd)) - # TODO - add support for all of the cgcreate options @staticmethod - def create(config, controller_list, cgname): + def create(config, controller_list, cgname, user_name=None, + group_name=None, dperm=None, fperm=None, tperm=None, + tasks_user_name=None, tasks_group_name=None, cghelp=False): if isinstance(controller_list, str): controller_list = [controller_list] @@ -136,6 +137,29 @@ class Cgroup(object): cmd.append('sudo') cmd.append(Cgroup.build_cmd_path('cgcreate')) + if user_name is not None and group_name is not None: + cmd.append('-a') + cmd.append('{}:{}'.format(user_name, group_name)) + + if dperm is not None: + cmd.append('-d') + cmd.append(dperm) + + if fperm is not None: + cmd.append('-f') + cmd.append(fperm) + + if tperm is not None: + cmd.append('-s') + cmd.append(tperm) + + if tasks_user_name is not None and taks_group_name is not None: + cmd.append('-t') + cmd.append('{}:{}'.format(tasks_user_name, tasks_group_name)) + + if cghelp: + cmd.append('-h') + controllers_and_path = '{}:{}'.format( ','.join(controller_list), cgname) -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:36:05
|
This patchset adds functional tests for the following patchset: [PATCH 00/10] Add C and Python Binding for tools The changes to libcgroup are available here: https://github.com/drakenclimber/libcgroup/tree/issues/cgxget5-pybindings3 The changes to the libcgroup tests are available here: https://github.com/drakenclimber/libcgroup-tests/tree/issues/cgxget5-pybindings Code coverage increased to 53.5%: https://coveralls.io/builds/44100945 I added a few functional tests, and all automated tests are passing. Results are here: https://github.com/drakenclimber/libcgroup/runs/4143613675 Tom Hromatka (4): ftests: Add a test for the python bindings to cgroup_cgxget() cgroup.py: Add support for cgcreate flags ftests: Add a test for the python bindings to cgroup_cgxset() ftests: Add a test for the python bindings to library_version() ftests/037-pybindings-cgxget.py | 130 +++++++++++++++++++++++ ftests/038-pybindings-cgxset.py | 120 +++++++++++++++++++++ ftests/039-pybindings-library_version.py | 77 ++++++++++++++ ftests/cgroup.py | 28 ++++- 4 files changed, 353 insertions(+), 2 deletions(-) create mode 100755 ftests/037-pybindings-cgxget.py create mode 100755 ftests/038-pybindings-cgxset.py create mode 100755 ftests/039-pybindings-library_version.py -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:36:05
|
Add a test for the python bindings to cgroup_cgxset() ----------------------------------------------------------------- Test Results: Run Date: Oct 13 15:34:29 Passed: 1 test(s) Skipped: 0 test(s) Failed: 0 test(s) ----------------------------------------------------------------- Timing Results: Test Time (sec) --------------------------------------------------------- setup 0.00 038-pybindings-cgxset.py 0.06 teardown 0.00 --------------------------------------------------------- Total Run Time 0.06 Signed-off-by: Tom Hromatka <tom...@or...> --- ftests/038-pybindings-cgxset.py | 120 ++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100755 ftests/038-pybindings-cgxset.py diff --git a/ftests/038-pybindings-cgxset.py b/ftests/038-pybindings-cgxset.py new file mode 100755 index 000000000000..53edab3c36fd --- /dev/null +++ b/ftests/038-pybindings-cgxset.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# +# cgxset functionality test using the python bindings +# +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Author: Tom Hromatka <tom...@or...> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# 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>. +# + +from cgroup import CgroupVersion +from cgroup import Cgroup as CgroupCli +from cgroup import CgroupVersion as CgroupCliVersion +from libcgroup import Cgroup, Version +import consts +import ftests +import os +from run import Run +import stat +import sys + +CONTROLLER = 'cpu' +CGNAME = "038cgxset" + +SETTING1 = 'cpu.shares' +VALUE1 = '512' + +SETTING2 = 'cpu.weight' +VALUE2 = '50' + +def prereqs(config): + if config.args.container: + result = consts.TEST_SKIPPED + cause = "This test cannot be run within a container" + return result, cause + + result = consts.TEST_PASSED + cause = None + + return result, cause + +def setup(config): + user_name = Run.run('whoami', shell_bool=True) + group_name = Run.run('groups', shell_bool=True).split(' ')[0] + + CgroupCli.create(config, controller_list=CONTROLLER, cgname=CGNAME, + user_name=user_name, group_name=group_name) + +def test(config): + result = consts.TEST_PASSED + cause = None + + cg1 = Cgroup(CGNAME, Version.CGROUP_V1) + cg1.add_controller(CONTROLLER) + cg1.add_setting(SETTING1, VALUE1) + + cg1.cgxset(Version.CGROUP_V1) + + value_v1 = CgroupCli.xget(config, setting=SETTING1, print_headers=False, + values_only=True, version=CgroupCliVersion.CGROUP_V1, + cgname=CGNAME) + + if value_v1 != VALUE1: + result = consts.TEST_FAILED + cause = "Expected {}, but received {}".format(VALUE1, value_v1) + return result, cause + + # Set the cpu.shares/cpu.weight to an arbitrary value to ensure + # the following v2 cgxset works properly + CgroupCli.xset(config, cgname=CGNAME, setting=SETTING1, value="1234", + version=CgroupCliVersion.CGROUP_V1) + + cg2 = Cgroup(CGNAME, Version.CGROUP_V2) + cg2.add_controller(CONTROLLER) + cg2.add_setting(SETTING2, VALUE2) + + cg2.cgxset(Version.CGROUP_V2) + + value_v2 = CgroupCli.xget(config, setting=SETTING2, print_headers=False, + values_only=True, version=CgroupCliVersion.CGROUP_V2, + cgname=CGNAME) + + if value_v2 != VALUE2: + result = consts.TEST_FAILED + cause = "Expected {}, but received {}".format(VALUE2, value_v2) + return result, cause + + return result, cause + +def teardown(config): + CgroupCli.delete(config, CONTROLLER, CGNAME) + +def main(config): + [result, cause] = prereqs(config) + if result != consts.TEST_PASSED: + return [result, cause] + + setup(config) + [result, cause] = test(config) + teardown(config) + + return [result, cause] + +if __name__ == '__main__': + config = ftests.parse_args() + # this test was invoked directly. run only it + config.args.num = int(os.path.basename(__file__).split('-')[0]) + sys.exit(ftests.main(config)) -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:36:03
|
Add a functional test that exercises the library_version() python bindings. ----------------------------------------------------------------- Test Results: Run Date: Oct 27 15:53:49 Passed: 1 test(s) Skipped: 0 test(s) Failed: 0 test(s) ----------------------------------------------------------------- Timing Results: Test Time (sec) --------------------------------------------------------- setup 0.00 039-pybindings-library_version.py 0.00 teardown 0.00 --------------------------------------------------------- Total Run Time 0.00 Signed-off-by: Tom Hromatka <tom...@or...> --- ftests/039-pybindings-library_version.py | 77 ++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100755 ftests/039-pybindings-library_version.py diff --git a/ftests/039-pybindings-library_version.py b/ftests/039-pybindings-library_version.py new file mode 100755 index 000000000000..61050a6877ea --- /dev/null +++ b/ftests/039-pybindings-library_version.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# +# get the library version using the python bindings +# +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Author: Tom Hromatka <tom...@or...> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# 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>. +# + +from libcgroup import Cgroup +import consts +import ftests +import os +import stat +import sys + +def prereqs(config): + return consts.TEST_PASSED, None + +def setup(config): + return consts.TEST_PASSED, None + +def test(config): + result = consts.TEST_PASSED + cause = None + + [major, minor, release] = Cgroup.library_version() + + if not isinstance(major, int): + result = consts.TEST_FAILED + cause = "Major version failed. Received {}".format(major) + return result, cause + + if not isinstance(minor, int): + result = consts.TEST_FAILED + cause = "Minor version failed. Received {}".format(minor) + return result, cause + + if not isinstance(release, int): + result = consts.TEST_FAILED + cause = "Release version failed. Received {}".format(release) + return result, cause + + return result, cause + +def teardown(config): + pass + +def main(config): + [result, cause] = prereqs(config) + if result != consts.TEST_PASSED: + return [result, cause] + + setup(config) + [result, cause] = test(config) + teardown(config) + + return [result, cause] + +if __name__ == '__main__': + config = ftests.parse_args() + # this test was invoked directly. run only it + config.args.num = int(os.path.basename(__file__).split('-')[0]) + sys.exit(ftests.main(config)) -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:36:02
|
Add a functional test that exercises the cgroup_cgxget() python bindings. ----------------------------------------------------------------- Test Results: Run Date: Oct 11 22:11:48 Passed: 1 test(s) Skipped: 0 test(s) Failed: 0 test(s) ----------------------------------------------------------------- Timing Results: Test Time (sec) --------------------------------------------------------- setup 0.00 037-pybindings-cgxget.py 0.04 teardown 0.00 --------------------------------------------------------- Total Run Time 0.04 Signed-off-by: Tom Hromatka <tom...@or...> --- ftests/037-pybindings-cgxget.py | 130 ++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100755 ftests/037-pybindings-cgxget.py diff --git a/ftests/037-pybindings-cgxget.py b/ftests/037-pybindings-cgxget.py new file mode 100755 index 000000000000..9159bc6198cd --- /dev/null +++ b/ftests/037-pybindings-cgxget.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# +# cgxget functionality test using the python bindings +# +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Author: Tom Hromatka <tom...@or...> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# 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>. +# + +from cgroup import CgroupVersion +from cgroup import Cgroup as CgroupCli +from libcgroup import Cgroup, Version +import consts +import ftests +import os +import sys + +CONTROLLER = 'cpu' +CGNAME = "037cgxget" + +SETTING1 = 'cpu.shares' +VALUE1 = '4096' + +SETTING2 = 'cpu.weight' +VALUE2 = '400' + +def prereqs(config): + if config.args.container: + result = consts.TEST_SKIPPED + cause = "This test cannot be run within a container" + return result, cause + + result = consts.TEST_PASSED + cause = None + + return result, cause + +def setup(config): + CgroupCli.create(config, CONTROLLER, CGNAME) + if CgroupVersion.get_version('cpu') == CgroupVersion.CGROUP_V1: + CgroupCli.set(config, CGNAME, SETTING1, VALUE1) + else: + CgroupCli.set(config, CGNAME, SETTING2, VALUE2) + +def test(config): + result = consts.TEST_PASSED + cause = None + + cg1 = Cgroup(CGNAME, Version.CGROUP_V1) + cg1.add_controller(CONTROLLER) + cg1.add_setting(SETTING1) + + cg1.cgxget(Version.CGROUP_V1) + + if len(cg1.controllers) != 1: + result = consts.TEST_FAILED + cause = "Controller length doesn't match, expected 1, but received {}".format( + len(cg1.controllers)) + return result, cause + + if len(cg1.controllers[CONTROLLER].settings) != 1: + result = consts.TEST_FAILED + cause = "Settings length doesn't match, expected 1, but received {}".format( + len(cg1.controllers[CONTROLLER].settings)) + return result, cause + + if cg1.controllers[CONTROLLER].settings[SETTING1] != VALUE1: + result = consts.TEST_FAILED + cause = "Expected {} = {} but received {}".format(SETTING1, VALUE1, + cg1.controllers[CONTROLLER].settings[SETTING1]) + return result, cause + + cg2 = Cgroup(CGNAME, Version.CGROUP_V2) + cg2.add_controller(CONTROLLER) + cg2.add_setting(SETTING2) + + cg2.cgxget(Version.CGROUP_V2) + + if len(cg2.controllers) != 1: + result = consts.TEST_FAILED + cause = "Controller length doesn't match, expected 1, but received {}".format( + len(cg2.controllers)) + return result, cause + + if len(cg2.controllers[CONTROLLER].settings) != 1: + result = consts.TEST_FAILED + cause = "Settings length doesn't match, expected 1, but received {}".format( + len(cg2.controllers[CONTROLLER].settings)) + return result, cause + + if cg2.controllers[CONTROLLER].settings[SETTING2] != VALUE2: + result = consts.TEST_FAILED + cause = "Expected {} = {} but received {}".format(SETTING2, VALUE2, + cg2.controllers[CONTROLLER].settings[SETTING2]) + return result, cause + + return result, cause + +def teardown(config): + CgroupCli.delete(config, CONTROLLER, CGNAME) + +def main(config): + [result, cause] = prereqs(config) + if result != consts.TEST_PASSED: + return [result, cause] + + setup(config) + [result, cause] = test(config) + teardown(config) + + return [result, cause] + +if __name__ == '__main__': + config = ftests.parse_args() + # this test was invoked directly. run only it + config.args.num = int(os.path.basename(__file__).split('-')[0]) + sys.exit(ftests.main(config)) -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:35:03
|
Remove the old python bindings. They will be replaced with Cython bindings in a subsequent commit. Signed-off-by: Tom Hromatka <tom...@or...> --- configure.ac | 13 ------------- src/Makefile.am | 6 +----- src/bindings/Makefile.am | 15 --------------- src/bindings/libcgroup.p | 21 --------------------- src/bindings/tests/stat.py | 35 ----------------------------------- 5 files changed, 1 insertion(+), 89 deletions(-) delete mode 100644 src/bindings/Makefile.am delete mode 100644 src/bindings/libcgroup.p delete mode 100644 src/bindings/tests/stat.py diff --git a/configure.ac b/configure.ac index cbe5cef91b05..7b43a9ec16b6 100644 --- a/configure.ac +++ b/configure.ac @@ -38,18 +38,6 @@ LT_INIT AC_CONFIG_SRCDIR([src]) AC_CONFIG_HEADER([config.h]) -AC_ARG_ENABLE([bindings], - [AS_HELP_STRING([--enable-bindings],[enable python bindings [default=no]])], - [ - if test "x$enableval" = xno; then - with_bindings=false - else - with_bindings=true - fi - ], - [with_bindings = false]) -AM_CONDITIONAL([WITH_BINDINGS], [test x$with_bindings = xtrue]) - # Process command line options AC_ARG_ENABLE([tools], [AS_HELP_STRING([--enable-tools],[compile libcgroup tools [default=yes]])], @@ -208,7 +196,6 @@ AC_CONFIG_FILES([Makefile src/daemon/Makefile src/tools/Makefile src/pam/Makefile - src/bindings/Makefile scripts/Makefile scripts/init.d/cgconfig scripts/init.d/cgred diff --git a/src/Makefile.am b/src/Makefile.am index f7c8903d5c2e..f7f07e4247f8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,11 +2,7 @@ BUILT_SOURCES = parse.c parse.h -if WITH_BINDINGS -BINDINGS_SUBDIR = bindings -endif - -SUBDIRS = . daemon pam tools $(BINDINGS_SUBDIR) +SUBDIRS = . daemon pam tools # generate parse.h from parse.y AM_YFLAGS = -d diff --git a/src/bindings/Makefile.am b/src/bindings/Makefile.am deleted file mode 100644 index d7e32bcd8848..000000000000 --- a/src/bindings/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -SUBDIRS = . -AM_CPPFLAGS = -I$(top_srcdir)/include - -lib_LTLIBRARIES = _libcgroup.la -_libcgroup_la_SOURCES = libcgroup.c -_libcgroup_la_LDFLAGS = $(shell python-config --ldflags) -module -avoid-version -_libcgroup_la_CFLAGS = $(shell python-config --cflags) -_libcgroup_la_LIBADD = $(top_builddir)/src/libcgroup.la -SWIG=swig - - -libcgroup.c: libcgroup.p $(top_srcdir)/include/libcgroup.h - cp libcgroup.p libcgroup.i - $(CC) $(INCLUDES) -DSWIG -E $(top_srcdir)/include/libcgroup.h >> libcgroup.i - $(SWIG) -python -o libcgroup.c libcgroup.i diff --git a/src/bindings/libcgroup.p b/src/bindings/libcgroup.p deleted file mode 100644 index ed3f32fd66ad..000000000000 --- a/src/bindings/libcgroup.p +++ /dev/null @@ -1,21 +0,0 @@ -%module libcgroup -%{ -#include "libcgroup.h" -%} - -%include typemaps.i -%include cpointer.i -%pointer_functions(int, intp); -%typemap (in) void** (void *temp) { - void *arg; - if ((arg = PyCObject_AsVoidPtr($input)) != NULL) { - $1 = &arg; - } else - $1 = &temp; -} - -%typemap (argout) void** { - PyObject *obj = PyCObject_FromVoidPtr(*$1, NULL); - $result = PyTuple_Pack(2, $result, obj); -} - diff --git a/src/bindings/tests/stat.py b/src/bindings/tests/stat.py deleted file mode 100644 index 3cfdb2468260..000000000000 --- a/src/bindings/tests/stat.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/python - -from libcgroup import * -from ctypes import * - -ret = cgroup_init() -if (ret != 0): - print cgroup_strerror(ret) - exit(1) - -# -# Add the correct controllers based on the mount point -# -cg_stat = cgroup_stat() -tree_handle = c_void_p() -info = cgroup_file_info() -lvl = new_intp() -ret1, tree_handle = cgroup_walk_tree_begin("memory", "/", 0, tree_handle, info, lvl) -root_len = len(info.full_path) - 1 -while ret1 != ECGEOF: - if (info.type == CGROUP_FILE_TYPE_DIR): - dir = info.full_path[root_len:] - print "\nDirectory %s\n" %(dir) - - p = c_void_p() - ret, p = cgroup_read_stats_begin("memory", dir, p, cg_stat) - while ret != ECGEOF: - print "%s:%s" %(cg_stat.name, cg_stat.value.strip('\n')) - ret, p = cgroup_read_stats_next(p, cg_stat) - - cgroup_read_stats_end(p) - ret1, tree_handle = cgroup_walk_tree_next(0, tree_handle, info, intp_value(lvl)) - -cgroup_walk_tree_end(tree_handle) -delete_intp(lvl) -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:35:03
|
Add a function, cgroup_version(), that returns the current version of the libcgroup library. Signed-off-by: Tom Hromatka <tom...@or...> --- configure.ac | 1 + include/libcgroup/.gitignore | 1 + include/libcgroup/{init.h => init.h.in} | 19 +++++++++++++++++++ src/api.c | 11 +++++++++++ src/libcgroup.map | 1 + 5 files changed, 33 insertions(+) create mode 100644 include/libcgroup/.gitignore rename include/libcgroup/{init.h => init.h.in} (80%) diff --git a/configure.ac b/configure.ac index 7b43a9ec16b6..2d10a527c1d4 100644 --- a/configure.ac +++ b/configure.ac @@ -201,6 +201,7 @@ AC_CONFIG_FILES([Makefile scripts/init.d/cgred samples/Makefile include/Makefile + include/libcgroup/init.h doc/Makefile doc/man/Makefile dist/Makefile diff --git a/include/libcgroup/.gitignore b/include/libcgroup/.gitignore new file mode 100644 index 000000000000..6d7255a8ce8a --- /dev/null +++ b/include/libcgroup/.gitignore @@ -0,0 +1 @@ +init.h diff --git a/include/libcgroup/init.h b/include/libcgroup/init.h.in similarity index 80% rename from include/libcgroup/init.h rename to include/libcgroup/init.h.in index ea2dcc98bc60..9c63e684ada6 100644 --- a/include/libcgroup/init.h +++ b/include/libcgroup/init.h.in @@ -13,6 +13,25 @@ extern "C" { #endif +#define CGROUP_VER_MAJOR @LIBRARY_VERSION_MAJOR@ +#define CGROUP_VER_MINOR @LIBRARY_VERSION_MINOR@ +#define CGROUP_VER_RELEASE @LIBRARY_VERSION_RELEASE@ + +struct cgroup_library_version { + unsigned int major; + unsigned int minor; + unsigned int release; +}; + +/** + * Query the library version information + * + * This function returns a pointer to a populated cgroup_library_version + * struct. The caller does not need to free the structure when finished. + * + */ +const struct cgroup_library_version *cgroup_version(void); + /** * @defgroup group_init 1. Initialization * @{ diff --git a/src/api.c b/src/api.c index bd77b54da7d5..91f4615a2f43 100644 --- a/src/api.c +++ b/src/api.c @@ -50,6 +50,12 @@ #include <linux/un.h> #include <grp.h> +const struct cgroup_library_version library_version = { + .major = CGROUP_VER_MAJOR, + .minor = CGROUP_VER_MINOR, + .release = CGROUP_VER_RELEASE, +}; + /* * The errno which happend the last time (have to be thread specific) */ @@ -5680,3 +5686,8 @@ int cgroup_get_controller_version(const char * const controller, return ECGROUPNOTEXIST; } + +const struct cgroup_library_version *cgroup_version(void) +{ + return &library_version; +} diff --git a/src/libcgroup.map b/src/libcgroup.map index 3ce7e1b00c58..99788ac56f45 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -144,4 +144,5 @@ CGROUP_3.0 { cgroup_convert_cgroup; cgroup_cgxget; cgroup_cgxset; + cgroup_version; } CGROUP_2.0; -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:35:03
|
Add python bindings via the --enable-python configure flag. Signed-off-by: Tom Hromatka <tom...@or...> --- .github/actions/setup-libcgroup/action.yml | 6 +- .github/workflows/continuous-integration.yml | 9 + configure.ac | 16 ++ src/Makefile.am | 3 + src/python/.gitignore | 6 + src/python/Makefile.am | 56 ++++ src/python/cgroup.pxd | 64 +++++ src/python/libcgroup.pyx | 274 +++++++++++++++++++ src/python/setup.py | 47 ++++ 9 files changed, 479 insertions(+), 2 deletions(-) create mode 100644 src/python/.gitignore create mode 100644 src/python/Makefile.am create mode 100644 src/python/cgroup.pxd create mode 100644 src/python/libcgroup.pyx create mode 100755 src/python/setup.py diff --git a/.github/actions/setup-libcgroup/action.yml b/.github/actions/setup-libcgroup/action.yml index fae416c8a410..01628b0a3886 100644 --- a/.github/actions/setup-libcgroup/action.yml +++ b/.github/actions/setup-libcgroup/action.yml @@ -26,13 +26,15 @@ runs: steps: - run: sudo apt-get update shell: bash - - run: sudo apt-get install libpam-dev lcov + - run: sudo apt-get install libpam-dev lcov python3-pip + shell: bash + - run: sudo pip install cython shell: bash - run: rm -fr tests/ shell: bash - run: ./bootstrap.sh shell: bash - - run: CFLAGS="$CFLAGS -g -O0 -Werror" ./configure --sysconfdir=/etc --localstatedir=/var --enable-code-coverage --enable-opaque-hierarchy="name=systemd" + - run: CFLAGS="$CFLAGS -g -O0 -Werror" ./configure --sysconfdir=/etc --localstatedir=/var --enable-code-coverage --enable-opaque-hierarchy="name=systemd" --enable-python shell: bash - run: make shell: bash diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 14fc04802f86..2ded6e9d3b2a 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -75,6 +75,9 @@ jobs: run: | # The cgroup v1 runner hosted by Github Actions doesn't allow # for exclusive cpusets. Thus, skip the cpuset automated test + pushd src/python/build/lib.* + export PYTHONPATH=$PYTHONPATH:$(pwd) + popd ./tests/ftests/ftests.py -l 10 -L ftests.log ./tests/ftests/ftests.py -l 10 -L ftests-nocontainer.log --skip 36 --no-container - name: Archive test logs @@ -125,6 +128,9 @@ jobs: uses: ./.github/actions/setup-libcgroup - name: Run functional tests run: | + pushd src/python/build/lib.* + export PYTHONPATH=$PYTHONPATH:$(pwd) + popd pushd tests/ftests make check popd @@ -169,6 +175,9 @@ jobs: uses: ./.github/actions/setup-libcgroup - name: Run functional tests run: | + pushd src/python/build/lib.* + export PYTHONPATH=$PYTHONPATH:$(pwd) + popd pushd tests/ftests make check popd diff --git a/configure.ac b/configure.ac index 2d10a527c1d4..84d7e688e4a7 100644 --- a/configure.ac +++ b/configure.ac @@ -75,6 +75,21 @@ AC_ARG_ENABLE([daemon], [with_daemon=true]) AM_CONDITIONAL([WITH_DAEMON], [test x$with_daemon = xtrue]) +AC_ARG_ENABLE([python], + [AS_HELP_STRING([--enable-python], + [build the python bindings, requires cython])]) +AS_IF([test "$enable_python" = yes], [ + # cython version check + AS_IF([test "$CYTHON_VER_MAJ" -eq 0 -a "$CYTHON_VER_MIN" -lt 29], [ + AC_MSG_ERROR([python bindings require cython 0.29 or higher]) + ]) + AM_PATH_PYTHON([3]) +]) +AM_CONDITIONAL([ENABLE_PYTHON], [test "$enable_python" = yes]) +AC_DEFINE_UNQUOTED([ENABLE_PYTHON], + [$(test "$enable_python" = yes && echo 1 || echo 0)], + [Python bindings build flag.]) + AC_ARG_ENABLE([initscript-install], [AS_HELP_STRING([--enable-initscript-install],[install init scripts [default=no]])], [ @@ -196,6 +211,7 @@ AC_CONFIG_FILES([Makefile src/daemon/Makefile src/tools/Makefile src/pam/Makefile + src/python/Makefile scripts/Makefile scripts/init.d/cgconfig scripts/init.d/cgred diff --git a/src/Makefile.am b/src/Makefile.am index 5227a0366072..176cf13c3333 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,6 +3,9 @@ BUILT_SOURCES = parse.c parse.h SUBDIRS = . daemon pam tools +if ENABLE_PYTHON +SUBDIRS += python +endif # generate parse.h from parse.y AM_YFLAGS = -d diff --git a/src/python/.gitignore b/src/python/.gitignore new file mode 100644 index 000000000000..8862a1395e13 --- /dev/null +++ b/src/python/.gitignore @@ -0,0 +1,6 @@ +build/ +Makefile +Makefile.in +__init__.py +*.c +*.swp diff --git a/src/python/Makefile.am b/src/python/Makefile.am new file mode 100644 index 000000000000..5c77add326bf --- /dev/null +++ b/src/python/Makefile.am @@ -0,0 +1,56 @@ +# +# Libcgroup Python Bindings +# +# Copyright (c) 2021 Oracle and/or its affiliates. +# Author: Tom Hromatka <tom...@or...> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# 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>. +# +@CODE_COVERAGE_RULES@ + +PY_DISTUTILS = \ + VERSION_RELEASE="@PACKAGE_VERSION@" \ + CPPFLAGS="-I\${top_srcdir}/include ${AM_CPPFLAGS} ${CPPFLAGS}" \ + CFLAGS="$(CODE_COVERAGE_CFLAGS) ${AM_CFLAGS} ${CFLAGS}" \ + LDFLAGS="$(CODE_COVERAGE_LIBS) ${AM_LDFLAGS} ${LDFLAGS}" \ + ${PYTHON} ${srcdir}/setup.py + +# support silent builds +PY_BUILD_0 = @echo " PYTHON " $@; ${PY_DISTUTILS} -q build +PY_BUILD_1 = ${PY_DISTUTILS} build +PY_BUILD_ = ${PY_BUILD_0} +PY_BUILD = ${PY_BUILD_@AM_V@} + +PY_INSTALL = ${PY_DISTUTILS} install + +EXTRA_DIST = cgroup.pxd libcgroup.pyx setup.py + +all-local: build + +build: ../libcgroup.la cgroup.pxd libcgroup.pyx setup.py + [ ${srcdir} == ${builddir} ] || cp ${srcdir}/libcgroup.pyx ${builddir} + ${PY_BUILD} && touch build + +install-exec-local: build + ${PY_INSTALL} --install-lib=${DESTDIR}/${pyexecdir} \ + --record=${DESTDIR}/${pyexecdir}/install_files.txt + +uninstall-local: + cat ${DESTDIR}/${pyexecdir}/install_files.txt | xargs ${RM} -f + ${RM} -f ${DESTDIR}/${pyexecdir}/install_files.txt + +clean-local: + [ ${srcdir} == ${builddir} ] || ${RM} -f ${builddir}/libcgroup.pyx + ${RM} -rf libcgroup.c build diff --git a/src/python/cgroup.pxd b/src/python/cgroup.pxd new file mode 100644 index 000000000000..82fa2af91a2d --- /dev/null +++ b/src/python/cgroup.pxd @@ -0,0 +1,64 @@ +# +# Libcgroup Python Bindings +# +# Copyright (c) 2021 Oracle and/or its affiliates. +# Author: Tom Hromatka <tom...@or...> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# 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>. +# + +# cython: language_level = 3str + +cdef extern from "libcgroup.h": + cdef struct cgroup: + pass + + cdef struct cgroup_controller: + pass + + cdef enum cg_version_t: + CGROUP_UNK + CGROUP_V1 + CGROUP_V2 + CGROUP_DISK + + cdef struct cgroup_library_version: + unsigned int major + unsigned int minor + unsigned int release + + int cgroup_init() + const cgroup_library_version * cgroup_version() + + cgroup *cgroup_new_cgroup(const char *name) + int cgroup_convert_cgroup(cgroup *out_cg, cg_version_t out_version, + cgroup *in_cg, cg_version_t in_version) + void cgroup_free(cgroup **cg) + + cgroup_controller *cgroup_add_controller(cgroup *cg, const char *name) + cgroup_controller *cgroup_get_controller(cgroup *cg, const char *name) + + int cgroup_add_value_string(cgroup_controller *cgc, const char *name, + const char *value) + int cgroup_get_value_string(cgroup_controller *cgc, const char *name, + char **value) + char *cgroup_get_value_name(cgroup_controller *cgc, int index) + int cgroup_get_value_name_count(cgroup_controller *cgc) + + int cgroup_cgxget(cgroup ** cg, cg_version_t version, + bint ignore_unmappable) + + int cgroup_cgxset(const cgroup * const cg, cg_version_t version, + bint ignore_unmappable) diff --git a/src/python/libcgroup.pyx b/src/python/libcgroup.pyx new file mode 100644 index 000000000000..cf43a5ad905d --- /dev/null +++ b/src/python/libcgroup.pyx @@ -0,0 +1,274 @@ +# +# Libcgroup Python Bindings +# +# Copyright (c) 2021 Oracle and/or its affiliates. +# Author: Tom Hromatka <tom...@or...> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# 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>. +# + +# cython: language_level = 3str + +""" Python bindings for the libcgroup library +""" + +__author__ = 'Tom Hromatka <tom...@or...>' +__date__ = "25 October 2021" + +cimport cgroup + +cdef class Version: + CGROUP_UNK = cgroup.CGROUP_UNK + CGROUP_V1 = cgroup.CGROUP_V1 + CGROUP_V2 = cgroup.CGROUP_V2 + CGROUP_DISK = cgroup.CGROUP_DISK + +def c_str(string): + return bytes(string, "ascii") + +def indent(in_str, cnt): + leading_indent = cnt * ' ' + return ''.join(leading_indent + line for line in in_str.splitlines(True)) + +class Controller: + def __init__(self, name): + self.name = name + # self.settings maps to + # struct control_value *values[CG_NV_MAX]; + self.settings = dict() + + def __str__(self): + out_str = "Controller {}\n".format(self.name) + + for setting_key in self.settings: + out_str += indent("{} = {}\n".format(setting_key, + self.settings[setting_key]), 4) + + return out_str + +cdef class Cgroup: + """ Python object representing a libcgroup cgroup """ + cdef cgroup.cgroup * _cgp + cdef public: + object name, controllers, version + + def __cinit__(self, name, version): + ret = cgroup.cgroup_init() + if ret != 0: + raise RuntimeError("Failed to initialize libcgroup: {}".format(ret)) + + self._cgp = cgroup.cgroup_new_cgroup(c_str(name)) + if self._cgp == NULL: + raise RuntimeError("Failed to create cgroup {}".format(name)) + + def __init__(self, name, version): + """Initialize this cgroup instance + + Arguments: + name - Name of this cgroup + version - Version of this cgroup + + Note: + Does not modify the cgroup sysfs. Does not read from the cgroup sysfs + """ + self.name = name + self.controllers = dict() + self.version = version + + def __str__(self): + out_str = "Cgroup {}\n".format(self.name) + for ctrl_key in self.controllers: + out_str += indent(str(self.controllers[ctrl_key]), 4) + + return out_str + + @staticmethod + def library_version(): + cdef const cgroup.cgroup_library_version * version + + version = cgroup.cgroup_version() + return [version.major, version.minor, version.release] + + def add_controller(self, ctrl_name): + """Add a controller to the Cgroup instance + + Arguments: + ctrl_name - name of the controller + + Description: + Adds a controller to the Cgroup instance + + Note: + Does not modify the cgroup sysfs + """ + cdef cgroup.cgroup_controller * cgcp + cdef cgroup.cgroup * cgp + + cgcp = cgroup.cgroup_add_controller(self._cgp, + c_str(ctrl_name)) + if cgcp == NULL: + raise RuntimeError("Failed to add controller {} to cgroup".format( + ctrl_name)) + + self.controllers[ctrl_name] = Controller(ctrl_name) + + def add_setting(self, setting_name, setting_value=None): + """Add a setting to the Cgroup/Controller instance + + Arguments: + setting_name - name of the cgroup setting, e.g. 'cpu.shares' + setting_value (optional) - value + + Description: + Adds a setting/value pair to the Cgroup/Controller instance + + Note: + Does not modify the cgroup sysfs + """ + cdef cgroup.cgroup_controller *cgcp + cdef char * value + + ctrl_name = setting_name.split('.')[0] + + cgcp = cgroup.cgroup_get_controller(self._cgp, + c_str(ctrl_name)) + if cgcp == NULL: + self.add_controller(ctrl_name) + + if setting_value == None: + ret = cgroup.cgroup_add_value_string(cgcp, + c_str(setting_name), NULL) + else: + ret = cgroup.cgroup_add_value_string(cgcp, + c_str(setting_name), c_str(setting_value)) + if ret != 0: + raise RuntimeError("Failed to add setting {}: {}".format( + setting_name, ret)) + + def _pythonize_cgroup(self): + """ + Given a populated self._cgp, populate the equivalent Python fields + """ + cdef char *setting_name + cdef char *setting_value + + for ctrlr_key in self.controllers: + cgcp = cgroup.cgroup_get_controller(self._cgp, + c_str(self.controllers[ctrlr_key].name)) + if cgcp == NULL: + raise RuntimeError("Failed to get controller {}".format( + ctrlr_key)) + + self.controllers[ctrlr_key] = Controller(ctrlr_key) + setting_cnt = cgroup.cgroup_get_value_name_count(cgcp) + + for i in range(0, setting_cnt): + setting_name = cgroup.cgroup_get_value_name(cgcp, i) + + ret = cgroup.cgroup_get_value_string(cgcp, + setting_name, &setting_value) + if ret != 0: + raise RuntimeError("Failed to get value {}: {}".format( + setting_name, ret)) + + name = setting_name.decode("ascii") + value = setting_value.decode("ascii").strip() + self.controllers[ctrlr_key].settings[name] = value + + def convert(self, out_version): + """Convert this cgroup to another cgroup version + + Arguments: + out_version - Version to convert to + + Return: + Returns the converted cgroup instance + + Description: + Convert this cgroup instance to a cgroup instance of a different + cgroup version + + Note: + Does not modify the cgroup sysfs. Does not read from the cgroup sysfs + """ + out_cgp = Cgroup(self.name, out_version) + ret = cgroup.cgroup_convert_cgroup(out_cgp._cgp, + out_version, self._cgp, self.version) + if ret != 0: + raise RuntimeError("Failed to convert cgroup: {}".format(ret)) + + for ctrlr_key in self.controllers: + out_cgp.controllers[ctrlr_key] = Controller(ctrlr_key) + + out_cgp._pythonize_cgroup() + + return out_cgp + + def cgxget(self, ignore_unmappable=False): + """Read the requested settings from the cgroup sysfs + + Arguments: + ignore_unmappable - Ignore cgroup settings that can't be converted + from one version to another + + Return: + Returns the cgroup instance that represents the settings read from + sysfs + + Description: + Given this cgroup instance, read the settings/values from the + cgroup sysfs. If the read was successful, the settings are + returned in the return value + + Note: + Reads from the cgroup sysfs + """ + cdef bint ignore + + if ignore_unmappable: + ignore = 1 + else: + ignore = 0 + + ret = cgroup.cgroup_cgxget(&self._cgp, self.version, ignore) + if ret != 0: + raise RuntimeError("cgxget failed: {}".format(ret)) + + self._pythonize_cgroup() + + def cgxset(self, ignore_unmappable=False): + """Write this cgroup to the cgroup sysfs + + Arguments: + ignore_unmappable - Ignore cgroup settings that can't be converted + from one version to another + + Description: + Write the settings/values in this cgroup instance to the cgroup sysfs + + Note: + Writes to the cgroup sysfs + """ + if ignore_unmappable: + ignore = 1 + else: + ignore = 0 + + ret = cgroup.cgroup_cgxset(self._cgp, self.version, ignore) + if ret != 0: + raise RuntimeError("cgxset failed: {}".format(ret)) + + def __dealloc__(self): + cgroup.cgroup_free(&self._cgp); diff --git a/src/python/setup.py b/src/python/setup.py new file mode 100755 index 000000000000..f4b95d4a1a80 --- /dev/null +++ b/src/python/setup.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +# +# Libcgroup Python Module Build Script +# + +# +# Copyright (c) 2021 Oracle and/or its affiliates. +# Author: Tom Hromatka <tom...@or...> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# 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>. +# + +import os + +from distutils.core import setup +from distutils.extension import Extension +from Cython.Distutils import build_ext + +setup( + name = "libcgroup", + version = os.environ["VERSION_RELEASE"], + description = "Python bindings for libcgroup", + url = "https://github.com/libcgroup/libcgroup", + maintainer = "Tom Hromatka", + maintainer_email = "tom...@or...", + license = "LGPLv2.1", + platforms = "Linux", + cmdclass = {'build_ext': build_ext}, + ext_modules = [ + Extension("libcgroup", ["libcgroup.pyx"], + # unable to handle libtool libraries directly + extra_objects=["../.libs/libcgroup.a"]) + ] +) -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:35:02
|
This patchset exposes the new cgxget and cgxset interfaces via the libcgroup C APIs library. To facilitate automated testing and code coverage, python bindings are also part of this patchset. Finally, it must be noted that these patches are built on top of the cgxget/cgxset patchset [1] currently out for review. I have created a simple example program to highlight potential usage of these new C APIs [2]. The changes to libcgroup are available here: https://github.com/drakenclimber/libcgroup/tree/issues/cgxget5-pybindings3 The changes to the libcgroup tests are available here: https://github.com/drakenclimber/libcgroup-tests/tree/issues/cgxget5-pybindings Code coverage increased to 53.5%: https://coveralls.io/builds/44100945 I added a few functional tests, and all automated tests are passing. Results are here: https://github.com/drakenclimber/libcgroup/runs/4143613675 [1] https://sourceforge.net/p/libcg/mailman/message/37317688/ [2] https://gist.github.com/drakenclimber/b3a6b4031807b31bef8ec2c98025453f Tom Hromatka (10): python: Delete old python bindings groups.h: Move cg_version_t to groups.h libcgroup.so: Export cgroup_convert_cgroup() cgxget: libcgroup.so: Add cgroup_cgxget() to library cgxset: libcgroup.so: Add cgroup_cgxset() to library libcgroup.so: Add a function to get the library version libcgroup.so: Add cgroup_get_controller_version() to groups.h python: Add python bindings using Cython github: Add a code coverage action git: tools: Ignore cgxget and cgxset .github/actions/code-coverage/action.yml | 46 ++++ .github/actions/setup-libcgroup/action.yml | 6 +- .github/workflows/continuous-integration.yml | 27 +- configure.ac | 30 +- include/Makefile.am | 4 +- include/libcgroup.h | 1 + include/libcgroup/.gitignore | 1 + include/libcgroup/groups.h | 34 +++ include/libcgroup/{init.h => init.h.in} | 19 ++ include/libcgroup/tools.h | 70 +++++ src/Makefile.am | 23 +- src/abstraction-common.h | 17 -- src/api.c | 11 + src/bindings/Makefile.am | 15 - src/bindings/libcgroup.p | 21 -- src/bindings/tests/stat.py | 35 --- src/libcgroup-internal.h | 17 -- src/libcgroup.map | 3 + src/python/.gitignore | 6 + src/python/Makefile.am | 56 ++++ src/python/cgroup.pxd | 64 +++++ src/python/libcgroup.pyx | 274 +++++++++++++++++++ src/python/setup.py | 47 ++++ src/tools/.gitignore | 2 + src/tools/cgget.c | 88 ++++-- src/tools/cgset.c | 40 +++ 26 files changed, 799 insertions(+), 158 deletions(-) create mode 100644 .github/actions/code-coverage/action.yml create mode 100644 include/libcgroup/.gitignore rename include/libcgroup/{init.h => init.h.in} (80%) create mode 100644 include/libcgroup/tools.h delete mode 100644 src/bindings/Makefile.am delete mode 100644 src/bindings/libcgroup.p delete mode 100644 src/bindings/tests/stat.py create mode 100644 src/python/.gitignore create mode 100644 src/python/Makefile.am create mode 100644 src/python/cgroup.pxd create mode 100644 src/python/libcgroup.pyx create mode 100755 src/python/setup.py -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:35:01
|
Git ignore the executables cgxget and cgxset Signed-off-by: Tom Hromatka <tom...@or...> --- src/tools/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/.gitignore b/src/tools/.gitignore index 2293fcf34872..3df02b5eec4a 100644 --- a/src/tools/.gitignore +++ b/src/tools/.gitignore @@ -4,7 +4,9 @@ cgcreate cgdelete cgexec cgget +cgxget cgset +cgxset cgsnapshot lscgroup lssubsys -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:35:01
|
Add a code coverage action to the Github workflow. As part of this code coverage action, ignore the C file that is auto-generated from the Cython code. Also ignore a couple Python header files that were confusing lcov. Signed-off-by: Tom Hromatka <tom...@or...> --- .github/actions/code-coverage/action.yml | 46 ++++++++++++++++++++ .github/workflows/continuous-integration.yml | 18 +++----- 2 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 .github/actions/code-coverage/action.yml diff --git a/.github/actions/code-coverage/action.yml b/.github/actions/code-coverage/action.yml new file mode 100644 index 000000000000..cd7af441e33a --- /dev/null +++ b/.github/actions/code-coverage/action.yml @@ -0,0 +1,46 @@ +# +# Action to collate the libcgroup code coverage data +# +# Copyright (c) 2021 Oracle and/or its affiliates. +# Author: Tom Hromatka <tom...@or...> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# 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>. +# + +name: Collate code coverage results +description: "Collate code coverage results" +runs: + using: "composite" + steps: + - run: lcov -d . -c -o lcov.tests + shell: bash + - run: | + lcov -r lcov.tests "/usr/include/python3.8/objimpl.h" \ + "/usr/include/python3.8/object.h" \ + "$(pwd)/src/python/libcgroup.c" \ + "$(pwd)/src/parse.c" \ + "$(pwd)/src/lex.c" \ + -o lcov.tests + shell: bash + - run: | + lcov -r lcov.base "/usr/include/python3.8/objimpl.h" \ + "/usr/include/python3.8/object.h" \ + "$(pwd)/src/python/libcgroup.c" \ + "$(pwd)/src/parse.c" \ + "$(pwd)/src/lex.c" \ + -o lcov.base + shell: bash + - run: lcov -a lcov.base -a lcov.tests -o lcov.total + shell: bash diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 2ded6e9d3b2a..7acccf9a836f 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -42,9 +42,7 @@ jobs: if: ${{ always() }} run: cat tests/gunit/test-suite.log - name: Collate code coverage results - run: | - lcov -d . -c -o lcov.tests - lcov -a lcov.base -a lcov.tests -o lcov.total + uses: ./.github/actions/code-coverage - name: Upload code coverage results uses: coverallsapp/github-action@master with: @@ -85,11 +83,9 @@ jobs: uses: actions/upload-artifact@v2 with: name: Cgroup v1 test logs - path: tests/ftests/*.log + path: ./*.log - name: Collate code coverage results - run: | - lcov -d . -c -o lcov.tests - lcov -a lcov.base -a lcov.tests -o lcov.total + uses: ./.github/actions/code-coverage - name: Upload code coverage results uses: coverallsapp/github-action@master with: @@ -146,9 +142,7 @@ jobs: name: Cgroup v1v2 test logs path: tests/ftests/*.log - name: Collate code coverage results - run: | - lcov -d . -c -o lcov.tests - lcov -a lcov.base -a lcov.tests -o lcov.total + uses: ./.github/actions/code-coverage - name: Upload code coverage results uses: coverallsapp/github-action@master with: @@ -193,9 +187,7 @@ jobs: name: Cgroup v2 test logs path: tests/ftests/*.log - name: Collate code coverage results - run: | - lcov -d . -c -o lcov.tests - lcov -a lcov.base -a lcov.tests -o lcov.total + uses: ./.github/actions/code-coverage - name: Upload code coverage results uses: coverallsapp/github-action@master with: -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:35:00
|
Add cgroup_cgxget() to libcgroup.so. Create a new header file, libcgroup/tools.h, to hold C APIs that are exported from the tools folder. Signed-off-by: Tom Hromatka <tom...@or...> --- include/Makefile.am | 4 +- include/libcgroup.h | 1 + include/libcgroup/tools.h | 57 +++++++++++++++++++++++++ src/Makefile.am | 16 +++++-- src/libcgroup.map | 1 + src/tools/cgget.c | 88 ++++++++++++++++++++++++++++++++------- 6 files changed, 146 insertions(+), 21 deletions(-) create mode 100644 include/libcgroup/tools.h diff --git a/include/Makefile.am b/include/Makefile.am index 752a624ca125..44a9c0930126 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,2 +1,2 @@ -# Using 'nobase_', we what groups.h in /usr/include/libcgroup/ directory -nobase_include_HEADERS = libcgroup.h libcgroup/error.h libcgroup/init.h libcgroup/groups.h libcgroup/tasks.h libcgroup/iterators.h libcgroup/config.h libcgroup/log.h +# Using 'nobase_', we want groups.h in /usr/include/libcgroup/ directory +nobase_include_HEADERS = libcgroup.h libcgroup/error.h libcgroup/init.h libcgroup/groups.h libcgroup/tasks.h libcgroup/iterators.h libcgroup/config.h libcgroup/log.h libcgroup/tools.h diff --git a/include/libcgroup.h b/include/libcgroup.h index 1c7d409a7ab1..17ab90eaca5b 100644 --- a/include/libcgroup.h +++ b/include/libcgroup.h @@ -25,6 +25,7 @@ #include <libcgroup/tasks.h> #include <libcgroup/config.h> #include <libcgroup/log.h> +#include <libcgroup/tools.h> #undef _LIBCGROUP_H_INSIDE diff --git a/include/libcgroup/tools.h b/include/libcgroup/tools.h new file mode 100644 index 000000000000..cc0918c14fa7 --- /dev/null +++ b/include/libcgroup/tools.h @@ -0,0 +1,57 @@ +/** + * Libcgroup tools header file + * + * Copyright (c) 2021 Oracle and/or its affiliates. + * Author: Tom Hromatka <tom...@or...> + */ + +/* + * This library is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License as + * published by the Free Software Foundation. + * + * 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>. + */ +#ifndef _LIBCGROUP_TOOLS_H +#define _LIBCGROUP_TOOLS_H + +#ifndef _LIBCGROUP_H_INSIDE +#error "Only <libcgroup.h> should be included directly." +#endif + +#ifndef SWIG +#include <features.h> +#include <sys/types.h> +#include <stdbool.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Read the setting-value pairs in the cgroup sysfs for cg. + * cgroup_cgxget() will perform the necessary conversions to match + * the "on-disk" format and then convert the data back to the + * requested version. If successful, cg will be populated with + * the setting-value pairs. + * + * @param cg Input/Output cgroup. Must be initialized and freed by the caller + * @param version Cgroup version of cg + * @param ignore_unmappable Ignore failures due to settings that cannot be + * converted from one cgroup version to another + */ +int cgroup_cgxget(struct cgroup ** cg, + enum cg_version_t version, bool ignore_unmappable); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _LIBCGROUP_TOOLS_H */ diff --git a/src/Makefile.am b/src/Makefile.am index f7f07e4247f8..d7716aa80b19 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,13 +11,23 @@ CLEANFILES = lex.c parse.c parse.h AM_CPPFLAGS = -I$(top_srcdir)/include lib_LTLIBRARIES = libcgroup.la libcgroupfortesting.la -libcgroup_la_SOURCES = parse.h parse.y lex.l api.c config.c libcgroup-internal.h libcgroup.map wrapper.c log.c abstraction-common.c abstraction-common.h abstraction-map.c abstraction-map.h abstraction-cpu.c abstraction-cpuset.c +libcgroup_la_SOURCES = parse.h parse.y lex.l api.c config.c \ + libcgroup-internal.h libcgroup.map wrapper.c log.c \ + abstraction-common.c abstraction-common.h \ + abstraction-map.c abstraction-map.h \ + abstraction-cpu.c abstraction-cpuset.c \ + tools/cgget.c libcgroup_la_LIBADD = -lpthread $(CODE_COVERAGE_LIBS) -libcgroup_la_CFLAGS = $(CODE_COVERAGE_CFLAGS) -DSTATIC=static +libcgroup_la_CFLAGS = $(CODE_COVERAGE_CFLAGS) -DSTATIC=static -DLIBCG_LIB \ + -fPIC libcgroup_la_LDFLAGS = -Wl,--version-script,$(srcdir)/libcgroup.map \ -version-number $(LIBRARY_VERSION_MAJOR):$(LIBRARY_VERSION_MINOR):$(LIBRARY_VERSION_RELEASE) -libcgroupfortesting_la_SOURCES = $(libcgroup_la_SOURCES) +libcgroupfortesting_la_SOURCES = parse.h parse.y lex.l api.c config.c \ + libcgroup-internal.h libcgroup.map wrapper.c log.c \ + abstraction-common.c abstraction-common.h \ + abstraction-map.c abstraction-map.h \ + abstraction-cpu.c abstraction-cpuset.c libcgroupfortesting_la_LIBADD = -lpthread $(CODE_COVERAGE_LIBS) libcgroupfortesting_la_CFLAGS = $(CODE_COVERAGE_CFLAGS) -DSTATIC= -DUNIT_TEST libcgroupfortesting_la_LDFLAGS = -Wl,--version-script,$(top_srcdir)/tests/gunit/libcgroup_unittest.map \ diff --git a/src/libcgroup.map b/src/libcgroup.map index d99a2ce73c04..fb161daeecf2 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -142,4 +142,5 @@ CGROUP_2.0 { CGROUP_3.0 { cgroup_convert_cgroup; + cgroup_cgxget; } CGROUP_2.0; diff --git a/src/tools/cgget.c b/src/tools/cgget.c index e407383d73a7..2aa5709e8dcd 100644 --- a/src/tools/cgget.c +++ b/src/tools/cgget.c @@ -11,7 +11,7 @@ #include "tools-common.h" -#ifdef CGXGET +#if defined(CGXGET) || defined(LIBCG_LIB) #include "abstraction-common.h" #endif @@ -20,13 +20,14 @@ #define LL_MAX 100 +#ifndef LIBCG_LIB static struct option const long_options[] = { #ifdef CGXGET {"v1", no_argument, NULL, '1'}, {"v2", no_argument, NULL, '2'}, {"ignore-unmappable", no_argument, NULL, 'i'}, -#endif +#endif /* CGXGET */ {"variable", required_argument, NULL, 'r'}, {"help", no_argument, NULL, 'h'}, {"all", no_argument, NULL, 'a'}, @@ -54,7 +55,7 @@ static void usage(int status, const char *program_name) "v2 format\n"); printf(" -i, --ignore-unmappable Do not return an error for settings " "that cannot be converted\n"); -#endif +#endif /* CGXGET */ printf(" -a, --all Print info about all relevant " "controllers\n"); printf(" -g <controllers> Controller which info should " @@ -409,7 +410,7 @@ static int parse_opts(int argc, char *argv[], struct cgroup **cg_list[], #else static int parse_opts(int argc, char *argv[], struct cgroup **cg_list[], int * const cg_list_len, int * const mode) -#endif +#endif /* CGXGET */ { bool do_not_fill_controller = false; bool fill_controller = false; @@ -424,7 +425,7 @@ static int parse_opts(int argc, char *argv[], struct cgroup **cg_list[], #else while ((c = getopt_long(argc, argv, "r:hnvg:a", long_options, NULL)) > 0) { -#endif +#endif /* CGXGET */ switch (c) { case 'h': usage(0, argv[0]); @@ -475,7 +476,7 @@ static int parse_opts(int argc, char *argv[], struct cgroup **cg_list[], case 'i': *ignore_unmappable = true; break; -#endif +#endif /* CGXGET */ default: usage(1, argv[0]); exit(1); @@ -496,6 +497,7 @@ static int parse_opts(int argc, char *argv[], struct cgroup **cg_list[], err: return ret; } +#endif /* !LIBCG_LIB */ static int get_cv_value(struct control_value * const cv, const char * const cg_name, @@ -710,6 +712,7 @@ static int get_cgroup_values(struct cgroup * const cg) return ret; } +#ifndef LIBCG_LIB static int get_values(struct cgroup *cg_list[], int cg_list_len) { int ret; @@ -724,7 +727,8 @@ static int get_values(struct cgroup *cg_list[], int cg_list_len) return ret; } -void print_control_values(const struct control_value * const cv, int mode) +static void print_control_values(const struct control_value * const cv, + int mode) { if (mode & MODE_SHOW_NAMES) printf("%s: ", cv->name); @@ -735,7 +739,8 @@ void print_control_values(const struct control_value * const cv, int mode) printf("%s\n", cv->value); } -void print_controller(const struct cgroup_controller * const cgc, int mode) +static void print_controller(const struct cgroup_controller * const cgc, + int mode) { int i; @@ -768,9 +773,9 @@ static void print_cgroups(struct cgroup *cg_list[], int cg_list_len, int mode) } #ifdef CGXGET -int convert_cgroups(struct cgroup **cg_list[], int cg_list_len, - enum cg_version_t in_version, - enum cg_version_t out_version) +static int convert_cgroups(struct cgroup **cg_list[], int cg_list_len, + enum cg_version_t in_version, + enum cg_version_t out_version) { struct cgroup **cg_converted_list; int i = 0, j, ret = 0; @@ -807,7 +812,7 @@ out: return ret; } -#endif +#endif /* CGXGET */ int main(int argc, char *argv[]) { @@ -818,7 +823,7 @@ int main(int argc, char *argv[]) #ifdef CGXGET enum cg_version_t version = CGROUP_UNK; bool ignore_unmappable = false; -#endif +#endif /* CGXGET */ /* No parameter on input? */ if (argc < 2) { @@ -838,7 +843,7 @@ int main(int argc, char *argv[]) &ignore_unmappable); #else ret = parse_opts(argc, argv, &cg_list, &cg_list_len, &mode); -#endif +#endif /* CGXGET */ if (ret) goto err; @@ -851,7 +856,7 @@ int main(int argc, char *argv[]) ret = 0; else if (ret) goto err; -#endif +#endif /* CGXGET */ ret = get_values(cg_list, cg_list_len); if (ret) @@ -861,7 +866,7 @@ int main(int argc, char *argv[]) ret = convert_cgroups(&cg_list, cg_list_len, CGROUP_DISK, version); if (ret) goto err; -#endif +#endif /* CGXGET */ print_cgroups(cg_list, cg_list_len, mode); @@ -871,3 +876,54 @@ err: return ret; } +#endif /* LIBCG_LIB */ + +#ifdef LIBCG_LIB +int cgroup_cgxget(struct cgroup **cg, + enum cg_version_t version, bool ignore_unmappable) +{ + struct cgroup *disk_cg, *out_cg; + int ret; + + if (!cg || !(*cg)) { + ret = ECGINVAL; + goto out; + } + + disk_cg = cgroup_new_cgroup((*cg)->name); + if (!disk_cg) { + ret = ECGCONTROLLERCREATEFAILED; + goto out; + } + + ret = cgroup_convert_cgroup(disk_cg, CGROUP_DISK, *cg, version); + if (ret == ECGNOVERSIONCONVERT && ignore_unmappable) + ret = 0; + else if (ret) + goto out; + + ret = get_cgroup_values(disk_cg); + if (ret) + goto out; + + out_cg = cgroup_new_cgroup((*cg)->name); + if (!out_cg) { + ret = ECGCONTROLLERCREATEFAILED; + goto out; + } + + ret = cgroup_convert_cgroup(out_cg, version, disk_cg, CGROUP_DISK); + if (ret) { + cgroup_free(&out_cg); + goto out; + } + + cgroup_free(cg); + *cg = out_cg; + +out: + if (disk_cg) + cgroup_free(&disk_cg); + return ret; +} +#endif /* LIBCG_LIB */ -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:35:00
|
Add cgroup_cgxset() to libcgroup.so. Signed-off-by: Tom Hromatka <tom...@or...> --- include/libcgroup/tools.h | 13 +++++++++++++ src/Makefile.am | 2 +- src/libcgroup.map | 1 + src/tools/cgset.c | 40 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/include/libcgroup/tools.h b/include/libcgroup/tools.h index cc0918c14fa7..ab23fdac86e8 100644 --- a/include/libcgroup/tools.h +++ b/include/libcgroup/tools.h @@ -50,6 +50,19 @@ extern "C" { int cgroup_cgxget(struct cgroup ** cg, enum cg_version_t version, bool ignore_unmappable); +/** + * Write the setting-value pairs in *cg to the cgroup sysfs. + * cgroup_cgxset() will perform the necessary conversions to match the + * "on-disk" format prior to writing to the cgroup sysfs. + * + * @param cg cgroup instance that will be written to the cgroup sysfs + * @param version Cgroup version of *cg + * @param ignore_unmappable Ignore failures due to settings that cannot be + * converted from one cgroup version to another + */ +int cgroup_cgxset(const struct cgroup * const cg, + enum cg_version_t version, bool ignore_unmappable); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/Makefile.am b/src/Makefile.am index d7716aa80b19..5227a0366072 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,7 +16,7 @@ libcgroup_la_SOURCES = parse.h parse.y lex.l api.c config.c \ abstraction-common.c abstraction-common.h \ abstraction-map.c abstraction-map.h \ abstraction-cpu.c abstraction-cpuset.c \ - tools/cgget.c + tools/cgget.c tools/cgset.c libcgroup_la_LIBADD = -lpthread $(CODE_COVERAGE_LIBS) libcgroup_la_CFLAGS = $(CODE_COVERAGE_CFLAGS) -DSTATIC=static -DLIBCG_LIB \ -fPIC diff --git a/src/libcgroup.map b/src/libcgroup.map index fb161daeecf2..3ce7e1b00c58 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -143,4 +143,5 @@ CGROUP_2.0 { CGROUP_3.0 { cgroup_convert_cgroup; cgroup_cgxget; + cgroup_cgxset; } CGROUP_2.0; diff --git a/src/tools/cgset.c b/src/tools/cgset.c index db4645c86c63..fff96a0474bb 100644 --- a/src/tools/cgset.c +++ b/src/tools/cgset.c @@ -338,3 +338,43 @@ err: free(name_value); return ret; } + +#ifdef LIBCG_LIB +int cgroup_cgxset(const struct cgroup * const cgroup, + enum cg_version_t version, bool ignore_unmappable) +{ + struct cgroup *converted_cgroup; + int ret; + + converted_cgroup = cgroup_new_cgroup(cgroup->name); + if (converted_cgroup == NULL) { + ret = ECGCONTROLLERCREATEFAILED; + goto err; + } + + ret = cgroup_convert_cgroup(converted_cgroup, CGROUP_DISK, + cgroup, version); + if (ret == ECGNOVERSIONCONVERT && ignore_unmappable) + /* The user has specified that we should ignore + * any errors due to being unable to map from v1 to + * v2 or vice versa + */ + ret = 0; + else if (ret) + goto err; + + /* modify cgroup based on values of the new one */ + ret = cgroup_modify_cgroup(converted_cgroup); + if (ret) { + fprintf(stderr, "cgroup modify error: %s \n", + cgroup_strerror(ret)); + goto err; + } + +err: + if (converted_cgroup) + cgroup_free(&converted_cgroup); + + return ret; +} +#endif /* LIBCG_LIB */ -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:34:59
|
Add cgroup_convert_cgroup() to libcgroup/groups.h Signed-off-by: Tom Hromatka <tom...@or...> --- include/libcgroup/groups.h | 17 +++++++++++++++++ src/abstraction-common.h | 17 ----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/libcgroup/groups.h b/include/libcgroup/groups.h index 89c60ac2c58e..0960a7d37a33 100644 --- a/include/libcgroup/groups.h +++ b/include/libcgroup/groups.h @@ -590,6 +590,23 @@ int cg_chmod_recursive(struct cgroup *cgroup, mode_t dir_mode, */ char *cgroup_get_cgroup_name(struct cgroup *cgroup); +/* + * Convert from one cgroup version to another version + * + * @param out_cgroup Destination cgroup + * @param out_version Destination cgroup version + * @param in_cgroup Source cgroup + * @param in_version Source cgroup version, only used if set to v1 or v2 + * + * @return 0 on success + * ECGFAIL conversion failed + * ECGCONTROLLERNOTEQUAL incorrect controller version provided + */ +int cgroup_convert_cgroup(struct cgroup * const out_cgroup, + enum cg_version_t out_version, + const struct cgroup * const in_cgroup, + enum cg_version_t in_version); + /** * @} * @} diff --git a/src/abstraction-common.h b/src/abstraction-common.h index e395b6da24fc..5e60b5e009f1 100644 --- a/src/abstraction-common.h +++ b/src/abstraction-common.h @@ -101,23 +101,6 @@ int cgroup_convert_unmappable(struct cgroup_controller * const dst_cgc, const char * const out_setting, void *in_dflt, void *out_dflt); -/* - * Convert from one cgroup version to another version - * - * @param out_cgroup Destination cgroup - * @param out_version Destination cgroup version - * @param in_cgroup Source cgroup - * @param in_version Source cgroup version, only used if set to v1 or v2 - * - * @return 0 on success - * ECGFAIL conversion failed - * ECGCONTROLLERNOTEQUAL incorrect controller version provided - */ -int cgroup_convert_cgroup(struct cgroup * const out_cgroup, - enum cg_version_t out_version, - const struct cgroup * const in_cgroup, - enum cg_version_t in_version); - /* cpu */ int cgroup_convert_cpu_nto1(struct cgroup_controller * const out_cgc, struct cgroup_controller * const in_cgc); -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:34:59
|
cgroup_get_controller_version() was being exported via the libcgroup map, but its prototype wasn't available in libcgroup.h. Add cgroup_get_controller_version() to libcgroup/groups.h Signed-off-by: Tom Hromatka <tom...@or...> --- include/libcgroup/groups.h | 10 ++++++++++ src/libcgroup-internal.h | 10 ---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/libcgroup/groups.h b/include/libcgroup/groups.h index 0960a7d37a33..c30cbb94031d 100644 --- a/include/libcgroup/groups.h +++ b/include/libcgroup/groups.h @@ -607,6 +607,16 @@ int cgroup_convert_cgroup(struct cgroup * const out_cgroup, const struct cgroup * const in_cgroup, enum cg_version_t in_version); +/** + * Get the cgroup version of a controller. Version is set to CGROUP_UNK + * if the version cannot be determined. + * + * @param controller The controller of interest + * @param version The version of the controller + */ +int cgroup_get_controller_version(const char * const controller, + enum cg_version_t * const version); + /** * @} * @} diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index 864ac80de582..b2dc085c5484 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -305,16 +305,6 @@ extern void cgroup_dictionary_iterator_end(void **handle); */ int cg_chmod_path(const char *path, mode_t mode, int owner_is_umask); -/** - * Get the cgroup version of a controller. Version is set to CGROUP_UNK - * if the version cannot be determined. - * - * @param controller The controller of interest - * @param version The version of the controller - */ -int cgroup_get_controller_version(const char * const controller, - enum cg_version_t * const version); - /** * Build the path to the tasks or cgroup.procs file * -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-11-09 16:34:59
|
Move cg_version_t to libcgroup/groups.h from libcgroup-internal.h Signed-off-by: Tom Hromatka <tom...@or...> --- include/libcgroup/groups.h | 7 +++++++ src/libcgroup-internal.h | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/libcgroup/groups.h b/include/libcgroup/groups.h index 39ec3cd13544..89c60ac2c58e 100644 --- a/include/libcgroup/groups.h +++ b/include/libcgroup/groups.h @@ -15,6 +15,13 @@ extern "C" { #endif +enum cg_version_t { + CGROUP_UNK = 0, + CGROUP_V1, + CGROUP_V2, + CGROUP_DISK = 0xFF, +}; + /** * Flags for cgroup_delete_cgroup_ext(). */ diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index 91aa810a7923..864ac80de582 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -85,13 +85,6 @@ extern "C" { #define max(x,y) ((y)<(x)?(x):(y)) #define min(x,y) ((y)>(x)?(x):(y)) -enum cg_version_t { - CGROUP_UNK = 0, - CGROUP_V1, - CGROUP_V2, - CGROUP_DISK = 0xFF, -}; - struct control_value { char name[FILENAME_MAX]; char value[CG_CONTROL_VALUE_MAX]; -- 2.31.1 |
From: Tom H. <tom...@or...> - 2021-07-09 21:54:16
|
Add support for cgxset to the Cgroup class The pydoc for Cgroup.xset() is available by running: $ python -c "from cgroup import Cgroup;help(Cgroup.xset)" Signed-off-by: Tom Hromatka <tom...@or...> --- ftests/cgroup.py | 69 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/ftests/cgroup.py b/ftests/cgroup.py index 72a200d6b135..06ca45693ae9 100644 --- a/ftests/cgroup.py +++ b/ftests/cgroup.py @@ -173,29 +173,8 @@ class Cgroup(object): Run.run(cmd) @staticmethod - def set(config, cgname=None, setting=None, value=None, copy_from=None, - cghelp=False): - """cgset equivalent method - - The following variants of cgset are being tested by the - automated functional tests: - - Command Test Number - cgset -r setting=value cgname various - cgset -r setting1=val1 -r setting2=val2 - -r setting3=val2 cgname 022 - cgset --copy_from foo bar 023 - cgset --copy_from foo bar1 bar2 024 - cgset -r setting=value foo bar 025 - cgset -r setting1=value1 setting2=value2 foo bar 026 - various invalid flag combinations 027 - """ - cmd = list() - - if not config.args.container: - cmd.append('sudo') - cmd.append(Cgroup.build_cmd_path('cgset')) - + def __set(config, cmd, cgname=None, setting=None, value=None, + copy_from=None, cghelp=False): if setting is not None or value is not None: if isinstance(setting, str) and isinstance(value, str): cmd.append('-r') @@ -231,6 +210,50 @@ class Cgroup(object): else: return Run.run(cmd) + @staticmethod + def set(config, cgname=None, setting=None, value=None, copy_from=None, + cghelp=False): + """cgset equivalent method + + The following variants of cgset are being tested by the + automated functional tests: + + Command Test Number + cgset -r setting=value cgname various + cgset -r setting1=val1 -r setting2=val2 + -r setting3=val2 cgname 022 + cgset --copy_from foo bar 023 + cgset --copy_from foo bar1 bar2 024 + cgset -r setting=value foo bar 025 + cgset -r setting1=value1 setting2=value2 foo bar 026 + various invalid flag combinations 027 + """ + cmd = list() + if not config.args.container: + cmd.append('sudo') + cmd.append(Cgroup.build_cmd_path('cgset')) + + return Cgroup.__set(config, cmd, cgname, setting, value, copy_from, + cghelp) + + @staticmethod + def xset(config, cgname=None, setting=None, value=None, copy_from=None, + version=CgroupVersion.CGROUP_UNK, cghelp=False): + """cgxset equivalent method + """ + cmd = list() + if not config.args.container: + cmd.append('sudo') + cmd.append(Cgroup.build_cmd_path('cgxset')) + + if version == CgroupVersion.CGROUP_V1: + cmd.append('-1') + elif version == CgroupVersion.CGROUP_V2: + cmd.append('-2') + + return Cgroup.__set(config, cmd, cgname, setting, value, copy_from, + cghelp) + @staticmethod def __get(config, cmd, controller=None, cgname=None, setting=None, print_headers=True, values_only=False, -- 2.25.1 |
From: Tom H. <tom...@or...> - 2021-07-09 21:54:14
|
Add support for cgxget to the Cgroup class The pydoc for Cgroup.xget() is available by running: $ python -c "from cgroup import Cgroup;help(Cgroup.xget)" Signed-off-by: Tom Hromatka <tom...@or...> --- ftests/cgroup.py | 82 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/ftests/cgroup.py b/ftests/cgroup.py index d3a3dfc25e4f..72a200d6b135 100644 --- a/ftests/cgroup.py +++ b/ftests/cgroup.py @@ -232,32 +232,9 @@ class Cgroup(object): return Run.run(cmd) @staticmethod - def get(config, controller=None, cgname=None, setting=None, - print_headers=True, values_only=False, - all_controllers=False, cghelp=False): - """cgget equivalent method - - Returns: - str: The stdout result of cgget - - The following variants of cgget() are being tested by the - automated functional tests: - - Command Test Number - cgget -r cpuset.cpus mycg 001 - cgget -r cpuset.cpus -r cpuset.mems mycg 008 - cgget -g cpu mycg 009 - cgget -g cpu:mycg 010 - cgget -r cpuset.cpus mycg1 mycg2 011 - cgget -r cpuset.cpus -r cpuset.mems mycg1 mycg2 012 - cgget -g cpu -g freezer mycg 013 - cgget -a mycg 014 - cgget -r memory.stat mycg (multiline value read) 015 - various invalid flag combinations 016 - """ - cmd = list() - cmd.append(Cgroup.build_cmd_path('cgget')) - + def __get(config, cmd, controller=None, cgname=None, setting=None, + print_headers=True, values_only=False, + all_controllers=False, cghelp=False): if not print_headers: cmd.append('-n') if values_only: @@ -318,6 +295,59 @@ class Cgroup(object): return ret + @staticmethod + def get(config, controller=None, cgname=None, setting=None, + print_headers=True, values_only=False, + all_controllers=False, cghelp=False): + """cgget equivalent method + + Returns: + str: The stdout result of cgget + + The following variants of cgget() are being tested by the + automated functional tests: + + Command Test Number + cgget -r cpuset.cpus mycg 001 + cgget -r cpuset.cpus -r cpuset.mems mycg 008 + cgget -g cpu mycg 009 + cgget -g cpu:mycg 010 + cgget -r cpuset.cpus mycg1 mycg2 011 + cgget -r cpuset.cpus -r cpuset.mems mycg1 mycg2 012 + cgget -g cpu -g freezer mycg 013 + cgget -a mycg 014 + cgget -r memory.stat mycg (multiline value read) 015 + various invalid flag combinations 016 + """ + cmd = list() + cmd.append(Cgroup.build_cmd_path('cgget')) + + return Cgroup.__get(config, cmd, controller, cgname, setting, + print_headers, values_only, all_controllers, + cghelp) + + @staticmethod + def xget(config, controller=None, cgname=None, setting=None, + print_headers=True, values_only=False, + all_controllers=False, version=CgroupVersion.CGROUP_UNK, + cghelp=False): + """cgxget equivalent method + + Returns: + str: The stdout result of cgxget + """ + cmd = list() + cmd.append(Cgroup.build_cmd_path('cgxget')) + + if version == CgroupVersion.CGROUP_V1: + cmd.append('-1') + elif version == CgroupVersion.CGROUP_V2: + cmd.append('-2') + + return Cgroup.__get(config, cmd, controller, cgname, setting, + print_headers, values_only, all_controllers, + cghelp) + @staticmethod def classify(config, controller, cgname, pid_list, sticky=False, cancel_sticky=False): -- 2.25.1 |
From: Tom H. <tom...@or...> - 2021-07-09 21:54:13
|
Add a functional test that exercises the cpu v1/v2 mappings. ----------------------------------------------------------------- Test Results: Run Date: Apr 19 18:39:16 Passed: 1 test(s) Skipped: 0 test(s) Failed: 0 test(s) ----------------------------------------------------------------- Timing Results: Test Time (sec) --------------------------------------------------------- setup 0.00 035-cgxget-cpu_settings.py 0.50 teardown 0.00 --------------------------------------------------------- Total Run Time 0.50 Signed-off-by: Tom Hromatka <tom...@or...> --- ftests/035-cgxget-cpu_settings.py | 86 +++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100755 ftests/035-cgxget-cpu_settings.py diff --git a/ftests/035-cgxget-cpu_settings.py b/ftests/035-cgxget-cpu_settings.py new file mode 100755 index 000000000000..ecbba22abbb7 --- /dev/null +++ b/ftests/035-cgxget-cpu_settings.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# +# cgxget functionality test - various cpu settings +# +# Copyright (c) 2021 Oracle and/or its affiliates. +# Author: Tom Hromatka <tom...@or...> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# 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>. +# + +from cgroup import Cgroup, CgroupVersion +import consts +import ftests +import os +import sys + +CONTROLLER = 'cpu' +CGNAME = '035cgxget' + +TABLE = [ + # writesetting, writeval, writever, readsetting, readval, readver + ['cpu.shares', '512', CgroupVersion.CGROUP_V1, 'cpu.shares', '512', CgroupVersion.CGROUP_V1], + ['cpu.shares', '512', CgroupVersion.CGROUP_V1, 'cpu.weight', '50', CgroupVersion.CGROUP_V2], + ['cpu.weight', '200', CgroupVersion.CGROUP_V2, 'cpu.shares', '2048', CgroupVersion.CGROUP_V1], + ['cpu.weight', '200', CgroupVersion.CGROUP_V2, 'cpu.weight', '200', CgroupVersion.CGROUP_V2], +] + +def prereqs(config): + result = consts.TEST_PASSED + cause = None + + return result, cause + +def setup(config): + Cgroup.create(config, CONTROLLER, CGNAME) + +def test(config): + result = consts.TEST_PASSED + cause = None + + for entry in TABLE: + Cgroup.xset(config, cgname=CGNAME, setting=entry[0], value=entry[1], + version=entry[2]) + + out = Cgroup.xget(config, cgname=CGNAME, setting=entry[3], + version=entry[5], values_only=True, + print_headers=False) + if out != entry[4]: + result = consts.TEST_FAILED + cause = "After setting {}={}, expected {}={}, but received {}={}".format( + entry[0], entry[1], entry[3], entry[4], entry[3], out) + return result, cause + + return result, cause + +def teardown(config): + Cgroup.delete(config, CONTROLLER, CGNAME) + +def main(config): + [result, cause] = prereqs(config) + if result != consts.TEST_PASSED: + return [result, cause] + + setup(config) + [result, cause] = test(config) + teardown(config) + + return [result, cause] + +if __name__ == '__main__': + config = ftests.parse_args() + # this test was invoked directly. run only it + config.args.num = int(os.path.basename(__file__).split('-')[0]) + sys.exit(ftests.main(config)) -- 2.25.1 |
From: Tom H. <tom...@or...> - 2021-07-09 21:54:13
|
This patchset adds support for cgxget/cgxset and adds a cgxget/cgxset functional test for the cpu controller. The changes to libcgroup are available here: https://github.com/drakenclimber/libcgroup/tree/issues/cgxget4 The changes to the libcgroup tests are available here: https://github.com/drakenclimber/libcgroup-tests/tree/issues/cgxget4 Overal code coverage increased 1.7% to 51.7%. Code coverage of src/abstraction-common.c is at 75.8%: https://coveralls.io/builds/41251128 Automated tests are passing and the results are here: https://github.com/drakenclimber/libcgroup/runs/3030300300 Tom Hromatka (3): ftests: Add support for cgxget to the Cgroup class ftests: Add support for cgxset to the Cgroup class ftests: Add a cgxget/cgxset test for the cpu controller ftests/035-cgxget-cpu_settings.py | 86 +++++++++++++++++++ ftests/cgroup.py | 137 +++++++++++++++++++++--------- 2 files changed, 181 insertions(+), 42 deletions(-) create mode 100755 ftests/035-cgxget-cpu_settings.py -- 2.25.1 |
From: Tom H. <tom...@or...> - 2021-07-09 21:52:32
|
Add a function - cgroup_convert_cgroup() - that can convert from one cgroup version to another. This function will be the building block for the libcgroup abstraction layer. Signed-off-by: Tom Hromatka <tom...@or...> --- src/abstraction-common.c | 103 +++++++++++++++++++++++++++++++++++++++ src/abstraction-common.h | 17 +++++++ src/libcgroup-internal.h | 1 + src/libcgroup.map | 4 ++ 4 files changed, 125 insertions(+) diff --git a/src/abstraction-common.c b/src/abstraction-common.c index df5fa1b3a452..e0e3984006b7 100644 --- a/src/abstraction-common.c +++ b/src/abstraction-common.c @@ -29,6 +29,7 @@ #include <unistd.h> #include "abstraction-common.h" +#include "abstraction-map.h" int cgroup_strtol(const char * const in_str, int base, long int * const out_value) @@ -108,3 +109,105 @@ out: return ret; } + +static int convert_setting(struct cgroup_controller * const out_cgc, + const struct control_value * const in_ctrl_val) +{ + const struct cgroup_abstraction_map *convert_tbl; + int tbl_sz = 0; + int ret = ECGINVAL; + int i; + + switch (out_cgc->version) { + case CGROUP_V1: + convert_tbl = cgroup_v2_to_v1_map; + tbl_sz = cgroup_v2_to_v1_map_sz; + break; + case CGROUP_V2: + convert_tbl = cgroup_v1_to_v2_map; + tbl_sz = cgroup_v1_to_v2_map_sz; + break; + default: + ret = ECGFAIL; + goto out; + } + + for (i = 0; i < tbl_sz; i++) { + if (strcmp(convert_tbl[i].in_setting, in_ctrl_val->name) == 0) { + ret = convert_tbl[i].cgroup_convert(out_cgc, + in_ctrl_val->value, + convert_tbl[i].out_setting, + convert_tbl[i].in_dflt, + convert_tbl[i].out_dflt); + if (ret) + goto out; + } + } + +out: + return ret; +} + +static int convert_controller(struct cgroup_controller * const out_cgc, + const struct cgroup_controller * const in_cgc) +{ + int ret; + int i; + + + if (in_cgc->version == out_cgc->version) { + ret = cgroup_copy_controller_values(out_cgc, in_cgc); + /* regardless of success/failure, there's nothing more to do */ + goto out; + } + + for (i = 0; i < in_cgc->index; i++) { + ret = convert_setting(out_cgc, in_cgc->values[i]); + if (ret) + goto out; + } + +out: + return ret; +} + +int cgroup_convert_cgroup(struct cgroup * const out_cgroup, + enum cg_version_t out_version, + const struct cgroup * const in_cgroup, + enum cg_version_t in_version) +{ + struct cgroup_controller *cgc; + int ret = 0; + int i; + + for (i = 0; i < in_cgroup->index; i++) { + cgc = cgroup_add_controller(out_cgroup, + in_cgroup->controller[i]->name); + if (cgc == NULL) { + ret = ECGFAIL; + goto out; + } + + /* the user has overridden the version */ + if (in_version == CGROUP_V1 || in_version == CGROUP_V2) { + in_cgroup->controller[i]->version = in_version; + } + + cgc->version = out_version; + + if (cgc->version == CGROUP_UNK || + cgc->version == CGROUP_DISK) { + ret = cgroup_get_controller_version(cgc->name, + &cgc->version); + if (ret) + goto out; + } + + ret = convert_controller(cgc, in_cgroup->controller[i]); + if (ret) + goto out; + } + +out: + return ret; +} diff --git a/src/abstraction-common.h b/src/abstraction-common.h index 02f7b9ff9541..69a28538e091 100644 --- a/src/abstraction-common.h +++ b/src/abstraction-common.h @@ -57,6 +57,23 @@ int cgroup_convert_int(struct cgroup_controller * const dst_cgc, const char * const out_setting, void *in_dflt, void *out_dflt); +/* + * Convert from one cgroup version to another version + * + * @param out_cgroup Destination cgroup + * @param out_version Destination cgroup version + * @param in_cgroup Source cgroup + * @param in_version Source cgroup version, only used if set to v1 or v2 + * + * @return 0 on success + * ECGFAIL conversion failed + * ECGCONTROLLERNOTEQUAL incorrect controller version provided + */ +int cgroup_convert_cgroup(struct cgroup * const out_cgroup, + enum cg_version_t out_version, + const struct cgroup * const in_cgroup, + enum cg_version_t in_version); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index 34c5be703920..6d9de03a00bc 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -89,6 +89,7 @@ enum cg_version_t { CGROUP_UNK = 0, CGROUP_V1, CGROUP_V2, + CGROUP_DISK = 0xFF, }; struct control_value { diff --git a/src/libcgroup.map b/src/libcgroup.map index 68098cd3accb..d99a2ce73c04 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -139,3 +139,7 @@ CGROUP_2.0 { cg_mount_table_lock; cgroup_get_controller_version; } CGROUP_0.42; + +CGROUP_3.0 { + cgroup_convert_cgroup; +} CGROUP_2.0; -- 2.25.1 |
From: Tom H. <tom...@or...> - 2021-07-09 21:52:32
|
Store the cgroup version in struct cgroup_controller. Each controller can be mounted separately, and thus the cgroup version is applicable at the controller level. Note that this commit requires cgroup_init() to be called by cgconfigparser. Storing the version in the cgroup_controller struct requires the cg_mount_table[] to be populated. Signed-off-by: Tom Hromatka <tom...@or...> --- src/libcgroup-internal.h | 13 +++++++------ src/tools/cgconfig.c | 7 +++++++ src/wrapper.c | 11 ++++++++++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index edc5abb9bdf6..cbec4cd361b9 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -85,6 +85,12 @@ extern "C" { #define max(x,y) ((y)<(x)?(x):(y)) #define min(x,y) ((y)>(x)?(x):(y)) +enum cg_version_t { + CGROUP_UNK = 0, + CGROUP_V1, + CGROUP_V2, +}; + struct control_value { char name[FILENAME_MAX]; char value[CG_CONTROL_VALUE_MAX]; @@ -99,6 +105,7 @@ struct cgroup_controller { struct control_value *values[CG_NV_MAX]; struct cgroup *cgroup; int index; + enum cg_version_t version; }; struct cgroup { @@ -119,12 +126,6 @@ struct cg_mount_point { struct cg_mount_point *next; }; -enum cg_version_t { - CGROUP_UNK = 0, - CGROUP_V1, - CGROUP_V2, -}; - struct cg_mount_table_s { /** Controller name. */ char name[FILENAME_MAX]; diff --git a/src/tools/cgconfig.c b/src/tools/cgconfig.c index e8bb5a2e553b..b5058db42e26 100644 --- a/src/tools/cgconfig.c +++ b/src/tools/cgconfig.c @@ -94,6 +94,13 @@ int main(int argc, char *argv[]) return -1; } + ret = cgroup_init(); + if (ret) { + fprintf(stderr, "%s: libcgroup initialization failed: %s\n", + argv[0], cgroup_strerror(ret)); + goto err; + } + error = cgroup_string_list_init(&cfg_files, argc/2); if (error) goto err; diff --git a/src/wrapper.c b/src/wrapper.c index 98ebcc266c41..0379da76c830 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -56,7 +56,7 @@ struct cgroup *cgroup_new_cgroup(const char *name) struct cgroup_controller *cgroup_add_controller(struct cgroup *cgroup, const char *name) { - int i; + int i, ret; struct cgroup_controller *controller; if (!cgroup) @@ -86,6 +86,15 @@ struct cgroup_controller *cgroup_add_controller(struct cgroup *cgroup, controller->cgroup = cgroup; controller->index = 0; + ret = cgroup_get_controller_version(controller->name, + &controller->version); + if (ret) { + cgroup_dbg("failed to get cgroup version for controller %s\n", + controller->name); + free(controller); + return NULL; + } + cgroup->controller[cgroup->index] = controller; cgroup->index++; -- 2.25.1 |
From: Tom H. <tom...@or...> - 2021-07-09 21:52:32
|
Remove static from cgroup_copy_controller_values() in api.c so that other files within libcgroup can invoke it. It will be used by the abstraction layer code in a subsequent commit. Also, declare *dst as a const pointer and *src as a const * const pointer. Subsequent abstraction layer checkins make heavy use of const and without these changes warnings (which continuous integration converts to errors) are thrown. Signed-off-by: Tom Hromatka <tom...@or...> --- src/api.c | 10 ++-------- src/libcgroup-internal.h | 11 +++++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/api.c b/src/api.c index 4a980a157cde..303f699357b6 100644 --- a/src/api.c +++ b/src/api.c @@ -2174,14 +2174,8 @@ err: } -/** - * @dst: Destination controller - * @src: Source controller from which values will be copied to dst - * - * Create a duplicate copy of values under the specified controller - */ -static int cgroup_copy_controller_values(struct cgroup_controller *dst, - struct cgroup_controller *src) +int cgroup_copy_controller_values(struct cgroup_controller * const dst, + const struct cgroup_controller * const src) { int i, ret = 0; diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index cbec4cd361b9..34c5be703920 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -364,6 +364,17 @@ int cgroup_fill_cgc(struct dirent *ctrl_dir, struct cgroup *cgroup, */ int cgroup_test_subsys_mounted(const char *ctrl_name); +/** + * Create a duplicate copy of values under the specified controller + * + * @dst: Destination controller + * @src: Source controller from which values will be copied to dst + * + * @return 0 on a successful copy, ECGOTHER if the copy failed + */ +int cgroup_copy_controller_values(struct cgroup_controller * const dst, + const struct cgroup_controller * const src); + /** * Functions that are defined as STATIC can be placed within the UNIT_TEST * ifdef. This will allow them to be included in the unit tests while -- 2.25.1 |