[PATCH] fio: Add option for setting cpu affinity mask
authorJens Axboe <axboe@suse.de>
Wed, 19 Oct 2005 08:16:21 +0000 (10:16 +0200)
committerJens Axboe <axboe@suse.de>
Wed, 19 Oct 2005 08:16:21 +0000 (10:16 +0200)
README.fio
fio.c

index 1bd93afb0c3bd01e58921fe8357da8be8e6184b4..8430f0c1325f94b32e49d97845b563112732bb99 100644 (file)
@@ -32,6 +32,7 @@ The <jobs> format is as follows:
        random          IO is randomized
        sequential      IO is sequential
        rate=x          Throttle rate to x KiB/sec
+       cpumask=x       Allow job to run on CPUs defined by mask
 
 
 Examples using cmd line jobs
diff --git a/fio.c b/fio.c
index 685c64a262ad6491c60bc3401994afe143f92350..b9c12e7442e52182b2bc689c7090d97f6a51faff 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -27,6 +27,7 @@
 #include <signal.h>
 #include <time.h>
 #include <ctype.h>
+#include <sched.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -96,6 +97,8 @@ static char *ini_file;
 
 static int shm_id;
 
+static cpu_set_t def_cpumask;
+
 #define DDIR_READ      (0)
 #define DDIR_WRITE     (1)
 
@@ -113,6 +116,7 @@ struct thread_data {
        int bs;
        int odirect;
        int delay_sleep;
+       cpu_set_t cpumask;
 
        unsigned int rate;
        unsigned int rate_usec_cycle;
@@ -416,6 +420,13 @@ void *thread_main(int shm_id, int offset, char *argv[])
        td = data + offset * sizeof(struct thread_data);
        td->pid = getpid();
 
+       td->fd = -1;
+
+       if (sched_setaffinity(td->pid, sizeof(td->cpumask), &td->cpumask) == -1) {
+               td->error = errno;
+               goto err;
+       }
+
        printf("Thread (%s) (pid=%u) (f=%s) started\n", td->ddir == DDIR_READ ? "read" : "write", td->pid, td->file_name);
        fflush(stdout);
 
@@ -468,11 +479,12 @@ void *thread_main(int shm_id, int offset, char *argv[])
        ret = 0;
 
 out:
-       close(td->fd);
        if (statbuf)
                free(statbuf);
        shutdown_stat_file(td);
 err:
+       if (td->fd != -1)
+               close(td->fd);
        sem_post(&td->done_mutex);
        if (ret)
                sem_post(&startup_sem);
@@ -513,7 +525,7 @@ void setup_rate(struct thread_data *td, int rate)
        td->rate_pending_usleep = 0;
 }
 
