Hi, I've attached another revision of the patch. It behaves basically the same as before, but I've completely re-written the code in the style of the --procsched example you already did in git.
Sorry for the delay, I've been busy with a few other things. > Thanks for improving the patch. Could you also document the new option > in the man page? > Could you add a check in configure.ac for the 'sys/syscall.h' header > as it's not present in all systems? > > No camel case plase. :) These are all fixed now. > The less globals used the better, you should be able to use the new > 'struct res_schedule' to hold some of this data, the rest should be > moved to an inner scope. That is done now. I've used just a single global - the same as the code for --procsched I think. > Try to define the function early on so that we don't need a prototype > for a static function. Done. I've moved the function to earlier in the source file and got rid of the prototype. > This should not be conditional, we always want the help available. > Also this would cause problems in case we wanted to add i18n support > here later on. Also it should be less than 80 chars wide. This is not conditional in the new version, and I've truncated it and put it on 2 rows. > I think probably better name this 'iosched', in line with 'procsched'. Agreed, and fixed. > Here only save optarg, and do the parsing and validation later on in > this same function. And you can use now xstrdup. Done, in the same was as the parsing for --procsched. > Indent the case at the same level as the switch, and no need for the > parenthesis in the case. Fixed the indenting, bug I couldn't get it to compile without the parenthesis in the case. > You can use parse_integer instead. Fixed. And the error checking in parse_integer is better than the error checking I implemented when I used strtol anyway. > We want as much validation as possible to happen always, so that a > packager trying this on an unsupported system would get a meaningful > error then, instead of having to wait for someone to run it and get it > to fail on a supported system. Fixed. There is validation on both <class> and <data> now. > The values to be printed should be on the code dealing with --test. Fixed. > Better to move this part into its own function. Done. I created a new function "set_io_sched". Let me know if there are any problems. Thanks Chris
diff -Nurp dpkg/configure.ac dpkg.new/configure.ac --- dpkg/configure.ac 2009-01-23 19:43:17.000000000 +0000 +++ dpkg.new/configure.ac 2009-01-23 18:31:35.000000000 +0000 @@ -73,7 +73,7 @@ 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 sys/cdefs.h kvm.h sys/syscall.h]) DPKG_CHECK_DEFINE(TIOCNOTTY, [sys/ioctl.h]) # Checks for typedefs, structures, and compiler characteristics. diff -Nurp dpkg/man/start-stop-daemon.8 dpkg.new/man/start-stop-daemon.8 --- dpkg/man/start-stop-daemon.8 2009-01-23 19:43:19.000000000 +0000 +++ dpkg.new/man/start-stop-daemon.8 2009-01-23 21:21:47.000000000 +0000 @@ -219,6 +219,13 @@ code for them to do this themselves. .BR \-N ", " \-\-nicelevel " \fIint\fP" This alters the priority of the process before starting it. .TP +.BR \-I ", " \-\-iosched " \fIclass\fP\fB:\fP\fIdata\fP" +This alters the IO scheduler class and data of the process before starting +it. The data can be optionally specified by appending a \fB:\fP followed +by the value. The default \fIdata\fP is 4, unless \fIclass\fP is \fBidle\fP, +when \fIdata\fP will always be 7. The currently supported values for +\fIclass\fP are \fBidle\fP, \fBbest-effort\fP and \fBreal-time\fP. +.TP .BR \-P ", " \-\-procsched " \fIpolicy\fP\fB:\fP\fIpriority\fP" This alters the process scheduler policy and priority of the process before starting it. The priority can be optionally specified by appending a \fB:\fP diff -Nurp dpkg/utils/start-stop-daemon.c dpkg.new/utils/start-stop-daemon.c --- dpkg/utils/start-stop-daemon.c 2009-01-23 19:43:20.000000000 +0000 +++ dpkg.new/utils/start-stop-daemon.c 2009-01-23 21:28:19.000000000 +0000 @@ -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 SUPPORT_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, data) (((class) << IOPRIO_CLASS_SHIFT) | data) +#define IO_SCHED_DATA_MIN 0 +#define IO_SCHED_DATA_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; @@ -336,6 +363,9 @@ do_help(void) " -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" +" -I|--iosched <class>:<data>\n" +" use <class> with <data> to set the IO\n" +" scheduler (default data is 4)\n" " -P|--procsched <policy[:prio]>\n" " use <policy> with <prio> for the kernel\n" " process scheduler (default prio is 0)\n" @@ -493,6 +523,58 @@ parse_proc_schedule(const char *string) } static void +parse_iosched(const char *string) +{ + char *class_str, *data_str; + int data = 0; + + class_str = xstrdup(string); + class_str = strtok(class_str, ":"); + data_str = strtok(NULL, ":"); + + if (data_str && parse_integer(data_str, &data) != 0) + fatal("Invalid IO scheduler data string"); + + 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; + } else if (strcmp(class_str, "best-effort") == 0) { + io_sched->policy = IOPRIO_CLASS_BE; + } else if (strcmp(class_str, "idle") == 0) { + io_sched->policy = IOPRIO_CLASS_IDLE; + } else { + badusage("Unrecognized IO scheduler class"); + } + + switch (io_sched->policy) { + case (IOPRIO_CLASS_IDLE): + io_sched->priority = 7; + break; + default: + if (data_str != NULL) { + io_sched->priority = data; + } else { + io_sched->priority = 4; + } + } + + if (io_sched->priority < IO_SCHED_DATA_MIN) + badusage("IO scheduler data less than min"); + if (io_sched->priority > IO_SCHED_DATA_MAX) + badusage("IO scheduler data greater than max"); +} + +#ifdef SUPPORT_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_proc_schedule(struct res_schedule *sched) { #ifdef _POSIX_PRIORITY_SCHEDULING @@ -506,6 +588,19 @@ set_proc_schedule(struct res_schedule *s } static void +set_io_sched(struct res_schedule *sched) +{ +#ifdef SUPPORT_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) { const char *after_hyph; @@ -606,6 +701,7 @@ parse_options(int argc, char * const *ar { "exec", 1, NULL, 'x'}, { "chuid", 1, NULL, 'c'}, { "nicelevel", 1, NULL, 'N'}, + { "iosched", 1, NULL, 'I'}, { "procsched", 1, NULL, 'P'}, { "umask", 1, NULL, 'k'}, { "background", 0, NULL, 'b'}, @@ -618,11 +714,12 @@ parse_options(int argc, char * const *ar const char *signal_str = NULL; const char *schedule_str = NULL; const char *proc_schedule_str = NULL; + const char *io_sched_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:I:P:k:bmR:g:d:", longopts, NULL); if (c == -1) break; @@ -685,6 +782,9 @@ parse_options(int argc, char * const *ar case 'N': /* --nice */ nicelevel = atoi(optarg); break; + case 'I': /* --iosched */ + io_sched_str = optarg; + break; case 'P': /* --procsched */ proc_schedule_str = optarg; break; @@ -720,6 +820,9 @@ parse_options(int argc, char * const *ar if (proc_schedule_str != NULL) parse_proc_schedule(proc_schedule_str); + + if (io_sched_str != NULL) + parse_iosched(io_sched_str); if (umask_str != NULL) { if (parse_umask(umask_str, &umask_value) != 0) @@ -1410,6 +1513,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(", and with IO scheduling class %s and data %i", + io_sched->policy_name, io_sched->priority); printf(".\n"); } if (testmode) @@ -1431,6 +1537,8 @@ main(int argc, char **argv) fatal("Unable to alter nice level by %i: %s", nicelevel, strerror(errno)); } + if (io_sched) + set_io_sched(io_sched); if (proc_sched) set_proc_schedule(proc_sched); if (umask_value >= 0)
signature.asc
Description: This is a digitally signed message part