-
Notifications
You must be signed in to change notification settings - Fork 37
Fix devdax_open_ipc_handle() and devdax_close_ipc_handle() #838
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
Changes from all commits
2034c4e
d182403
454fcd9
a677109
74b91bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,7 @@ umf_memory_provider_ops_t *umfDevDaxMemoryProviderOps(void) { | |
#include "utils_concurrency.h" | ||
#include "utils_log.h" | ||
|
||
#define NODESET_STR_BUF_LEN 1024 | ||
#define DEVDAX_PAGE_SIZE_2MB ((size_t)(2 * 1024 * 1024)) // == 2 MB | ||
|
||
#define TLS_MSG_BUF_LEN 1024 | ||
|
||
|
@@ -228,15 +228,20 @@ static umf_result_t devdax_alloc(void *provider, size_t size, size_t alignment, | |
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
// alignment must be a power of two and a multiple of sizeof(void *) | ||
if (alignment && | ||
((alignment & (alignment - 1)) || (alignment % sizeof(void *)))) { | ||
LOG_ERR("wrong alignment: %zu (not a power of 2 or a multiple of " | ||
"sizeof(void *))", | ||
alignment); | ||
// alignment must be a power of two and a multiple or a divider of the page size | ||
if (alignment && ((alignment & (alignment - 1)) || | ||
((alignment % DEVDAX_PAGE_SIZE_2MB) && | ||
(DEVDAX_PAGE_SIZE_2MB % alignment)))) { | ||
LOG_ERR("wrong alignment: %zu (not a power of 2 or a multiple or a " | ||
"divider of the page size (%zu))", | ||
alignment, DEVDAX_PAGE_SIZE_2MB); | ||
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
if (IS_NOT_ALIGNED(alignment, DEVDAX_PAGE_SIZE_2MB)) { | ||
alignment = ALIGN_UP(alignment, DEVDAX_PAGE_SIZE_2MB); | ||
} | ||
|
||
devdax_memory_provider_t *devdax_provider = | ||
(devdax_memory_provider_t *)provider; | ||
|
||
|
@@ -300,7 +305,7 @@ static umf_result_t devdax_get_recommended_page_size(void *provider, | |
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
*page_size = utils_get_page_size(); | ||
*page_size = DEVDAX_PAGE_SIZE_2MB; | ||
|
||
return UMF_RESULT_SUCCESS; | ||
} | ||
|
@@ -369,9 +374,11 @@ static umf_result_t devdax_allocation_merge(void *provider, void *lowPtr, | |
} | ||
|
||
typedef struct devdax_ipc_data_t { | ||
char dd_path[PATH_MAX]; // path to the /dev/dax | ||
size_t dd_size; // size of the /dev/dax | ||
size_t offset; // offset of the data | ||
char path[PATH_MAX]; // path to the /dev/dax | ||
unsigned protection; // combination of OS-specific memory protection flags | ||
// offset of the data (from the beginning of the devdax mapping) - see devdax_get_ipc_handle() | ||
size_t offset; | ||
size_t length; // length of the data | ||
} devdax_ipc_data_t; | ||
|
||
static umf_result_t devdax_get_ipc_handle_size(void *provider, size_t *size) { | ||
|
@@ -386,8 +393,6 @@ static umf_result_t devdax_get_ipc_handle_size(void *provider, size_t *size) { | |
|
||
static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr, | ||
size_t size, void *providerIpcData) { | ||
(void)size; // unused | ||
|
||
if (provider == NULL || ptr == NULL || providerIpcData == NULL) { | ||
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
@@ -396,11 +401,12 @@ static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr, | |
(devdax_memory_provider_t *)provider; | ||
|
||
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData; | ||
strncpy(devdax_ipc_data->path, devdax_provider->path, PATH_MAX - 1); | ||
devdax_ipc_data->path[PATH_MAX - 1] = '\0'; | ||
devdax_ipc_data->protection = devdax_provider->protection; | ||
devdax_ipc_data->offset = | ||
(size_t)((uintptr_t)ptr - (uintptr_t)devdax_provider->base); | ||
strncpy(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX - 1); | ||
devdax_ipc_data->dd_path[PATH_MAX - 1] = '\0'; | ||
devdax_ipc_data->dd_size = devdax_provider->size; | ||
devdax_ipc_data->length = size; | ||
|
||
return UMF_RESULT_SUCCESS; | ||
} | ||
|
@@ -416,16 +422,9 @@ static umf_result_t devdax_put_ipc_handle(void *provider, | |
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData; | ||
|
||
// verify the path of the /dev/dax | ||
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) { | ||
if (strncmp(devdax_ipc_data->path, devdax_provider->path, PATH_MAX)) { | ||
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)", | ||
devdax_provider->path, devdax_ipc_data->dd_path); | ||
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
// verify the size of the /dev/dax | ||
if (devdax_ipc_data->dd_size != devdax_provider->size) { | ||
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)", | ||
devdax_provider->size, devdax_ipc_data->dd_size); | ||
devdax_provider->path, devdax_ipc_data->path); | ||
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
|
@@ -438,58 +437,54 @@ static umf_result_t devdax_open_ipc_handle(void *provider, | |
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
devdax_memory_provider_t *devdax_provider = | ||
(devdax_memory_provider_t *)provider; | ||
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData; | ||
|
||
// verify it is the same devdax - first verify the path | ||
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) { | ||
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)", | ||
devdax_provider->path, devdax_ipc_data->dd_path); | ||
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
// verify the size of the /dev/dax | ||
if (devdax_ipc_data->dd_size != devdax_provider->size) { | ||
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)", | ||
devdax_provider->size, devdax_ipc_data->dd_size); | ||
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
umf_result_t ret = UMF_RESULT_SUCCESS; | ||
int fd = utils_devdax_open(devdax_provider->path); | ||
int fd = utils_devdax_open(devdax_ipc_data->path); | ||
if (fd == -1) { | ||
LOG_PERR("opening a devdax (%s) failed", devdax_provider->path); | ||
LOG_PERR("opening the devdax (%s) failed", devdax_ipc_data->path); | ||
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
unsigned map_sync_flag = 0; | ||
utils_translate_mem_visibility_flag(UMF_MEM_MAP_SYNC, &map_sync_flag); | ||
|
||
// It is just a workaround for case when | ||
// devdax_alloc() was called with the size argument | ||
// that is not a multiplier of DEVDAX_PAGE_SIZE_2MB. | ||
size_t offset_aligned = devdax_ipc_data->offset; | ||
size_t length_aligned = devdax_ipc_data->length; | ||
utils_align_ptr_down_size_up((void **)&offset_aligned, &length_aligned, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really need this call to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it is needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I got it. In case of arbitrary alignment such logic makes sense, but does arbitrary alignment in case of any memory provider (not only devdax) makes sense. I can assume that alignment always is a multiply of the page size. Did I miss something? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. User-requested alignment (given as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, but the memory provider API is closer to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the main issue is that we cannot require the size (in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think with alloc function everything is easy, we can support 4KB allocations because we just update the offset and do actual mapping at the init phase. The question is about ope_ip_handle how should we implement it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vinser52 please review the new version - there is no up-alignment in open/close_IPC_handle any more There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new IPC tests (#845) pass too: https://github.com/oneapi-src/unified-memory-framework/actions/runs/11596112796/job/32286377438 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vinser52 Done. |
||
DEVDAX_PAGE_SIZE_2MB); | ||
|
||
// 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) { | ||
char *addr = | ||
utils_mmap_file(NULL, length_aligned, devdax_ipc_data->protection, | ||
map_sync_flag, fd, offset_aligned); | ||
if (addr == NULL) { | ||
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED, | ||
errno); | ||
|
||
LOG_PERR("devdax mapping failed (path: %s, size: %zu, protection: %i, " | ||
"fd: %i)", | ||
devdax_provider->path, devdax_provider->size, | ||
devdax_provider->protection, fd); | ||
ret = UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
"fd: %i, offset: %zu)", | ||
devdax_ipc_data->path, length_aligned, | ||
devdax_ipc_data->protection, fd, offset_aligned); | ||
|
||
*ptr = NULL; | ||
(void)utils_close_fd(fd); | ||
|
||
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
} | ||
|
||
LOG_DEBUG("devdax mapped (path: %s, size: %zu, protection: %i, fd: %i, " | ||
"offset: %zu)", | ||
devdax_provider->path, devdax_provider->size, | ||
devdax_provider->protection, fd, devdax_ipc_data->offset); | ||
"offset: %zu) to address %p", | ||
devdax_ipc_data->path, length_aligned, | ||
devdax_ipc_data->protection, fd, offset_aligned, addr); | ||
|
||
(void)utils_close_fd(fd); | ||
*ptr = addr; | ||
|
||
*ptr = base + devdax_ipc_data->offset; | ||
(void)utils_close_fd(fd); | ||
|
||
return ret; | ||
return UMF_RESULT_SUCCESS; | ||
} | ||
|
||
static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr, | ||
|
@@ -498,16 +493,15 @@ static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr, | |
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
devdax_memory_provider_t *devdax_provider = | ||
(devdax_memory_provider_t *)provider; | ||
size = ALIGN_UP(size, DEVDAX_PAGE_SIZE_2MB); | ||
|
||
errno = 0; | ||
int ret = utils_munmap(devdax_provider->base, devdax_provider->size); | ||
int ret = utils_munmap(ptr, size); | ||
// ignore error when size == 0 | ||
if (ret && (size > 0)) { | ||
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_FREE_FAILED, | ||
errno); | ||
LOG_PERR("memory unmapping failed"); | ||
LOG_PERR("memory unmapping failed (ptr: %p, size: %zu)", ptr, size); | ||
|
||
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To ensure I understand it correctly, will 4 KB also pass this check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, 4kB is a divider of 2MB