Skip to content

Commit ccd1784

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 349b320 commit ccd1784

File tree

2 files changed

+54
-60
lines changed

2 files changed

+54
-60
lines changed

src/provider/provider_devdax_memory.c

Lines changed: 49 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,11 @@ static umf_result_t devdax_allocation_merge(void *provider, void *lowPtr,
378378
}
379379

380380
typedef struct devdax_ipc_data_t {
381-
char dd_path[PATH_MAX]; // path to the /dev/dax
382-
size_t dd_size; // size of the /dev/dax
383-
size_t offset; // offset of the data
381+
char path[PATH_MAX]; // path to the /dev/dax
382+
unsigned protection; // combination of OS-specific memory protection flags
383+
// offset of the data (from the beginning of the devdax mapping) - see devdax_get_ipc_handle()
384+
size_t offset;
385+
size_t length; // length of the data
384386
} devdax_ipc_data_t;
385387

386388
static umf_result_t devdax_get_ipc_handle_size(void *provider, size_t *size) {
@@ -395,8 +397,6 @@ static umf_result_t devdax_get_ipc_handle_size(void *provider, size_t *size) {
395397

396398
static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr,
397399
size_t size, void *providerIpcData) {
398-
(void)size; // unused
399-
400400
if (provider == NULL || ptr == NULL || providerIpcData == NULL) {
401401
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
402402
}
@@ -405,11 +405,12 @@ static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr,
405405
(devdax_memory_provider_t *)provider;
406406

407407
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;
408+
strncpy(devdax_ipc_data->path, devdax_provider->path, PATH_MAX - 1);
409+
devdax_ipc_data->path[PATH_MAX - 1] = '\0';
410+
devdax_ipc_data->protection = devdax_provider->protection;
408411
devdax_ipc_data->offset =
409412
(size_t)((uintptr_t)ptr - (uintptr_t)devdax_provider->base);
410-
strncpy(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX - 1);
411-
devdax_ipc_data->dd_path[PATH_MAX - 1] = '\0';
412-
devdax_ipc_data->dd_size = devdax_provider->size;
413+
devdax_ipc_data->length = size;
413414

414415
return UMF_RESULT_SUCCESS;
415416
}
@@ -425,16 +426,9 @@ static umf_result_t devdax_put_ipc_handle(void *provider,
425426
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;
426427

427428
// verify the path of the /dev/dax
428-
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) {
429+
if (strncmp(devdax_ipc_data->path, devdax_provider->path, PATH_MAX)) {
429430
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)",
430-
devdax_provider->path, devdax_ipc_data->dd_path);
431-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
432-
}
433-
434-
// verify the size of the /dev/dax
435-
if (devdax_ipc_data->dd_size != devdax_provider->size) {
436-
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)",
437-
devdax_provider->size, devdax_ipc_data->dd_size);
431+
devdax_provider->path, devdax_ipc_data->path);
438432
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
439433
}
440434

@@ -447,58 +441,56 @@ static umf_result_t devdax_open_ipc_handle(void *provider,
447441
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
448442
}
449443

450-
devdax_memory_provider_t *devdax_provider =
451-
(devdax_memory_provider_t *)provider;
452444
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;
453445

454-
// verify it is the same devdax - first verify the path
455-
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) {
456-
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)",
457-
devdax_provider->path, devdax_ipc_data->dd_path);
458-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
459-
}
460-
461-
// verify the size of the /dev/dax
462-
if (devdax_ipc_data->dd_size != devdax_provider->size) {
463-
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)",
464-
devdax_provider->size, devdax_ipc_data->dd_size);
465-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
466-
}
467-
468-
umf_result_t ret = UMF_RESULT_SUCCESS;
469-
int fd = utils_devdax_open(devdax_provider->path);
446+
int fd = utils_devdax_open(devdax_ipc_data->path);
470447
if (fd == -1) {
471-
LOG_PERR("opening a devdax (%s) failed", devdax_provider->path);
448+
LOG_PERR("opening the devdax (%s) failed", devdax_ipc_data->path);
472449
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
473450
}
474451

