2 * ionice: set or get process io scheduling class and priority
4 * Copyright (C) 2005 Jens Axboe <jens@axboe.dk>
6 * Released under the terms of the GNU General Public License version 2
14 #include <sys/syscall.h>
23 static inline int ioprio_set(int which, int who, int ioprio)
25 return syscall(SYS_ioprio_set, which, who, ioprio);
28 static inline int ioprio_get(int which, int who)
30 return syscall(SYS_ioprio_get, which, who);
41 IOPRIO_WHO_PROCESS = 1,
46 #define IOPRIO_CLASS_SHIFT (13)
47 #define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
49 #define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
50 #define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
51 #define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
53 const char *to_prio[] = {
54 [IOPRIO_CLASS_NONE] = "none",
55 [IOPRIO_CLASS_RT] = "realtime",
56 [IOPRIO_CLASS_BE] = "best-effort",
57 [IOPRIO_CLASS_IDLE] = "idle"
60 static int parse_ioclass(const char *str)
64 for (i = 0; i < ARRAY_SIZE(to_prio); i++)
65 if (!strcasecmp(str, to_prio[i]))
70 static void ioprio_print(int pid)
72 int ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);
75 err(EXIT_FAILURE, _("ioprio_get failed"));
77 int ioclass = IOPRIO_PRIO_CLASS(ioprio);
78 const char *name = _("unknown");
80 if (ioclass > 0 && (size_t) ioclass < ARRAY_SIZE(to_prio))
81 name = to_prio[ioclass];
83 if (ioclass != IOPRIO_CLASS_IDLE)
84 printf("%s: prio %lu\n", name,
85 IOPRIO_PRIO_DATA(ioprio));
91 static void ioprio_setpid(pid_t pid, int ioclass, int data)
93 int rc = ioprio_set(IOPRIO_WHO_PROCESS, pid,
94 IOPRIO_PRIO_VALUE(ioclass, data));
96 if (rc == -1 && !tolerant)
97 err(EXIT_FAILURE, _("ioprio_set failed"));
100 static void __attribute__ ((__noreturn__)) usage(FILE * out)
104 "%1$s - sets or gets process io scheduling class and priority.\n"
107 " %1$s [OPTION] -p PID [PID...]\n"
108 " %1$s [OPTION] COMMAND\n"
111 " -c, --class <class> scheduling class name or number\n"
112 " 0: none, 1: realtime, 2: best-effort, 3: idle\n"
113 " -n, --classdata <num> scheduling class data\n"
114 " 0-7 for realtime and best-effort classes\n"
115 " -p, --pid=PID view or modify already running process\n"
116 " -t, --ignore ignore failures\n"
117 " -V, --version output version information and exit\n"
118 " -h, --help display this help and exit\n\n"),
119 program_invocation_short_name);
121 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
124 int main(int argc, char **argv)
126 int data = 4, set = 0, ioclass = IOPRIO_CLASS_BE, c;
129 static const struct option longopts[] = {
130 { "classdata", required_argument, NULL, 'n' },
131 { "class", required_argument, NULL, 'c' },
132 { "help", no_argument, NULL, 'h' },
133 { "ignore", no_argument, NULL, 't' },
134 { "pid", required_argument, NULL, 'p' },
135 { "version", no_argument, NULL, 'V' },
139 setlocale(LC_ALL, "");
140 bindtextdomain(PACKAGE, LOCALEDIR);
143 while ((c = getopt_long(argc, argv, "+n:c:p:tVh", longopts, NULL)) != EOF)
146 data = strtol_or_err(optarg, _("failed to parse class data"));
150 if (isdigit(*optarg))
151 ioclass = strtol_or_err(optarg,
152 _("failed to parse class"));
154 ioclass = parse_ioclass(optarg);
157 _("unknown scheduling class: '%s'"),
163 pid = strtol_or_err(optarg, _("failed to parse pid"));
169 printf(_("%s from %s\n"),
170 program_invocation_short_name, PACKAGE_STRING);
179 case IOPRIO_CLASS_NONE:
180 if ((set & 1) && !tolerant)
181 warnx(_("ignoring given class data for none class"));
184 case IOPRIO_CLASS_RT:
185 case IOPRIO_CLASS_BE:
187 case IOPRIO_CLASS_IDLE:
188 if ((set & 1) && !tolerant)
189 warnx(_("ignoring given class data for idle class"));
194 warnx(_("unknown prio class %d"), ioclass);
198 if (!set && !pid && optind == argc)
200 * ionice without options, print the current ioprio
204 else if (!set && pid) {
206 * ionice -p PID [PID ...]
210 for(; argv[optind]; ++optind) {
211 pid = strtol_or_err(argv[optind], _("failed to parse pid"));
214 } else if (set && pid) {
216 * ionice -c CLASS -p PID [PID ...]
218 ioprio_setpid(pid, ioclass, data);
220 for(; argv[optind]; ++optind) {
221 pid = strtol_or_err(argv[optind], _("failed to parse pid"));
222 ioprio_setpid(pid, ioclass, data);
224 } else if (argv[optind]) {
226 * ionice [-c CLASS] COMMAND
228 ioprio_setpid(0, ioclass, data);
229 execvp(argv[optind], &argv[optind]);
230 err(EXIT_FAILURE, _("executing %s failed"), argv[optind]);