[PATCH] Add ioscheduler=x option to allow setting io scheduler
authorJens Axboe <axboe@suse.de>
Tue, 6 Jun 2006 17:39:10 +0000 (10:39 -0700)
committerJens Axboe <axboe@suse.de>
Tue, 6 Jun 2006 17:39:10 +0000 (10:39 -0700)
README
fio-ini.c
fio.c
fio.h

diff --git a/README b/README
index aec8207ce27c980e70ebbdb49abffc4af7e0a9f1..24bf5a007a6c6c37537ab94d1fd8ab3ea4b21b8d 100644 (file)
--- a/README
+++ b/README
@@ -113,6 +113,7 @@ The <jobs> format is as follows:
        nice=x          Run job at given nice value.
        exec_prerun=x   Run 'x' before job io is begun.
        exec_postrun=x  Run 'x' after job io has finished.
        nice=x          Run job at given nice value.
        exec_prerun=x   Run 'x' before job io is begun.
        exec_postrun=x  Run 'x' after job io has finished.
+       ioscheduler=x   Use ioscheduler 'x' for this job.
 
 Examples using a job file
 -------------------------
 
 Examples using a job file
 -------------------------
index 0c874085f466002c5893c994914ead475d412f4a..d2122e3fd3c7f17361b0f1d7ced0dab4fcabc510 100644 (file)
--- a/fio-ini.c
+++ b/fio-ini.c
@@ -664,6 +664,12 @@ static int str_postrun_cb(struct thread_data *td, char *file)
        return 0;
 }
 
        return 0;
 }
 
+static int str_iosched_cb(struct thread_data *td, char *file)
+{
+       td->ioscheduler = strdup(file);
+       return 0;
+}
+
 int parse_jobs_ini(char *file)
 {
        unsigned int prioclass, prio, cpu, global, il;
 int parse_jobs_ini(char *file)
 {
        unsigned int prioclass, prio, cpu, global, il;
@@ -927,6 +933,10 @@ int parse_jobs_ini(char *file)
                                fgetpos(f, &off);
                                continue;
                        }
                                fgetpos(f, &off);
                                continue;
                        }
+                       if (!check_str(p, "ioscheduler", str_iosched_cb, td)) {
+                               fgetpos(f, &off);
+                               continue;
+                       }
 
                        printf("Client%d: bad option %s\n",td->thread_number,p);
                        return 1;
 
                        printf("Client%d: bad option %s\n",td->thread_number,p);
                        return 1;
diff --git a/fio.c b/fio.c
index 79c11d5cdcee503d879c510e8e57036df421d895..bd938979f61caa3f59152d50c4eee03b24b84c53 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -1787,9 +1787,58 @@ static void init_disk_util(struct thread_data *td)
                sprintf(foo, "%s", p);
        }
 
                sprintf(foo, "%s", p);
        }
 
+       td->sysfs_root = strdup(foo);
        disk_util_add(dev, foo);
 }
 
        disk_util_add(dev, foo);
 }
 
+static int switch_ioscheduler(struct thread_data *td)
+{
+       char tmp[256], tmp2[128];
+       FILE *f;
+       int ret;
+
+       sprintf(tmp, "%s/queue/scheduler", td->sysfs_root);
+
+       f = fopen(tmp, "r+");
+       if (!f) {
+               td_verror(td, errno);
+               return 1;
+       }
+
+       /*
+        * Set io scheduler.
+        */
+       ret = fwrite(td->ioscheduler, strlen(td->ioscheduler), 1, f);
+       if (ferror(f) || ret != 1) {
+               td_verror(td, errno);
+               fclose(f);
+               return 1;
+       }
+
+       rewind(f);
+
+       /*
+        * Read back and check that the selected scheduler is now the default.
+        */
+       ret = fread(tmp, 1, sizeof(tmp), f);
+       if (ferror(f) || ret < 0) {
+               td_verror(td, errno);
+               fclose(f);
+               return 1;
+       }
+
+       sprintf(tmp2, "[%s]", td->ioscheduler);
+       if (!strstr(tmp, tmp2)) {
+               fprintf(stderr, "fio: io scheduler %s not found\n", td->ioscheduler);
+               td_verror(td, EINVAL);
+               fclose(f);
+               return 1;
+       }
+
+       fclose(f);
+       return 0;
+}
+
 static void disk_util_timer_arm(void)
 {
        itimer.it_value.tv_sec = 0;
 static void disk_util_timer_arm(void)
 {
        itimer.it_value.tv_sec = 0;
@@ -1869,6 +1918,9 @@ static void *thread_main(void *data)
        if (init_random_state(td))
                goto err;
 
        if (init_random_state(td))
                goto err;
 
+       if (td->ioscheduler && switch_ioscheduler(td))
+               goto err;
+
        td_set_runstate(td, TD_INITIALIZED);
        sem_post(&startup_sem);
        sem_wait(&td->mutex);
        td_set_runstate(td, TD_INITIALIZED);
        sem_post(&startup_sem);
        sem_wait(&td->mutex);
@@ -1946,6 +1998,10 @@ err:
                free(td->exec_prerun);
        if (td->exec_postrun)
                free(td->exec_postrun);
                free(td->exec_prerun);
        if (td->exec_postrun)
                free(td->exec_postrun);
+       if (td->ioscheduler)
+               free(td->ioscheduler);
+       if (td->sysfs_root)
+               free(td->sysfs_root);
        cleanup_io(td);
        cleanup_io_u(td);
        td_set_runstate(td, TD_EXITED);
        cleanup_io(td);
        cleanup_io_u(td);
        td_set_runstate(td, TD_EXITED);
diff --git a/fio.h b/fio.h
index d765ac6e2ebda32595940375ee8767a39322d65f..76a114f288c4434c7ceccc4d01d84870115d5f8b 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -161,6 +161,10 @@ struct thread_data {
        void *iolog_buf;
        FILE *iolog_f;
 
        void *iolog_buf;
        FILE *iolog_f;
 
+       char *sysfs_root;
+
+       char *ioscheduler;
+
        struct drand48_data bsrange_state;
        struct drand48_data verify_state;
 
        struct drand48_data bsrange_state;
        struct drand48_data verify_state;