Merge branch 'per-engine-pre-write-function' of https://github.com/lukaszstolarczuk/fio
[fio.git] / engines / filestat.c
index 6c87c4c2222b50282e4cd636c3698d7244214c3e..405f028d11cd383aa48d4e6c3840a592a1074b4b 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;
@@ -19,17 +21,37 @@ struct fc_data {
 
 struct filestat_options {
        void *pad;
-       unsigned int lstat;
+       unsigned int stat_type;
+};
+
+enum {
+       FIO_FILESTAT_STAT       = 1,
+       FIO_FILESTAT_LSTAT      = 2,
+       FIO_FILESTAT_STATX      = 3,
 };
 
 static struct fio_option options[] = {
        {
-               .name   = "lstat",
-               .lname  = "lstat",
-               .type   = FIO_OPT_BOOL,
-               .off1   = offsetof(struct filestat_options, lstat),
-               .help   = "Use lstat(2) to measure lookup/getattr performance",
-               .def    = "0",
+               .name   = "stat_type",
+               .lname  = "stat_type",
+               .type   = FIO_OPT_STR,
+               .off1   = offsetof(struct filestat_options, stat_type),
+               .help   = "Specify stat system call type to measure lookup/getattr performance",
+               .def    = "stat",
+               .posval = {
+                         { .ival = "stat",
+                           .oval = FIO_FILESTAT_STAT,
+                           .help = "Use stat(2)",
+                         },
+                         { .ival = "lstat",
+                           .oval = FIO_FILESTAT_LSTAT,
+                           .help = "Use lstat(2)",
+                         },
+                         { .ival = "statx",
+                           .oval = FIO_FILESTAT_STATX,
+                           .help = "Use statx(2) if exists",
+                         },
+               },
                .category = FIO_OPT_C_ENGINE,
                .group  = FIO_OPT_G_FILESTAT,
        },
@@ -44,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);
@@ -60,17 +86,36 @@ static int stat_file(struct thread_data *td, struct fio_file *f)
        if (do_lat)
                fio_gettime(&start, NULL);
 
-       if (o->lstat)
-               ret = lstat(f->file_name, &statbuf);
-       else
+       switch (o->stat_type){
+       case FIO_FILESTAT_STAT:
                ret = stat(f->file_name, &statbuf);
+               break;
+       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;
+       }
 
        if (ret == -1) {
                char buf[FIO_VERROR_SIZE];
                int e = errno;
 
-               snprintf(buf, sizeof(buf), "%sstat(%s)",
-                       o->lstat ? "l" : "", f->file_name);
+               snprintf(buf, sizeof(buf), "stat(%s) type=%u", f->file_name,
+                       o->stat_type);
                td_verror(td, e, buf);
                return 1;
        }