From: Josef Bacik <jbacik@xxxxxx> Currently there's no way for a user to specify a directory that doesn't exist yet for a job. Fix this by looking for paths in the file name provided by the job and creating any subdirectories that may be required. Signed-off-by: Josef Bacik <jbacik@xxxxxx> --- filesetup.c | 43 +++++++++++++++++++++++++++++++++++++++++++ fio.h | 6 ++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/filesetup.c b/filesetup.c index a7bbcede08d1..b390caa29526 100644 --- a/filesetup.c +++ b/filesetup.c @@ -1523,6 +1523,45 @@ bool exists_and_not_regfile(const char *filename) return true; } +static void create_work_dirs(struct thread_data *td, const char *fname) +{ + char path[PATH_MAX]; + char *start, *end; + int dirfd; + bool need_close = true; + + if (td->o.directory) { + dirfd = open(td->o.directory, O_DIRECTORY | O_RDONLY); + if (dirfd < 0) { + log_err("fio: failed to open dir (%s): %d\n", + td->o.directory, errno); + assert(0); + } + } else { + dirfd = AT_FDCWD; + need_close = false; + } + + memcpy(path, fname, PATH_MAX); + start = end = path; + while ((end = strchr(end, FIO_OS_PATH_SEPARATOR)) != NULL) { + if (end == start) + break; + *end = '\0'; + errno = 0; + if (mkdirat(dirfd, start, 0600) && errno != EEXIST) { + log_err("fio: failed to create dir (%s): %d\n", + start, errno); + assert(0); + } + *end = FIO_OS_PATH_SEPARATOR; + end++; + } + if (need_close) + close(dirfd); + td->flags |= TD_F_DIRS_CREATED; +} + int add_file(struct thread_data *td, const char *fname, int numjob, int inc) { int cur_files = td->files_index; @@ -1538,6 +1577,10 @@ 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); + /* clean cloned siblings using existing files */ if (numjob && is_already_allocated(file_name) && !exists_and_not_regfile(fname)) diff --git a/fio.h b/fio.h index 28d064cfe868..2856dd5e708c 100644 --- a/fio.h +++ b/fio.h @@ -87,6 +87,7 @@ enum { __TD_F_NO_PROGRESS, __TD_F_REGROW_LOGS, __TD_F_MMAP_KEEP, + __TD_F_DIRS_CREATED, __TD_F_LAST, /* not a real bit, keep last */ }; @@ -106,6 +107,7 @@ enum { TD_F_NO_PROGRESS = 1U << __TD_F_NO_PROGRESS, TD_F_REGROW_LOGS = 1U << __TD_F_REGROW_LOGS, TD_F_MMAP_KEEP = 1U << __TD_F_MMAP_KEEP, + TD_F_DIRS_CREATED = 1U << __TD_F_DIRS_CREATED, }; enum { @@ -606,8 +608,8 @@ enum { TD_NR, }; -#define TD_ENG_FLAG_SHIFT 16 -#define TD_ENG_FLAG_MASK ((1U << 16) - 1) +#define TD_ENG_FLAG_SHIFT 17 +#define TD_ENG_FLAG_MASK ((1U << 17) - 1) static inline enum fio_ioengine_flags td_ioengine_flags(struct thread_data *td) { -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe fio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html