+ flist_for_each_safe(n, tmp, &list) {
+ unsigned long long sz;
+
+ fm = flist_entry(n, struct fio_mount, list);
+ flist_del(&fm->list);
+
+ sz = get_fs_size(fm->base);
+ if (sz && sz != -1ULL)
+ ret += sz;
+
+ free(fm);
+ }
+
+ return ret;
+}
+
+/*
+ * 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;
+
+ dprint(FD_FILE, "setup files\n");
+
+ if (td->o.read_iolog_file)
+ return 0;
+
+ /*
+ * 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;
+ }
+
+ if (td->o.fill_device)
+ td->fill_device_size = get_fs_free_counts(td);
+
+ /*
+ * device/file sizes are zero and no size given, punt
+ */
+ if ((!total_size || total_size == -1ULL) && !td->o.size &&
+ !(td->io_ops->flags & FIO_NOIO) && !td->o.fill_device) {
+ log_err("%s: you need to specify size=\n", td->o.name);
+ td_verror(td, EINVAL, "total_file_size");
+ return 1;
+ }
+
+ /*
+ * now file sizes are known, so we can set ->io_size. if size= is
+ * not given, ->io_size is just equal to ->real_file_size. if size
+ * is given, ->io_size is size / nr_files.
+ */
+ extend_size = total_size = 0;
+ need_extend = 0;
+ for_each_file(td, f, i) {
+ f->file_offset = td->o.start_offset;
+
+ if (!td->o.file_size_low) {
+ /*
+ * no file size range given, file size is equal to
+ * total size divided by number of files. if that is
+ * zero, set it to the real file size.
+ */
+ f->io_size = td->o.size / td->o.nr_files;
+ if (!f->io_size)
+ f->io_size = f->real_file_size - f->file_offset;
+ } else if (f->real_file_size < td->o.file_size_low ||
+ f->real_file_size > td->o.file_size_high) {
+ if (f->file_offset > td->o.file_size_low)
+ goto err_offset;
+ /*
+ * file size given. if it's fixed, use that. if it's a
+ * range, generate a random size in-between.
+ */
+ if (td->o.file_size_low == td->o.file_size_high) {
+ f->io_size = td->o.file_size_low
+ - f->file_offset;
+ } else {
+ f->io_size = get_rand_file_size(td)
+ - f->file_offset;
+ }
+ } else
+ f->io_size = f->real_file_size - f->file_offset;
+
+ if (f->io_size == -1ULL)
+ total_size = -1ULL;
+ else
+ total_size += f->io_size;
+
+ if (f->filetype == FIO_TYPE_FILE &&
+ (f->io_size + f->file_offset) > f->real_file_size &&
+ !(td->io_ops->flags & FIO_DISKLESSIO)) {
+ if (!td->o.create_on_open) {
+ need_extend++;
+ extend_size += (f->io_size + f->file_offset);
+ } else
+ f->real_file_size = f->io_size + f->file_offset;
+ fio_file_set_extend(f);