From 77f9221af4305f59b71fbba7304907fa68184583 Mon Sep 17 00:00:00 2001 From: Lukasz Dorau Date: Fri, 20 Sep 2024 21:00:46 +0200 Subject: [PATCH 1/3] Add UMF_MEM_MAP_SYNC for MAP_SYNC on Linux only Signed-off-by: Lukasz Dorau --- include/umf/memory_provider.h | 3 ++- src/utils/utils_linux_common.c | 3 +++ src/utils/utils_macosx_common.c | 2 ++ src/utils/utils_windows_common.c | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/umf/memory_provider.h b/include/umf/memory_provider.h index fb217a0e8..073b04efb 100644 --- a/include/umf/memory_provider.h +++ b/include/umf/memory_provider.h @@ -20,7 +20,8 @@ extern "C" { /// @brief Memory visibility mode typedef enum umf_memory_visibility_t { UMF_MEM_MAP_PRIVATE = 1, ///< private memory mapping - UMF_MEM_MAP_SHARED, ///< shared memory mapping (supported on Linux only) + UMF_MEM_MAP_SHARED, ///< shared memory mapping (Linux only) + UMF_MEM_MAP_SYNC, ///< direct mapping of persistent memory (supported only for files supporting DAX, Linux only) } umf_memory_visibility_t; /// @brief Protection of the memory allocations diff --git a/src/utils/utils_linux_common.c b/src/utils/utils_linux_common.c index f5f76be21..0c9347f92 100644 --- a/src/utils/utils_linux_common.c +++ b/src/utils/utils_linux_common.c @@ -31,6 +31,9 @@ utils_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, case UMF_MEM_MAP_SHARED: *out_flag = MAP_SHARED; return UMF_RESULT_SUCCESS; + case UMF_MEM_MAP_SYNC: + *out_flag = MAP_SYNC; + return UMF_RESULT_SUCCESS; } return UMF_RESULT_ERROR_INVALID_ARGUMENT; } diff --git a/src/utils/utils_macosx_common.c b/src/utils/utils_macosx_common.c index 9c91e2b01..d54b346b2 100644 --- a/src/utils/utils_macosx_common.c +++ b/src/utils/utils_macosx_common.c @@ -23,6 +23,8 @@ utils_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, return UMF_RESULT_SUCCESS; case UMF_MEM_MAP_SHARED: return UMF_RESULT_ERROR_NOT_SUPPORTED; // not supported on MacOSX + case UMF_MEM_MAP_SYNC: + return UMF_RESULT_ERROR_NOT_SUPPORTED; // not supported on MacOSX } return UMF_RESULT_ERROR_INVALID_ARGUMENT; } diff --git a/src/utils/utils_windows_common.c b/src/utils/utils_windows_common.c index 33faa1b97..fa1b76c9d 100644 --- a/src/utils/utils_windows_common.c +++ b/src/utils/utils_windows_common.c @@ -96,6 +96,8 @@ utils_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, return UMF_RESULT_SUCCESS; case UMF_MEM_MAP_SHARED: return UMF_RESULT_ERROR_NOT_SUPPORTED; // not supported on Windows yet + case UMF_MEM_MAP_SYNC: + return UMF_RESULT_ERROR_NOT_SUPPORTED; // not supported on Windows yet } return UMF_RESULT_ERROR_INVALID_ARGUMENT; } From c03f5f6d6adf7a50ed2f4df6d8e2771600e1cdce Mon Sep 17 00:00:00 2001 From: Lukasz Dorau Date: Mon, 23 Sep 2024 12:04:55 +0200 Subject: [PATCH 2/3] Rename utils_devdax_mmap to utils_mmap_file and improve it Rename utils_devdax_mmap to utils_mmap_file and improve it: - add support for MAP_PRIVATE - add flags and fd_offset arguments Signed-off-by: Lukasz Dorau --- src/provider/provider_devdax_memory.c | 18 +++++-- src/utils/utils_common.h | 3 +- src/utils/utils_linux_common.c | 67 ++++++++++++++++++++------- src/utils/utils_macosx_common.c | 5 +- src/utils/utils_windows_common.c | 7 ++- 5 files changed, 75 insertions(+), 25 deletions(-) diff --git a/src/provider/provider_devdax_memory.c b/src/provider/provider_devdax_memory.c index ed0c2a25d..45fc725cc 100644 --- a/src/provider/provider_devdax_memory.c +++ b/src/provider/provider_devdax_memory.c @@ -130,8 +130,13 @@ static umf_result_t devdax_initialize(void *params, void **provider) { goto err_free_devdax_provider; } - devdax_provider->base = utils_devdax_mmap(NULL, devdax_provider->size, - devdax_provider->protection, fd); + unsigned map_sync_flag = 0; + utils_translate_mem_visibility_flag(UMF_MEM_MAP_SYNC, &map_sync_flag); + + // mmap /dev/dax with the MAP_SYNC xor MAP_SHARED flag (if MAP_SYNC fails) + devdax_provider->base = utils_mmap_file(NULL, devdax_provider->size, + devdax_provider->protection, + map_sync_flag, fd, 0 /* offset */); utils_close_fd(fd); if (devdax_provider->base == NULL) { LOG_PDEBUG("devdax memory mapping failed (path=%s, size=%zu)", @@ -458,8 +463,13 @@ static umf_result_t devdax_open_ipc_handle(void *provider, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - char *base = utils_devdax_mmap(NULL, devdax_provider->size, - devdax_provider->protection, fd); + unsigned map_sync_flag = 0; + utils_translate_mem_visibility_flag(UMF_MEM_MAP_SYNC, &map_sync_flag); + + // mmap /dev/dax with the MAP_SYNC xor MAP_SHARED flag (if MAP_SYNC fails) + char *base = utils_mmap_file(NULL, devdax_provider->size, + devdax_provider->protection, map_sync_flag, fd, + 0 /* offset */); if (base == NULL) { devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED, errno); diff --git a/src/utils/utils_common.h b/src/utils/utils_common.h index a58614061..999fc5745 100644 --- a/src/utils/utils_common.h +++ b/src/utils/utils_common.h @@ -124,7 +124,8 @@ int utils_set_file_size(int fd, size_t size); void *utils_mmap(void *hint_addr, size_t length, int prot, int flag, int fd, size_t fd_offset); -void *utils_devdax_mmap(void *hint_addr, size_t length, int prot, int fd); +void *utils_mmap_file(void *hint_addr, size_t length, int prot, int flags, + int fd, size_t fd_offset); int utils_munmap(void *addr, size_t length); diff --git a/src/utils/utils_linux_common.c b/src/utils/utils_linux_common.c index 0c9347f92..f1e6beb5d 100644 --- a/src/utils/utils_linux_common.c +++ b/src/utils/utils_linux_common.c @@ -39,24 +39,57 @@ utils_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, } /* - * MMap a /dev/dax device. - * First try to mmap with (MAP_SHARED_VALIDATE | MAP_SYNC) flags - * which allows flushing from the user-space. If MAP_SYNC fails - * try to mmap with MAP_SHARED flag (without MAP_SYNC). + * Map given file into memory. + * If (flags & MAP_PRIVATE) it uses just mmap. Otherwise, if (flags & MAP_SYNC) + * it tries to mmap with (flags | MAP_SHARED_VALIDATE | MAP_SYNC) + * which allows flushing from the user-space. If MAP_SYNC fails and the user + * did not specify it by himself it tries to mmap with (flags | MAP_SHARED). */ -void *utils_devdax_mmap(void *hint_addr, size_t length, int prot, int fd) { - void *ptr = utils_mmap(hint_addr, length, prot, - MAP_SHARED_VALIDATE | MAP_SYNC, fd, 0); - if (ptr) { - LOG_DEBUG( - "devdax mapped with the (MAP_SHARED_VALIDATE | MAP_SYNC) flags"); - return ptr; - } - - ptr = utils_mmap(hint_addr, length, prot, MAP_SHARED, fd, 0); - if (ptr) { - LOG_DEBUG("devdax mapped with the MAP_SHARED flag"); - return ptr; +void *utils_mmap_file(void *hint_addr, size_t length, int prot, int flags, + int fd, size_t fd_offset) { + void *addr; + + /* + * MAP_PRIVATE and MAP_SHARED are mutually exclusive, + * therefore mmap with MAP_PRIVATE is executed separately. + */ + if (flags & MAP_PRIVATE) { + addr = utils_mmap(hint_addr, length, prot, flags, fd, fd_offset); + if (addr == MAP_FAILED) { + LOG_PERR("mapping file with the MAP_PRIVATE flag failed"); + return NULL; + } + + LOG_DEBUG("file mapped with the MAP_PRIVATE flag"); + return addr; + } + + errno = 0; + + if (flags & MAP_SYNC) { + /* try to mmap with MAP_SYNC flag */ + const int sync_flags = MAP_SHARED_VALIDATE | MAP_SYNC; + addr = utils_mmap(hint_addr, length, prot, flags | sync_flags, fd, + fd_offset); + if (addr) { + LOG_DEBUG("file mapped with the MAP_SYNC flag"); + return addr; + } + + LOG_PERR("mapping file with the MAP_SYNC flag failed"); + } + + if ((!(flags & MAP_SYNC)) || errno == EINVAL || errno == ENOTSUP || + errno == EOPNOTSUPP) { + /* try to mmap with MAP_SHARED flag (without MAP_SYNC) */ + const int shared_flags = (flags & (~MAP_SYNC)) | MAP_SHARED; + addr = utils_mmap(hint_addr, length, prot, shared_flags, fd, fd_offset); + if (addr) { + LOG_DEBUG("file mapped with the MAP_SHARED flag"); + return addr; + } + + LOG_PERR("mapping file with the MAP_SHARED flag failed"); } return NULL; diff --git a/src/utils/utils_macosx_common.c b/src/utils/utils_macosx_common.c index d54b346b2..586f0fa52 100644 --- a/src/utils/utils_macosx_common.c +++ b/src/utils/utils_macosx_common.c @@ -29,11 +29,14 @@ utils_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } -void *utils_devdax_mmap(void *hint_addr, size_t length, int prot, int fd) { +void *utils_mmap_file(void *hint_addr, size_t length, int prot, int flags, + int fd, size_t fd_offset) { (void)hint_addr; // unused (void)length; // unused (void)prot; // unused + (void)flags; // unused (void)fd; // unused + (void)fd_offset; // unused return NULL; // not supported } diff --git a/src/utils/utils_windows_common.c b/src/utils/utils_windows_common.c index fa1b76c9d..4646b6f55 100644 --- a/src/utils/utils_windows_common.c +++ b/src/utils/utils_windows_common.c @@ -147,12 +147,15 @@ void *utils_mmap(void *hint_addr, size_t length, int prot, int flag, int fd, return VirtualAlloc(hint_addr, length, MEM_RESERVE | MEM_COMMIT, prot); } -void *utils_devdax_mmap(void *hint_addr, size_t length, int prot, int fd) { +void *utils_mmap_file(void *hint_addr, size_t length, int prot, int flags, + int fd, size_t fd_offset) { (void)hint_addr; // unused (void)length; // unused (void)prot; // unused + (void)flags; // unused (void)fd; // unused - return NULL; // not supported on Windows + (void)fd_offset; // unused + return NULL; // not supported } int utils_munmap(void *addr, size_t length) { From dadb2b6f74c75af2aaf842e5e4fdc1a8e5876f07 Mon Sep 17 00:00:00 2001 From: Lukasz Dorau Date: Fri, 20 Sep 2024 11:51:53 +0200 Subject: [PATCH 3/3] Add support for mapping with MAP_SYNC to file provider Add support for mapping with MAP_SYNC to file provider: use utils_mmap_file() instead of utils_mmap(). Signed-off-by: Lukasz Dorau --- README.md | 2 ++ src/provider/provider_file_memory.c | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0cfc50cdc..048bcfaf7 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,8 @@ so it should be used with a pool manager that will take over the managing of the provided memory - for example the jemalloc pool with the `disable_provider_free` parameter set to true. +The memory visibility mode parameter must be set to `UMF_MEM_MAP_SYNC` in case of FSDAX. + ##### Requirements 1) Linux OS diff --git a/src/provider/provider_file_memory.c b/src/provider/provider_file_memory.c index 757dcb1d0..ed9b23164 100644 --- a/src/provider/provider_file_memory.c +++ b/src/provider/provider_file_memory.c @@ -261,7 +261,7 @@ static umf_result_t file_mmap_aligned(file_memory_provider_t *file_provider, ASSERT_IS_ALIGNED(extended_size, page_size); ASSERT_IS_ALIGNED(offset_fd, page_size); - void *ptr = utils_mmap(NULL, extended_size, prot, flag, fd, offset_fd); + void *ptr = utils_mmap_file(NULL, extended_size, prot, flag, fd, offset_fd); if (ptr == NULL) { LOG_PERR("memory mapping failed"); return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; @@ -612,8 +612,9 @@ static umf_result_t file_open_ipc_handle(void *provider, void *providerIpcData, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - *ptr = utils_mmap(NULL, file_ipc_data->size, file_provider->protection, - file_provider->visibility, fd, file_ipc_data->offset_fd); + *ptr = utils_mmap_file(NULL, file_ipc_data->size, file_provider->protection, + file_provider->visibility, fd, + file_ipc_data->offset_fd); (void)utils_close_fd(fd); if (*ptr == NULL) { file_store_last_native_error(UMF_FILE_RESULT_ERROR_ALLOC_FAILED, errno);