filesetup: fix directory creation issues
authorSitsofe Wheeler <sitsofe@yahoo.com>
Sun, 8 Dec 2019 18:03:57 +0000 (18:03 +0000)
committerSitsofe Wheeler <sitsofe@yahoo.com>
Wed, 18 Dec 2019 17:17:01 +0000 (17:17 +0000)
- 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 <astolfor@microsoft.com>
Signed-off-by: Sitsofe Wheeler <sitsofe@yahoo.com>
configure
filesetup.c
options.c
os/os-windows.h
os/os.h

index e32d5dcf8735d16c129f529ddacb0965cee71f62..a1279693a550ac45ffd4da9e1c3722c17100f9ca 100755 (executable)
--- 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 <sys/stat.h>
-#include <sys/types.h>
-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
index ed3646a4bbe75e598e556970084bcb328c30fa3e..b45a58265a140700bfb96b4e6dd0930e4ed1a6c2 100644 (file)
@@ -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;
index fad1857e20fbfb34eb1c804981b17d86bf4b43fc..e4262def7285a68e80e9c1a295e6a4bd6dd8456a 100644 (file)
--- 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);
index 3e9f73413b26a5f2c5e778b63df4281f2e7df994..6061d8c70761447ef53ed841d3f9316313845ad4 100644 (file)
@@ -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 dadcd87bcd9625daad0728ffd2d8ce4bbd473e47..9a280e541f1b505a45622f7649279650c0c1165c 100644 (file)
--- 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 */