summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorChris Coulson <chrisccoulson@googlemail.com>2009-02-26 09:06:15 +0200
committerGuillem Jover <guillem@debian.org>2009-02-26 09:06:15 +0200
commitb0569c7d4d744e3902ab606284411dd304ceafc6 (patch)
tree82ba06ae53c7e213f93263d235694fbb4ebdf754 /utils
parent69c9250259d3abb8feb632898e5a495e74a33fc8 (diff)
downloaddpkg-b0569c7d4d744e3902ab606284411dd304ceafc6.tar.gz
s-s-d: Support setting the IO scheduler class and priority
Add new option -I, --iosched <class[:priority]>. Closes: #443535 Signed-off-by: Guillem Jover <guillem@debian.org>
Diffstat (limited to 'utils')
-rw-r--r--utils/start-stop-daemon.c98
1 files changed, 97 insertions, 1 deletions
diff --git a/utils/start-stop-daemon.c b/utils/start-stop-daemon.c
index 8171dc3d4..34ee0221d 100644
--- a/utils/start-stop-daemon.c
+++ b/utils/start-stop-daemon.c
@@ -111,6 +111,27 @@
#include <error.h>
#endif
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
+
+#if defined(SYS_ioprio_set) && defined(linux)
+#define HAVE_IOPRIO_SET
+#endif
+
+enum {
+ IOPRIO_WHO_PROCESS = 1,
+ IOPRIO_WHO_PGRP,
+ IOPRIO_WHO_USER,
+};
+
+enum {
+ IOPRIO_CLASS_NONE,
+ IOPRIO_CLASS_RT,
+ IOPRIO_CLASS_BE,
+ IOPRIO_CLASS_IDLE,
+};
+
static int testmode = 0;
static int quietmode = 0;
static int exitnodo = 1;
@@ -136,6 +157,11 @@ static const char *progname = "";
static int nicelevel = 0;
static int umask_value = -1;
+#define IOPRIO_CLASS_SHIFT 13
+#define IOPRIO_PRIO_VALUE(class, prio) (((class) << IOPRIO_CLASS_SHIFT) | (prio))
+#define IO_SCHED_PRIO_MIN 0
+#define IO_SCHED_PRIO_MAX 7
+
static struct stat exec_stat;
#if defined(OSHURD)
static struct proc_stat_list *procset = NULL;
@@ -168,6 +194,7 @@ struct schedule_item {
};
static struct res_schedule *proc_sched = NULL;
+static struct res_schedule *io_sched = NULL;
static int schedule_length;
static struct schedule_item *schedule = NULL;
@@ -339,6 +366,8 @@ do_help(void)
" -P|--procsched <policy[:prio]>\n"
" use <policy> with <prio> for the kernel\n"
" process scheduler (default prio is 0)\n"
+" -I|--iosched <class[:prio]> use <class> with <prio> to set the IO\n"
+" scheduler (default prio is 4)\n"
" -k|--umask <mask> change the umask to <mask> before starting\n"
" -b|--background force the process to detach\n"
" -m|--make-pidfile create the pidfile before starting\n"
@@ -493,6 +522,40 @@ parse_proc_schedule(const char *string)
}
static void
+parse_io_schedule(const char *string)
+{
+ char *class_str, *prio_str;
+ int prio = 4;
+
+ class_str = xstrdup(string);
+ class_str = strtok(class_str, ":");
+ prio_str = strtok(NULL, ":");
+
+ if (prio_str && parse_integer(prio_str, &prio) != 0)
+ fatal("invalid IO scheduler priority");
+
+ io_sched = xmalloc(sizeof(*io_sched));
+ io_sched->policy_name = class_str;
+
+ if (strcmp(class_str, "real-time") == 0) {
+ io_sched->policy = IOPRIO_CLASS_RT;
+ io_sched->priority = prio;
+ } else if (strcmp(class_str, "best-effort") == 0) {
+ io_sched->policy = IOPRIO_CLASS_BE;
+ io_sched->priority = prio;
+ } else if (strcmp(class_str, "idle") == 0) {
+ io_sched->policy = IOPRIO_CLASS_IDLE;
+ io_sched->priority = 7;
+ } else
+ badusage("invalid IO scheduler policy");
+
+ if (io_sched->priority < IO_SCHED_PRIO_MIN)
+ badusage("IO scheduler priority less than min");
+ if (io_sched->priority > IO_SCHED_PRIO_MAX)
+ badusage("IO scheduler priority greater than max");
+}
+
+static void
set_proc_schedule(struct res_schedule *sched)
{
#ifdef _POSIX_PRIORITY_SCHEDULING
@@ -505,6 +568,26 @@ set_proc_schedule(struct res_schedule *sched)
#endif
}
+#ifdef HAVE_IOPRIO_SET
+static inline int
+ioprio_set(int which, int who, int ioprio)
+{
+ return syscall(SYS_ioprio_set, which, who, ioprio);
+}
+#endif
+
+static void
+set_io_schedule(struct res_schedule *sched)
+{
+#ifdef HAVE_IOPRIO_SET
+ int io_sched_mask;
+
+ io_sched_mask = IOPRIO_PRIO_VALUE(sched->policy, sched->priority);
+ if (ioprio_set(IOPRIO_WHO_PROCESS, getpid(), io_sched_mask) == -1)
+ fatal("Unable to alter IO priority to mask %i", io_sched_mask);
+#endif
+}
+
static void
parse_schedule_item(const char *string, struct schedule_item *item)
{
@@ -607,6 +690,7 @@ parse_options(int argc, char * const *argv)
{ "chuid", 1, NULL, 'c'},
{ "nicelevel", 1, NULL, 'N'},
{ "procsched", 1, NULL, 'P'},
+ { "iosched", 1, NULL, 'I'},
{ "umask", 1, NULL, 'k'},
{ "background", 0, NULL, 'b'},
{ "make-pidfile", 0, NULL, 'm'},
@@ -618,11 +702,12 @@ parse_options(int argc, char * const *argv)
const char *signal_str = NULL;
const char *schedule_str = NULL;
const char *proc_schedule_str = NULL;
+ const char *io_schedule_str = NULL;
int c;
for (;;) {
c = getopt_long(argc, argv,
- "HKSVa:n:op:qr:s:tu:vx:c:N:P:k:bmR:g:d:",
+ "HKSVa:n:op:qr:s:tu:vx:c:N:P:I:k:bmR:g:d:",
longopts, NULL);
if (c == -1)
break;
@@ -688,6 +773,9 @@ parse_options(int argc, char * const *argv)
case 'P': /* --procsched */
proc_schedule_str = optarg;
break;
+ case 'I': /* --iosched */
+ io_schedule_str = optarg;
+ break;
case 'k': /* --umask <mask> */
umask_str = optarg;
break;
@@ -721,6 +809,9 @@ parse_options(int argc, char * const *argv)
if (proc_schedule_str != NULL)
parse_proc_schedule(proc_schedule_str);
+ if (io_schedule_str != NULL)
+ parse_io_schedule(io_schedule_str);
+
if (umask_str != NULL) {
if (parse_umask(umask_str, &umask_value) != 0)
badusage("umask value must be a positive number");
@@ -1410,6 +1501,9 @@ main(int argc, char **argv)
if (proc_sched)
printf(", with scheduling policy %s with priority %i",
proc_sched->policy_name, proc_sched->priority);
+ if (io_sched)
+ printf(", with IO scheduling class %s with priority %i",
+ io_sched->policy_name, io_sched->priority);
printf(".\n");
}
if (testmode)
@@ -1433,6 +1527,8 @@ main(int argc, char **argv)
}
if (proc_sched)
set_proc_schedule(proc_sched);
+ if (io_sched)
+ set_io_schedule(io_sched);
if (umask_value >= 0)
umask(umask_value);
if (mpidfile && pidfile != NULL) {