From 8fabefc1ceb2c9374c256b5e819a695bc94aedff Mon Sep 17 00:00:00 2001 From: Kacper Stefanski Date: Mon, 14 Feb 2022 00:02:23 +0100 Subject: [PATCH] rpma: add support for libpmem2 to librpma engine in APM mode Add support for libpmem2 to librpma fio engine in the APM mode. Signed-off-by: Kacper Stefanski --- Makefile | 12 ++++- configure | 29 +++++++++++- engines/librpma_fio.c | 52 ++++++--------------- engines/librpma_fio.h | 7 ++- engines/librpma_fio_pmem.h | 67 +++++++++++++++++++++++++++ engines/librpma_fio_pmem2.h | 91 +++++++++++++++++++++++++++++++++++++ 6 files changed, 215 insertions(+), 43 deletions(-) create mode 100644 engines/librpma_fio_pmem.h create mode 100644 engines/librpma_fio_pmem2.h diff --git a/Makefile b/Makefile index 634d2c9313..f947f11c71 100644 --- 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 diff --git a/configure b/configure index a2b9bd4cc8..7741ef4fd8 100755 --- 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 +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 diff --git a/engines/librpma_fio.c b/engines/librpma_fio.c index a78a1e5767..42d6163ea1 100644 --- a/engines/librpma_fio.c +++ b/engines/librpma_fio.c @@ -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, @@ -13,9 +13,11 @@ * GNU General Public License for more details. */ -#include "librpma_fio.h" - -#include +#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); } diff --git a/engines/librpma_fio.h b/engines/librpma_fio.h index 912902357d..480ded1bde 100644 --- a/engines/librpma_fio.h +++ b/engines/librpma_fio.h @@ -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 index 0000000000..4854292c4a --- /dev/null +++ b/engines/librpma_fio_pmem.h @@ -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 +#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 index 0000000000..09a51f5f40 --- /dev/null +++ b/engines/librpma_fio_pmem2.h @@ -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 +#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); +}