]> git.ipfire.org Git - thirdparty/util-linux.git/blame - schedutils/ionice.c
rev: be careful with close()
[thirdparty/util-linux.git] / schedutils / ionice.c
CommitLineData
48d7b13a
KZ
1/*
2 * ionice: set or get process io scheduling class and priority
3 *
357e7c3b 4 * Copyright (C) 2005 Jens Axboe <jens@axboe.dk>
48d7b13a
KZ
5 *
6 * Released under the terms of the GNU General Public License version 2
7 *
8 */
9#include <stdio.h>
10#include <stdlib.h>
11#include <errno.h>
12#include <getopt.h>
13#include <unistd.h>
48d7b13a 14#include <sys/syscall.h>
fe040397 15#include <ctype.h>
5bd11d0d
KZ
16
17#include "nls.h"
8abcf290 18#include "strutils.h"
eb76ca98 19#include "c.h"
ed8ec2a6 20#include "closestream.h"
24295096 21
ef0fe2e8
SM
22static int tolerant;
23
48d7b13a
KZ
24static inline int ioprio_set(int which, int who, int ioprio)
25{
4dfadf9c 26 return syscall(SYS_ioprio_set, which, who, ioprio);
48d7b13a
KZ
27}
28
29static inline int ioprio_get(int which, int who)
30{
4dfadf9c 31 return syscall(SYS_ioprio_get, which, who);
48d7b13a
KZ
32}
33
34enum {
35 IOPRIO_CLASS_NONE,
36 IOPRIO_CLASS_RT,
37 IOPRIO_CLASS_BE,
38 IOPRIO_CLASS_IDLE,
39};
40
41enum {
42 IOPRIO_WHO_PROCESS = 1,
43 IOPRIO_WHO_PGRP,
44 IOPRIO_WHO_USER,
45};
46
560cdabb
KZ
47#define IOPRIO_CLASS_SHIFT (13)
48#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
49
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)
53
2ba641e5 54static const char *to_prio[] = {
560cdabb
KZ
55 [IOPRIO_CLASS_NONE] = "none",
56 [IOPRIO_CLASS_RT] = "realtime",
57 [IOPRIO_CLASS_BE] = "best-effort",
58 [IOPRIO_CLASS_IDLE] = "idle"
59};
48d7b13a 60
fe040397
KZ
61static int parse_ioclass(const char *str)
62{
cee12fc6 63 size_t i;
fe040397
KZ
64
65 for (i = 0; i < ARRAY_SIZE(to_prio); i++)
66 if (!strcasecmp(str, to_prio[i]))
67 return i;
68 return -1;
69}
70
bd2ff3d2 71static void ioprio_print(int pid, int who)
ef0fe2e8 72{
bd2ff3d2 73 int ioprio = ioprio_get(who, pid);
ef0fe2e8
SM
74
75 if (ioprio == -1)
76 err(EXIT_FAILURE, _("ioprio_get failed"));
77 else {
560cdabb 78 int ioclass = IOPRIO_PRIO_CLASS(ioprio);
cbc1dc96
KZ
79 const char *name = _("unknown");
80
b422f5fe 81 if (ioclass >= 0 && (size_t) ioclass < ARRAY_SIZE(to_prio))
cbc1dc96 82 name = to_prio[ioclass];
560cdabb
KZ
83
84 if (ioclass != IOPRIO_CLASS_IDLE)
65f25186 85 printf(_("%s: prio %lu\n"), name,
8c219bf4 86 IOPRIO_PRIO_DATA(ioprio));
560cdabb 87 else
cbc1dc96 88 printf("%s\n", name);
ef0fe2e8
SM
89 }
90}
91
bd2ff3d2 92static void ioprio_setid(int which, int ioclass, int data, int who)
ef0fe2e8 93{
bd2ff3d2 94 int rc = ioprio_set(who, which,
560cdabb 95 IOPRIO_PRIO_VALUE(ioclass, data));
ef0fe2e8
SM
96
97 if (rc == -1 && !tolerant)
98 err(EXIT_FAILURE, _("ioprio_set failed"));
99}
100
6e1eda6f 101static void __attribute__((__noreturn__)) usage(void)
48d7b13a 102{
6e1eda6f 103 FILE *out = stdout;
2d745ee6
BS
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);
109
451dbcfa
BS
110 fputs(USAGE_SEPARATOR, out);
111 fputs(_("Show or change the I/O-scheduling class and priority of a process.\n"), out);
112
2d745ee6
BS
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);
122
123 fputs(USAGE_SEPARATOR, out);
f45f3ec3 124 printf(USAGE_HELP_OPTIONS(24));
2d745ee6 125
f45f3ec3 126 printf(USAGE_MAN_TAIL("ionice(1)"));
976b7580 127
6e1eda6f 128 exit(EXIT_SUCCESS);
48d7b13a
KZ
129}
130
a5e9b75f 131int main(int argc, char **argv)
48d7b13a 132{
560cdabb 133 int data = 4, set = 0, ioclass = IOPRIO_CLASS_BE, c;
bd2ff3d2
MY
134 int which = 0, who = 0;
135 const char *invalid_msg = NULL;
48d7b13a 136
976b7580
SK
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' },
bd2ff3d2
MY
143 { "pgid", required_argument, NULL, 'P' },
144 { "uid", required_argument, NULL, 'u' },
976b7580
SK
145 { "version", no_argument, NULL, 'V' },
146 { NULL, 0, NULL, 0 }
147 };
148
5bd11d0d
KZ
149 setlocale(LC_ALL, "");
150 bindtextdomain(PACKAGE, LOCALEDIR);
151 textdomain(PACKAGE);
2c308875 152 close_stdout_atexit();
5bd11d0d 153
bd2ff3d2 154 while ((c = getopt_long(argc, argv, "+n:c:p:P:u:tVh", longopts, NULL)) != EOF)
48d7b13a
KZ
155 switch (c) {
156 case 'n':
630ed89d 157 data = strtos32_or_err(optarg, _("invalid class data argument"));
8dbfe5a1 158 set |= 1;
48d7b13a
KZ
159 break;
160 case 'c':
fe040397 161 if (isdigit(*optarg))
630ed89d
KZ
162 ioclass = strtos32_or_err(optarg,
163 _("invalid class argument"));
fe040397
KZ
164 else {
165 ioclass = parse_ioclass(optarg);
166 if (ioclass < 0)
167 errx(EXIT_FAILURE,
168 _("unknown scheduling class: '%s'"),
169 optarg);
170 }
8dbfe5a1 171 set |= 2;
48d7b13a
KZ
172 break;
173 case 'p':
bd2ff3d2
MY
174 if (who)
175 errx(EXIT_FAILURE,
2d745ee6 176 _("can handle only one of pid, pgid or uid at once"));
bd2ff3d2
MY
177 invalid_msg = _("invalid PID argument");
178 which = strtos32_or_err(optarg, invalid_msg);
179 who = IOPRIO_WHO_PROCESS;
180 break;
181 case 'P':
182 if (who)
183 errx(EXIT_FAILURE,
2d745ee6 184 _("can handle only one of pid, pgid or uid at once"));
bd2ff3d2
MY
185 invalid_msg = _("invalid PGID argument");
186 which = strtos32_or_err(optarg, invalid_msg);
187 who = IOPRIO_WHO_PGRP;
188 break;
189 case 'u':
190 if (who)
191 errx(EXIT_FAILURE,
2d745ee6 192 _("can handle only one of pid, pgid or uid at once"));
b6973e5d 193 invalid_msg = _("invalid UID argument");
bd2ff3d2
MY
194 which = strtos32_or_err(optarg, invalid_msg);
195 who = IOPRIO_WHO_USER;
48d7b13a 196 break;
4d125dfc
LK
197 case 't':
198 tolerant = 1;
199 break;
2c308875 200
976b7580 201 case 'V':
2c308875 202 print_version(EXIT_SUCCESS);
48d7b13a 203 case 'h':
6e1eda6f 204 usage();
48d7b13a 205 default:
677ec86c 206 errtryhelp(EXIT_FAILURE);
48d7b13a 207 }
48d7b13a 208
ef0fe2e8 209 switch (ioclass) {
48d7b13a 210 case IOPRIO_CLASS_NONE:
cbc1dc96 211 if ((set & 1) && !tolerant)
5dc9371c 212 warnx(_("ignoring given class data for none class"));
560cdabb 213 data = 0;
48d7b13a
KZ
214 break;
215 case IOPRIO_CLASS_RT:
216 case IOPRIO_CLASS_BE:
217 break;
218 case IOPRIO_CLASS_IDLE:
cbc1dc96 219 if ((set & 1) && !tolerant)
5bd11d0d 220 warnx(_("ignoring given class data for idle class"));
560cdabb 221 data = 7;
48d7b13a
KZ
222 break;
223 default:
cbc1dc96
KZ
224 if (!tolerant)
225 warnx(_("unknown prio class %d"), ioclass);
226 break;
48d7b13a
KZ
227 }
228
bd2ff3d2 229 if (!set && !which && optind == argc)
fcc2b2da
KZ
230 /*
231 * ionice without options, print the current ioprio
232 */
bd2ff3d2
MY
233 ioprio_print(0, IOPRIO_WHO_PROCESS);
234 else if (!set && who) {
fcc2b2da 235 /*
bd2ff3d2 236 * ionice -p|-P|-u ID [ID ...]
fcc2b2da 237 */
bd2ff3d2 238 ioprio_print(which, who);
48d7b13a 239
ef0fe2e8 240 for(; argv[optind]; ++optind) {
bd2ff3d2
MY
241 which = strtos32_or_err(argv[optind], invalid_msg);
242 ioprio_print(which, who);
48d7b13a 243 }
bd2ff3d2 244 } else if (set && who) {
fcc2b2da 245 /*
bd2ff3d2 246 * ionice -c CLASS -p|-P|-u ID [ID ...]
fcc2b2da 247 */
bd2ff3d2 248 ioprio_setid(which, ioclass, data, who);
ef0fe2e8 249
fcc2b2da 250 for(; argv[optind]; ++optind) {
bd2ff3d2
MY
251 which = strtos32_or_err(argv[optind], invalid_msg);
252 ioprio_setid(which, ioclass, data, who);
2b258413 253 }
fcc2b2da
KZ
254 } else if (argv[optind]) {
255 /*
256 * ionice [-c CLASS] COMMAND
257 */
bd2ff3d2 258 ioprio_setid(0, ioclass, data, IOPRIO_WHO_PROCESS);
fcc2b2da 259 execvp(argv[optind], &argv[optind]);
61b62222 260 errexec(argv[optind]);
6e1eda6f
RM
261 } else {
262 warnx(_("bad usage"));
263 errtryhelp(EXIT_FAILURE);
264 }
48d7b13a 265
a5e9b75f 266 return EXIT_SUCCESS;
48d7b13a 267}