From: Christian Goeschel Ndjomouo Date: Tue, 31 Mar 2026 15:38:09 +0000 (-0400) Subject: chrt: support the 'PID:inode' address format X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=47b9ba6ba23e150d1c3ec21788022d649e06f6e0;p=thirdparty%2Futil-linux.git chrt: support the 'PID:inode' address format This patch enables support for the PID:inode address format. It removes a sentinel value from ctl->pid that controls the PID parsing behavior and introduces a dedicated variable parse_pid (member of struct chrt_ctl), which makes the code a bit more readable and coherent. Signed-off-by: Christian Goeschel Ndjomouo --- diff --git a/schedutils/chrt.1.adoc b/schedutils/chrt.1.adoc index b8d8874bc..4c6dbde1c 100644 --- a/schedutils/chrt.1.adoc +++ b/schedutils/chrt.1.adoc @@ -40,11 +40,12 @@ chrt - manipulate the real-time attributes of a process *chrt* [options] [_priority_] _command_ [_argument_...] -*chrt --pid* [options] [_priority_] _PID_ +*chrt --pid* [options] [_priority_] _PID_[:_inode_] == DESCRIPTION -*chrt* sets or retrieves the real-time scheduling attributes of an existing _PID_, or runs _command_ with the given attributes. +*chrt* sets or retrieves the real-time scheduling attributes of an existing _PID_[:_inode_], or runs _command_ with the given attributes. +The _inode_ uniquely identifies the process identity in the pidfs. To retrieve a process's inode number you can use the *getino*(1) utility. == POLICY OPTIONS @@ -118,12 +119,12 @@ ____ //TRANSLATORS: Keep {colon} untranslated You can also retrieve the real-time attributes of an existing task{colon}:: ____ -*chrt --pid* _PID_ +*chrt --pid* _PID_[:_inode_] ____ //TRANSLATORS: Keep {colon} untranslated Or set them{colon}:: ____ -*chrt --pid* _policy-option priority PID_ +*chrt --pid* _policy-option_ _priority_ _PID_[:_inode_] ____ For example, to set the scheduling policy to *SCHED_RR* (round-robin) and the priority to *30* for process *1234*{colon}:: ____ @@ -131,11 +132,11 @@ ____ ____ Reset priorities to default for a process{colon}:: ____ -*chrt --pid -o 0* _PID_ +*chrt --pid -o 0* _PID_[:_inode_] ____ Set a custom slice of 1 ms for a *SCHED_OTHER* task (priority is optional for policies other than *SCHED_FIFO* and *SCHED_RR*){colon}:: ____ -*chrt --pid -o -T 1000000* _PID_ +*chrt --pid -o -T 1000000* _PID_[:_inode_] ____ See *sched*(7) for a detailed discussion of the different scheduler classes and how they interact. @@ -159,7 +160,8 @@ mailto:kzak@redhat.com[Karel Zak] *nice*(1), *renice*(1), *taskset*(1), -*sched*(7) +*sched*(7), +*getino*(1) See *sched_setscheduler*(2) for a description of the Linux scheduling scheme. diff --git a/schedutils/chrt.c b/schedutils/chrt.c index 5ba9964c1..3e4ea41d5 100644 --- a/schedutils/chrt.c +++ b/schedutils/chrt.c @@ -35,13 +35,16 @@ #include "strutils.h" #include "procfs.h" #include "sched_attr.h" - +#include "pidutils.h" +#include "pidfd-utils.h" /* control struct */ struct chrt_ctl { - pid_t pid; - int policy; /* SCHED_* */ - int priority; + pid_t pid; + uint64_t pidfd_ino; + int pidfd; + int policy; /* SCHED_* */ + int priority; uint64_t runtime; /* --sched-* options */ uint64_t deadline; @@ -50,21 +53,30 @@ struct chrt_ctl { unsigned int all_tasks : 1, /* all threads of the PID */ reset_on_fork : 1, /* SCHED_RESET_ON_FORK or SCHED_FLAG_RESET_ON_FORK */ altered : 1, /* sched_set**() used */ - verbose : 1; /* verbose output */ + verbose : 1, /* verbose output */ + parse_pid : 1; /* expect a PID as last command line argument */ }; static void __attribute__((__noreturn__)) usage(void) { FILE *out = stdout; + char *pid_arg = NULL; + +#ifdef USE_PIDFD_INO_SUPPORT + pid_arg = "PID[:inode]"; +#else + pid_arg = "PID"; +#endif + fputs(_("Show or change the real-time scheduling attributes of a process.\n"), out); fputs(USAGE_SEPARATOR, out); - fputs(_("Set policy:\n" + fprintf(out, _("Set policy:\n" " chrt [options] [] [...]\n" - " chrt --pid [options] [] \n"), out); + " chrt --pid [options] [] <%s>\n"), pid_arg); fputs(USAGE_SEPARATOR, out); - fputs(_("Get policy:\n" - " chrt --pid \n"), out); + fprintf(out, _("Get policy:\n" + " chrt --pid <%s>\n"), pid_arg); fputs(USAGE_SEPARATOR, out); fputs(_("Policy options:\n"), out); @@ -397,7 +409,13 @@ static void set_sched(struct chrt_ctl *ctl) int main(int argc, char **argv) { - struct chrt_ctl _ctl = { .pid = -1, .policy = SCHED_RR }, *ctl = &_ctl; + struct chrt_ctl _ctl = { + .parse_pid = 0, + .pid = 0, + .pidfd_ino = 0, + .pidfd = -1, + .policy = SCHED_RR + }, *ctl = &_ctl; int c; bool policy_given = false, need_prio = false; @@ -474,7 +492,7 @@ int main(int argc, char **argv) policy_given = true; break; case 'p': - ctl->pid = 0; /* indicate that a PID is expected */ + ctl->parse_pid = 1; /* indicate that a PID is expected */ break; case 'r': ctl->policy = SCHED_RR; @@ -509,10 +527,11 @@ int main(int argc, char **argv) } /* If option --pid was given, parse the very last argument as a PID. */ - if (ctl->pid == 0) { + if (ctl->parse_pid) { errno = 0; - /* strtopid_or_err() is not suitable here, as 0 can be passed. */ - ctl->pid = strtos32_or_err(argv[argc - 1], _("invalid PID argument")); + ul_parse_pid_str_or_err(argv[argc - 1], &ctl->pid, &ctl->pidfd_ino, UL_PID_ZERO); + if (ctl->pidfd_ino > 0) + ctl->pidfd = ul_get_valid_pidfd_or_err(ctl->pid, ctl->pidfd_ino); /* If no policy nor priority was given, show current settings. */ if (!policy_given && argc - optind == 1) { @@ -524,21 +543,21 @@ int main(int argc, char **argv) if (ctl->policy == SCHED_RR) need_prio = true; - if (ctl->pid > -1 && ctl->verbose) + if (ctl->parse_pid && ctl->verbose) show_sched_info(ctl); - if (argc - optind > 1 && (ctl->pid > -1 || isdigit_string(argv[optind]))) { + if (argc - optind > 1 && (ctl->parse_pid || isdigit_string(argv[optind]))) { errno = 0; ctl->priority = strtos32_or_err(argv[optind], _("invalid priority argument")); - optind++; - } else if (need_prio && ctl->pid == -1 && isdigit_string(argv[optind])) + } else if (need_prio && !ctl->parse_pid && isdigit_string(argv[optind])) { errx(EXIT_FAILURE, _("no command or priority specified")); - else if (need_prio) + } else if (need_prio) { errx(EXIT_FAILURE, _("policy %s requires a priority argument"), get_policy_name(ctl->policy)); - else + } else { ctl->priority = 0; + } if (ctl->runtime && !supports_runtime_param(ctl->policy)) errx(EXIT_FAILURE, _("--sched-runtime option is supported for %s"), @@ -562,19 +581,20 @@ int main(int argc, char **argv) if (ctl->deadline || ctl->period) errx(EXIT_FAILURE, _("SCHED_DEADLINE is unsupported")); #endif - if (ctl->pid == -1) - ctl->pid = 0; if (ctl->priority < sched_get_priority_min(ctl->policy) || - sched_get_priority_max(ctl->policy) < ctl->priority) + sched_get_priority_max(ctl->policy) < ctl->priority) errx(EXIT_FAILURE, - _("unsupported priority value for the policy: %d: see --max for valid range"), - ctl->priority); + _("unsupported priority value for the policy: %d: see --max for valid range"), + ctl->priority); set_sched(ctl); if (ctl->verbose) show_sched_info(ctl); - if (!ctl->pid) { + if (ctl->pidfd >= 0) + close(ctl->pidfd); + + if (!ctl->parse_pid) { argv += optind; if (argv[0] && strcmp(argv[0], "--") == 0)