Fix zoning issue with seq-io and randommap issue
authorgvkovai <gv.kovai@gmail.com>
Tue, 12 Sep 2017 15:17:40 +0000 (11:17 -0400)
committergvkovai <gv.kovai@gmail.com>
Thu, 14 Sep 2017 16:34:39 +0000 (12:34 -0400)
The case of zonerange < zonesize scenario was not handled
correctly earlier. When zonesize > zonerange, IO must continue
in the same zonerange of the size zonesize for seq-io.

For random io, zonesize > zonerange leads to sequential io
after first zonerange size of io is done when 'norandommap'
is not set. In this case, map needs to be reset for every
zonerange size of IO on a zone.

<seqzoneread.fio>
=====
[global]
ioengine=libaio
direct=1
time_based
disk_util=0
continue_on_error=all
rate_process=poisson
write_iolog=offsetlog
[db-dss1]
bs=8K
filesize=524288M
zonesize=9M
zonerange=3M
zoneskip=1M
filename=/dev/sdb
rw=read
iodepth=1
rate_iops=100
======
sudo ./fio --runtime 120 --debug=file,io,blktrace --write_iops_log=/tmp/IOPS
           --write_lat_log=/tmp/LAT --status-interval=10
           --output=/tmp/fio.out --output-format=json seqzoneread.fio
see issue for more details and plots which describes the issue and fix.

fixes #450 .

io_u.c

diff --git a/io_u.c b/io_u.c
index db043e4..41feeac 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -850,6 +850,45 @@ void requeue_io_u(struct thread_data *td, struct io_u **io_u)
        *io_u = NULL;
 }
 
+static void __fill_io_u_zone(struct thread_data *td, struct io_u *io_u)
+{
+       struct fio_file *f = io_u->file;
+
+       /*
+        * See if it's time to switch to a new zone
+        */
+       if (td->zone_bytes >= td->o.zone_size && td->o.zone_skip) {
+               td->zone_bytes = 0;
+               f->file_offset += td->o.zone_range + td->o.zone_skip;
+
+               /*
+                * Wrap from the beginning, if we exceed the file size
+                */
+               if (f->file_offset >= f->real_file_size)
+                       f->file_offset = f->real_file_size - f->file_offset;
+               f->last_pos[io_u->ddir] = f->file_offset;
+               td->io_skip_bytes += td->o.zone_skip;
+       }
+
+       /*
+        * If zone_size > zone_range, then maintain the same zone until
+        * zone_bytes >= zone_size.
+        */
+       if (f->last_pos[io_u->ddir] >= (f->file_offset + td->o.zone_range)) {
+               dprint(FD_IO, "io_u maintain zone offset=%" PRIu64 "/last_pos=%" PRIu64 "\n",
+                               f->file_offset, f->last_pos[io_u->ddir]);
+               f->last_pos[io_u->ddir] = f->file_offset;
+       }
+
+       /*
+        * For random: if 'norandommap' is not set and zone_size > zone_range,
+        * map needs to be reset as it's done with zone_range everytime.
+        */
+       if ((td->zone_bytes % td->o.zone_range) == 0) {
+               fio_file_reset(td, f);
+       }
+}
+
 static int fill_io_u(struct thread_data *td, struct io_u *io_u)
 {
        unsigned int is_random;
@@ -866,21 +905,10 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
                goto out;
 
        /*
-        * See if it's time to switch to a new zone
+        * When file is zoned zone_range is always positive
         */
-       if (td->zone_bytes >= td->o.zone_size && td->o.zone_skip) {
-               struct fio_file *f = io_u->file;
-
-               td->zone_bytes = 0;
-               f->file_offset += td->o.zone_range + td->o.zone_skip;
-
-               /*
-                * Wrap from the beginning, if we exceed the file size
-                */
-               if (f->file_offset >= f->real_file_size)
-                       f->file_offset = f->real_file_size - f->file_offset;
-               f->last_pos[io_u->ddir] = f->file_offset;
-               td->io_skip_bytes += td->o.zone_skip;
+       if (td->o.zone_range) {
+               __fill_io_u_zone(td, io_u);
        }
 
        /*