Skip to content

Commit 903c467

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 41e15e8 commit 903c467

File tree

2 files changed

+47
-55
lines changed

2 files changed

+47
-55
lines changed

src/provider/provider_devdax_memory.c

Lines changed: 42 additions & 50 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);
446+
// length and offset passed to mmap() have to be page-aligned
447+
if (IS_NOT_ALIGNED(devdax_ipc_data->offset, DEVDAX_PAGE_SIZE_2MB)) {
448+
LOG_ERR("incorrect offset (%zu) in IPC handle - it is not page-aligned",
449+
devdax_ipc_data->offset);
458450
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
459451
}
460452

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-
}
453+
// length and offset passed to mmap() have to be page-aligned
454+
size_t length_aligned =
455+
ALIGN_UP(devdax_ipc_data->length, DEVDAX_PAGE_SIZE_2MB);
467456

468-
umf_result_t ret = UMF_RESULT_SUCCESS;
469-
int fd = utils_devdax_open(devdax_provider->path);
457+
int fd = utils_devdax_open(devdax_ipc_data->path);
470458
if (fd == -1) {
471-
LOG_PERR("opening a devdax (%s) failed", devdax_provider->path);
459+
LOG_PERR("opening the devdax (%s) failed", devdax_ipc_data->path);
472460
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
473461
}
474462

475463
unsigned map_sync_flag = 0;
476464
utils_translate_mem_visibility_flag(UMF_MEM_MAP_SYNC, &map_sync_flag);
477465

478466
// 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) {
467+
char *addr =
468+
utils_mmap_file(NULL, length_aligned, devdax_ipc_data->protection,
469+
map_sync_flag, fd, devdax_ipc_data->offset);
470+
if (addr == NULL) {
483471
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED,
484472
errno);
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, length_aligned,
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, length_aligned,
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,16 @@ 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;
502+
// size passed to munmap() has to have the same value as in devdax_open_ipc_handle()
503+
size = ALIGN_UP(size, DEVDAX_PAGE_SIZE_2MB);
512504

513505
errno = 0;
514-
int ret = utils_munmap(devdax_provider->base, devdax_provider->size);
506+
int ret = utils_munmap(ptr, size);
515507
// ignore error when size == 0
516508
if (ret && (size > 0)) {
517509
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_FREE_FAILED,
518510
errno);
519-
LOG_PERR("memory unmapping failed");
511+
LOG_PERR("memory unmapping failed (ptr: %p, size: %zu)", ptr, size);
520512

521513
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
522514
}

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)