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>
20 #include "closestream.h"
24 static inline int ioprio_set(int which
, int who
, int ioprio
)
26 return syscall(SYS_ioprio_set
, which
, who
, ioprio
);
29 static inline int ioprio_get(int which
, int who
)
31 return syscall(SYS_ioprio_get
, which
, who
);
42 IOPRIO_WHO_PROCESS
= 1,
47 #define IOPRIO_CLASS_SHIFT (13)
48 #define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
50 #define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
51 #define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
52 #define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
54 static const char *to_prio
[] = {
55 [IOPRIO_CLASS_NONE
] = "none",
56 [IOPRIO_CLASS_RT
] = "realtime",
57 [IOPRIO_CLASS_BE
] = "best-effort",
58 [IOPRIO_CLASS_IDLE
] = "idle"
61 static int parse_ioclass(const char *str
)
65 for (i
= 0; i
< ARRAY_SIZE(to_prio
); i
++)
66 if (!strcasecmp(str
, to_prio
[i
]))
71 static void ioprio_print(int pid
, int who
)
73 int ioprio
= ioprio_get(who
, pid
);
76 err(EXIT_FAILURE
, _("ioprio_get failed"));
78 int ioclass
= IOPRIO_PRIO_CLASS(ioprio
);
79 const char *name
= _("unknown");
81 if (ioclass
>= 0 && (size_t) ioclass
< ARRAY_SIZE(to_prio
))
82 name
= to_prio
[ioclass
];
84 if (ioclass
!= IOPRIO_CLASS_IDLE
)
85 printf(_("%s: prio %lu\n"), name
,
86 IOPRIO_PRIO_DATA(ioprio
));
92 static void ioprio_setid(int which
, int ioclass
, int data
, int who
)
94 int rc
= ioprio_set(who
, which
,
95 IOPRIO_PRIO_VALUE(ioclass
, data
));
97 if (rc
== -1 && !tolerant
)
98 err(EXIT_FAILURE
, _("ioprio_set failed"));
101 static void __attribute__((__noreturn__
)) usage(void)
104 fputs(USAGE_HEADER
, out
);
105 fprintf(out
, _(" %1$s [options] -p <pid>...\n"
106 " %1$s [options] -P <pgid>...\n"
107 " %1$s [options] -u <uid>...\n"
108 " %1$s [options] <command>\n"), program_invocation_short_name
);
110 fputs(USAGE_SEPARATOR
, out
);
111 fputs(_("Show or change the I/O-scheduling class and priority of a process.\n"), out
);
113 fputs(USAGE_OPTIONS
, out
);
114 fputs(_(" -c, --class <class> name or number of scheduling class,\n"
115 " 0: none, 1: realtime, 2: best-effort, 3: idle\n"), out
);
116 fputs(_(" -n, --classdata <num> priority (0..7) in the specified scheduling class,\n"
117 " only for the realtime and best-effort classes\n"), out
);
118 fputs(_(" -p, --pid <pid>... act on these already running processes\n"), out
);
119 fputs(_(" -P, --pgid <pgrp>... act on already running processes in these groups\n"), out
);
120 fputs(_(" -t, --ignore ignore failures\n"), out
);
121 fputs(_(" -u, --uid <uid>... act on already running processes owned by these users\n"), out
);
123 fputs(USAGE_SEPARATOR
, out
);
124 printf(USAGE_HELP_OPTIONS(24));
126 printf(USAGE_MAN_TAIL("ionice(1)"));
131 int main(int argc
, char **argv
)
133 int data
= 4, set
= 0, ioclass
= IOPRIO_CLASS_BE
, c
;
134 int which
= 0, who
= 0;
135 const char *invalid_msg
= NULL
;
137 static const struct option longopts
[] = {
138 { "classdata", required_argument
, NULL
, 'n' },
139 { "class", required_argument
, NULL
, 'c' },
140 { "help", no_argument
, NULL
, 'h' },
141 { "ignore", no_argument
, NULL
, 't' },
142 { "pid", required_argument
, NULL
, 'p' },
143 { "pgid", required_argument
, NULL
, 'P' },
144 { "uid", required_argument
, NULL
, 'u' },
145 { "version", no_argument
, NULL
, 'V' },
149 setlocale(LC_ALL
, "");
150 bindtextdomain(PACKAGE
, LOCALEDIR
);
152 close_stdout_atexit();
154 while ((c
= getopt_long(argc
, argv
, "+n:c:p:P:u:tVh", longopts
, NULL
)) != EOF
)
157 data
= strtos32_or_err(optarg
, _("invalid class data argument"));
161 if (isdigit(*optarg
))
162 ioclass
= strtos32_or_err(optarg
,
163 _("invalid class argument"));
165 ioclass
= parse_ioclass(optarg
);
168 _("unknown scheduling class: '%s'"),
176 _("can handle only one of pid, pgid or uid at once"));
177 invalid_msg
= _("invalid PID argument");
178 which
= strtos32_or_err(optarg
, invalid_msg
);
179 who
= IOPRIO_WHO_PROCESS
;
184 _("can handle only one of pid, pgid or uid at once"));
185 invalid_msg
= _("invalid PGID argument");
186 which
= strtos32_or_err(optarg
, invalid_msg
);
187 who
= IOPRIO_WHO_PGRP
;
192 _("can handle only one of pid, pgid or uid at once"));
193 invalid_msg
= _("invalid UID argument");
194 which
= strtos32_or_err(optarg
, invalid_msg
);
195 who
= IOPRIO_WHO_USER
;
202 print_version(EXIT_SUCCESS
);
206 errtryhelp(EXIT_FAILURE
);
210 case IOPRIO_CLASS_NONE
:
211 if ((set
& 1) && !tolerant
)
212 warnx(_("ignoring given class data for none class"));
215 case IOPRIO_CLASS_RT
:
216 case IOPRIO_CLASS_BE
:
218 case IOPRIO_CLASS_IDLE
:
219 if ((set
& 1) && !tolerant
)
220 warnx(_("ignoring given class data for idle class"));
225 warnx(_("unknown prio class %d"), ioclass
);
229 if (!set
&& !which
&& optind
== argc
)
231 * ionice without options, print the current ioprio
233 ioprio_print(0, IOPRIO_WHO_PROCESS
);
234 else if (!set
&& who
) {
236 * ionice -p|-P|-u ID [ID ...]
238 ioprio_print(which
, who
);
240 for(; argv
[optind
]; ++optind
) {
241 which
= strtos32_or_err(argv
[optind
], invalid_msg
);
242 ioprio_print(which
, who
);
244 } else if (set
&& who
) {
246 * ionice -c CLASS -p|-P|-u ID [ID ...]
248 ioprio_setid(which
, ioclass
, data
, who
);
250 for(; argv
[optind
]; ++optind
) {
251 which
= strtos32_or_err(argv
[optind
], invalid_msg
);
252 ioprio_setid(which
, ioclass
, data
, who
);
254 } else if (argv
[optind
]) {
256 * ionice [-c CLASS] COMMAND
258 ioprio_setid(0, ioclass
, data
, IOPRIO_WHO_PROCESS
);
259 execvp(argv
[optind
], &argv
[optind
]);
260 errexec(argv
[optind
]);
262 warnx(_("bad usage"));
263 errtryhelp(EXIT_FAILURE
);