+ dprint(FD_IO, "failed finding a free block\n");
+ return 1;
+}
+
+static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
+ enum fio_ddir ddir, unsigned long long *b)
+{
+ unsigned long long r, lastb;
+ int loops = 5;
+
+ lastb = last_block(td, f, ddir);
+ if (!lastb)
+ return 1;
+
+ do {
+ r = os_random_long(&td->random_state);
+ dprint(FD_RANDOM, "off rand %llu\n", r);
+ *b = (lastb - 1) * (r / ((unsigned long long) OS_RAND_MAX + 1.0));
+
+ /*
+ * if we are not maintaining a random map, we are done.
+ */
+ if (!file_randommap(td, f))
+ return 0;
+
+ /*
+ * calculate map offset and check if it's free
+ */
+ if (random_map_free(f, *b))
+ return 0;
+
+ dprint(FD_RANDOM, "get_next_rand_offset: offset %llu busy\n",
+ *b);
+ } while (--loops);
+
+ /*
+ * we get here, if we didn't suceed in looking up a block. generate
+ * a random start offset into the filemap, and find the first free
+ * block from there.
+ */
+ loops = 10;
+ do {
+ f->last_free_lookup = (f->num_maps - 1) *
+ (r / (OS_RAND_MAX + 1.0));
+ if (!get_next_free_block(td, f, ddir, b))
+ return 0;
+
+ r = os_random_long(&td->random_state);
+ } while (--loops);
+
+ /*
+ * that didn't work either, try exhaustive search from the start
+ */
+ f->last_free_lookup = 0;
+ return get_next_free_block(td, f, ddir, b);
+}
+
+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)) {
+ dprint(FD_IO, "%s: rand offset failed, last=%llu, size=%llu\n",
+ f->file_name, f->last_pos, f->real_file_size);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int get_next_seq_block(struct thread_data *td, struct fio_file *f,
+ enum fio_ddir ddir, unsigned long long *b)
+{
+ assert(ddir_rw(ddir));
+
+ if (f->last_pos < f->real_file_size) {
+ *b = (f->last_pos - f->file_offset) / td->o.min_bs[ddir];
+ return 0;
+ }
+