From d0e7a15270f20954a5b00bd7401ab3cc0ae584c6 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Fri, 23 Aug 2024 10:35:29 +0200 Subject: [PATCH] fio: non-repeating file_service_type roundrobin1 and random1 These servicing modes does not repeat file until completion previous operation. Streaming IO-engines might not handle several requests to one "file" at once. Or such workload might not match any real scenarios. Signed-off-by: Konstantin Khlebnikov --- file.h | 5 +++++ fio.h | 1 + init.c | 3 ++- io_u.c | 23 ++++++++++++++++++++--- options.c | 10 ++++++++++ 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/file.h b/file.h index e38ed2f123..0974e9749c 100644 --- a/file.h +++ b/file.h @@ -35,6 +35,7 @@ enum fio_file_flags { FIO_FILE_axmap = 1 << 7, /* uses axmap */ FIO_FILE_lfsr = 1 << 8, /* lfsr is used */ FIO_FILE_smalloc = 1 << 9, /* smalloc file/file_name */ + FIO_FILE_busy = 1 << 10, /* out of service */ }; enum file_lock_mode { @@ -53,6 +54,9 @@ enum { FIO_FSERVICE_RR = 2, FIO_FSERVICE_SEQ = 3, __FIO_FSERVICE_NONUNIFORM = 0x100, + __FIO_FSERVICE_NONREPEAT = 0x200, + FIO_FSERVICE_RANDOM1 = __FIO_FSERVICE_NONREPEAT | FIO_FSERVICE_RANDOM, + FIO_FSERVICE_RR1 = __FIO_FSERVICE_NONREPEAT | FIO_FSERVICE_RR, FIO_FSERVICE_ZIPF = __FIO_FSERVICE_NONUNIFORM | 4, FIO_FSERVICE_PARETO = __FIO_FSERVICE_NONUNIFORM | 5, FIO_FSERVICE_GAUSS = __FIO_FSERVICE_NONUNIFORM | 6, @@ -196,6 +200,7 @@ FILE_FLAG_FNS(partial_mmap); FILE_FLAG_FNS(axmap); FILE_FLAG_FNS(lfsr); FILE_FLAG_FNS(smalloc); +FILE_FLAG_FNS(busy); #undef FILE_FLAG_FNS /* diff --git a/fio.h b/fio.h index 4bb6cfa7f3..5b66c171d1 100644 --- a/fio.h +++ b/fio.h @@ -235,6 +235,7 @@ struct thread_data { unsigned int files_index; unsigned int nr_open_files; unsigned int nr_done_files; + unsigned int nr_busy_files; union { unsigned int next_file; struct frand_state next_file_state; diff --git a/init.c b/init.c index ff3e9a90d5..2d5db55d15 100644 --- a/init.c +++ b/init.c @@ -1077,7 +1077,8 @@ void td_fill_rand_seeds(struct thread_data *td) use64); init_rand_seed(&td->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF], false); - if (td->o.file_service_type == FIO_FSERVICE_RANDOM) + if (td->o.file_service_type == FIO_FSERVICE_RANDOM || + td->o.file_service_type == FIO_FSERVICE_RANDOM1) init_rand_seed(&td->next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF], use64); else if (td->o.file_service_type & __FIO_FSERVICE_NONUNIFORM) init_rand_file_service(td); diff --git a/io_u.c b/io_u.c index 40b0908237..a1968a4d66 100644 --- a/io_u.c +++ b/io_u.c @@ -852,6 +852,11 @@ void put_io_u(struct thread_data *td, struct io_u *io_u) if (needs_lock) __td_io_u_lock(td); + if (io_u->file && (td->o.file_service_type & __FIO_FSERVICE_NONREPEAT)) { + fio_file_clear_busy(io_u->file); + td->nr_busy_files--; + } + if (io_u->file && !(io_u->flags & IO_U_F_NO_FILE_PUT)) put_file_log(td, io_u->file); @@ -1308,7 +1313,8 @@ static unsigned int __get_next_fileno_rand(struct thread_data *td) { unsigned long fileno; - if (td->o.file_service_type == FIO_FSERVICE_RANDOM) { + if (td->o.file_service_type == FIO_FSERVICE_RANDOM || + td->o.file_service_type == FIO_FSERVICE_RANDOM1) { uint64_t frand_max = rand_max(&td->next_file_state); unsigned long r; @@ -1348,8 +1354,11 @@ static struct fio_file *get_next_file_rand(struct thread_data *td, fno = __get_next_fileno_rand(td); f = td->files[fno]; - if (fio_file_done(f)) + if (fio_file_done(f) || fio_file_busy(f)) { + if (td->nr_busy_files >= td->nr_open_files) + return ERR_PTR(-EBUSY); continue; + } if (!fio_file_open(f)) { int err; @@ -1391,7 +1400,9 @@ static struct fio_file *get_next_file_rr(struct thread_data *td, int goodf, td->next_file = 0; dprint(FD_FILE, "trying file %s %x\n", f->file_name, f->flags); - if (fio_file_done(f)) { + if (fio_file_done(f) || fio_file_busy(f)) { + if (td->nr_busy_files >= td->nr_open_files) + return ERR_PTR(-EBUSY); f = NULL; continue; } @@ -1452,6 +1463,7 @@ static struct fio_file *__get_next_file(struct thread_data *td) } if (td->o.file_service_type == FIO_FSERVICE_RR || + td->o.file_service_type == FIO_FSERVICE_RR1 || td->o.file_service_type == FIO_FSERVICE_SEQ) f = get_next_file_rr(td, FIO_FILE_open, FIO_FILE_closing); else @@ -1462,6 +1474,11 @@ static struct fio_file *__get_next_file(struct thread_data *td) td->file_service_file = f; td->file_service_left = td->file_service_nr - 1; + + if (f && (td->o.file_service_type & __FIO_FSERVICE_NONREPEAT)) { + fio_file_set_busy(f); + td->nr_busy_files++; + } out: if (f) dprint(FD_FILE, "get_next_file: %p [%s]\n", f, f->file_name); diff --git a/options.c b/options.c index ab650bb748..518c34d1b7 100644 --- a/options.c +++ b/options.c @@ -1061,6 +1061,8 @@ static int str_fst_cb(void *data, const char *str) case FIO_FSERVICE_RANDOM: case FIO_FSERVICE_RR: case FIO_FSERVICE_SEQ: + case FIO_FSERVICE_RANDOM1: + case FIO_FSERVICE_RR1: nr = get_opt_postfix(str); if (nr) { td->file_service_nr = atoi(nr); @@ -2766,6 +2768,14 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .oval = FIO_FSERVICE_SEQ, .help = "Finish one file before moving to the next", }, + { .ival = "random1", + .oval = FIO_FSERVICE_RANDOM1, + .help = "Choose a file at random (uniform) non-repeating", + }, + { .ival = "roundrobin1", + .oval = FIO_FSERVICE_RR1, + .help = "Round robin non-repeating", + }, }, .parent = "nrfiles", .hide = 1,