+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;
+ int loops = 5;
+
+ do {
+ r = os_random_long(&td->random_state);
+ dprint(FD_RANDOM, "off rand %llu\n", r);
+ *b = (last_block(td, f, ddir) - 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);
+}
+