The following commit has been merged in the master branch:
commit b0569c7d4d744e3902ab606284411dd304ceafc6
Author: Chris Coulson <chrisccoul...@googlemail.com>
Date:   Thu Feb 26 09:06:15 2009 +0200

    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 <guil...@debian.org>

diff --git a/ChangeLog b/ChangeLog
index 955fa43..49e0bb7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2009-02-26  Chris Coulson  <chrisccoul...@googlemail.com>,
+            Guillem Jover  <guil...@debian.org>
+
+       * configure.ac (AC_CHECK_HEADERS): Add 'sys/syscall.h'.
+       * man/start-stop-daemon.8: Document new option --iosched.
+       * utils/start-stop-daemon.c [HAVE_SYS_SYSCALL_H]: Include
+       <sys/syscall.h>.
+       (HAVE_IOPRIO_SET) [SYS_ioprio_set, linux]: New macro.
+       (IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT): New anonymous enum.
+       (IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE): Likewise.
+       (IOPRIO_WHO_PROCESS, IOPRIO_WHO_PGRP, IOPRIO_WHO_USER): Likewise.
+       (IOPRIO_CLASS_SHIFT, IOPRIO_PRIO_VALUE, IO_SCHED_PRIO_MIN)
+       (IO_SCHED_PRIO_MAX): New macros.
+       (io_sched): New variable.
+       (do_help): Document --iosched.
+       (ioprio_set) [HAVE_IOPRIO_SET]: New function.
+       (parse_io_schedule, set_io_schedule): Likewise.
+       (parse_options): Add 'iosched' to longopts. Add 'I:' to getopt_long
+       call. Handle 'I' as getopt_long return value. Call parse_io_schedule
+       if io_schedule_str is not NULL.
+       (main): Print io_sched values if --test is used. Call set_io_schedule
+       if io_sched is not NULL.
+
 2009-02-26  Romain Francoise <rfranco...@debian.org>,
             Guillem Jover  <guil...@debian.org>
 
diff --git a/configure.ac b/configure.ac
index 53694ca..3d3b607 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,7 +73,8 @@ fi
 
 # Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS([stddef.h error.h locale.h libintl.h sys/cdefs.h kvm.h])
+AC_CHECK_HEADERS([stddef.h error.h locale.h libintl.h kvm.h \
+                  sys/cdefs.h sys/syscall.h])
 DPKG_CHECK_DEFINE(TIOCNOTTY, [sys/ioctl.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
diff --git a/debian/changelog b/debian/changelog
index 4d76100..67128bd 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -62,6 +62,9 @@ dpkg (1.15.0) UNRELEASED; urgency=low
   * Print correct feature name on «dpkg --assert-*» failures.
   * Add progress reporting to dpkg while reading the file list database.
     Based on a patch by Romain Francoise.
+  * Add new option --iosched to start-stop-daemon to be able to set the
+    IO scheduling class and priority. Closes: #443535
+    Thanks to Chris Coulson <chrisccoul...@googlemail.com>.
 
   [ Raphael Hertzog ]
   * Enhance dpkg-shlibdeps's error message when a library can't be found to
diff --git a/man/start-stop-daemon.8 b/man/start-stop-daemon.8
index 26996b9..1e6c00f 100644
--- a/man/start-stop-daemon.8
+++ b/man/start-stop-daemon.8
@@ -225,6 +225,13 @@ starting it. The priority can be optionally specified by 
appending a \fB:\fP
 followed by the value. The default \fIpriority\fP is 0. The currently
 supported policy values are \fBother\fP, \fBfifo\fP and \fBrr\fP.
 .TP
+.BR \-I ", " \-\-iosched " \fIclass\fP\fB:\fP\fIpriority\fP"
+This alters the IO scheduler class and priority of the process before starting
+it. The priority can be optionally specified by appending a \fB:\fP followed
+by the value. The default \fIpriority\fP is 4, unless \fIclass\fP is 
\fBidle\fP,
+then \fIpriority\fP will always be 7. The currently supported values for
+\fIclass\fP are \fBidle\fP, \fBbest-effort\fP and \fBreal-time\fP.
+.TP
 .BR \-k ", " \-\-umask " \fImask\fP"
 This sets the umask of the process before starting it.
 .TP
diff --git a/utils/start-stop-daemon.c b/utils/start-stop-daemon.c
index 8171dc3..34ee022 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) {

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to debian-dpkg-cvs-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to