td_ioengine_flagged(td, FIO_NOIO))
return 0;
+ if (f->filetype == FIO_TYPE_CHAR)
+ return 0;
+
if (!fio_file_open(f)) {
if (td->io_ops->open_file(td, f)) {
log_err("fio: cannot pre-read, failed to open file\n");
uint64_t get_start_offset(struct thread_data *td, struct fio_file *f)
{
struct thread_options *o = &td->o;
+ unsigned long long align_bs;
+ unsigned long long 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 +
+ td->subjob_number * o->offset_increment;
+ }
+
+ return offset;
}
/*
total_size = -1ULL;
else {
if (o->size_percent) {
- f->io_size = (f->io_size * o->size_percent) / 100;
+ uint64_t file_size;
+
+ file_size = f->io_size + f->file_offset;
+ f->io_size = (file_size *
+ o->size_percent) / 100;
+ if (f->io_size > (file_size - f->file_offset))
+ f->io_size = file_size - f->file_offset;
+
f->io_size -= (f->io_size % td_min_bs(td));
}
total_size += f->io_size;