Fix multithread issues when operating on a single shared file
[fio.git] / filesetup.c
index e664f8b42f795f4d03675e437870382a0243b13b..b30a2932db1ae309f5aa06a8b1f0e53b759ef0b6 100644 (file)
@@ -143,7 +143,7 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
        if (unlink_file || new_layout) {
                int ret;
 
-               dprint(FD_FILE, "layout unlink %s\n", f->file_name);
+               dprint(FD_FILE, "layout %d unlink %d %s\n", new_layout, unlink_file, f->file_name);
 
                ret = td_io_unlink_file(td, f);
                if (ret != 0 && ret != ENOENT) {
@@ -198,6 +198,9 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
                }
        }
 
+
+       dprint(FD_FILE, "fill file %s, size %llu\n", f->file_name, (unsigned long long) f->real_file_size);
+
        left = f->real_file_size;
        bs = td->o.max_bs[DDIR_WRITE];
        if (bs > left)
@@ -226,11 +229,16 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
                        if (r < 0) {
                                int __e = errno;
 
-                               if (__e == ENOSPC) {
+                               if (__e == ENOSPC || __e == EDQUOT) {
+                                       const char *__e_name;
                                        if (td->o.fill_device)
                                                break;
-                                       log_info("fio: ENOSPC on laying out "
-                                                "file, stopping\n");
+                                       if (__e == ENOSPC)
+                                               __e_name = "ENOSPC";
+                                       else
+                                               __e_name = "EDQUOT";
+                                       log_info("fio: %s on laying out "
+                                                "file, stopping\n", __e_name);
                                }
                                td_verror(td, errno, "write");
                        } else
@@ -1019,7 +1027,6 @@ int longest_existing_path(char *path) {
        while (!done) {
                buf_pos = strrchr(buf, FIO_OS_PATH_SEPARATOR);
                if (!buf_pos) {
-                       done = true;
                        offset = 0;
                        break;
                }
@@ -1074,6 +1081,45 @@ static bool create_work_dirs(struct thread_data *td, const char *fname)
        return true;
 }
 
+int setup_shared_file(struct thread_data *td)
+{
+       struct fio_file *f;
+       uint64_t file_size;
+       int err = 0;
+
+       if (td->o.nr_files > 1) {
+               log_err("fio: shared file setup called for multiple files\n");
+               return -1;
+       }
+
+       get_file_sizes(td);
+
+       f = td->files[0];
+
+       if (f == NULL) {
+               log_err("fio: NULL shared file\n");
+               return -1;
+       }
+
+       file_size = thread_number * td->o.size;
+       dprint(FD_FILE, "shared setup %s real_file_size=%llu, desired=%llu\n", 
+                       f->file_name, (unsigned long long)f->real_file_size, (unsigned long long)file_size);
+
+       if (f->real_file_size < file_size) {
+               dprint(FD_FILE, "fio: extending shared file\n");
+               f->real_file_size = file_size;
+               err = extend_file(td, f);
+               if (!err) {
+                       err = __file_invalidate_cache(td, f, 0, f->real_file_size);
+               }
+               get_file_sizes(td);
+               dprint(FD_FILE, "shared setup new real_file_size=%llu\n", 
+                               (unsigned long long)f->real_file_size);
+       }
+
+       return err;
+}
+
 /*
  * Open the files and setup files sizes, creating files if necessary.
  */
@@ -1088,7 +1134,7 @@ int setup_files(struct thread_data *td)
        const unsigned long long bs = td_min_bs(td);
        uint64_t fs = 0;
 
-       dprint(FD_FILE, "setup files\n");
+       dprint(FD_FILE, "setup files (thread_number=%d, subjob_number=%d)\n", td->thread_number, td->subjob_number);
 
        old_state = td_bump_runstate(td, TD_SETTING_UP);
 
@@ -1115,9 +1161,6 @@ int setup_files(struct thread_data *td)
        if (err)
                goto err_out;
 
-       if (o->read_iolog_file)
-               goto done;
-
        if (td->o.zone_mode == ZONE_MODE_ZBD) {
                err = zbd_init_files(td);
                if (err)
@@ -1125,6 +1168,9 @@ int setup_files(struct thread_data *td)
        }
        zbd_recalc_options_with_zone_granularity(td);
 
+       if (o->read_iolog_file)
+               goto done;
+
        /*
         * check sizes. if the files/devices do not exist and the size
         * isn't passed to fio, abort.
@@ -1482,7 +1528,7 @@ static bool init_rand_distribution(struct thread_data *td)
 
 /*
  * Check if the number of blocks exceeds the randomness capability of
- * the selected generator. Tausworthe is 32-bit, the others are fullly
+ * the selected generator. Tausworthe is 32-bit, the others are fully
  * 64-bit capable.
  */
 static int check_rand_gen_limits(struct thread_data *td, struct fio_file *f,
@@ -2027,11 +2073,12 @@ void dup_files(struct thread_data *td, struct thread_data *org)
        if (!org->files)
                return;
 
-       td->files = malloc(org->files_index * sizeof(f));
+       td->files = calloc(org->files_index, sizeof(f));
 
        if (td->o.file_lock_mode != FILE_LOCK_NONE)
                td->file_locks = malloc(org->files_index);
 
+       assert(org->files_index >= org->o.nr_files);
        for_each_file(org, f, i) {
                struct fio_file *__f;