From: Jens Axboe Date: Fri, 23 Feb 2007 07:45:55 +0000 (+0100) Subject: Add option to select how to service multiple files X-Git-Tag: fio-1.12~21 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=0aabe160c38efc3c42157fac2a9af08e070341c6;hp=5945b9b45474a9a717a3db2310822aa5064fb38b 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 --- 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;