+ struct fio_file *f;
+ unsigned int i;
+ int err = 0;
+
+ for_each_file(td, f, i) {
+ if (td->io_ops->open_file(td, f)) {
+ if (td->error != ENOENT) {
+ log_err("%s\n", td->verror);
+ err = 1;
+ }
+ clear_error(td);
+ } else {
+ if (td->io_ops->close_file)
+ td->io_ops->close_file(td, f);
+ }
+
+ if (f->real_file_size == -1ULL && td->o.size)
+ f->real_file_size = td->o.size / td->o.nr_files;
+ }
+
+ return err;
+}
+
+/*
+ * Open the files and setup files sizes, creating files if necessary.
+ */
+int setup_files(struct thread_data *td)
+{
+ unsigned long long total_size, extend_size;
+ struct fio_file *f;
+ unsigned int i;
+ int err = 0, need_extend;
+
+ /*
+ * if ioengine defines a setup() method, it's responsible for
+ * opening the files and setting f->real_file_size to indicate
+ * the valid range for that file.
+ */
+ if (td->io_ops->setup)
+ err = td->io_ops->setup(td);
+ else
+ err = get_file_sizes(td);
+
+ if (err)
+ return err;
+
+ /*
+ * check sizes. if the files/devices do not exist and the size
+ * isn't passed to fio, abort.
+ */
+ total_size = 0;
+ for_each_file(td, f, i) {
+ if (f->real_file_size == -1ULL)
+ total_size = -1ULL;
+ else
+ total_size += f->real_file_size;
+ }
+
+ /*
+ * device/file sizes are zero and no size given, punt
+ */
+ if ((!total_size || total_size == -1ULL) && !td->o.size) {
+ log_err("%s: you need to specify size=\n", td->o.name);
+ td_verror(td, EINVAL, "total_file_size");