Skip to content

Commit 52fd361

Browse files
committed
Fix devdax_open_ipc_handle() and devdax_close_ipc_handle()
devdax_open_ipc_handle() has to use the path of the remote /dev/dax got from the IPC handle, not the local one. devdax_open_ipc_handle() has to use also the memory protection got from the IPC handle, so let's add the memory protection to the IPC handle. devdax_open_ipc_handle() should mmap only the required range of memory, not the whole /dev/dax device, so let's add the length of the allocation to the IPC handle. devdax_close_ipc_handle() should unmap only the required range of memory, not the whole /dev/dax device. Fixes: #846 Signed-off-by: Lukasz Dorau <[email protected]>
1 parent a677109 commit 52fd361

File tree

2 files changed

+45
-59
lines changed

2 files changed

+45
-59
lines changed

src/provider/provider_devdax_memory.c

Lines changed: 40 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -374,9 +374,11 @@ static umf_result_t devdax_allocation_merge(void *provider, void *lowPtr,
374374
}
375375

376376
typedef struct devdax_ipc_data_t {
377-
char dd_path[PATH_MAX]; // path to the /dev/dax
378-
size_t dd_size; // size of the /dev/dax
379-
size_t offset; // offset of the data
377+
char path[PATH_MAX]; // path to the /dev/dax
378+
unsigned protection; // combination of OS-specific memory protection flags
379+
// offset of the data (from the beginning of the devdax mapping) - see devdax_get_ipc_handle()
380+
size_t offset;
381+
size_t length; // length of the data
380382
} devdax_ipc_data_t;
381383

382384
static umf_result_t devdax_get_ipc_handle_size(void *provider, size_t *size) {
@@ -391,8 +393,6 @@ static umf_result_t devdax_get_ipc_handle_size(void *provider, size_t *size) {
391393

392394
static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr,
393395
size_t size, void *providerIpcData) {
394-
(void)size; // unused
395-
396396
if (provider == NULL || ptr == NULL || providerIpcData == NULL) {
397397
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
398398
}
@@ -401,11 +401,12 @@ static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr,
401401
(devdax_memory_provider_t *)provider;
402402

403403
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;
404+
strncpy(devdax_ipc_data->path, devdax_provider->path, PATH_MAX - 1);
405+
devdax_ipc_data->path[PATH_MAX - 1] = '\0';
406+
devdax_ipc_data->protection = devdax_provider->protection;
404407
devdax_ipc_data->offset =
405408
(size_t)((uintptr_t)ptr - (uintptr_t)devdax_provider->base);
406-
strncpy(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX - 1);
407-
devdax_ipc_data->dd_path[PATH_MAX - 1] = '\0';
408-
devdax_ipc_data->dd_size = devdax_provider->size;
409+
devdax_ipc_data->length = size;
409410

410411
return UMF_RESULT_SUCCESS;
411412
}
@@ -421,16 +422,9 @@ static umf_result_t devdax_put_ipc_handle(void *provider,
421422
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;
422423

423424
// verify the path of the /dev/dax
424-
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) {
425+
if (strncmp(devdax_ipc_data->path, devdax_provider->path, PATH_MAX)) {
425426
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)",
426-
devdax_provider->path, devdax_ipc_data->dd_path);
427-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
428-
}
429-
430-
// verify the size of the /dev/dax
431-
if (devdax_ipc_data->dd_size != devdax_provider->size) {
432-
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)",
433-
devdax_provider->size, devdax_ipc_data->dd_size);
427+
devdax_provider->path, devdax_ipc_data->path);
434428
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
435429
}
436430

@@ -443,58 +437,51 @@ static umf_result_t devdax_open_ipc_handle(void *provider,
443437
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
444438
}
445439

446-
devdax_memory_provider_t *devdax_provider =
447-
(devdax_memory_provider_t *)provider;
448440
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;
449441

450-
// verify it is the same devdax - first verify the path
451-
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) {
452-
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)",
453-
devdax_provider->path, devdax_ipc_data->dd_path);
454-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
455-
}
456-
457-
// verify the size of the /dev/dax
458-
if (devdax_ipc_data->dd_size != devdax_provider->size) {
459-
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)",
460-
devdax_provider->size, devdax_ipc_data->dd_size);
461-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
462-
}
463-
464-
umf_result_t ret = UMF_RESULT_SUCCESS;
465-
int fd = utils_devdax_open(devdax_provider->path);
442+
int fd = utils_devdax_open(devdax_ipc_data->path);
466443
if (fd == -1) {
467-
LOG_PERR("opening a devdax (%s) failed", devdax_provider->path);
444+
LOG_PERR("opening the devdax (%s) failed", devdax_ipc_data->path);
468445
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
469446
}
470447

