fio: Add advise THP option to mmap engine
authorKeith Busch <keith.busch@intel.com>
Thu, 18 Apr 2019 16:25:56 +0000 (10:25 -0600)
committerJens Axboe <axboe@kernel.dk>
Thu, 18 Apr 2019 16:46:19 +0000 (10:46 -0600)
The Linux specific transparent hugepage memory advisory has potentially
significant implications for how the memory management behaves. If the
platform supports it, add a new mmap ioengine specific option that advises
HUGEPAGE on an mmap'ed range. The option availability is detected during
configure. If the option is set, fio can test THP when used with private
anonymous memory (i.e. mmap /dev/zero).

Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
configure
engines/mmap.c
optgroup.h

index 6e549cdc859d63346c8009a9fa6e1055827af5fe..3c882f0f4a5de5eda8e1a65680ff797cd07d4d36 100755 (executable)
--- a/configure
+++ b/configure
@@ -2326,6 +2326,30 @@ if compile_prog "-Wimplicit-fallthrough" "" "-Wimplicit-fallthrough"; then
 fi
 print_config "-Wimplicit-fallthrough" "$fallthrough"
 
 fi
 print_config "-Wimplicit-fallthrough" "$fallthrough"
 
+##########################################
+# check for MADV_HUGEPAGE support
+if test "$thp" != "yes" ; then
+  thp="no"
+fi
+if test "$esx" != "yes" ; then
+  cat > $TMPC <<EOF
+#include <sys/mman.h>
+int main(void)
+{
+  return madvise(0, 0x1000, MADV_HUGEPAGE);
+}
+EOF
+  if compile_prog "" "" "thp" ; then
+    thp=yes
+  else
+    if test "$thp" = "yes" ; then
+      feature_not_found "Transparent Huge Page" ""
+    fi
+    thp=no
+  fi
+fi
+print_config "MADV_HUGEPAGE" "$thp"
+
 #############################################################################
 
 if test "$wordsize" = "64" ; then
 #############################################################################
 
 if test "$wordsize" = "64" ; then
@@ -2600,6 +2624,9 @@ fi
 if test "$fallthrough" = "yes"; then
   CFLAGS="$CFLAGS -Wimplicit-fallthrough"
 fi
 if test "$fallthrough" = "yes"; then
   CFLAGS="$CFLAGS -Wimplicit-fallthrough"
 fi
+if test "$thp" = "yes" ; then
+  output_sym "CONFIG_HAVE_THP"
+fi
 
 echo "LIBS+=$LIBS" >> $config_host_mak
 echo "GFIO_LIBS+=$GFIO_LIBS" >> $config_host_mak
 
 echo "LIBS+=$LIBS" >> $config_host_mak
 echo "GFIO_LIBS+=$GFIO_LIBS" >> $config_host_mak
index 308b4665444cd619b73e6f5c3aeefbed78e56002..55ba1ab36c9a163bec27a788ee05497ef94c6cad 100644 (file)
@@ -11,6 +11,7 @@
 #include <sys/mman.h>
 
 #include "../fio.h"
 #include <sys/mman.h>
 
 #include "../fio.h"
+#include "../optgroup.h"
 #include "../verify.h"
 
 /*
 #include "../verify.h"
 
 /*
@@ -26,11 +27,40 @@ struct fio_mmap_data {
        off_t mmap_off;
 };
 
        off_t mmap_off;
 };
 
+#ifdef CONFIG_HAVE_THP
+struct mmap_options {
+       void *pad;
+       unsigned int thp;
+};
+
+static struct fio_option options[] = {
+       {
+               .name   = "thp",
+               .lname  = "Transparent Huge Pages",
+               .type   = FIO_OPT_INT,
+               .off1   = offsetof(struct mmap_options, thp),
+               .help   = "Memory Advise Huge Page",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_MMAP,
+       },
+       {
+               .name = NULL,
+       },
+};
+#endif
+
 static bool fio_madvise_file(struct thread_data *td, struct fio_file *f,
                             size_t length)
 
 {
        struct fio_mmap_data *fmd = FILE_ENG_DATA(f);
 static bool fio_madvise_file(struct thread_data *td, struct fio_file *f,
                             size_t length)
 
 {
        struct fio_mmap_data *fmd = FILE_ENG_DATA(f);
+#ifdef CONFIG_HAVE_THP
+       struct mmap_options *o = td->eo;
+
+       /* Ignore errors on this optional advisory */
+       if (o->thp)
+               madvise(fmd->mmap_ptr, length, MADV_HUGEPAGE);
+#endif
 
        if (!td->o.fadvise_hint)
                return true;
 
        if (!td->o.fadvise_hint)
                return true;
