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) {

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to