-void add_job(const char *filename, int rw, int bs, int direct, int prio, int random, int delay, int rate)
+void add_job(const char *filename, int rw, int bs, int direct, int prio, int random, int delay, int rate, cpu_set_t cpumask)
 {
        struct thread_data *td = &threads[thread_number++];
 
@@ -529,6 +541,7 @@ void add_job(const char *filename, int rw, int bs, int direct, int prio, int ran
        td->odirect = direct;
        td->bs = bs;
        td->delay_sleep = delay;
+       td->cpumask = cpumask;
 
        if (rate)
                setup_rate(td, rate);
@@ -536,6 +549,18 @@ void add_job(const char *filename, int rw, int bs, int direct, int prio, int ran
        printf("Client%d: file=%s, rw=%d, prio=%d, seq=%d, odir=%d, bs=%d, rate=%d\n", thread_number, filename, rw, prio, !random, direct, bs, rate);
 }
 
+static void fill_cpu_mask(cpu_set_t cpumask, int cpu)
+{
+       int i;
+
+       CPU_ZERO(&cpumask);
+
+       for (i = 0; i < sizeof(int) * 8; i++) {
+               if ((1 << i) & cpu)
+                       CPU_SET(i, &cpumask);
+       }
+}
+
 void fill_option(const char *input, char *output)
 {
        int i;
@@ -559,8 +584,9 @@ void fill_option(const char *input, char *output)
  */
 int parse_jobs_cmd(int argc, char *argv[], int index)
 {
-       int rw, bs, direct, prio, random, prioclass, delay, rate;
+       int rw, bs, direct, prio, random, prioclass, delay, rate, cpu;
        char *string, *filename, *p, *c;
+       cpu_set_t cpumask;
        int i;
 
        string = malloc(256);
@@ -582,6 +608,7 @@ int parse_jobs_cmd(int argc, char *argv[], int index)
                prioclass = 2;
                delay = 0;
                rate = 0;
+               memcpy(&cpumask, &def_cpumask, sizeof(cpumask));
 
                c = strstr(p, "rw=");
                if (c) {
@@ -641,6 +668,15 @@ int parse_jobs_cmd(int argc, char *argv[], int index)
                        rate = strtoul(string, NULL, 10);
                }
 
+               c = strstr(p, "cpumask=");
+               if (c) {
+                       c += 8;
+                       fill_option(c, string);
+                       cpu = strtoul(string, NULL, 10);
+                       fill_cpu_mask(cpumask, cpu);
+               }
+
+
                c = strstr(p, "random");
                if (c)
                        random = 1;
@@ -648,7 +684,7 @@ int parse_jobs_cmd(int argc, char *argv[], int index)
                if (c)
                        random = 0;
 
-               add_job(filename, rw, bs, direct, (prioclass << IOPRIO_CLASS_SHIFT) | prio, random, delay, rate);
+               add_job(filename, rw, bs, direct, (prioclass << IOPRIO_CLASS_SHIFT) | prio, random, delay, rate, cpumask);
        }
 
        free(string);
@@ -684,7 +720,8 @@ int is_empty(char *line)
 
 int parse_jobs_ini(char *file)
 {
-       int rw, bs, direct, prio, random, prioclass, delay, rate, jobs;
+       int rw, bs, direct, prio, random, prioclass, delay, rate, jobs, cpu;
+       cpu_set_t cpumask;
        char *string, *name;
        fpos_t off;
        FILE *f;
@@ -715,6 +752,8 @@ int parse_jobs_ini(char *file)
                prioclass = 2;
                delay = 0;
                rate = 0;
+               memcpy(&cpumask, &def_cpumask, sizeof(cpumask));
+               cpu = 0;
 
                fgetpos(f, &off);
                while ((p = fgets(string, 4096, f)) != NULL) {
@@ -749,6 +788,11 @@ int parse_jobs_ini(char *file)
                                fgetpos(f, &off);
                                continue;
                        }
+                       if (!check_int(p, "cpumask", &cpu)) {
+                               fill_cpu_mask(cpumask, cpu);
+                               fgetpos(f, &off);
+                               continue;
+                       }
                        if (!strcmp(p, "sequential")) {
                                sequential = 1;
                                fgetpos(f, &off);
@@ -762,7 +806,7 @@ int parse_jobs_ini(char *file)
                }
                fsetpos(f, &off);
 
-               add_job(name, rw, bs, direct, (prioclass << IOPRIO_CLASS_SHIFT) | prio, random, delay, rate);
+               add_job(name, rw, bs, direct, (prioclass << IOPRIO_CLASS_SHIFT) | prio, random, delay, rate, cpumask);
                jobs++;
        }
 
@@ -831,6 +875,11 @@ int main(int argc, char *argv[])
        static unsigned long read_mb, write_mb, read_agg, write_agg;
        int i, jobs;
 
+       if (sched_getaffinity(getpid(), sizeof(def_cpumask), &def_cpumask) == -1) {
+               perror("sched_getaffinity");
+               return 1;
+       }
+
        shm_id = shmget(0, (argc - 1) * sizeof(struct thread_data), IPC_CREAT | 0600);
        if (shm_id == -1) {
                perror("shmget");