From dc3ccd8101f81803c7a46d4e239911f7d97bed1b Mon Sep 17 00:00:00 2001
From: Roy Marples <roy@marples.name>
Date: Mon, 14 Dec 2009 08:47:48 +0000
Subject: start-stop-daemon can now set process IO scheduling.

---
 src/rc/start-stop-daemon.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

(limited to 'src/rc')

diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c
index 9f7af9b8..bd6c7bfe 100644
--- a/src/rc/start-stop-daemon.c
+++ b/src/rc/start-stop-daemon.c
@@ -47,6 +47,10 @@
 #include <sys/time.h>
 #include <sys/wait.h>
 
+#ifdef __linux__
+#include <sys/syscall.h> /* For io priority */
+#endif
+
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -104,6 +108,13 @@ static char *changeuser, *ch_root, *ch_dir;
 
 extern char **environ;
 
+#ifdef __linux__
+static inline int ioprio_set(int which, int who, int ioprio)
+{
+	return syscall(SYS_ioprio_set, which, who, ioprio);
+}
+#endif
+
 static void
 free_schedulelist(void)
 {
@@ -589,8 +600,9 @@ expand_home(const char *home, const char *path)
 }
 
 #include "_usage.h"
-#define getoptstring "KN:PR:Sbc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" getoptstring_COMMON
+#define getoptstring "I:KN:PR:Sbc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" getoptstring_COMMON
 static const struct option longopts[] = {
+	{ "ionice",       1, NULL, 'I'},
 	{ "stop",         0, NULL, 'K'},
 	{ "nicelevel",    1, NULL, 'N'},
 	{ "retry",        1, NULL, 'R'},
@@ -619,6 +631,7 @@ static const struct option longopts[] = {
 	longopts_COMMON
 };
 static const char * const longopts_help[] = {
+	"Set an ionice class:data when starting", 
 	"Stop daemon",
 	"Set a nicelevel when starting",
 	"Retry schedule to use when stopping",
@@ -675,7 +688,7 @@ start_stop_daemon(int argc, char **argv)
 	char *pidfile = NULL;
 	char *retry = NULL;
 	int sig = -1;
-	int nicelevel = 0;
+	int nicelevel = 0, ionicec = -1, ioniced = 0;
 	bool background = false;
 	bool makepidfile = false;
 	bool interpreted = false;
@@ -738,6 +751,17 @@ start_stop_daemon(int argc, char **argv)
 	while ((opt = getopt_long(argc, argv, getoptstring, longopts,
 		    (int *) 0)) != -1)
 		switch (opt) {
+		case 'I': /* --ionice */
+			if (sscanf(optarg, "%d:%d", &ionicec, &ioniced) == 0)
+				eerrorx("%s: invalid ionice `%s'",
+				    applet, optarg);
+			if (ionicec == 0)
+				ioniced = 0;
+			else if (ionicec == 3)
+				ioniced = 7;
+			ionicec <<= 13; /* class shift */
+			break;
+
 		case 'K':  /* --stop */
 			stop = true;
 			break;
@@ -1121,6 +1145,14 @@ start_stop_daemon(int argc, char **argv)
 				    strerror(errno));
 		}
 
+/* Only linux suports setting an IO priority */
+#ifdef __linux__
+		if (ionicec != -1 &&
+		    ioprio_set(1, mypid, ionicec | ioniced) == -1)
+			eerrorx("%s: ioprio_set %d %d: %s", applet,
+			    ionicec, ioniced, strerror(errno));
+#endif
+
 		if (ch_root && chroot(ch_root) < 0)
 			eerrorx("%s: chroot `%s': %s",
 			    applet, ch_root, strerror(errno));
-- 
cgit v1.2.3