From: Christian Goeschel Ndjomouo Date: Mon, 1 Jun 2026 21:53:28 +0000 (-0400) Subject: chcpu: fix persistent partial success exit code X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=89fa13125b02247a489de484e7d6d67b006f7a2a;p=thirdparty%2Futil-linux.git chcpu: fix persistent partial success exit code Previously, cpu_enable() and cpu_configure() compared the number of fails with ctx->maxcpus and if equal it returned -1, which culminated over to an exit code of 1 (failure). Otherwise, if there were fails but less than ctx->maxcpus the fucntions return code 1 would result in an exit code 64 indicating partial success. Since ctx->maxcpus describes the maximum number of CPUs supported by the kernel, in practice, this failure mode isn't really useful as it means that a user would need to fail the configuration of every possible CPU. This is why chcpu(8) almost always returns 64. It is better to store the actual amount of requested CPUs and then compare the amount of fails to it and provide more meaningful exit codes. Signed-off-by: Christian Goeschel Ndjomouo --- diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c index cfc02babd..0d2946222 100644 --- a/sys-utils/chcpu.c +++ b/sys-utils/chcpu.c @@ -49,18 +49,15 @@ #define _PATH_SYS_CPU "/sys/devices/system/cpu" -#define cpu_is_set(cpu, count, cpuset) \ - (CPU_ISSET_S((cpu), CPU_ALLOC_SIZE(count), cpuset)) -#define num_online_cpus(count, cpuset) (CPU_COUNT_S(CPU_ALLOC_SIZE(count), cpuset)) - struct chcpu_context { - struct path_cxt *sys; /* _PATH_SYS_CPU handler */ + struct path_cxt *sys; /* _PATH_SYS_CPU handler */ cpu_set_t *cpu_set, *online_cpus; size_t setsize; - int maxcpus; + int maxcpus, + ncpus; bool isdump; /* live system or sys dump ? */ }; @@ -87,7 +84,7 @@ static int cpu_enable(struct chcpu_context *ctx, int enable) int fails = 0; for (cpu = 0; cpu < ctx->maxcpus; cpu++) { - if (!cpu_is_set(cpu, ctx->setsize, ctx->cpu_set)) + if (!CPU_ISSET_S(cpu, ctx->setsize, ctx->cpu_set)) continue; if (ul_path_accessf(ctx->sys, F_OK, "cpu%d", cpu) != 0) { warnx(_("CPU %d does not exist"), cpu); @@ -123,7 +120,7 @@ static int cpu_enable(struct chcpu_context *ctx, int enable) printf(_("CPU %d enabled\n"), cpu); } else { if (ctx->online_cpus - && num_online_cpus(ctx->maxcpus, ctx->online_cpus) == 1) { + && CPU_COUNT_S(ctx->setsize, ctx->online_cpus) == 1) { warnx(_("CPU %d disable failed (last enabled CPU)"), cpu); fails++; continue; @@ -140,7 +137,7 @@ static int cpu_enable(struct chcpu_context *ctx, int enable) } } - return fails == 0 ? 0 : fails == ctx->maxcpus ? -1 : 1; + return fails == 0 ? 0 : fails == ctx->ncpus ? -1 : 1; } static int cpu_rescan(struct path_cxt *sys) @@ -185,7 +182,7 @@ static int cpu_configure(struct chcpu_context *ctx, int configure) int fails = 0; for (cpu = 0; cpu < ctx->maxcpus; cpu++) { - if (!cpu_is_set(cpu, ctx->setsize, ctx->cpu_set)) + if (!CPU_ISSET_S(cpu, ctx->setsize, ctx->cpu_set)) continue; if (ul_path_accessf(ctx->sys, F_OK, "cpu%d", cpu) != 0) { warnx(_("CPU %d does not exist"), cpu); @@ -207,7 +204,7 @@ static int cpu_configure(struct chcpu_context *ctx, int configure) continue; } if (current == 1 && configure == 0 && ctx->online_cpus && - cpu_is_set(cpu, ctx->maxcpus, ctx->online_cpus)) { + CPU_ISSET_S(cpu, ctx->setsize, ctx->online_cpus)) { warnx(_("CPU %d deconfigure failed (CPU is enabled)"), cpu); fails++; continue; @@ -229,7 +226,7 @@ static int cpu_configure(struct chcpu_context *ctx, int configure) } } - return fails == 0 ? 0 : fails == ctx->maxcpus ? -1 : 1; + return fails == 0 ? 0 : fails == ctx->ncpus ? -1 : 1; } static void cpu_parse(struct chcpu_context *ctx, char *cpu_string) @@ -237,8 +234,10 @@ static void cpu_parse(struct chcpu_context *ctx, char *cpu_string) int rc; rc = cpulist_parse(cpu_string, ctx->cpu_set, ctx->setsize, 1); - if (rc == 0) + if (rc == 0) { + ctx->ncpus = CPU_COUNT_S(ctx->setsize, ctx->cpu_set); return; + } if (rc == 2) errx(EXIT_FAILURE, _("invalid CPU number in CPU list: %s"), cpu_string); errx(EXIT_FAILURE, _("failed to parse CPU list: %s"), cpu_string);