Hi, I have re-written the patch again now. It now accepts both IO scheduler class and IO scheduler data with a single flag, as you said you would prefer earlier (in the format "-I <class>:<data>"). Also, on non-Linux platforms or Linux systems that don't support ioprio_set, passing the '-I' flag will have no effect, as the new code won't be compiled in (it will just silently ignore it).
There is error-checking on the scheduler class string. To convert the scheduler data string in to an integer, I used strtol(), as that allows a certain level of error checking in the string to be converted, so it detects if you pass non-integer characters as the scheduler data (as opposed to just converting it to zero, as atoi() does, which is valid anyway). Let me know what you think. Regards Chris
=== modified file 'utils/start-stop-daemon.c' --- utils/start-stop-daemon.c 2009-01-13 17:28:50 +0000 +++ utils/start-stop-daemon.c 2009-01-13 22:01:36 +0000 @@ -103,6 +103,26 @@ #include <error.h> #endif +#include <sys/syscall.h> +#if defined(SYS_ioprio_set) && defined(linux) +# define SupportIOPrioSet +#endif + +#ifdef SupportIOPrioSet +enum { + IOPRIO_WHO_PROCESS = 1, + IOPRIO_WHO_PGRP, + IOPRIO_WHO_USER, +}; + +enum { + IOPRIO_CLASS_NONE, + IOPRIO_CLASS_RT, + IOPRIO_CLASS_BE, + IOPRIO_CLASS_IDLE, +}; +#endif + static int testmode = 0; static int quietmode = 0; static int exitnodo = 1; @@ -127,6 +147,18 @@ static const char *progname = ""; static int nicelevel = 0; static int umask_value = -1; +#ifdef SupportIOPrioSet +static int ioprio_mask = 0; +static char *ioprio_class_in = NULL; +static char *ioprio_data_in = NULL; +static int ioprio_class = IOPRIO_CLASS_BE; +static long int ioprio_data = 4; +static long int ioprio_data_temp = 0; +static char *temp = NULL; + +#define IOPRIO_CLASS_SHIFT 13 +#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) +#endif static struct stat exec_stat; #if defined(OSHURD) @@ -169,6 +201,9 @@ static int pid_is_exec(pid_t pid, const struct stat *esb); #endif +#ifdef SupportIOPrioSet +static inline int ioprio_set(int which, int who, int ioprio); +#endif static void fatal(const char *format, ...) NONRETURNING PRINTFFORMAT(1, 2); @@ -308,6 +343,9 @@ " -r|--chroot <directory> chroot to <directory> before starting\n" " -d|--chdir <directory> change to <directory> (default is /)\n" " -N|--nicelevel <incr> add incr to the process's nice level\n" +#ifdef SupportIOPrioSet +" -I|--ioprio <class>:<data> set the process's IO scheduler class and class data\n" +#endif " -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" @@ -520,6 +558,7 @@ { "exec", 1, NULL, 'x'}, { "chuid", 1, NULL, 'c'}, { "nicelevel", 1, NULL, 'N'}, + { "ioprio", 1, NULL, 'I'}, { "umask", 1, NULL, 'k'}, { "background", 0, NULL, 'b'}, { "make-pidfile", 0, NULL, 'm'}, @@ -533,9 +572,9 @@ int c; for (;;) { - c = getopt_long(argc, argv, - "HKSVa:n:op:qr:s:tu:vx:c:N:k:bmR:g:d:", - longopts, NULL); + c = getopt_long(argc, argv, + "HKSVa:n:op:qr:s:tu:vx:c:N:I:k:bmR:g:d:", + longopts, NULL); if (c == -1) break; switch (c) { @@ -597,6 +636,13 @@ case 'N': /* --nice */ nicelevel = atoi(optarg); break; + case 'I': /* --ioprio */ +#ifdef SupportIOPrioSet + ioprio_class_in = strdup(optarg); + ioprio_class_in = strtok(ioprio_class_in, ":"); + ioprio_data_in = strtok(NULL, ":"); +#endif + break; case 'k': /* --umask <mask> */ umask_str = optarg; break; @@ -1221,6 +1267,14 @@ } } +#ifdef SupportIOPrioSet +static inline int +ioprio_set (int which, int who, int ioprio) +{ + return syscall(SYS_ioprio_set, which, who, ioprio); +} +#endif + int main(int argc, char **argv) { @@ -1334,6 +1388,40 @@ fatal("Unable to alter nice level by %i: %s", nicelevel, strerror(errno)); } +#ifdef SupportIOPrioSet + if (ioprio_class_in != NULL) { + if (strcmp(ioprio_class_in, "real-time") == 0) { + ioprio_class = IOPRIO_CLASS_RT; + } else if (strcmp(ioprio_class_in, "best-effort") == 0) { + ioprio_class = IOPRIO_CLASS_BE; + } else if (strcmp(ioprio_class_in, "idle") == 0) { + ioprio_class = IOPRIO_CLASS_IDLE; + } else { + fatal("Unrecognized IO scheduler class %s", ioprio_class_in); + } + switch (ioprio_class) { + case (IOPRIO_CLASS_IDLE): + ioprio_data = 7; + break; + default: + if (ioprio_data_in != NULL) { + ioprio_data_temp = strtol(ioprio_data_in, &temp, 10); + if (ioprio_data_in != temp) { + ioprio_data = ioprio_data_temp; + } else { + fatal("Unrecognized IO scheduler class data %s", ioprio_data_in); + } + } + } + ioprio_mask = IOPRIO_PRIO_VALUE(ioprio_class, ioprio_data); + if (quietmode < 0) + printf("IO priority mask %i", ioprio_mask); + errno = 0; + if ((ioprio_set(IOPRIO_WHO_PROCESS, getpid(), ioprio_mask) == -1) && (errno != 0)) + fatal("Unable to alter IO priority to mask %i: %s", + ioprio_mask, strerror(errno)); + } +#endif if (umask_value >= 0) umask(umask_value); if (mpidfile && pidfile != NULL) {
signature.asc
Description: This is a digitally signed message part