t/fiotestlib: pass command-line options to FioJobFileTest
[fio.git] / io_u.c
diff --git a/io_u.c b/io_u.c
index 4254675acc7d0b922c4950906ca40fef91c81a36..09e5f15a8b1ffe785adcd546da1e8232c9f47399 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -940,6 +940,65 @@ static void setup_strided_zone_mode(struct thread_data *td, struct io_u *io_u)
                fio_file_reset(td, f);
 }
 
+static int fill_multi_range_io_u(struct thread_data *td, struct io_u *io_u)
+{
+       bool is_random;
+       uint64_t buflen, i = 0;
+       struct trim_range *range;
+       struct fio_file *f = io_u->file;
+       uint8_t *buf;
+
+       buf = io_u->buf;
+       buflen = 0;
+
+       while (i < td->o.num_range) {
+               range = (struct trim_range *)buf;
+               if (get_next_offset(td, io_u, &is_random)) {
+                       dprint(FD_IO, "io_u %p, failed getting offset\n",
+                              io_u);
+                       break;
+               }
+
+               io_u->buflen = get_next_buflen(td, io_u, is_random);
+               if (!io_u->buflen) {
+                       dprint(FD_IO, "io_u %p, failed getting buflen\n", io_u);
+                       break;
+               }
+
+               if (io_u->offset + io_u->buflen > io_u->file->real_file_size) {
+                       dprint(FD_IO, "io_u %p, off=0x%llx + len=0x%llx exceeds file size=0x%llx\n",
+                              io_u,
+                              (unsigned long long) io_u->offset, io_u->buflen,
+                              (unsigned long long) io_u->file->real_file_size);
+                       break;
+               }
+
+               range->start = io_u->offset;
+               range->len = io_u->buflen;
+               buflen += io_u->buflen;
+               f->last_start[io_u->ddir] = io_u->offset;
+               f->last_pos[io_u->ddir] = io_u->offset + range->len;
+
+               buf += sizeof(struct trim_range);
+               i++;
+
+               if (td_random(td) && file_randommap(td, io_u->file))
+                       mark_random_map(td, io_u, io_u->offset, io_u->buflen);
+               dprint_io_u(io_u, "fill");
+       }
+       if (buflen) {
+               /*
+                * Set buffer length as overall trim length for this IO, and
+                * tell the ioengine about the number of ranges to be trimmed.
+                */
+               io_u->buflen = buflen;
+               io_u->number_trim = i;
+               return 0;
+       }
+
+       return 1;
+}
+
 static int fill_io_u(struct thread_data *td, struct io_u *io_u)
 {
        bool is_random;
@@ -966,22 +1025,27 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
        else if (td->o.zone_mode == ZONE_MODE_ZBD)
                setup_zbd_zone_mode(td, io_u);
 
-       /*
-        * No log, let the seq/rand engine retrieve the next buflen and
-        * position.
-        */
-       if (get_next_offset(td, io_u, &is_random)) {
-               dprint(FD_IO, "io_u %p, failed getting offset\n", io_u);
-               return 1;
-       }
+       if (multi_range_trim(td, io_u)) {
+               if (fill_multi_range_io_u(td, io_u))
+                       return 1;
+       } else {
+               /*
+                * No log, let the seq/rand engine retrieve the next buflen and
+                * position.
+                */
+               if (get_next_offset(td, io_u, &is_random)) {
+                       dprint(FD_IO, "io_u %p, failed getting offset\n", io_u);
+                       return 1;
+               }
 
-       io_u->buflen = get_next_buflen(td, io_u, is_random);
-       if (!io_u->buflen) {
-               dprint(FD_IO, "io_u %p, failed getting buflen\n", io_u);
-               return 1;
+               io_u->buflen = get_next_buflen(td, io_u, is_random);
+               if (!io_u->buflen) {
+                       dprint(FD_IO, "io_u %p, failed getting buflen\n", io_u);
+                       return 1;
+               }
        }
-
        offset = io_u->offset;
+
        if (td->o.zone_mode == ZONE_MODE_ZBD) {
                ret = zbd_adjust_block(td, io_u);
                if (ret == io_u_eof) {
@@ -1004,11 +1068,12 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
        /*
         * mark entry before potentially trimming io_u
         */
-       if (td_random(td) && file_randommap(td, io_u->file))
+       if (!multi_range_trim(td, io_u) && td_random(td) && file_randommap(td, io_u->file))
                io_u->buflen = mark_random_map(td, io_u, offset, io_u->buflen);
 
 out:
-       dprint_io_u(io_u, "fill");
+       if (!multi_range_trim(td, io_u))
+               dprint_io_u(io_u, "fill");
        io_u->verify_offset = io_u->offset;
        td->zone_bytes += io_u->buflen;
        return 0;
@@ -1814,7 +1879,7 @@ struct io_u *get_io_u(struct thread_data *td)
 
        assert(fio_file_open(f));
 
-       if (ddir_rw(io_u->ddir)) {
+       if (ddir_rw(io_u->ddir) && !multi_range_trim(td, io_u)) {
                if (!io_u->buflen && !td_ioengine_flagged(td, FIO_NOIO)) {
                        dprint(FD_IO, "get_io_u: zero buflen on %p\n", io_u);
                        goto err_put;
@@ -1830,8 +1895,9 @@ struct io_u *get_io_u(struct thread_data *td)
                                        io_u->buflen);
                        } else if ((td->flags & TD_F_SCRAMBLE_BUFFERS) &&
                                   !(td->flags & TD_F_COMPRESS) &&
-                                  !(td->flags & TD_F_DO_VERIFY))
+                                  !(td->flags & TD_F_DO_VERIFY)) {
                                do_scramble = 1;
+                       }
                } else if (io_u->ddir == DDIR_READ) {
                        /*
                         * Reset the buf_filled parameters so next time if the