+/*
+ * Get next file to service by doing round robin between all available ones
+ */
+static struct fio_file *get_next_file_rr(struct thread_data *td, int goodf,
+ int badf)
+{
+ unsigned int old_next_file = td->next_file;
+ struct fio_file *f;
+
+ do {
+ int opened = 0;
+
+ f = td->files[td->next_file];
+
+ td->next_file++;
+ if (td->next_file >= td->o.nr_files)
+ td->next_file = 0;
+
+ dprint(FD_FILE, "trying file %s %x\n", f->file_name, f->flags);
+ if (fio_file_done(f)) {
+ f = NULL;
+ continue;
+ }
+
+ if (!fio_file_open(f)) {
+ int err;
+
+ err = td_io_open_file(td, f);
+ if (err) {
+ dprint(FD_FILE, "error %d on open of %s\n",
+ err, f->file_name);
+ f = NULL;
+ continue;
+ }
+ opened = 1;
+ }
+
+ dprint(FD_FILE, "goodf=%x, badf=%x, ff=%x\n", goodf, badf,
+ f->flags);
+ if ((!goodf || (f->flags & goodf)) && !(f->flags & badf))
+ break;
+
+ if (opened)
+ td_io_close_file(td, f);
+
+ f = NULL;
+ } while (td->next_file != old_next_file);
+
+ dprint(FD_FILE, "get_next_file_rr: %p\n", f);
+ return f;
+}
+
+static struct fio_file *__get_next_file(struct thread_data *td)
+{
+ struct fio_file *f;
+
+ assert(td->o.nr_files <= td->files_index);
+
+ if (td->nr_done_files >= td->o.nr_files) {
+ dprint(FD_FILE, "get_next_file: nr_open=%d, nr_done=%d,"
+ " nr_files=%d\n", td->nr_open_files,
+ td->nr_done_files,
+ td->o.nr_files);
+ return NULL;
+ }
+
+ f = td->file_service_file;
+ if (f && fio_file_open(f) && !fio_file_closing(f)) {
+ if (td->o.file_service_type == FIO_FSERVICE_SEQ)
+ goto out;
+ if (td->file_service_left--)
+ goto out;
+ }
+
+ if (td->o.file_service_type == FIO_FSERVICE_RR ||
+ td->o.file_service_type == FIO_FSERVICE_SEQ)
+ f = get_next_file_rr(td, FIO_FILE_open, FIO_FILE_closing);
+ else
+ f = get_next_file_rand(td, FIO_FILE_open, FIO_FILE_closing);
+
+ td->file_service_file = f;
+ td->file_service_left = td->file_service_nr - 1;
+out:
+ dprint(FD_FILE, "get_next_file: %p [%s]\n", f, f->file_name);
+ return f;
+}
+
+static struct fio_file *get_next_file(struct thread_data *td)
+{
+ struct prof_io_ops *ops = &td->prof_io_ops;
+
+ if (ops->get_next_file)
+ return ops->get_next_file(td);
+
+ return __get_next_file(td);
+}
+
+static int set_io_u_file(struct thread_data *td, struct io_u *io_u)
+{
+ struct fio_file *f;
+
+ do {
+ f = get_next_file(td);
+ if (!f)
+ return 1;
+
+ io_u->file = f;
+ get_file(f);
+
+ if (!fill_io_u(td, io_u))
+ break;
+
+ put_file_log(td, f);
+ td_io_close_file(td, f);
+ io_u->file = NULL;
+ fio_file_set_done(f);
+ td->nr_done_files++;
+ dprint(FD_FILE, "%s: is done (%d of %d)\n", f->file_name,
+ td->nr_done_files, td->o.nr_files);
+ } while (1);
+
+ return 0;
+}
+
+