471448
unsigned map_sync_flag = 0;
472449
utils_translate_mem_visibility_flag(UMF_MEM_MAP_SYNC, &map_sync_flag);
473450

451+
size_t offset_aligned = devdax_ipc_data->offset;
452+
size_t length_aligned = devdax_ipc_data->length;
453+
utils_align_ptr_down_size_up((void **)&offset_aligned, &length_aligned,
454+
DEVDAX_PAGE_SIZE_2MB);
455+
474456
// mmap /dev/dax with the MAP_SYNC xor MAP_SHARED flag (if MAP_SYNC fails)
475-
char *base = utils_mmap_file(NULL, devdax_provider->size,
476-
devdax_provider->protection, map_sync_flag, fd,
477-
0 /* offset */);
478-
if (base == NULL) {
457+
char *addr =
458+
utils_mmap_file(NULL, length_aligned, devdax_ipc_data->protection,
459+
map_sync_flag, fd, offset_aligned);
460+
if (addr == NULL) {
479461
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED,
480462
errno);
463+
481464
LOG_PERR("devdax mapping failed (path: %s, size: %zu, protection: %i, "
482-
"fd: %i)",
483-
devdax_provider->path, devdax_provider->size,
484-
devdax_provider->protection, fd);
485-
ret = UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
465+
"fd: %i, offset: %zu)",
466+
devdax_ipc_data->path, length_aligned,
467+
devdax_ipc_data->protection, fd, offset_aligned);
468+
469+
*ptr = NULL;
470+
(void)utils_close_fd(fd);
471+
472+
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
486473
}
487474

488475
LOG_DEBUG("devdax mapped (path: %s, size: %zu, protection: %i, fd: %i, "
489-
"offset: %zu)",
490-
devdax_provider->path, devdax_provider->size,
491-
devdax_provider->protection, fd, devdax_ipc_data->offset);
476+
"offset: %zu) to address %p",
477+
devdax_ipc_data->path, length_aligned,
478+
devdax_ipc_data->protection, fd, offset_aligned, addr);
492479

493-
(void)utils_close_fd(fd);
480+
*ptr = addr;
494481

495-
*ptr = base + devdax_ipc_data->offset;
482+
(void)utils_close_fd(fd);
496483

497-
return ret;
484+
return UMF_RESULT_SUCCESS;
498485
}
499486

500487
static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr,
@@ -503,16 +490,15 @@ static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr,
503490
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
504491
}
505492

506-
devdax_memory_provider_t *devdax_provider =
507-
(devdax_memory_provider_t *)provider;
493+
size = ALIGN_UP(size, DEVDAX_PAGE_SIZE_2MB);
508494

509495
errno = 0;
510-
int ret = utils_munmap(devdax_provider->base, devdax_provider->size);
496+
int ret = utils_munmap(ptr, size);
511497
// ignore error when size == 0
512498
if (ret && (size > 0)) {
513499
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_FREE_FAILED,
514500
errno);
515-
LOG_PERR("memory unmapping failed");
501+
LOG_PERR("memory unmapping failed (ptr: %p, size: %zu)", ptr, size);
516502

517503
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
518504
}

test/provider_devdax_memory.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ TEST_P(umfProviderTest, alloc_2page_align_page_size) {
199199
PURGE_NONE);
200200
}
201201

202+
TEST_P(umfProviderTest, alloc_page64_align_page_div_2) {
203+
test_alloc_free_success(provider.get(), page_plus_64, page_size / 2,
204+
PURGE_NONE);
205+
}
206+
202207
TEST_P(umfProviderTest, purge_lazy) {
203208
test_alloc_free_success(provider.get(), page_size, 0, PURGE_LAZY);
204209
}
@@ -209,11 +214,6 @@ TEST_P(umfProviderTest, purge_force) {
209214

210215
// negative tests using test_alloc_failure
211216

212-
TEST_P(umfProviderTest, alloc_page64_align_page_div_2) {
213-
test_alloc_failure(provider.get(), page_plus_64, page_size / 2,
214-
UMF_RESULT_ERROR_INVALID_ARGUMENT, 0);
215-
}
216-
217217
TEST_P(umfProviderTest, alloc_page64_align_page_minus_1_WRONG_ALIGNMENT_1) {
218218
test_alloc_failure(provider.get(), page_plus_64, page_size - 1,
219219
UMF_RESULT_ERROR_INVALID_ARGUMENT, 0);

0 commit comments

Comments
 (0)