From: Jens Axboe Date: Mon, 28 Apr 2014 18:08:47 +0000 (-0600) Subject: Add option for io_limit X-Git-Tag: fio-2.1.9~12 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=77731b29c35286a43ca6109ebf13389169ec20e9 Add option for io_limit 'size' denotes both the size of the region for IO, as well as the amount of IO to transfer. Sometimes it's useful to be able to set them separately instead. With this patch, you can do: size=100G io_limit=10G and have fio do 10G of IO between 0..100G of the address space. Signed-off-by: Jens Axboe --- diff --git a/HOWTO b/HOWTO index f74360de..1c89d75f 100644 --- a/HOWTO +++ b/HOWTO @@ -430,6 +430,14 @@ size=int The total size of file io for this job. Fio will run until is given, fio will use 20% of the full size of the given files or devices. +io_limit=int Normally fio operates within the region set by 'size', which + means that the 'size' option sets both the region and size of + IO to be performed. Sometimes that is not what you want. With + this option, it is possible to define just the amount of IO + that fio should do. For instance, if 'size' is set to 20G and + 'io_limit' is set to 5G, fio will perform IO within the first + 20G but exit when 5G have been done. + filesize=int Individual file sizes. May be a range, in which case fio will select sizes for files at random within the given range and limited to 'size' in total (if that is given). If not diff --git a/backend.c b/backend.c index 12e562b2..e0f8aa76 100644 --- a/backend.c +++ b/backend.c @@ -645,7 +645,7 @@ static unsigned int exceeds_number_ios(struct thread_data *td) static int io_bytes_exceeded(struct thread_data *td) { - unsigned long long bytes; + unsigned long long bytes, limit; if (td_rw(td)) bytes = td->this_io_bytes[DDIR_READ] + td->this_io_bytes[DDIR_WRITE]; @@ -656,7 +656,12 @@ static int io_bytes_exceeded(struct thread_data *td) else bytes = td->this_io_bytes[DDIR_TRIM]; - return bytes >= td->o.size || exceeds_number_ios(td); + if (td->o.io_limit) + limit = td->o.io_limit; + else + limit = td->o.size; + + return bytes >= limit || exceeds_number_ios(td); } /* @@ -1141,6 +1146,8 @@ static int switch_ioscheduler(struct thread_data *td) static int keep_running(struct thread_data *td) { + unsigned long long limit; + if (td->done) return 0; if (td->o.time_based) @@ -1152,14 +1159,19 @@ static int keep_running(struct thread_data *td) if (exceeds_number_ios(td)) return 0; - if (td->o.size != -1ULL && ddir_rw_sum(td->io_bytes) < td->o.size) { + if (td->o.io_limit) + limit = td->o.io_limit; + else + limit = td->o.size; + + if (limit != -1ULL && ddir_rw_sum(td->io_bytes) < limit) { uint64_t diff; /* * If the difference is less than the minimum IO size, we * are done. */ - diff = td->o.size - ddir_rw_sum(td->io_bytes); + diff = limit - ddir_rw_sum(td->io_bytes); if (diff < td_max_bs(td)) return 0; diff --git a/cconv.c b/cconv.c index ee3b0ca6..2f7177d9 100644 --- a/cconv.c +++ b/cconv.c @@ -80,6 +80,7 @@ void convert_thread_options_to_cpu(struct thread_options *o, o->iodepth_batch = le32_to_cpu(top->iodepth_batch); o->iodepth_batch_complete = le32_to_cpu(top->iodepth_batch_complete); o->size = le64_to_cpu(top->size); + o->io_limit = le64_to_cpu(top->io_limit); o->size_percent = le32_to_cpu(top->size_percent); o->fill_device = le32_to_cpu(top->fill_device); o->file_append = le32_to_cpu(top->file_append); @@ -428,6 +429,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top, memcpy(top->buffer_pattern, o->buffer_pattern, MAX_PATTERN_SIZE); top->size = __cpu_to_le64(o->size); + top->io_limit = __cpu_to_le64(o->io_limit); top->verify_backlog = __cpu_to_le64(o->verify_backlog); top->start_delay = __cpu_to_le64(o->start_delay); top->start_delay_high = __cpu_to_le64(o->start_delay_high); diff --git a/filesetup.c b/filesetup.c index 79eea9f8..b6cf2e7d 100644 --- a/filesetup.c +++ b/filesetup.c @@ -944,8 +944,12 @@ int setup_files(struct thread_data *td) * iolog already set the total io size, if we read back * stored entries. */ - if (!o->read_iolog_file) - td->total_io_size = o->size * o->loops; + if (!o->read_iolog_file) { + if (o->io_limit) + td->total_io_size = o->io_limit * o->loops; + else + td->total_io_size = o->size * o->loops; + } done: if (o->create_only) diff --git a/fio.1 b/fio.1 index 8cf37780..eeb036e4 100644 --- a/fio.1 +++ b/fio.1 @@ -369,8 +369,16 @@ Unless \fBnrfiles\fR and \fBfilesize\fR options are given, this amount will be divided between the available files for the job. If not set, fio will use the full size of the given files or devices. If the files do not exist, size must be given. It is also possible to give size as a percentage between 1 and -100. If size=20% is given, fio will use 20% of the full size of the given files -or devices. +100. If size=20% is given, fio will use 20% of the full size of the given +files or devices. +.TP +.BI io_limit \fR=\fPint +Normally fio operates within the region set by \fBsize\fR, which means that +the \fBsize\fR option sets both the region and size of IO to be performed. +Sometimes that is not what you want. With this option, it is possible to +define just the amount of IO that fio should do. For instance, if \fBsize\fR +is set to 20G and \fBio_limit\fR is set to 5G, fio will perform IO within +the first 20G but exit when 5G have been done. .TP .BI fill_device \fR=\fPbool "\fR,\fB fill_fs" \fR=\fPbool Sets size to something really large and waits for ENOSPC (no space left on diff --git a/options.c b/options.c index 50af7b49..163c5fc9 100644 --- a/options.c +++ b/options.c @@ -1594,6 +1594,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_INVALID, }, + { + .name = "io_limit", + .lname = "IO Limit", + .type = FIO_OPT_STR_VAL, + .off1 = td_var_offset(io_limit), + .interval = 1024 * 1024, + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_INVALID, + }, { .name = "fill_device", .lname = "Fill device", diff --git a/server.h b/server.h index 2958e730..4f09f284 100644 --- a/server.h +++ b/server.h @@ -38,7 +38,7 @@ struct fio_net_cmd_reply { }; enum { - FIO_SERVER_VER = 33, + FIO_SERVER_VER = 34, FIO_SERVER_MAX_FRAGMENT_PDU = 1024, FIO_SERVER_MAX_CMD_MB = 2048, diff --git a/thread_options.h b/thread_options.h index 46421205..41b6e54e 100644 --- a/thread_options.h +++ b/thread_options.h @@ -52,6 +52,7 @@ struct thread_options { unsigned int iodepth_batch_complete; unsigned long long size; + unsigned long long io_limit; unsigned int size_percent; unsigned int fill_device; unsigned int file_append; @@ -280,6 +281,7 @@ struct thread_options_pack { uint32_t iodepth_batch_complete; uint64_t size; + uint64_t io_limit; uint32_t size_percent; uint32_t fill_device; uint32_t file_append;