>I'd stop referencing blockalign here to avoid confusion Done. >Actually it will should apply to all workloads because a random workload won't be able to generate an offset that is less than the aligned offset. The offset_align will only apply if % is used in offset (not byte offset). Agreed if sequential or random IO, get_start_offset() is invoked for starting LBA. Applied updates. >Why check ba here? I don't think we get anything from trying to align the offset to blockalign given its behaviour. Done. >Isn't FIO_OPT_INT more appropriate? Good point, same as blockalign. >Actually here's a question - what does .interval do? Looks like it is used to override the default value of 1 in gopt_new_int(): interval = 1.0; if (o->interval) interval = o->interval; i->spin = gtk_spin_button_new_with_range(o->minval, maxval, interval); But your larger question may be why do some options have interval (e.g. offset) and some not have interval (e.g. ioengine). Here is a v2 patch: diff --git a/HOWTO b/HOWTO index 22a5849..e7142c5 100644 --- a/HOWTO +++ b/HOWTO @@ -1128,13 +1128,20 @@ I/O type .. option:: offset=int Start I/O at the provided offset in the file, given as either a fixed size in - bytes 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 + bytes or a percentage. If a percentage is given, the generated offset will be + aligned to the minimum ``blocksize`` or to the value of ``offset_align`` if + provided. 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. A percentage can be specified by a number between 1 and 100 followed by '%', for example, ``offset=20%`` to specify 20%. +.. option:: offset_align=int + + If set to non-zero value, the byte offset generated by a percentage ``offset`` + is aligned upwards to this value. Defaults to 0 meaning that a percentage + offset is aligned to the minimum block size. + .. option:: offset_increment=int If this is provided, then the real offset becomes `offset + offset_increment diff --git a/cconv.c b/cconv.c index f809fd5..dc3c4e6 100644 --- a/cconv.c +++ b/cconv.c @@ -105,6 +105,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_align = le64_to_cpu(top->start_offset_align); o->start_offset_percent = le32_to_cpu(top->start_offset_percent); for (i = 0; i < DDIR_RWDIR_CNT; i++) { @@ -548,6 +549,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_align = __cpu_to_le64(o->start_offset_align); 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); diff --git a/filesetup.c b/filesetup.c index 7a602d4..5d7ea5c 100644 --- a/filesetup.c +++ b/filesetup.c @@ -869,12 +869,10 @@ uint64_t get_start_offset(struct thread_data *td, struct fio_file *f) if (o->start_offset_percent > 0) { /* - * if blockalign is provided, find the min across read, write, - * and trim + * if offset_align is provided, set initial offset */ - 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); + if (fio_option_is_set(o, start_offset_align)) { + align_bs = o->start_offset_align; } else { /* else take the minimum block size */ align_bs = td_min_bs(td); diff --git a/fio.1 b/fio.1 index 7787ef2..96d8f11 100644 --- a/fio.1 +++ b/fio.1 @@ -913,13 +913,19 @@ should be associated with them. .TP .BI offset \fR=\fPint Start I/O at the provided offset in the file, given as either a fixed size in -bytes 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 +bytes or a percentage. If a percentage is given, the generated offset will be +aligned to the minimum \fBblocksize\fR or to the value of \fBoffset_align\fR if +provided. 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. A percentage can be specified by a number between 1 and 100 followed by '%', for example, `offset=20%' to specify 20%. .TP +.BI offset_align \fR=\fPint +If set to non-zero value, the byte offset generated by a percentage \fBoffset\fR +is aligned upwards to this value. Defaults to 0 meaning that a percentage +offset is aligned to the minimum block size. +.TP .BI offset_increment \fR=\fPint If this is provided, then the real offset becomes `\fBoffset\fR + \fBoffset_increment\fR * thread_number', where the thread number is a counter that starts at 0 and diff --git a/options.c b/options.c index ddcc4e5..e88dc2c 100644 --- a/options.c +++ b/options.c @@ -2019,6 +2019,17 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .group = FIO_OPT_G_INVALID, }, { + .name = "offset_align", + .lname = "IO offset alignment", + .type = FIO_OPT_INT, + .off1 = offsetof(struct thread_options, start_offset_align), + .help = "Start IO from this offset alignment", + .def = "0", + .interval = 1024 * 1024, + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_INVALID, + }, + { .name = "offset_increment", .lname = "IO offset increment", .type = FIO_OPT_STR_VAL, diff --git a/thread_options.h b/thread_options.h index 1813cdc..5a037bf 100644 --- a/thread_options.h +++ b/thread_options.h @@ -78,6 +78,7 @@ struct thread_options { unsigned long long file_size_low; unsigned long long file_size_high; unsigned long long start_offset; + unsigned long long start_offset_align; unsigned int bs[DDIR_RWDIR_CNT]; unsigned int ba[DDIR_RWDIR_CNT]; @@ -355,6 +356,7 @@ struct thread_options_pack { uint64_t file_size_low; uint64_t file_size_high; uint64_t start_offset; + uint64_t start_offset_align; uint32_t bs[DDIR_RWDIR_CNT]; uint32_t ba[DDIR_RWDIR_CNT]; Regards, Jeff ��.n��������+%������w��{.n�������^n�r������&��z�ޗ�zf���h���~����������_��+v���)ߣ