@@ -50,11 +80,27 @@ static bool fio_madvise_file(struct thread_data *td, struct fio_file *f,
        return true;
 }
 
        return true;
 }
 
+#ifdef CONFIG_HAVE_THP
+static int fio_mmap_get_shared(struct thread_data *td)
+{
+       struct mmap_options *o = td->eo;
+
+       if (o->thp)
+               return MAP_PRIVATE;
+       return MAP_SHARED;
+}
+#else
+static int fio_mmap_get_shared(struct thread_data *td)
+{
+       return MAP_SHARED;
+}
+#endif
+
 static int fio_mmap_file(struct thread_data *td, struct fio_file *f,
                         size_t length, off_t off)
 {
        struct fio_mmap_data *fmd = FILE_ENG_DATA(f);
 static int fio_mmap_file(struct thread_data *td, struct fio_file *f,
                         size_t length, off_t off)
 {
        struct fio_mmap_data *fmd = FILE_ENG_DATA(f);
-       int flags = 0;
+       int flags = 0, shared = fio_mmap_get_shared(td);
 
        if (td_rw(td) && !td->o.verify_only)
                flags = PROT_READ | PROT_WRITE;
 
        if (td_rw(td) && !td->o.verify_only)
                flags = PROT_READ | PROT_WRITE;
@@ -66,7 +112,7 @@ static int fio_mmap_file(struct thread_data *td, struct fio_file *f,
        } else
                flags = PROT_READ;
 
        } else
                flags = PROT_READ;
 
-       fmd->mmap_ptr = mmap(NULL, length, flags, MAP_SHARED, f->fd, off);
+       fmd->mmap_ptr = mmap(NULL, length, flags, shared, f->fd, off);
        if (fmd->mmap_ptr == MAP_FAILED) {
                fmd->mmap_ptr = NULL;
                td_verror(td, errno, "mmap");
        if (fmd->mmap_ptr == MAP_FAILED) {
                fmd->mmap_ptr = NULL;
                td_verror(td, errno, "mmap");
@@ -275,6 +321,10 @@ static struct ioengine_ops ioengine = {
        .close_file     = fio_mmapio_close_file,
        .get_file_size  = generic_get_file_size,
        .flags          = FIO_SYNCIO | FIO_NOEXTEND,
        .close_file     = fio_mmapio_close_file,
        .get_file_size  = generic_get_file_size,
        .flags          = FIO_SYNCIO | FIO_NOEXTEND,
+#ifdef CONFIG_HAVE_THP
+       .options        = options,
+       .option_struct_size = sizeof(struct mmap_options),
+#endif
 };
 
 static void fio_init fio_mmapio_register(void)
 };
 
 static void fio_init fio_mmapio_register(void)
index adf4d09bbc18af119f843abd9e59eb6361cea5a2..bf1bb0360ce5247654be5f9227497208e512979b 100644 (file)
@@ -61,6 +61,7 @@ enum opt_category_group {
        __FIO_OPT_G_MTD,
        __FIO_OPT_G_HDFS,
        __FIO_OPT_G_SG,
        __FIO_OPT_G_MTD,
        __FIO_OPT_G_HDFS,
        __FIO_OPT_G_SG,
+       __FIO_OPT_G_MMAP,
        __FIO_OPT_G_NR,
 
        FIO_OPT_G_RATE          = (1ULL << __FIO_OPT_G_RATE),
        __FIO_OPT_G_NR,
 
        FIO_OPT_G_RATE          = (1ULL << __FIO_OPT_G_RATE),
@@ -97,6 +98,7 @@ enum opt_category_group {
        FIO_OPT_G_MTD           = (1ULL << __FIO_OPT_G_MTD),
        FIO_OPT_G_HDFS          = (1ULL << __FIO_OPT_G_HDFS),
        FIO_OPT_G_SG            = (1ULL << __FIO_OPT_G_SG),
        FIO_OPT_G_MTD           = (1ULL << __FIO_OPT_G_MTD),
        FIO_OPT_G_HDFS          = (1ULL << __FIO_OPT_G_HDFS),
        FIO_OPT_G_SG            = (1ULL << __FIO_OPT_G_SG),
+       FIO_OPT_G_MMAP          = (1ULL << __FIO_OPT_G_MMAP),
        FIO_OPT_G_INVALID       = (1ULL << __FIO_OPT_G_NR),
 };
 
        FIO_OPT_G_INVALID       = (1ULL << __FIO_OPT_G_NR),
 };