Skip to content

Add support for mapping with MAP_SYNC to file provider #746

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion include/umf/memory_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 14 additions & 4 deletions src/provider/provider_devdax_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)",
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 4 additions & 3 deletions src/provider/provider_file_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion src/utils/utils_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
70 changes: 53 additions & 17 deletions src/utils/utils_linux_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,65 @@ 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;
}

/*
* 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;
Expand Down
7 changes: 6 additions & 1 deletion src/utils/utils_macosx_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,20 @@ 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;
}

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
}

Expand Down
9 changes: 7 additions & 2 deletions src/utils/utils_windows_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -145,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) {
Expand Down
Loading