From: Christian Goeschel Ndjomouo Date: Fri, 29 May 2026 23:46:40 +0000 (-0400) Subject: chcpu: add --sysroot option X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cd1242f85e76894ae36d83d1cc922ac8308f057f;p=thirdparty%2Futil-linux.git chcpu: add --sysroot option This patch makes it possible to configure the CPUs on a Linux system other than the one on which the chcpu command is called. To achieve this users can simply define the root directory of the sys/ directory with the --sysroot command line option. It is also beneficial for regression tests, as these make use of sysfs tar archive dumps. To properly implement this new feature, the syspath initialization had to be deferred until after all option arguments, especially --sysroot, have been parsed, which simplified the path access check. Along the way a small refactoring of the enable,disable,configure & deconfigure option parsing had been done, more precisely the CPU list option argument is now saved in a variable 'cpu_list_arg' to defer the CPU list validity check until after all option arguments have been parsed to simplify the logic. Lastly, getopt(3)'s 'optarg' variable is used instead of argv[optind-1] to store the options argument, which is more idiomatic and readable. Signed-off-by: Christian Goeschel Ndjomouo --- diff --git a/bash-completion/chcpu b/bash-completion/chcpu index 50b1da4a3..fb21051d5 100644 --- a/bash-completion/chcpu +++ b/bash-completion/chcpu @@ -41,6 +41,10 @@ _chcpu_module() COMPREPLY=( $(compgen -W "horizontal vertical" -- $cur) ) return 0 ;; + '-s'|'--sysroot') + COMPREPLY=( $(compgen -d -- $cur) ) + return 0 + ;; '-h'|'--help'|'-V'|'--version') return 0 ;; @@ -52,6 +56,7 @@ _chcpu_module() --deconfigure --dispatch --rescan + --sysroot --version" COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) ) return 0 diff --git a/sys-utils/chcpu.8.adoc b/sys-utils/chcpu.8.adoc index f8aec0f35..5b49ab203 100644 --- a/sys-utils/chcpu.8.adoc +++ b/sys-utils/chcpu.8.adoc @@ -54,6 +54,9 @@ The workload is concentrated on few CPUs. *-r*, *--rescan*:: Trigger a rescan of CPUs. After a rescan, the Linux kernel recognizes the new CPUs. Use this option on systems that do not automatically detect newly attached CPUs. +*-s*, *--sysroot* _directory_:: +Configure CPUs for a Linux instance other than the instance from which the *chcpu* command is issued. The specified _directory_ is the system root of the Linux instance to be configured. + include::man-common/help-version.adoc[] == EXIT STATUS diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c index 1e8f8cb3c..cb0b9f522 100644 --- a/sys-utils/chcpu.c +++ b/sys-utils/chcpu.c @@ -251,6 +251,7 @@ static void __attribute__((__noreturn__)) usage(void) " -g, --deconfigure deconfigure cpus\n" " -p, --dispatch set dispatching mode\n" " -r, --rescan trigger rescan of cpus\n" + " -s, --sysroot use the specified directory as system root\n" ), stdout); fprintf(stdout, USAGE_HELP_OPTIONS(31)); @@ -265,6 +266,7 @@ int main(int argc, char *argv[]) size_t setsize; int cmd = -1; int c, rc; + char *sysroot = NULL, *cpu_list_arg = NULL; static const struct option longopts[] = { { "configure", required_argument, NULL, 'c' }, @@ -274,6 +276,7 @@ int main(int argc, char *argv[]) { "enable", required_argument, NULL, 'e' }, { "help", no_argument, NULL, 'h' }, { "rescan", no_argument, NULL, 'r' }, + { "sysroot", required_argument, NULL, 's'}, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; @@ -289,58 +292,42 @@ int main(int argc, char *argv[]) textdomain(PACKAGE); close_stdout_atexit(); - ul_path_init_debug(); - sys = ul_new_path(_PATH_SYS_CPU); - if (!sys) - err(EXIT_FAILURE, _("failed to initialize sysfs handler")); - - maxcpus = get_max_number_of_cpus(); - if (maxcpus < 1) - errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting")); - - if (ul_path_access(sys, F_OK, "online") == 0) - ul_path_readf_cpulist(sys, &cpu_set, maxcpus, "online"); - else - cpu_set = CPU_ALLOC(maxcpus); - if (!cpu_set) - err(EXIT_FAILURE, _("cpuset_alloc failed")); - - setsize = CPU_ALLOC_SIZE(maxcpus); - - while ((c = getopt_long(argc, argv, "c:d:e:g:hp:rV", longopts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "c:d:e:g:hp:rs:V", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); switch (c) { case 'c': cmd = CMD_CPU_CONFIGURE; - cpu_parse(argv[optind - 1], cpu_set, setsize); + cpu_list_arg = optarg; break; case 'd': cmd = CMD_CPU_DISABLE; - cpu_parse(argv[optind - 1], cpu_set, setsize); + cpu_list_arg = optarg; break; case 'e': cmd = CMD_CPU_ENABLE; - cpu_parse(argv[optind - 1], cpu_set, setsize); + cpu_list_arg = optarg; break; case 'g': cmd = CMD_CPU_DECONFIGURE; - cpu_parse(argv[optind - 1], cpu_set, setsize); + cpu_list_arg = optarg; break; case 'p': - if (strcmp("horizontal", argv[optind - 1]) == 0) + if (strcmp("horizontal", optarg) == 0) cmd = CMD_CPU_DISPATCH_HORIZONTAL; - else if (strcmp("vertical", argv[optind - 1]) == 0) + else if (strcmp("vertical", optarg) == 0) cmd = CMD_CPU_DISPATCH_VERTICAL; else errx(EXIT_FAILURE, _("unsupported argument: %s"), - argv[optind -1 ]); + optarg); break; case 'r': cmd = CMD_CPU_RESCAN; break; - + case 's': + sysroot = optarg; + break; case 'h': usage(); case 'V': @@ -355,6 +342,31 @@ int main(int argc, char *argv[]) errtryhelp(EXIT_FAILURE); } + ul_path_init_debug(); + sys = ul_new_path(_PATH_SYS_CPU); + if (!sys) + err(EXIT_FAILURE, _("failed to initialize sysfs handler")); + if (sysroot && ul_path_set_prefix(sys, sysroot) != 0) + err(EXIT_FAILURE, _("failed to set up different sysroot")); + if (!ul_path_is_accessible(sys)) + err(EXIT_FAILURE, _("cannot open %s"), _PATH_SYS_CPU); + + maxcpus = get_max_number_of_cpus(); + if (maxcpus < 1) + errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting")); + + if (ul_path_access(sys, F_OK, "online") == 0) + ul_path_readf_cpulist(sys, &cpu_set, maxcpus, "online"); + else + cpu_set = CPU_ALLOC(maxcpus); + if (!cpu_set) + err(EXIT_FAILURE, _("cpuset_alloc failed")); + + setsize = CPU_ALLOC_SIZE(maxcpus); + + if (cpu_list_arg) + cpu_parse(cpu_list_arg, cpu_set, setsize); + switch (cmd) { case CMD_CPU_ENABLE: rc = cpu_enable(sys, cpu_set, maxcpus, 1);