.. 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
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]);
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);
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;
}
/*
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
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);
.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",
};
enum {
- FIO_SERVER_VER = 61,
+ FIO_SERVER_VER = 62,
FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
FIO_SERVER_MAX_CMD_MB = 2048,
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;
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;