+ret_good:
+ f->failed_rands = 0;
+ret:
+ return 0;
+}
+
+static int get_next_rand_block(struct thread_data *td, struct fio_file *f,
+ enum fio_ddir ddir, unsigned long long *b)
+{
+ if (!get_next_rand_offset(td, f, ddir, b))
+ return 0;
+
+ if (td->o.time_based) {
+ fio_file_reset(f);
+ if (!get_next_rand_offset(td, f, ddir, b))
+ return 0;
+ }
+
+ dprint(FD_IO, "%s: rand offset failed, last=%llu, size=%llu\n",
+ f->file_name, f->last_pos, f->real_file_size);
+ return 1;
+}
+
+static int get_next_seq_offset(struct thread_data *td, struct fio_file *f,
+ enum fio_ddir ddir, unsigned long long *offset)
+{
+ assert(ddir_rw(ddir));
+
+ if (f->last_pos >= f->io_size + get_start_offset(td) && td->o.time_based)
+ f->last_pos = f->last_pos - f->io_size;
+
+ if (f->last_pos < f->real_file_size) {
+ unsigned long long pos;
+
+ if (f->last_pos == f->file_offset && td->o.ddir_seq_add < 0)
+ f->last_pos = f->real_file_size;
+
+ pos = f->last_pos - f->file_offset;
+ if (pos)
+ pos += td->o.ddir_seq_add;
+
+ *offset = pos;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int get_next_block(struct thread_data *td, struct io_u *io_u,
+ enum fio_ddir ddir, int rw_seq)
+{
+ struct fio_file *f = io_u->file;
+ unsigned long long b, offset;
+ int ret;
+
+ assert(ddir_rw(ddir));
+
+ b = offset = -1ULL;
+
+ if (rw_seq) {
+ if (td_random(td))
+ ret = get_next_rand_block(td, f, ddir, &b);
+ else
+ ret = get_next_seq_offset(td, f, ddir, &offset);
+ } else {
+ io_u->flags |= IO_U_F_BUSY_OK;
+
+ if (td->o.rw_seq == RW_SEQ_SEQ) {
+ ret = get_next_seq_offset(td, f, ddir, &offset);
+ if (ret)
+ ret = get_next_rand_block(td, f, ddir, &b);
+ } else if (td->o.rw_seq == RW_SEQ_IDENT) {
+ if (f->last_start != -1ULL)
+ offset = f->last_start - f->file_offset;
+ else
+ offset = 0;
+ ret = 0;
+ } else {
+ log_err("fio: unknown rw_seq=%d\n", td->o.rw_seq);
+ ret = 1;
+ }
+ }
+
+ if (!ret) {
+ if (offset != -1ULL)
+ io_u->offset = offset;
+ else if (b != -1ULL)
+ io_u->offset = b * td->o.ba[ddir];
+ else {
+ log_err("fio: bug in offset generation\n");
+ ret = 1;
+ }
+ }
+
+ return ret;