From 0aabe160c38efc3c42157fac2a9af08e070341c6 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 23 Feb 2007 08:45:55 +0100 Subject: [PATCH 1/1] Add option to select how to service multiple files Right now we just round robin the open files, but sometimes you just want to randomly go through the files. Add a 'file_service' option for that, default to round robin still. Signed-off-by: Jens Axboe --- fio.h | 14 +++++++++++++- init.c | 32 +++++++++++++++++++++++++++++--- io_u.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/fio.h b/fio.h index 959e52f3..8c46b3f9 100644 --- a/fio.h +++ b/fio.h @@ -280,7 +280,10 @@ struct thread_data { struct fio_file *files; unsigned int nr_files; unsigned int nr_uniq_files; - unsigned int next_file; + union { + unsigned int next_file; + os_random_state_t next_file_state; + }; int error; pid_t pid; char *orig_buffer; @@ -340,6 +343,7 @@ struct thread_data { unsigned int rwmixread; unsigned int rwmixwrite; unsigned int nice; + unsigned int file_service_type; char *read_iolog_file; char *write_iolog_file; @@ -436,6 +440,14 @@ struct thread_data { struct itimerval timer; }; +/* + * roundrobin available files, or choose one at random. + */ +enum { + FIO_FSERVICE_RANDOM = 1, + FIO_FSERVICE_RR = 2, +}; + /* * 30 second per-io_u timeout, with 5 second intervals to avoid resetting * the timer on each queue operation. diff --git a/init.c b/init.c index c8f27ade..01e615f9 100644 --- a/init.c +++ b/init.c @@ -33,6 +33,7 @@ static int str_prioclass_cb(void *, unsigned int *); #endif static int str_exitall_cb(void); static int str_cpumask_cb(void *, unsigned int *); +static int str_file_service_cb(void *, const char *); #define __stringify_1(x) #x #define __stringify(x) __stringify_1(x) @@ -152,6 +153,14 @@ static struct fio_option options[] = { .help = "Split job workload between this number of files", .def = "1", }, + { + .name = "file_service_type", + .type = FIO_OPT_STR, + .cb = str_file_service_cb, + .help = "How to select which file to service next", + .def = "roundrobin", + .posval = { "random", "roundrobin" }, + }, { .name = "fsync", .type = FIO_OPT_INT, @@ -841,7 +850,7 @@ err: */ int init_random_state(struct thread_data *td) { - unsigned long seeds[4]; + unsigned long seeds[5]; int fd, num_maps, blocks, i; struct fio_file *f; @@ -865,12 +874,13 @@ int init_random_state(struct thread_data *td) os_random_seed(seeds[0], &td->bsrange_state); os_random_seed(seeds[1], &td->verify_state); os_random_seed(seeds[2], &td->rwmix_state); + os_random_seed(seeds[3], &td->next_file_state); if (td->sequential) return 0; if (td->rand_repeatable) - seeds[3] = FIO_RANDSEED * td->thread_number; + seeds[4] = FIO_RANDSEED * td->thread_number; if (!td->norandommap) { for_each_file(td, f, i) { @@ -882,7 +892,7 @@ int init_random_state(struct thread_data *td) } } - os_random_seed(seeds[3], &td->random_state); + os_random_seed(seeds[4], &td->random_state); return 0; } @@ -1087,6 +1097,22 @@ static int str_cpumask_cb(void *data, unsigned int *val) return 0; } +static int str_file_service_cb(void *data, const char *str) +{ + struct thread_data *td = data; + + if (!strncmp(str, "random", 6)) { + td->file_service_type = FIO_FSERVICE_RANDOM; + return 0; + } else if (!strncmp(str, "roundrobin", 10)) { + td->file_service_type = FIO_FSERVICE_RR; + return 0; + } + + log_err("fio: file_service= random, roundrobin\n"); + return 1; +} + /* * This is our [ini] type file parser. */ diff --git a/io_u.c b/io_u.c index ab85193d..6fb754e7 100644 --- a/io_u.c +++ b/io_u.c @@ -325,7 +325,27 @@ static void io_u_mark_latency(struct thread_data *td, unsigned long msec) td->io_u_lat[index]++; } -static struct fio_file *get_next_file(struct thread_data *td) +/* + * Get next file to service by choosing one at random + */ +static struct fio_file *get_next_file_rand(struct thread_data *td) +{ + long r = os_random_long(&td->next_file_state); + unsigned int fileno; + struct fio_file *f; + + do { + fileno = (unsigned int) ((double) (td->nr_files - 1) * r / (RAND_MAX + 1.0)); + f = &td->files[fileno]; + if (f->fd != -1) + return f; + } while (1); +} + +/* + * Get next file to service by doing round robin between all available ones + */ +static struct fio_file *get_next_file_rr(struct thread_data *td) { unsigned int old_next_file = td->next_file; struct fio_file *f; @@ -393,7 +413,11 @@ struct io_u *get_io_u(struct thread_data *td) if (io_u->file) goto out; - f = get_next_file(td); + if (td->file_service_type == FIO_FSERVICE_RR) + f = get_next_file_rr(td); + else + f = get_next_file_rand(td); + if (!f) { put_io_u(td, io_u); return NULL; -- 2.25.1