engines/filestat: add statx(2) syscall support
authorTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Mon, 2 Mar 2020 15:31:25 +0000 (00:31 +0900)
committerTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Mon, 2 Mar 2020 15:31:25 +0000 (00:31 +0900)
This commit
1) tests existence of statx(2) and libc support on ./confiugre.
2) adds oslib/statx.c and implements statx(2) using above result.
3) adds statx(2) support in filestat ioengine.

Confirmed compilation on Fedora31, FreeBSD, and NetBSD.

Signed-off-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
Makefile
configure
engines/filestat.c
oslib/statx.c [new file with mode: 0644]
oslib/statx.h [new file with mode: 0644]

index 72ab39e..9a5dea7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -132,6 +132,9 @@ endif
 ifndef CONFIG_INET_ATON
   SOURCE += oslib/inet_aton.c
 endif
+ifndef CONFIG_HAVE_STATX
+  SOURCE += oslib/statx.c
+endif
 ifdef CONFIG_GFAPI
   SOURCE += engines/glusterfs.c
   SOURCE += engines/glusterfs_sync.c
index a121770..5de86ca 100755 (executable)
--- a/configure
+++ b/configure
@@ -2551,6 +2551,50 @@ if compile_prog "" "" "gettid"; then
 fi
 print_config "gettid" "$gettid"
 
+##########################################
+# check for statx(2) support by libc
+statx="no"
+cat > $TMPC << EOF
+#include <unistd.h>
+#include <sys/stat.h>
+
+int main(int argc, char **argv)
+{
+       struct statx st;
+       return statx(-1, *argv, 0, 0, &st);
+}
+EOF
+if compile_prog "" "" "statx"; then
+  statx="yes"
+fi
+print_config "statx(2)/libc" "$statx"
+
+##########################################
+# check for statx(2) support by kernel
+statx_syscall="no"
+cat > $TMPC << EOF
+#include <unistd.h>
+#include <linux/stat.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+
+static int _statx(int dfd, const char *pathname, int flags, unsigned int mask,
+                 struct statx *buffer)
+{
+       return syscall(__NR_statx, dfd, pathname, flags, mask, buffer);
+}
+
+int main(int argc, char **argv)
+{
+       struct statx st;
+       return _statx(-1, *argv, 0, 0, &st);
+}
+EOF
+if compile_prog "" "" "statx_syscall"; then
+  statx_syscall="yes"
+fi
+print_config "statx(2)/syscall" "$statx_syscall"
+
 #############################################################################
 
 if test "$wordsize" = "64" ; then
@@ -2843,6 +2887,12 @@ fi
 if test "$gettid" = "yes"; then
   output_sym "CONFIG_HAVE_GETTID"
 fi
+if test "$statx" = "yes"; then
+  output_sym "CONFIG_HAVE_STATX"
+fi
+if test "$statx_syscall" = "yes"; then
+  output_sym "CONFIG_HAVE_STATX_SYSCALL"
+fi
 if test "$fallthrough" = "yes"; then
   CFLAGS="$CFLAGS -Wimplicit-fallthrough"
 fi
index 68a340b..405f028 100644 (file)
@@ -5,6 +5,7 @@
  * of the file stat.
  */
 #include <stdio.h>
+#include <stdlib.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/types.h>
@@ -12,6 +13,7 @@
 #include <unistd.h>
 #include "../fio.h"
 #include "../optgroup.h"
+#include "../oslib/statx.h"
 
 struct fc_data {
        enum fio_ddir stat_ddir;
@@ -25,7 +27,7 @@ struct filestat_options {
 enum {
        FIO_FILESTAT_STAT       = 1,
        FIO_FILESTAT_LSTAT      = 2,
-       /*FIO_FILESTAT_STATX    = 3,*/
+       FIO_FILESTAT_STATX      = 3,
 };
 
 static struct fio_option options[] = {
@@ -45,12 +47,10 @@ static struct fio_option options[] = {
                            .oval = FIO_FILESTAT_LSTAT,
                            .help = "Use lstat(2)",
                          },
-                         /*
                          { .ival = "statx",
                            .oval = FIO_FILESTAT_STATX,
-                           .help = "Use statx(2)",
+                           .help = "Use statx(2) if exists",
                          },
-                         */
                },
                .category = FIO_OPT_C_ENGINE,
                .group  = FIO_OPT_G_FILESTAT,
@@ -66,6 +66,10 @@ static int stat_file(struct thread_data *td, struct fio_file *f)
        struct timespec start;
        int do_lat = !td->o.disable_lat;
        struct stat statbuf;
+#ifndef WIN32
+       struct statx statxbuf;
+       char *abspath;
+#endif
        int ret;
 
        dprint(FD_FILE, "fd stat %s\n", f->file_name);
@@ -89,6 +93,18 @@ static int stat_file(struct thread_data *td, struct fio_file *f)
        case FIO_FILESTAT_LSTAT:
                ret = lstat(f->file_name, &statbuf);
                break;
+       case FIO_FILESTAT_STATX:
+#ifndef WIN32
+               abspath = realpath(f->file_name, NULL);
+               if (abspath) {
+                       ret = statx(-1, abspath, 0, STATX_ALL, &statxbuf);
+                       free(abspath);
+               } else
+                       ret = -1;
+#else
+               ret = -1;
+#endif
+               break;
        default:
                ret = -1;
                break;
diff --git a/oslib/statx.c b/oslib/statx.c
new file mode 100644 (file)
index 0000000..1ca81ad
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef CONFIG_HAVE_STATX
+#include "statx.h"
+
+#ifdef CONFIG_HAVE_STATX_SYSCALL
+#include <unistd.h>
+#include <sys/syscall.h>
+
+int statx(int dfd, const char *pathname, int flags, unsigned int mask,
+         struct statx *buffer)
+{
+       return syscall(__NR_statx, dfd, pathname, flags, mask, buffer);
+}
+#else
+#include <errno.h>
+
+int statx(int dfd, const char *pathname, int flags, unsigned int mask,
+         struct statx *buffer)
+{
+       errno = EINVAL;
+       return -1;
+}
+#endif
+#endif
diff --git a/oslib/statx.h b/oslib/statx.h
new file mode 100644 (file)
index 0000000..d9758f7
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef CONFIG_HAVE_STATX
+#ifdef CONFIG_HAVE_STATX_SYSCALL
+#include <linux/stat.h>
+#include <sys/stat.h>
+#else
+#define STATX_ALL 0
+#undef statx
+struct statx
+{
+};
+#endif
+int statx(int dfd, const char *pathname, int flags, unsigned int mask,
+         struct statx *buffer);
+#endif