doc: IO -> I/O, sync filecreate documentation
[fio.git] / filesetup.c
index 0631a01f96a635789f925e6f54f7abf9a23ce92f..5d7ea5c02e17b10357aea99a998bd885901f7bad 100644 (file)
@@ -869,12 +869,10 @@ uint64_t get_start_offset(struct thread_data *td, struct fio_file *f)
 
        if (o->start_offset_percent > 0) {
                /*
-                * if blockalign is provided, find the min across read, write,
-                * and trim
+                * if offset_align is provided, set initial offset
                 */
-               if (fio_option_is_set(o, ba)) {
-                       align_bs = (unsigned long long) min(o->ba[DDIR_READ], o->ba[DDIR_WRITE]);
-                       align_bs = min((unsigned long long) o->ba[DDIR_TRIM], align_bs);
+               if (fio_option_is_set(o, start_offset_align)) {
+                       align_bs = o->start_offset_align;
                } else {
                        /* else take the minimum block size */
                        align_bs = td_min_bs(td);
@@ -1523,6 +1521,42 @@ bool exists_and_not_regfile(const char *filename)
        return true;
 }
 
+static int create_work_dirs(struct thread_data *td, const char *fname)
+{
+       char path[PATH_MAX];
+       char *start, *end;
+
+       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;
+       }
+
+       end = start;
+       while ((end = strchr(end, FIO_OS_PATH_SEPARATOR)) != NULL) {
+               if (end == start)
+                       break;
+               *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);
+                       return 1;
+               }
+               *end = FIO_OS_PATH_SEPARATOR;
+               end++;
+       }
+       td->flags |= TD_F_DIRS_CREATED;
+       return 0;
+}
+
 int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
 {
        int cur_files = td->files_index;
@@ -1538,6 +1572,11 @@ int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
 
        sprintf(file_name + len, "%s", fname);
 
+       if (strchr(fname, FIO_OS_PATH_SEPARATOR) &&
+           !(td->flags & TD_F_DIRS_CREATED) &&
+           create_work_dirs(td, fname))
+               return 1;
+
        /* clean cloned siblings using existing files */
        if (numjob && is_already_allocated(file_name) &&
            !exists_and_not_regfile(fname))
@@ -1725,7 +1764,7 @@ static int recurse_dir(struct thread_data *td, const char *dirname)
                if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
                        continue;
 
-               sprintf(full_path, "%s%s%s", dirname, FIO_OS_PATH_SEPARATOR, dir->d_name);
+               sprintf(full_path, "%s%c%s", dirname, FIO_OS_PATH_SEPARATOR, dir->d_name);
 
                if (lstat(full_path, &sb) == -1) {
                        if (errno != ENOENT) {