From da86774e5a002acf2c8d779b805305bc193fc0a5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 6 Jun 2006 10:39:10 -0700 Subject: [PATCH 1/1] [PATCH] Add ioscheduler=x option to allow setting io scheduler --- README | 1 + fio-ini.c | 10 ++++++++++ fio.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fio.h | 4 ++++ 4 files changed, 71 insertions(+) diff --git a/README b/README index aec8207c..24bf5a00 100644 --- a/README +++ b/README @@ -113,6 +113,7 @@ The 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. + ioscheduler=x Use ioscheduler 'x' for this job. Examples using a job file ------------------------- diff --git a/fio-ini.c b/fio-ini.c index 0c874085..d2122e3f 100644 --- 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; } +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; @@ -927,6 +933,10 @@ int parse_jobs_ini(char *file) 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; diff --git a/fio.c b/fio.c index 79c11d5c..bd938979 100644 --- a/fio.c +++ b/fio.c @@ -1787,9 +1787,58 @@ static void init_disk_util(struct thread_data *td) sprintf(foo, "%s", p); } + td->sysfs_root = strdup(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; @@ -1869,6 +1918,9 @@ static void *thread_main(void *data) 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); @@ -1946,6 +1998,10 @@ err: 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); diff --git a/fio.h b/fio.h index d765ac6e..76a114f2 100644 --- a/fio.h +++ b/fio.h @@ -161,6 +161,10 @@ struct thread_data { void *iolog_buf; FILE *iolog_f; + char *sysfs_root; + + char *ioscheduler; + struct drand48_data bsrange_state; struct drand48_data verify_state; -- 2.25.1