From df18600fd06258b96ae6f6b530ecdff541c2a82d Mon Sep 17 00:00:00 2001 From: Sitsofe Wheeler Date: Sun, 8 Dec 2019 18:03:57 +0000 Subject: [PATCH] filesetup: fix directory creation issues - Fix double directory prefix concatenation that was happening after 95af8dd57a7a9a564f99492bb1e04bb6d13b95b1 ("filesetup: don't call create_work_dirs() for ioengine with FIO_DISKLESSIO") refactored some code - Stop always using '/' and switch to using FIO_OS_PATH_SEPARATOR when concatenating the directory value to the filename in set_name_idx() - Change the permissions directories are created with to have the execute bit so they can be entered(!) - Fix bug where filenames that were absolute unix paths would prevent the creation of intermediate directories - Remove the configure mkdir test and introduce fio_mkdir to hide mkdir platform differences - Make Windows mkdir emulation more robust against multiple slashes after the drive letter and when dealing dealing with with paths containing drive letters in general This commit makes the following work on Windows: ./fio --thread --name=doubleslashtest \ --filename='C\:\\Windows\Temp\fio.tmp' --size=4k --bs=4k --rw=read The next example now works when D:\1\ exists but D:\1\2\ doesn't: ./fio --thread --name=mkdirtest --directory='D\:\1' \ --filename='2\fio.tmp' --size=4k --bs=4k --rw=read The following now works on macOS/Linux when /tmp/1/ exists but /tmp/1/2/ doesn't: ./fio --name=mkdirtest --directory='/tmp/1' \ --filename='2/fio.tmp' --size=4k --bs=4k --rw=read Fixes https://github.com/axboe/fio/issues/784 , https://github.com/axboe/fio/issues/864 and https://github.com/axboe/fio/issues/870 Tested-by: Astolfo Rueda Signed-off-by: Sitsofe Wheeler --- configure | 19 ------------------- filesetup.c | 22 +++++++--------------- options.c | 3 ++- os/os-windows.h | 19 +++++++++++++++++++ os/os.h | 4 ++++ 5 files changed, 32 insertions(+), 35 deletions(-) diff --git a/configure b/configure index e32d5dcf..a1279693 100755 --- a/configure +++ b/configure @@ -2316,22 +2316,6 @@ if test "$enable_cuda" = "yes" && compile_prog "" "-lcuda" "cuda"; then fi print_config "cuda" "$cuda" -########################################## -# mkdir() probe. mingw apparently has a one-argument mkdir :/ -mkdir_two="no" -cat > $TMPC << EOF -#include -#include -int main(int argc, char **argv) -{ - return mkdir("/tmp/bla", 0600); -} -EOF -if compile_prog "" "" "mkdir(a, b)"; then - mkdir_two="yes" -fi -print_config "mkdir(a, b)" "$mkdir_two" - ########################################## # check for cc -march=native build_native="no" @@ -2705,9 +2689,6 @@ fi if test "$cuda" = "yes" ; then output_sym "CONFIG_CUDA" fi -if test "$mkdir_two" = "yes" ; then - output_sym "CONFIG_HAVE_MKDIR_TWO" -fi if test "$march_set" = "no" && test "$build_native" = "yes" ; then output_sym "CONFIG_BUILD_NATIVE" fi diff --git a/filesetup.c b/filesetup.c index ed3646a4..b45a5826 100644 --- a/filesetup.c +++ b/filesetup.c @@ -918,26 +918,18 @@ static bool 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; - } + snprintf(path, PATH_MAX, "%s", fname); + start = path; end = start; 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 + if (fio_mkdir(path, 0700) && errno != EEXIST) { log_err("fio: failed to create dir (%s): %d\n", start, errno); return false; diff --git a/options.c b/options.c index fad1857e..e4262def 100644 --- a/options.c +++ b/options.c @@ -1235,7 +1235,8 @@ int set_name_idx(char *target, size_t tlen, char *input, int index, len = snprintf(target, tlen, "%s/%s.", fname, client_sockaddr_str); } else - len = snprintf(target, tlen, "%s/", fname); + len = snprintf(target, tlen, "%s%c", fname, + FIO_OS_PATH_SEPARATOR); target[tlen - 1] = '\0'; free(p); diff --git a/os/os-windows.h b/os/os-windows.h index 3e9f7341..6061d8c7 100644 --- a/os/os-windows.h +++ b/os/os-windows.h @@ -35,6 +35,7 @@ int rand_r(unsigned *); #define FIO_HAVE_CPU_AFFINITY #define FIO_HAVE_CHARDEV_SIZE #define FIO_HAVE_GETTID +#define FIO_EMULATED_MKDIR_TWO #define FIO_PREFERRED_ENGINE "windowsaio" #define FIO_PREFERRED_CLOCK_SOURCE CS_CGETTIME @@ -197,6 +198,24 @@ static inline int fio_set_sched_idle(void) return (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE))? 0 : -1; } +static inline int fio_mkdir(const char *path, mode_t mode) { + DWORD dwAttr = GetFileAttributesA(path); + + if (dwAttr != INVALID_FILE_ATTRIBUTES && + (dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { + errno = EEXIST; + return -1; + } + + if (CreateDirectoryA(path, NULL) == 0) { + log_err("CreateDirectoryA = %d\n", GetLastError()); + errno = win_to_posix_error(GetLastError()); + return -1; + } + + return 0; +} + #ifdef CONFIG_WINDOWS_XP #include "os-windows-xp.h" #else diff --git a/os/os.h b/os/os.h index dadcd87b..9a280e54 100644 --- a/os/os.h +++ b/os/os.h @@ -407,4 +407,8 @@ static inline bool os_cpu_has(cpu_features feature) } #endif +#ifndef FIO_EMULATED_MKDIR_TWO +# define fio_mkdir(path, mode) mkdir(path, mode) #endif + +#endif /* FIO_OS_H */ -- 2.25.1