rpma: add support for libpmem2 to librpma engine in APM mode
authorKacper Stefanski <kacper.stefanski@intel.com>
Sun, 13 Feb 2022 23:02:23 +0000 (00:02 +0100)
committerLukasz Dorau <lukasz.dorau@intel.com>
Tue, 6 Sep 2022 11:47:28 +0000 (13:47 +0200)
Add support for libpmem2 to librpma fio engine in the APM mode.

Signed-off-by: Kacper Stefanski <kacper.stefanski@intel.com>
Makefile
configure
engines/librpma_fio.c
engines/librpma_fio.h
engines/librpma_fio_pmem.h [new file with mode: 0644]
engines/librpma_fio_pmem2.h [new file with mode: 0644]

index 634d2c931345658a2cfcc6c5872f1ec0ce24fe2d..f947f11c71eb7acc29dc40be6fa24893056ecc28 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -111,13 +111,21 @@ endif
 ifdef CONFIG_LIBRPMA_APM
   librpma_apm_SRCS = engines/librpma_apm.c
   librpma_fio_SRCS = engines/librpma_fio.c
-  librpma_apm_LIBS = -lrpma -lpmem
+  ifdef CONFIG_LIBPMEM2_INSTALLED
+    librpma_apm_LIBS = -lrpma -lpmem2
+  else
+    librpma_apm_LIBS = -lrpma -lpmem
+  endif
   ENGINES += librpma_apm
 endif
 ifdef CONFIG_LIBRPMA_GPSPM
   librpma_gpspm_SRCS = engines/librpma_gpspm.c engines/librpma_gpspm_flush.pb-c.c
   librpma_fio_SRCS = engines/librpma_fio.c
-  librpma_gpspm_LIBS = -lrpma -lpmem -lprotobuf-c
+  ifdef CONFIG_LIBPMEM2_INSTALLED
+    librpma_gpspm_LIBS = -lrpma -lpmem2 -lprotobuf-c
+  else
+    librpma_gpspm_LIBS = -lrpma -lpmem -lprotobuf-c
+  endif
   ENGINES += librpma_gpspm
 endif
 ifdef librpma_fio_SRCS
index a2b9bd4cc8f4bba04de60a207f4b8913614f0b2c..7741ef4fd850853aa4ba60a7453c15f927f89b8e 100755 (executable)
--- a/configure
+++ b/configure
@@ -2201,6 +2201,26 @@ EOF
 fi
 print_config "libpmem1_5" "$libpmem1_5"
 
+##########################################
+# Check whether we have libpmem2
+if test "$libpmem2" != "yes" ; then
+  libpmem2="no"
+fi
+cat > $TMPC << EOF
+#include <libpmem2.h>
+int main(int argc, char **argv)
+{
+  struct pmem2_config *cfg;
+  pmem2_config_new(&cfg);
+  pmem2_config_delete(&cfg);
+  return 0;
+}
+EOF
+if compile_prog "" "-lpmem2" "libpmem2"; then
+  libpmem2="yes"
+fi
+print_config "libpmem2" "$libpmem2"
+
 ##########################################
 # Check whether we have libpmemblk
 # libpmem is a prerequisite
@@ -2990,11 +3010,13 @@ if test "$libverbs" = "yes" -a "$rdmacm" = "yes" ; then
 fi
 # librpma is supported on the 'x86_64' architecture for now
 if test "$cpu" = "x86_64" -a "$libverbs" = "yes" -a "$rdmacm" = "yes" \
-    -a "$librpma" = "yes" -a "$libpmem" = "yes" ; then
+    -a "$librpma" = "yes" \
+    && test "$libpmem" = "yes" -o "$libpmem2" = "yes" ; then
   output_sym "CONFIG_LIBRPMA_APM"
 fi
 if test "$cpu" = "x86_64" -a "$libverbs" = "yes" -a "$rdmacm" = "yes" \
-    -a "$librpma" = "yes" -a "$libpmem" = "yes" -a "$libprotobuf_c" = "yes" ; then
+    -a "$librpma" = "yes" -a "$libprotobuf_c" = "yes" \
+    && test "$libpmem" = "yes" -o "$libpmem2" = "yes" ; then
   output_sym "CONFIG_LIBRPMA_GPSPM"
 fi
 if test "$clock_gettime" = "yes" ; then
@@ -3138,6 +3160,9 @@ fi
 if test "$pmem" = "yes" ; then
   output_sym "CONFIG_LIBPMEM"
 fi
+if test "$libpmem2" = "yes" ; then
+  output_sym "CONFIG_LIBPMEM2_INSTALLED"
+fi
 if test "$libime" = "yes" ; then
   output_sym "CONFIG_IME"
 fi
