From: Tom Hromatka Date: Mon, 3 Apr 2023 15:39:31 +0000 (-0600) Subject: cgcreate: Add support to create a systemd scope X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a2d66c126fe4e8f98347423accfcf2735d614e0;p=thirdparty%2Flibcgroup.git cgcreate: Add support to create a systemd scope Add support to create a systemd scope. A user can create a delegated systemd scope using the following format: $ cgcreate -c -g :/ e.g. $ cgcreate -c -g cpu,memory:libcgroup.slice/database.scope Signed-off-by: Tom Hromatka Reviewed-by: Kamalesh Babulal (cherry picked from commit d789745d786ac30ec3fdba0525da003abcef120f) --- diff --git a/include/libcgroup/systemd.h b/include/libcgroup/systemd.h index 39f69743..b2e55c69 100644 --- a/include/libcgroup/systemd.h +++ b/include/libcgroup/systemd.h @@ -119,6 +119,18 @@ int cgroup_add_systemd_opts(const char * const conf, const char * const value); */ void cgroup_cleanup_systemd_opts(void); +/* + * Write the specified slice and scope to the libcgroup systemd run file. This + * slice and scope will then be used as the default cgroup root. Subsequent + * libcgroup commands, cgget, etc., will utilize this slice and scope when + * constructing the libcgroup path + * + * @param slice Slice name, e.g. libcgroup.slice + * @param scope Scope name, e.g. database.scope + */ +int cgroup_write_systemd_default_cgroup(const char * const slice, + const char * const scope); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/config.c b/src/config.c index ad83f133..9fcfc032 100644 --- a/src/config.c +++ b/src/config.c @@ -2079,8 +2079,8 @@ static int remove_systemd_default_cgroup_file(void) * cgroup_set_default_systemd_cgroup() for setting * systemd_default_cgroup used to form the cgroup path. */ -static int cgroup_write_systemd_default_cgroup(const char * const slice, - const char * const scope) +int cgroup_write_systemd_default_cgroup(const char * const slice, + const char * const scope) { FILE *systemd_def_cgrp_f; int ret, len; diff --git a/src/libcgroup.map b/src/libcgroup.map index 28ce7d40..b0f0356a 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -156,4 +156,5 @@ CGROUP_3.0 { cgroup_get_controller_name; cgroup_create_scope2; cgroup_set_default_systemd_cgroup; + cgroup_write_systemd_default_cgroup; } CGROUP_2.0; diff --git a/src/tools/cgcreate.c b/src/tools/cgcreate.c index 5a3e0f48..14606b8e 100644 --- a/src/tools/cgcreate.c +++ b/src/tools/cgcreate.c @@ -42,11 +42,66 @@ static void usage(int status, const char *program_name) info(" -s, --tperm=mode Tasks file permissions\n"); info(" -t : Owner of the tasks file\n"); #ifdef WITH_SYSTEMD - info(" -b Ignore default systemd "); + info(" -b Ignore default systemd"); + info("delegate hierarchy\n"); + info(" -c, --scope Create a delegated systemd scope\n"); + info(" -S, --setdefault Set this scope as the default scope "); info("delegate hierarchy\n"); #endif } +#ifdef WITH_SYSTEMD +static int create_systemd_scope(struct cgroup * const cg, const char * const prog_name, + int set_default) +{ + struct cgroup_systemd_scope_opts opts; + char slice[FILENAME_MAX]; + char *scope; + int ret; + int len; + + ret = cgroup_set_default_scope_opts(&opts); + if (ret) + return ret; + + ret = cgroup_create_scope2(cg, 0, &opts); + if (!ret && set_default) { + scope = strstr(cg->name, "/"); + len = strlen(cg->name) - strlen(scope); + strncpy(slice, cg->name, len); + slice[len] = '\0'; + scope++; + + ret = cgroup_write_systemd_default_cgroup(slice, scope); + /* + * cgroup_write_systemd_default_cgroup() returns 0 on failure + */ + if (ret == 0) { + err("%s: failed to write default %s/%s to ", + prog_name, slice, scope); + err("/var/run/libcgroup/systemd\n"); + ret = ECGINVAL; + goto err; + } + + /* + * the default was successfully set. override the return of "1" back to + * the usual "0" on success. + */ + ret = 0; + } + +err: + return ret; +} +#else +static int create_systemd_scope(struct cgroup * const cg, const char * const prog_name, + int set_default) +{ + return ECGINVAL; +} +#endif /* WITH_SYSTEMD */ + int main(int argc, char *argv[]) { static struct option long_opts[] = { @@ -57,6 +112,10 @@ int main(int argc, char *argv[]) {"dperm", required_argument, NULL, 'd'}, {"fperm", required_argument, NULL, 'f'}, {"tperm", required_argument, NULL, 's'}, +#ifdef WITH_SYSTEMD + {"scope", no_argument, NULL, 'c'}, + {"setdefault", no_argument, NULL, 'S'}, +#endif /* WITH_SYSTEMD */ {0, 0, 0, 0}, }; @@ -64,6 +123,8 @@ int main(int argc, char *argv[]) gid_t tgid = CGRULE_INVALID, agid = CGRULE_INVALID; int ignore_default_systemd_delegate_slice = 0; + int create_scope = 0; + int set_default_scope = 0; struct cgroup_group_spec **cgroup_list; struct cgroup_controller *cgc; @@ -98,11 +159,17 @@ int main(int argc, char *argv[]) #ifdef WITH_SYSTEMD /* parse arguments */ - while ((c = getopt_long(argc, argv, "a:t:g:hd:f:s:b", long_opts, NULL)) > 0) { + while ((c = getopt_long(argc, argv, "a:t:g:hd:f:s:bcS", long_opts, NULL)) > 0) { switch (c) { case 'b': ignore_default_systemd_delegate_slice = 1; break; + case 'c': + create_scope = 1; + break; + case 'S': + set_default_scope = 1; + break; #else while ((c = getopt_long(argc, argv, "a:t:g:hd:f:s:", long_opts, NULL)) > 0) { switch (c) { @@ -155,6 +222,20 @@ int main(int argc, char *argv[]) } } +#ifdef WITH_SYSTEMD + if (ignore_default_systemd_delegate_slice && create_scope) { + err("%s: \"-b\" and \"-c\" are mutually exclusive\n", argv[0]); + ret = EXIT_BADARGS; + goto err; + } + + if (set_default_scope && !create_scope) { + err("%s: \"-S\" requires \"-c\" to be provided\n", argv[0]); + ret = EXIT_BADARGS; + goto err; + } +#endif + /* no cgroup name */ if (argv[optind]) { err("%s: wrong arguments (%s)\n", argv[0], argv[optind]); @@ -169,8 +250,8 @@ int main(int argc, char *argv[]) goto err; } - /* this is false always for disable-systemd */ - if (!ignore_default_systemd_delegate_slice) + /* this will always be false if WITH_SYSTEMD is not defined */ + if (!create_scope && !ignore_default_systemd_delegate_slice) cgroup_set_default_systemd_cgroup(); /* for each new cgroup */ @@ -221,7 +302,11 @@ int main(int argc, char *argv[]) if (dirm_change | filem_change) cgroup_set_permissions(cgroup, dir_mode, file_mode, tasks_mode); - ret = cgroup_create_cgroup(cgroup, 0); + if (create_scope) { + ret = create_systemd_scope(cgroup, argv[0], set_default_scope); + } else { + ret = cgroup_create_cgroup(cgroup, 0); + } if (ret) { err("%s: can't create cgroup %s: %s\n", argv[0], cgroup->name, cgroup_strerror(ret));