allow a percent value for the offset parameter
authorBrantley West <brantley@nutanix.com>
Tue, 16 May 2017 21:10:05 +0000 (17:10 -0400)
committerBrantley West <cbwest@gmail.com>
Mon, 5 Jun 2017 15:31:53 +0000 (11:31 -0400)
HOWTO
cconv.c
filesetup.c
fio.1
options.c
server.h
thread_options.h

diff --git a/HOWTO b/HOWTO
index d9e881abdcc3aa2495cc18957d3b4c681d943f8d..e39111fa620ce20cbba070f536d44a01925a069c 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -1072,10 +1072,11 @@ I/O type
 
 .. option:: offset=int
 
-       Start I/O at the given offset in the file. The data before the given offset
-       will not be touched. This effectively caps the file size at `real_size -
-       offset`. Can be combined with :option:`size` to constrain the start and
-       end range that I/O will be done within.
+       Start I/O at the provided offset in the file, given as either a fixed size or
+       a percentage. If a percentage is given, the next ``blockalign``-ed offset
+       will be used. Data before the given offset will not be touched. This
+       effectively caps the file size at `real_size - offset`. Can be combined with
+       :option:`size` to constrain the start and end range of the I/O workload.
 
 .. option:: offset_increment=int
 
diff --git a/cconv.c b/cconv.c
index 3295824b5a26f18459fa119fbeeb00596342fb5f..bf4c5175fa4c7bbe09eeb4dcbe099d46f4e3d913 100644 (file)
--- a/cconv.c
+++ b/cconv.c
@@ -104,6 +104,7 @@ void convert_thread_options_to_cpu(struct thread_options *o,
        o->file_size_low = le64_to_cpu(top->file_size_low);
        o->file_size_high = le64_to_cpu(top->file_size_high);
        o->start_offset = le64_to_cpu(top->start_offset);
+       o->start_offset_percent = le32_to_cpu(top->start_offset_percent);
 
        for (i = 0; i < DDIR_RWDIR_CNT; i++) {
                o->bs[i] = le32_to_cpu(top->bs[i]);
@@ -543,6 +544,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
        top->file_size_low = __cpu_to_le64(o->file_size_low);
        top->file_size_high = __cpu_to_le64(o->file_size_high);
        top->start_offset = __cpu_to_le64(o->start_offset);
+       top->start_offset_percent = __cpu_to_le32(o->start_offset_percent);
        top->trim_backlog = __cpu_to_le64(o->trim_backlog);
        top->offset_increment = __cpu_to_le64(o->offset_increment);
        top->number_ios = __cpu_to_le64(o->number_ios);
index 612e79474dc4b43c0707d6a43dccf3d98a2f9e8f..25ce0c0d88852a162d7afcc1f02952116f7cf842 100644 (file)
@@ -833,12 +833,35 @@ static unsigned long long get_fs_free_counts(struct thread_data *td)
 uint64_t get_start_offset(struct thread_data *td, struct fio_file *f)
 {
        struct thread_options *o = &td->o;
+       unsigned long long align_bs;  /* align the offset to this block size */
+       unsigned long long offset;  /* align_bs-aligned offset */
 
        if (o->file_append && f->filetype == FIO_TYPE_FILE)
                return f->real_file_size;
 
-       return td->o.start_offset +
-               td->subjob_number * td->o.offset_increment;
+       if (o->start_offset_percent > 0) {
+
+               /* if blockalign is provided, find the min across read, write, and trim */
+               if (fio_option_is_set(o, ba)) {
+                       align_bs = (unsigned long long) min(o->ba[DDIR_READ], o->ba[DDIR_WRITE]);
+                       align_bs = min((unsigned long long) o->ba[DDIR_TRIM], align_bs);
+               } else {  /* else take the minimum block size */
+                       align_bs = td_min_bs(td);
+               }
+
+               /* calculate the raw offset */
+               offset = (f->real_file_size * o->start_offset_percent / 100) +
+                       (td->subjob_number * o->offset_increment);
+
+               /* block align the offset at the next available boundary at
+                  ceiling(offset / align_bs) * align_bs */
+               offset = (offset / align_bs + (offset % align_bs != 0)) * align_bs;
+
+       } else {  /* start_offset_percent not set */
+               offset = o->start_offset + o->start_offset +
+                       td->subjob_number * o->offset_increment;
+       }
+       return offset;
 }
 
 /*
diff --git a/fio.1 b/fio.1
index 0167c23e8ead51904fec13213b052da4d0eaed9e..31eb161c373634511e4d8d896966bffdd7744ef0 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -904,7 +904,11 @@ If true, use buffered I/O.  This is the opposite of the \fBdirect\fR parameter.
 Default: true.
 .TP
 .BI offset \fR=\fPint
-Offset in the file to start I/O. Data before the offset will not be touched.
+Start I/O at the provided offset in the file, given as either a fixed size or a
+percentage. If a percentage is given, the next \fBblockalign\fR-ed offset will
+be used. Data before the given offset will not be touched. This effectively
+caps the file size at (real_size - offset). Can be combined with \fBsize\fR to
+constrain the start and end range of the I/O workload.
 .TP
 .BI offset_increment \fR=\fPint
 If this is provided, then the real offset becomes the
index b489e90210ae008be47b427195242a56272daa90..dcee7e55a90efe4fbe38dc250296d4849537def5 100644 (file)
--- a/options.c
+++ b/options.c
@@ -1381,6 +1381,21 @@ static int str_gtod_reduce_cb(void *data, int *il)
        return 0;
 }
 
+static int str_offset_cb(void *data, unsigned long long *__val)
+{
+       struct thread_data *td = cb_data_to_td(data);
+       unsigned long long v = *__val;
+
+       if (parse_is_percent(v)) {
+               td->o.start_offset = 0;
+               td->o.start_offset_percent = -1ULL - v;
+               dprint(FD_PARSE, "SET start_offset_percent %d\n", td->o.start_offset_percent);
+       } else
+               td->o.start_offset = v;
+
+       return 0;
+}
+
 static int str_size_cb(void *data, unsigned long long *__val)
 {
        struct thread_data *td = cb_data_to_td(data);
@@ -1938,6 +1953,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .lname  = "IO offset",
                .alias  = "fileoffset",
                .type   = FIO_OPT_STR_VAL,
+               .cb     = str_offset_cb,
                .off1   = offsetof(struct thread_options, start_offset),
                .help   = "Start IO from this offset",
                .def    = "0",
index 5c720d46285166107fbad514b9e6b53d7f8b4961..fff680405d2a7220e904c8d3714f337d9e4c4059 100644 (file)
--- a/server.h
+++ b/server.h
@@ -49,7 +49,7 @@ struct fio_net_cmd_reply {
 };
 
 enum {
-       FIO_SERVER_VER                  = 61,
+       FIO_SERVER_VER                  = 62,
 
        FIO_SERVER_MAX_FRAGMENT_PDU     = 1024,
        FIO_SERVER_MAX_CMD_MB           = 2048,
index d0f3fe932a4d35e39c0e57482445c507e9dc50d1..493e92ec2ae36e9cfa9aca95129bdf5057cb2681 100644 (file)
@@ -200,6 +200,7 @@ struct thread_options {
        unsigned int numa_mem_prefer_node;
        char *numa_memnodes;
        unsigned int gpu_dev_id;
+       unsigned int start_offset_percent;
 
        unsigned int iolog;
        unsigned int rwmixcycle;
@@ -469,7 +470,7 @@ struct thread_options_pack {
        uint8_t log_gz_cpumask[FIO_TOP_STR_MAX];
 #endif
        uint32_t gpu_dev_id;
-       uint32_t pad;
+       uint32_t start_offset_percent;
        uint32_t cpus_allowed_policy;
        uint32_t iolog;
        uint32_t rwmixcycle;