>Hmm, > >I see a few choices for trying to solve alignment of the offset and forced alignment of sequential blocks: >* Introduce an "offset_align" option solely for aligning the "initial" >offset and stop trying to use blockalign in the offset. Document it well to stop confusion with blockalign. >* Document blockalign as ONLY working for random I/O or >* Do blockalign for sequential I/O on a per I/O basis (potentially creating gappy I/O). This is also the request from >https://github.com/axboe/fio/issues/341 . Technically this is has a big overlap with zoned I/O and the existing "generated offset" used in rw >option but perhaps it's just different enough to be justified? > >Thoughts? I tried the first approach. Second approach seems set on random I/O already. Third approach seems problematic with gappy I/O, unless you really want to skip some LBAs (possible, just not my intention on this workload). # fio --name=test_job --ioengine=libaio --direct=1 --rw=read --iodepth=1 --size=100% --bs=4k --filename=/dev/nvme1n1 --number_ios=8 --offset=50% --log_offset=1 --write_iops_log=test_job --offset_align=8k # cat test_job_iops.1.log 0, 1, 0, 4096, 1600315899904 0, 1, 0, 4096, 1600315904000 0, 1, 0, 4096, 1600315908096 0, 1, 0, 4096, 1600315912192 0, 1, 0, 4096, 1600315916288 0, 1, 0, 4096, 1600315920384 0, 1, 0, 4096, 1600315924480 0, 1, 0, 4096, 1600315928576 diff --git a/HOWTO b/HOWTO index 22a5849..c611fae 100644 --- a/HOWTO +++ b/HOWTO @@ -1128,13 +1128,19 @@ 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 + bytes or a percentage. If a percentage is given, the next ``bs`` ``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. 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 a precentage offset is given, the provided offset is ``blockalign``-ed to + the ``blocksize``. This value will align the initial I/O to a new alignment. + Applies to sequential workloads only. + .. 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..97535e7 100644 --- a/filesetup.c +++ b/filesetup.c @@ -869,10 +869,15 @@ uint64_t get_start_offset(struct thread_data *td, struct fio_file *f) if (o->start_offset_percent > 0) { /* + * if offset_align is provided, set initial offset + */ + if (fio_option_is_set(o, start_offset_align)) { + align_bs = o->start_offset_align; + /* * if blockalign is provided, find the min across read, write, * and trim */ - if (fio_option_is_set(o, ba)) { + } else 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 { diff --git a/fio.1 b/fio.1 index 7787ef2..098ca2e 100644 --- a/fio.1 +++ b/fio.1 @@ -913,13 +913,18 @@ 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 +bytes or a percentage. If a percentage is given, the next \fBbs\fR \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. 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 a precentage offset is given, the provided offset is \fBblockalign\fR\-ed to +the \fBblocksize\fR. This value will align the initial I/O to a new alignment. +Applies to sequential workloads only. +.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..a7821d7 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_STR_VAL, + .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���)ߣ