index a78a1e57676bb3665a06f09485130ed9f2637a47..42d6163ea19e1e14ae9c275bde19773a24b3fa03 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * librpma_fio: librpma_apm and librpma_gpspm engines' common part.
  *
- * Copyright 2021, Intel Corporation
+ * Copyright 2021-2022, Intel Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License,
  * GNU General Public License for more details.
  */
 
-#include "librpma_fio.h"
-
-#include <libpmem.h>
+#ifdef CONFIG_LIBPMEM2_INSTALLED
+#include "librpma_fio_pmem2.h"
+#else
+#include "librpma_fio_pmem.h"
+#endif /* CONFIG_LIBPMEM2_INSTALLED */
 
 struct fio_option librpma_fio_options[] = {
        {
@@ -111,10 +113,8 @@ char *librpma_fio_allocate_dram(struct thread_data *td, size_t size,
 char *librpma_fio_allocate_pmem(struct thread_data *td, struct fio_file *f,
                size_t size, struct librpma_fio_mem *mem)
 {
-       size_t size_mmap = 0;
-       char *mem_ptr = NULL;
-       int is_pmem = 0;
        size_t ws_offset;
+       mem->mem_ptr = NULL;
 
        if (size % page_size) {
                log_err("fio: size (%zu) is not aligned to page size (%zu)\n",
@@ -135,48 +135,24 @@ char *librpma_fio_allocate_pmem(struct thread_data *td, struct fio_file *f,
                return NULL;
        }
 
-       /* map the file */
-       mem_ptr = pmem_map_file(f->file_name, 0 /* len */, 0 /* flags */,
-                       0 /* mode */, &size_mmap, &is_pmem);
-       if (mem_ptr == NULL) {
-               log_err("fio: pmem_map_file(%s) failed\n", f->file_name);
-               /* pmem_map_file() sets errno on failure */
-               td_verror(td, errno, "pmem_map_file");
-               return NULL;
-       }
-
-       /* pmem is expected */
-       if (!is_pmem) {
-               log_err("fio: %s is not located in persistent memory\n",
+       if (librpma_fio_pmem_map_file(f, size, mem, ws_offset)) {
+               log_err("fio: librpma_fio_pmem_map_file(%s) failed\n",
                        f->file_name);
-               goto err_unmap;
-       }
-
-       /* check size of allocated persistent memory */
-       if (size_mmap < ws_offset + size) {
-               log_err(
-                       "fio: %s is too small to handle so many threads (%zu < %zu)\n",
-                       f->file_name, size_mmap, ws_offset + size);
-               goto err_unmap;
+               return NULL;
        }
 
        log_info("fio: size of memory mapped from the file %s: %zu\n",
-               f->file_name, size_mmap);
-
-       mem->mem_ptr = mem_ptr;
-       mem->size_mmap = size_mmap;
+               f->file_name, mem->size_mmap);
 
-       return mem_ptr + ws_offset;
+       log_info("fio: library used to map PMem from file: %s\n", RPMA_PMEM_USED);
 
-err_unmap:
-       (void) pmem_unmap(mem_ptr, size_mmap);
-       return NULL;
+       return mem->mem_ptr ? mem->mem_ptr + ws_offset : NULL;
 }
 
 void librpma_fio_free(struct librpma_fio_mem *mem)
 {
        if (mem->size_mmap)
-               (void) pmem_unmap(mem->mem_ptr, mem->size_mmap);
+               librpma_fio_unmap(mem);
        else
                free(mem->mem_ptr);
 }
index 912902357de1cc64b6fa324fb9b7b30684ca9856..480ded1bde15b24f80209ae688cf49ee26e0d2d5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * librpma_fio: librpma_apm and librpma_gpspm engines' common header.
  *
- * Copyright 2021, Intel Corporation
+ * Copyright 2021-2022, Intel Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License,
@@ -72,6 +72,11 @@ struct librpma_fio_mem {
 
        /* size of the mapped persistent memory */
        size_t size_mmap;
+
+#ifdef CONFIG_LIBPMEM2_INSTALLED
+       /* libpmem2 structure used for mapping PMem */
+       struct pmem2_map *map;
+#endif
 };
 
 char *librpma_fio_allocate_dram(struct thread_data *td, size_t size,
diff --git a/engines/librpma_fio_pmem.h b/engines/librpma_fio_pmem.h
new file mode 100644 (file)
index 0000000..4854292
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * librpma_fio_pmem: allocates pmem using libpmem.
+ *
+ * Copyright 2022, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2 as published by the Free Software Foundation..
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <libpmem.h>
+#include "librpma_fio.h"
+
+#define RPMA_PMEM_USED "libpmem"
+
+static int librpma_fio_pmem_map_file(struct fio_file *f, size_t size,
+               struct librpma_fio_mem *mem, size_t ws_offset)
+{
+       int is_pmem = 0;
+       size_t size_mmap = 0;
+
+       /* map the file */
+       mem->mem_ptr = pmem_map_file(f->file_name, 0 /* len */, 0 /* flags */,
+                       0 /* mode */, &size_mmap, &is_pmem);
+       if (mem->mem_ptr == NULL) {
+               /* pmem_map_file() sets errno on failure */
+               log_err("fio: pmem_map_file(%s) failed: %s (errno %i)\n",
+                       f->file_name, strerror(errno), errno);
+               return -1;
+       }
+
+       /* pmem is expected */
+       if (!is_pmem) {
+               log_err("fio: %s is not located in persistent memory\n",
+                       f->file_name);
+               goto err_unmap;
+       }
+
+       /* check size of allocated persistent memory */
+       if (size_mmap < ws_offset + size) {
+               log_err(
+                       "fio: %s is too small to handle so many threads (%zu < %zu)\n",
+                       f->file_name, size_mmap, ws_offset + size);
+               goto err_unmap;
+       }
+
+       log_info("fio: size of memory mapped from the file %s: %zu\n",
+               f->file_name, size_mmap);
+
+       mem->size_mmap = size_mmap;
+
+       return 0;
+
+err_unmap:
+       (void) pmem_unmap(mem->mem_ptr, size_mmap);
+       return -1;
+}
+
+static inline void librpma_fio_unmap(struct librpma_fio_mem *mem)
+{
+       (void) pmem_unmap(mem->mem_ptr, mem->size_mmap);
+}
diff --git a/engines/librpma_fio_pmem2.h b/engines/librpma_fio_pmem2.h
new file mode 100644 (file)
index 0000000..09a51f5
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * librpma_fio_pmem2: allocates pmem using libpmem2.
+ *
+ * Copyright 2022, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2 as published by the Free Software Foundation..
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <libpmem2.h>
+#include "librpma_fio.h"
+
+#define RPMA_PMEM_USED "libpmem2"
+
+static int librpma_fio_pmem_map_file(struct fio_file *f, size_t size,
+               struct librpma_fio_mem *mem, size_t ws_offset)
+{
+       int fd;
+       struct pmem2_config *cfg = NULL;
+       struct pmem2_map *map = NULL;
+       struct pmem2_source *src = NULL;
+
+       size_t size_mmap;
+
+       if((fd = open(f->file_name, O_RDWR)) < 0) {
+               log_err("fio: cannot open fio file\n");
+               return -1;
+       }
+
+       if (pmem2_source_from_fd(&src, fd) != 0) {
+               log_err("fio: pmem2_source_from_fd() failed\n");
+               goto err_close;
+       }
+
+       if (pmem2_config_new(&cfg) != 0) {
+               log_err("fio: pmem2_config_new() failed\n");
+               goto err_source_delete;
+       }
+
+       if (pmem2_config_set_required_store_granularity(cfg,
+                                       PMEM2_GRANULARITY_CACHE_LINE) != 0) {
+               log_err("fio: pmem2_config_set_required_store_granularity() failed: %s\n", pmem2_errormsg());
+               goto err_config_delete;
+       }
+
+       if (pmem2_map_new(&map, cfg, src) != 0) {
+               log_err("fio: pmem2_map_new(%s) failed: %s\n", f->file_name, pmem2_errormsg());
+               goto err_config_delete;
+       }
+
+       size_mmap = pmem2_map_get_size(map);
+
+       /* check size of allocated persistent memory */
+       if (size_mmap < ws_offset + size) {
+               log_err(
+                       "fio: %s is too small to handle so many threads (%zu < %zu)\n",
+                       f->file_name, size_mmap, ws_offset + size);
+               goto err_map_delete;
+       }
+
+       mem->mem_ptr = pmem2_map_get_address(map);
+       mem->size_mmap = size_mmap;
+       mem->map = map;
+       pmem2_config_delete(&cfg);
+       pmem2_source_delete(&src);
+       close(fd);
+
+       return 0;
+
+err_map_delete:
+       pmem2_map_delete(&map);
+err_config_delete:
+       pmem2_config_delete(&cfg);
+err_source_delete:
+       pmem2_source_delete(&src);
+err_close:
+       close(fd);
+
+       return -1;
+}
+
+static inline void librpma_fio_unmap(struct librpma_fio_mem *mem)
+{
+       (void) pmem2_map_delete(&mem->map);
+}