Allow offload with FAKEIO engines
[fio.git] / filesetup.c
index 7d54c9f1ef5bc8f92b0e5bbf19285d2f7ecfed17..e44f31c716a63eb12440da37fd50d3552db39e10 100644 (file)
@@ -95,6 +95,18 @@ static void fallocate_file(struct thread_data *td, struct fio_file *f)
                break;
                }
 #endif /* CONFIG_LINUX_FALLOCATE */
+       case FIO_FALLOCATE_TRUNCATE: {
+               int r;
+
+               dprint(FD_FILE, "ftruncate file %s size %llu\n",
+                               f->file_name,
+                               (unsigned long long) f->real_file_size);
+               r = ftruncate(f->fd, f->real_file_size);
+               if (r != 0)
+                       td_verror(td, errno, "ftruncate");
+
+               break;
+       }
        default:
                log_err("fio: unknown fallocate mode: %d\n", td->o.fallocate_mode);
                assert(0);
@@ -901,33 +913,71 @@ uint64_t get_start_offset(struct thread_data *td, struct fio_file *f)
        return offset;
 }
 
+/*
+ * Find longest path component that exists and return its length
+ */
+int longest_existing_path(char *path) {
+       char buf[PATH_MAX];
+       bool done;
+       char *buf_pos;
+       int offset;
+#ifdef WIN32
+       DWORD dwAttr;
+#else
+       struct stat sb;
+#endif
+
+       sprintf(buf, "%s", path);
+       done = false;
+       while (!done) {
+               buf_pos = strrchr(buf, FIO_OS_PATH_SEPARATOR);
+               if (!buf_pos) {
+                       done = true;
+                       offset = 0;
+                       break;
+               }
+
+               *(buf_pos + 1) = '\0';
+
+#ifdef WIN32
+               dwAttr = GetFileAttributesA(buf);
+               if (dwAttr != INVALID_FILE_ATTRIBUTES) {
+                       done = true;
+               }
+#else
+               if (stat(buf, &sb) == 0)
+                       done = true;
+#endif
+               if (done)
+                       offset = buf_pos - buf;
+               else
+                       *buf_pos = '\0';
+       }
+
+       return offset;
+}
+
 static bool create_work_dirs(struct thread_data *td, const char *fname)
 {
        char path[PATH_MAX];
        char *start, *end;
+       int offset;
 
-       if (td->o.directory) {
-               snprintf(path, PATH_MAX, "%s%c%s", td->o.directory,
-                        FIO_OS_PATH_SEPARATOR, fname);
-               start = strstr(path, fname);
-       } else {
-               snprintf(path, PATH_MAX, "%s", fname);
-               start = path;
-       }
+       snprintf(path, PATH_MAX, "%s", fname);
+       start = path;
 
-       end = start;
+       offset = longest_existing_path(path);
+       end = start + offset;
        while ((end = strchr(end, FIO_OS_PATH_SEPARATOR)) != NULL) {
-               if (end == start)
-                       break;
+               if (end == start) {
+                       end++;
+                       continue;
+               }
                *end = '\0';
                errno = 0;
-#ifdef CONFIG_HAVE_MKDIR_TWO
-               if (mkdir(path, 0600) && errno != EEXIST) {
-#else
-               if (mkdir(path) && errno != EEXIST) {
-#endif
-                       log_err("fio: failed to create dir (%s): %d\n",
-                               start, errno);
+               if (fio_mkdir(path, 0700) && errno != EEXIST) {
+                       log_err("fio: failed to create dir (%s): %s\n",
+                               start, strerror(errno));
                        return false;
                }
                *end = FIO_OS_PATH_SEPARATOR;
@@ -1089,6 +1139,8 @@ int setup_files(struct thread_data *td)
                if (f->io_size == -1ULL)
                        total_size = -1ULL;
                else {
+                       uint64_t io_size;
+
                         if (o->size_percent && o->size_percent != 100) {
                                uint64_t file_size;
 
@@ -1100,7 +1152,14 @@ int setup_files(struct thread_data *td)
 
                                f->io_size -= (f->io_size % td_min_bs(td));
                        }
-                       total_size += f->io_size;
+
+                       io_size = f->io_size;
+                       if (o->io_size_percent && o->io_size_percent != 100) {
+                               io_size *= o->io_size_percent;
+                               io_size /= 100;
+                       }
+
+                       total_size += io_size;
                }
 
                if (f->filetype == FIO_TYPE_FILE &&
@@ -1218,7 +1277,7 @@ done:
        td_restore_runstate(td, old_state);
 
        if (td->o.zone_mode == ZONE_MODE_ZBD) {
-               err = zbd_init(td);
+               err = zbd_setup_files(td);
                if (err)
                        goto err_out;
        }
@@ -1275,7 +1334,9 @@ static bool init_rand_distribution(struct thread_data *td)
        unsigned int i;
        int state;
 
-       if (td->o.random_distribution == FIO_RAND_DIST_RANDOM)
+       if (td->o.random_distribution == FIO_RAND_DIST_RANDOM ||
+           td->o.random_distribution == FIO_RAND_DIST_ZONED ||
+           td->o.random_distribution == FIO_RAND_DIST_ZONED_ABS)
                return false;
 
        state = td_bump_runstate(td, TD_SETTING_UP);
@@ -1393,11 +1454,23 @@ void close_files(struct thread_data *td)
        }
 }
 
+void fio_file_free(struct fio_file *f)
+{
+       if (fio_file_axmap(f))
+               axmap_free(f->io_axmap);
+       if (!fio_file_smalloc(f)) {
+               free(f->file_name);
+               free(f);
+       } else {
+               sfree(f->file_name);
+               sfree(f);
+       }
+}
+
 void close_and_free_files(struct thread_data *td)
 {
        struct fio_file *f;
        unsigned int i;
-       bool use_free = td_ioengine_flagged(td, FIO_NOFILEHASH);
 
        dprint(FD_FILE, "close files\n");
 
@@ -1417,21 +1490,8 @@ void close_and_free_files(struct thread_data *td)
                        td_io_unlink_file(td, f);
                }
 
-               zbd_free_zone_info(f);
-
-               if (use_free)
-                       free(f->file_name);
-               else
-                       sfree(f->file_name);
-               f->file_name = NULL;
-               if (fio_file_axmap(f)) {
-                       axmap_free(f->io_axmap);
-                       f->io_axmap = NULL;
-               }
-               if (use_free)
-                       free(f);
-               else
-                       sfree(f);
+               zbd_close_file(f);
+               fio_file_free(f);
        }
 
        td->o.filename = NULL;
@@ -1557,6 +1617,8 @@ static struct fio_file *alloc_new_file(struct thread_data *td)
        f->fd = -1;
        f->shadow_fd = -1;
        fio_file_reset(td, f);
+       if (!td_ioengine_flagged(td, FIO_NOFILEHASH))
+               fio_file_set_smalloc(f);
        return f;
 }