]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - schedutils/ionice.c
agetty: don't put the VC into canonical mode
[thirdparty/util-linux.git] / schedutils / ionice.c
index ac721215b0f4262b17c03949233c51b4fedc287d..b4c6a82a2e1b02e80d99c9ec6e59a43f406447ce 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ionice: set or get process io scheduling class and priority
  *
- * Copyright (C) 2005 Jens Axboe <axboe@suse.de> SUSE Labs
+ * Copyright (C) 2005 Jens Axboe <jens@axboe.dk>
  *
  * Released under the terms of the GNU General Public License version 2
  *
 #include <errno.h>
 #include <getopt.h>
 #include <unistd.h>
-#include <sys/ptrace.h>
 #include <sys/syscall.h>
-#include <asm/unistd.h>
-
-#if !defined(SYS_ioprio_get) || !defined(SYS_ioprio_set)
-
-# if defined(__i386__)
-#  define __NR_ioprio_set              289
-#  define __NR_ioprio_get              290
-# elif defined(__powerpc__) || defined(__powerpc64__)
-#  define __NR_ioprio_set              273
-#  define __NR_ioprio_get              274
-# elif defined(__x86_64__)
-#  define __NR_ioprio_set              251
-#  define __NR_ioprio_get              252
-# elif defined(__ia64__)
-#  define __NR_ioprio_set              1274
-#  define __NR_ioprio_get              1275
-# elif defined(__alpha__)
-#  define __NR_ioprio_set              442
-#  define __NR_ioprio_get              443
-# elif defined(__s390x__) || defined(__s390__)
-#  define __NR_ioprio_set              282
-#  define __NR_ioprio_get              283
-# elif defined(__sparc__) || defined(__sparc64__)
-#  define __NR_ioprio_set              196
-#  define __NR_ioprio_get              218
-# else
-#  error "Unsupported arch"
-# endif
-
-# define SYS_ioprio_get                __NR_ioprio_get
-# define SYS_ioprio_set                __NR_ioprio_set
-
-#endif /* !SYS_ioprio_get */
+#include <ctype.h>
+
+#include "nls.h"
+#include "strutils.h"
+#include "c.h"
+#include "closestream.h"
+
+static int tolerant;
 
 static inline int ioprio_set(int which, int who, int ioprio)
 {
@@ -70,84 +44,224 @@ enum {
        IOPRIO_WHO_USER,
 };
 
-#define IOPRIO_CLASS_SHIFT     13
+#define IOPRIO_CLASS_SHIFT     (13)
+#define IOPRIO_PRIO_MASK       ((1UL << IOPRIO_CLASS_SHIFT) - 1)
+
+#define IOPRIO_PRIO_CLASS(mask)        ((mask) >> IOPRIO_CLASS_SHIFT)
+#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
+#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
+
+static const char *to_prio[] = {
+       [IOPRIO_CLASS_NONE] = "none",
+       [IOPRIO_CLASS_RT]   = "realtime",
+       [IOPRIO_CLASS_BE]   = "best-effort",
+       [IOPRIO_CLASS_IDLE] = "idle"
+};
+
+static int parse_ioclass(const char *str)
+{
+       size_t i;
+
+       for (i = 0; i < ARRAY_SIZE(to_prio); i++)
+               if (!strcasecmp(str, to_prio[i]))
+                       return i;
+       return -1;
+}
+
+static void ioprio_print(int pid, int who)
+{
+       int ioprio = ioprio_get(who, pid);
+
+       if (ioprio == -1)
+               err(EXIT_FAILURE, _("ioprio_get failed"));
+       else {
+               int ioclass = IOPRIO_PRIO_CLASS(ioprio);
+               const char *name = _("unknown");
+
+               if (ioclass >= 0 && (size_t) ioclass < ARRAY_SIZE(to_prio))
+                       name = to_prio[ioclass];
+
+               if (ioclass != IOPRIO_CLASS_IDLE)
+                       printf(_("%s: prio %lu\n"), name,
+                              IOPRIO_PRIO_DATA(ioprio));
+               else
+                       printf("%s\n", name);
+       }
+}
+
+static void ioprio_setid(int which, int ioclass, int data, int who)
+{
+       int rc = ioprio_set(who, which,
+                           IOPRIO_PRIO_VALUE(ioclass, data));
 
-const char *to_prio[] = { "none", "realtime", "best-effort", "idle", };
+       if (rc == -1 && !tolerant)
+               err(EXIT_FAILURE, _("ioprio_set failed"));
+}
 
-static void usage(void)
+static void __attribute__((__noreturn__)) usage(void)
 {
-       printf("Usage: ionice [OPTIONS] [COMMAND [ARG]...]\n");
-       printf("Sets or gets process io scheduling class and priority.\n");
-       printf("\n\t-n\tClass data (typically 0-7, lower being higher prio)\n");
-       printf("\t-c\tScheduling class\n");
-       printf("\t\t\t1: realtime, 2: best-effort, 3: idle\n");
-       printf("\t-p\tProcess pid\n");
-       printf("\t-h\tThis help page\n");
-       printf("\nJens Axboe <axboe@suse.de> (C) 2005\n");
+       FILE *out = stdout;
+       fputs(USAGE_HEADER, out);
+       fprintf(out,  _(" %1$s [options] -p <pid>...\n"
+                       " %1$s [options] -P <pgid>...\n"
+                       " %1$s [options] -u <uid>...\n"
+                       " %1$s [options] <command>\n"), program_invocation_short_name);
+
+       fputs(USAGE_SEPARATOR, out);
+       fputs(_("Show or change the I/O-scheduling class and priority of a process.\n"), out);
+
+       fputs(USAGE_OPTIONS, out);
+       fputs(_(" -c, --class <class>    name or number of scheduling class,\n"
+               "                          0: none, 1: realtime, 2: best-effort, 3: idle\n"), out);
+       fputs(_(" -n, --classdata <num>  priority (0..7) in the specified scheduling class,\n"
+               "                          only for the realtime and best-effort classes\n"), out);
+       fputs(_(" -p, --pid <pid>...     act on these already running processes\n"), out);
+       fputs(_(" -P, --pgid <pgrp>...   act on already running processes in these groups\n"), out);
+       fputs(_(" -t, --ignore           ignore failures\n"), out);
+       fputs(_(" -u, --uid <uid>...     act on already running processes owned by these users\n"), out);
+
+       fputs(USAGE_SEPARATOR, out);
+       printf(USAGE_HELP_OPTIONS(24));
+
+       printf(USAGE_MAN_TAIL("ionice(1)"));
+
+       exit(EXIT_SUCCESS);
 }
 
-int main(int argc, char *argv[])
+int main(int argc, char **argv)
 {
-       int ioprio = 4, set = 0, ioprio_class = IOPRIO_CLASS_BE;
-       int c, pid = 0;
+       int data = 4, set = 0, ioclass = IOPRIO_CLASS_BE, c;
+       int which = 0, who = 0;
+       const char *invalid_msg = NULL;
+
+       static const struct option longopts[] = {
+               { "classdata", required_argument, NULL, 'n' },
+               { "class",     required_argument, NULL, 'c' },
+               { "help",      no_argument,       NULL, 'h' },
+               { "ignore",    no_argument,       NULL, 't' },
+               { "pid",       required_argument, NULL, 'p' },
+               { "pgid",      required_argument, NULL, 'P' },
+               { "uid",       required_argument, NULL, 'u' },
+               { "version",   no_argument,       NULL, 'V' },
+               { NULL, 0, NULL, 0 }
+       };
 
-       while ((c = getopt(argc, argv, "+n:c:p:h")) != EOF) {
+       setlocale(LC_ALL, "");
+       bindtextdomain(PACKAGE, LOCALEDIR);
+       textdomain(PACKAGE);
+       atexit(close_stdout);
+
+       while ((c = getopt_long(argc, argv, "+n:c:p:P:u:tVh", longopts, NULL)) != EOF)
                switch (c) {
                case 'n':
-                       ioprio = strtol(optarg, NULL, 10);
-                       set = 1;
+                       data = strtos32_or_err(optarg, _("invalid class data argument"));
+                       set |= 1;
                        break;
                case 'c':
-                       ioprio_class = strtol(optarg, NULL, 10);
-                       set = 1;
+                       if (isdigit(*optarg))
+                               ioclass = strtos32_or_err(optarg,
+                                               _("invalid class argument"));
+                       else {
+                               ioclass = parse_ioclass(optarg);
+                               if (ioclass < 0)
+                                       errx(EXIT_FAILURE,
+                                               _("unknown scheduling class: '%s'"),
+                                               optarg);
+                       }
+                       set |= 2;
                        break;
                case 'p':
-                       pid = strtol(optarg, NULL, 10);
+                       if (who)
+                               errx(EXIT_FAILURE,
+                                    _("can handle only one of pid, pgid or uid at once"));
+                       invalid_msg = _("invalid PID argument");
+                       which = strtos32_or_err(optarg, invalid_msg);
+                       who = IOPRIO_WHO_PROCESS;
+                       break;
+               case 'P':
+                       if (who)
+                               errx(EXIT_FAILURE,
+                                    _("can handle only one of pid, pgid or uid at once"));
+                       invalid_msg = _("invalid PGID argument");
+                       which = strtos32_or_err(optarg, invalid_msg);
+                       who = IOPRIO_WHO_PGRP;
                        break;
+               case 'u':
+                       if (who)
+                               errx(EXIT_FAILURE,
+                                    _("can handle only one of pid, pgid or uid at once"));
+                       invalid_msg = _("invalid UID argument");
+                       which = strtos32_or_err(optarg, invalid_msg);
+                       who = IOPRIO_WHO_USER;
+                       break;
+               case 't':
+                       tolerant = 1;
+                       break;
+               case 'V':
+                       printf(UTIL_LINUX_VERSION);
+                       return EXIT_SUCCESS;
                case 'h':
-               default:
                        usage();
-                       exit(0);
+               default:
+                       errtryhelp(EXIT_FAILURE);
                }
-       }
 
-       switch (ioprio_class) {
+       switch (ioclass) {
                case IOPRIO_CLASS_NONE:
-                       ioprio_class = IOPRIO_CLASS_BE;
+                       if ((set & 1) && !tolerant)
+                               warnx(_("ignoring given class data for none class"));
+                       data = 0;
                        break;
                case IOPRIO_CLASS_RT:
                case IOPRIO_CLASS_BE:
                        break;
                case IOPRIO_CLASS_IDLE:
-                       ioprio = 7;
+                       if ((set & 1) && !tolerant)
+                               warnx(_("ignoring given class data for idle class"));
+                       data = 7;
                        break;
                default:
-                       printf("bad prio class %d\n", ioprio_class);
-                       return 1;
+                       if (!tolerant)
+                               warnx(_("unknown prio class %d"), ioclass);
+                       break;
        }
 
-       if (!set) {
-               if (!pid && argv[optind])
-                       pid = strtol(argv[optind], NULL, 10);
+       if (!set && !which && optind == argc)
+               /*
+                * ionice without options, print the current ioprio
+                */
+               ioprio_print(0, IOPRIO_WHO_PROCESS);
+       else if (!set && who) {
+               /*
+                * ionice -p|-P|-u ID [ID ...]
+                */
+               ioprio_print(which, who);
 
-               ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);
+               for(; argv[optind]; ++optind) {
+                       which = strtos32_or_err(argv[optind], invalid_msg);
+                       ioprio_print(which, who);
+               }
+       } else if (set && who) {
+               /*
+                * ionice -c CLASS -p|-P|-u ID [ID ...]
+                */
+               ioprio_setid(which, ioclass, data, who);
 
-               if (ioprio == -1)
-                       perror("ioprio_get");
-               else {
-                       ioprio_class = ioprio >> IOPRIO_CLASS_SHIFT;
-                       ioprio = ioprio & 0xff;
-                       printf("%s: prio %d\n", to_prio[ioprio_class], ioprio);
+               for(; argv[optind]; ++optind) {
+                       which = strtos32_or_err(argv[optind], invalid_msg);
+                       ioprio_setid(which, ioclass, data, who);
                }
+       } else if (argv[optind]) {
+               /*
+                * ionice [-c CLASS] COMMAND
+                */
+               ioprio_setid(0, ioclass, data, IOPRIO_WHO_PROCESS);
+               execvp(argv[optind], &argv[optind]);
+               errexec(argv[optind]);
        } else {
-               if (ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio | ioprio_class << IOPRIO_CLASS_SHIFT) == -1) {
-                       perror("ioprio_set");
-                       return 1;
-               }
-
-               if (argv[optind])
-                       execvp(argv[optind], &argv[optind]);
+               warnx(_("bad usage"));
+               errtryhelp(EXIT_FAILURE);
        }
 
-       return 0;
+       return EXIT_SUCCESS;
 }