475452
unsigned map_sync_flag = 0;
476453
utils_translate_mem_visibility_flag(UMF_MEM_MAP_SYNC, &map_sync_flag);
477454

478455
// mmap /dev/dax with the MAP_SYNC xor MAP_SHARED flag (if MAP_SYNC fails)
479-
char *base = utils_mmap_file(NULL, devdax_provider->size,
480-
devdax_provider->protection, map_sync_flag, fd,
481-
0 /* offset */);
482-
if (base == NULL) {
456+
char *addr = utils_mmap_file(NULL, devdax_ipc_data->length,
457+
devdax_ipc_data->protection, map_sync_flag, fd,
458+
devdax_ipc_data->offset);
459+
if (addr == NULL) {
483460
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED,
484461
errno);
462+
463+
if (IS_NOT_ALIGNED(devdax_ipc_data->offset, DEVDAX_PAGE_SIZE_2MB)) {
464+
LOG_WARN("offset (%zu) is not aligned to the page size (%zu)",
465+
devdax_ipc_data->offset, DEVDAX_PAGE_SIZE_2MB);
466+
}
467+
468+
if (IS_NOT_ALIGNED(devdax_ipc_data->length, DEVDAX_PAGE_SIZE_2MB)) {
469+
LOG_WARN("length (%zu) is not aligned to the page size (%zu)",
470+
devdax_ipc_data->length, DEVDAX_PAGE_SIZE_2MB);
471+
}
472+
485473
LOG_PERR("devdax mapping failed (path: %s, size: %zu, protection: %i, "
486-
"fd: %i)",
487-
devdax_provider->path, devdax_provider->size,
488-
devdax_provider->protection, fd);
489-
ret = UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
474+
"fd: %i, offset: %zu)",
475+
devdax_ipc_data->path, devdax_ipc_data->length,
476+
devdax_ipc_data->protection, fd, devdax_ipc_data->offset);
477+
478+
*ptr = NULL;
479+
(void)utils_close_fd(fd);
480+
481+
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
490482
}
491483

492484
LOG_DEBUG("devdax mapped (path: %s, size: %zu, protection: %i, fd: %i, "
493-
"offset: %zu)",
494-
devdax_provider->path, devdax_provider->size,
495-
devdax_provider->protection, fd, devdax_ipc_data->offset);
485+
"offset: %zu) to address %p",
486+
devdax_ipc_data->path, devdax_ipc_data->length,
487+
devdax_ipc_data->protection, fd, devdax_ipc_data->offset, addr);
496488

497-
(void)utils_close_fd(fd);
489+
*ptr = addr;
498490

499-
*ptr = base + devdax_ipc_data->offset;
491+
(void)utils_close_fd(fd);
500492

501-
return ret;
493+
return UMF_RESULT_SUCCESS;
502494
}
503495

504496
static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr,
@@ -507,16 +499,18 @@ static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr,
507499
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
508500
}
509501

510-
devdax_memory_provider_t *devdax_provider =
511-
(devdax_memory_provider_t *)provider;
512-
513502
errno = 0;
514-
int ret = utils_munmap(devdax_provider->base, devdax_provider->size);
503+
int ret = utils_munmap(ptr, size);
515504
// ignore error when size == 0
516505
if (ret && (size > 0)) {
517506
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_FREE_FAILED,
518507
errno);
519-
LOG_PERR("memory unmapping failed");
508+
if (IS_NOT_ALIGNED(size, DEVDAX_PAGE_SIZE_2MB)) {
509+
LOG_WARN("size (%zu) is not aligned to the page size (%zu)", size,
510+
DEVDAX_PAGE_SIZE_2MB);
511+
}
512+
513+
LOG_PERR("memory unmapping failed (ptr: %p, size: %zu)", ptr, size);
520514

521515
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
522516
}

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)