Add option for io_limit
authorJens Axboe <axboe@fb.com>
Mon, 28 Apr 2014 18:08:47 +0000 (12:08 -0600)
committerJens Axboe <axboe@fb.com>
Mon, 28 Apr 2014 18:08:47 +0000 (12:08 -0600)
'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 <axboe@fb.com>
HOWTO
backend.c
cconv.c
filesetup.c
fio.1
options.c
server.h
thread_options.h

diff --git a/HOWTO b/HOWTO
index f74360dee4becc4298bf7e7b8685a284550e552d..1c89d75f29cf6a01264d9f6dbbaaefc9b529a9e8 100644 (file)
--- 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
index 12e562b2a369fc9338001d7b8e8f4254704bf4f6..e0f8aa76f584dc8f978c1f2649fae5292f563718 100644 (file)
--- 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 ee3b0ca673a51d9790f6bbdab8ed545f72027906..2f7177d9b1e6e4e23cbecc6c37706b4ce3ed2bfd 100644 (file)
--- 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);
index 79eea9f879fb42b1f21607e5fe4df1fe4d498cd5..b6cf2e7df1e9e8b47681917a1d43741168d9e2bd 100644 (file)
@@ -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 8cf37780044a7ffd0f509ccae04f765cea2297d9..eeb036e486957e0c9dbfe8d4c3b27a1e8370cfed 100644 (file)
--- 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
index 50af7b499f4b37bfcda231dcfef0aaebf9e8d7f8..163c5fc9298595a4a26184371db6c74448244921 100644 (file)
--- 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",
index 2958e7306c3ecb4c28d02c1309b0f2de9ed59a13..4f09f2848b93acd426d7e7a48a9898edd9099799 100644 (file)
--- 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,
index 46421205cdf9f1ba5fb0c3da997adcc98055bda4..41b6e54e73726ad03fba363247706cb7f56e4772 100644 (file)
@@ -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;