Allow ranges of CPUs in cpus_allowed option
For a larger number of CPUs, it's a bit of a bother having to set
each one individually. Plus, you typically want to bind to a range of
CPUs, to keep the job core local (or whatever your preference). So extend
cpus_allowed to take ranges of CPU numbers as well. Now you can do:
cpus_allowed=0-7
and have your job confined to CPUs 0 through 7.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/HOWTO b/HOWTO
index 5a55c1a..7bd71a9 100644
--- a/HOWTO
+++ b/HOWTO
@@ -590,7 +590,9 @@
 
 cpus_allowed=str Controls the same options as cpumask, but it allows a text
 		setting of the permitted CPUs instead. So to use CPUs 1 and
-		5, you would specify cpus_allowed=1,5.
+		5, you would specify cpus_allowed=1,5. This options also
+		allows a range of CPUs. Say you wanted a binding to CPUs
+		1, 5, and 8-15, you would set cpus_allowed=1,5,8-15.
 
 startdelay=time	Start this job the specified number of seconds after fio
 		has started. Only useful if the job file contains several
diff --git a/options.c b/options.c
index b890420..1953e3d 100644
--- a/options.c
+++ b/options.c
@@ -249,9 +249,12 @@
 
 	CPU_ZERO(&td->o.cpumask);
 
-	for (i = 0; i < sizeof(int) * 8; i++)
-		if ((1 << i) & *val)
+	for (i = 0; i < sizeof(int) * 8; i++) {
+		if ((1 << i) & *val) {
+			dprint(FD_PARSE, "set cpu allowed %d\n", i);
 			CPU_SET(*val, &td->o.cpumask);
+		}
+	}
 
 	td->o.cpumask_set = 1;
 	return 0;
@@ -270,9 +273,29 @@
 	strip_blank_end(str);
 
 	while ((cpu = strsep(&str, ",")) != NULL) {
+		char *str2, *cpu2;
+		int icpu, icpu2;
+
 		if (!strlen(cpu))
 			break;
-		CPU_SET(atoi(cpu), &td->o.cpumask);
+
+		str2 = cpu;
+		icpu2 = -1;
+		while ((cpu2 = strsep(&str2, "-")) != NULL) {
+			if (!strlen(cpu2))
+				break;
+
+			icpu2 = atoi(cpu2);
+		}
+
+		icpu = atoi(cpu);
+		if (icpu2 == -1)
+			icpu2 = icpu;
+		while (icpu <= icpu2) {
+			dprint(FD_PARSE, "set cpu allowed %d\n", icpu);
+			CPU_SET(atoi(cpu), &td->o.cpumask);
+			icpu++;
+		}
 	}
 
 	free(p);