On Wed, 2009-01-07 at 22:06 +0200, Guillem Jover wrote:
> 
> ===snip===
> 
> 
> As Colin already mentioned, glibc does not yet provide such wrappers
> (it's also stated in the man page).
> 
> This is also highly Linux specific, and even then the syscall will
> only be defined for recent kernels. All this should be made
> conditional, and in case it's not supported (old Linux, or non-Linux)
> it shuld be a no-op, so that programs can safely call it w/o worring
> that it will fail on systems not supporting this.
> 
> The other issue with this being highly Linux specific is that it's a
> bit difficult to predict how other systems might implement something
> similar and if it will fit with this interface. But I guess we'll just
> have to cope with that when it happens. :)

I have re-worked the patch slightly. I have now written it so that the
new code will only compile in on linux systems that support the
ioprio_set system call. The patch should not affect other systems and
older linux kernels that do not support this call. I don't know if this
is the right way to do it though.
> 
> ===snip===
> 
> Right, the naming is rather confusing. Another issue is that there's
> no argument validation. Also I think I'd prefer to have something
> like '-I <ioclass>[:<ioprio>]', with <ioclass> being a string. So you
> could do '-I idle' or '-I real-time:4' or similar.
> 
> thanks,
> guillem
I've re-written the patch to support changing the IO scheduler class and
priority, although not in the way that you would prefer (yet). The
interface is now basically the same as the interface to the ionice
utility (although in this case, you specify -C for scheduler class and
-P for priority, instead of -c and -n).

The patch has argument validation for scheduler class now. For priority,
there is no specific validation, but I've tested it and the system call
returns an error if you specify 0 < -P > 7, which is caught by
start-stop-daemon and results in an error message.

I'm not familiar with submitting patches to Debian as I've never done it
before, so I've prepared the patch in the same way as if I were
submitting it to Ubuntu. Please tell me if that's wrong ;)

Regards
Chris
diff -Nru dpkg-1.14.24/debian/changelog dpkg-1.14.25/debian/changelog
--- dpkg-1.14.24/debian/changelog	2008-12-29 04:38:33.000000000 +0000
+++ dpkg-1.14.25/debian/changelog	2009-01-07 19:54:53.000000000 +0000
@@ -1,3 +1,10 @@
+dpkg (1.14.25) unstable; urgency=low
+
+  * start-stop-daemon: Add support for changing a process's 
+    scheudling class and priority.
+
+ -- Chris Coulson <chrisccoul...@googlemail.com>  Wed, 07 Jan 2009 19:53:30 +0000
+
 dpkg (1.14.24) unstable; urgency=low
 
   [ Raphael Hertzog ]
diff -Nru dpkg-1.14.24/utils/start-stop-daemon.c dpkg-1.14.25/utils/start-stop-daemon.c
--- dpkg-1.14.24/utils/start-stop-daemon.c	2008-12-26 04:49:01.000000000 +0000
+++ dpkg-1.14.25/utils/start-stop-daemon.c	2009-01-08 13:55:06.000000000 +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,14 @@
 static const char *progname = "";
 static int nicelevel = 0;
 static int umask_value = -1;
+#ifdef SupportIOPrioSet
+static int ioprio = 4;
+static int ioprio_class = IOPRIO_CLASS_BE;
+static int set_ioprio = 0;
+static int ioprio_mask = 0;
+
+#define IOPRIO_CLASS_SHIFT	13
+#endif
 
 static struct stat exec_stat;
 #if defined(OSHURD)
@@ -168,7 +196,9 @@
 #if defined(OSLinux) || defined(OShpux)
 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 +338,10 @@
 "  -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
+"  -C|--ioschedclass <class>     set the process's IO scheduler class\n"
+"  -P|--ioschedprio <data>       set the process's IO scheduler 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 +554,10 @@
 		{ "exec",	  1, NULL, 'x'},
 		{ "chuid",	  1, NULL, 'c'},
 		{ "nicelevel",	  1, NULL, 'N'},
+#ifdef SupportIOPrioSet
+		{ "ioschedclass",	1, NULL, 'C'},
+		{ "ioschedprio",	1, NULL, 'P'},
+#endif
 		{ "umask",	  1, NULL, 'k'},
 		{ "background",	  0, NULL, 'b'},
 		{ "make-pidfile", 0, NULL, 'm'},
@@ -533,9 +571,15 @@
 	int c;
 
 	for (;;) {
+#ifdef SupportIOPrioSet
+		c = getopt_long(argc, argv,
+		                "HKSVa:n:op:qr:s:tu:vx:c:N:C:P:k:bmR:g:d:",
+		                longopts, NULL);
+#else
 		c = getopt_long(argc, argv,
 		                "HKSVa:n:op:qr:s:tu:vx:c:N:k:bmR:g:d:",
 		                longopts, NULL);
+#endif
 		if (c == -1)
 			break;
 		switch (c) {
@@ -597,6 +641,16 @@
 		case 'N':  /* --nice */
 			nicelevel = atoi(optarg);
 			break;
+#ifdef SupportIOPrioSet
+		case 'C':  /* --ioschedclass */
+			ioprio_class = atoi(optarg);
+			set_ioprio = 1;
+			break;
+		case 'P':  /* --ioschedprio */
+			ioprio = atoi(optarg);
+			set_ioprio = 1;			
+			break;
+#endif
 		case 'k':  /* --umask <mask> */
 			umask_str = optarg;
 			break;
@@ -1221,6 +1275,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 +1396,36 @@
 			fatal("Unable to alter nice level by %i: %s",
 			      nicelevel, strerror(errno));
 	}
+#ifdef SupportIOPrioSet
+	if (set_ioprio) {
+		switch (ioprio_class) {
+			case IOPRIO_CLASS_NONE:
+				/* Set to best-effort */
+				if (quietmode < 0)
+					printf("Ignoring user defined IO scheduler class. Setting to IOPRIO_CLASS_BE");
+				ioprio_class = IOPRIO_CLASS_BE;
+				break;
+			case IOPRIO_CLASS_RT:
+			case IOPRIO_CLASS_BE:
+				break;
+			case IOPRIO_CLASS_IDLE:
+				/* Ignore priority for the idle class */
+				if (quietmode < 0)
+					printf ("Ignoring any user defined IO scheduler priority. Setting to priority 7");
+				ioprio = 7;
+				break;
+			default:
+				fatal("Bad IO scheduler class: %i", ioprio_class);
+		}
+		ioprio_mask = ioprio | ioprio_class << IOPRIO_CLASS_SHIFT;
+		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