Skip to content

Commit 77ef32a

Browse files
authored
Merge pull request #838 from ldorau/Fix_devdax_open_ipc_handle
Fix devdax_open_ipc_handle() and devdax_close_ipc_handle()
2 parents 3bae087 + 74b91bb commit 77ef32a

File tree

6 files changed

+106
-79
lines changed

6 files changed

+106
-79
lines changed

src/base_alloc/base_alloc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ umf_ba_pool_t *umf_ba_create(size_t size) {
168168
char *data_ptr = (char *)&pool->data;
169169
size_t size_left = pool_size - offsetof(umf_ba_pool_t, data);
170170

171-
utils_align_ptr_size((void **)&data_ptr, &size_left, MEMORY_ALIGNMENT);
171+
utils_align_ptr_up_size_down((void **)&data_ptr, &size_left,
172+
MEMORY_ALIGNMENT);
172173

173174
// init free_lock
174175
utils_mutex_t *mutex = utils_mutex_init(&pool->metadata.free_lock);
@@ -209,7 +210,8 @@ void *umf_ba_alloc(umf_ba_pool_t *pool) {
209210
size_t size_left =
210211
pool->metadata.pool_size - offsetof(umf_ba_next_pool_t, data);
211212

212-
utils_align_ptr_size((void **)&data_ptr, &size_left, MEMORY_ALIGNMENT);
213+
utils_align_ptr_up_size_down((void **)&data_ptr, &size_left,
214+
MEMORY_ALIGNMENT);
213215
ba_divide_memory_into_chunks(pool, data_ptr, size_left);
214216
}
215217

src/base_alloc/base_alloc_linear.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ umf_ba_linear_pool_t *umf_ba_linear_create(size_t pool_size) {
9898
void *data_ptr = &pool->data;
9999
size_t size_left = pool_size - offsetof(umf_ba_linear_pool_t, data);
100100

101-
utils_align_ptr_size(&data_ptr, &size_left, MEMORY_ALIGNMENT);
101+
utils_align_ptr_up_size_down(&data_ptr, &size_left, MEMORY_ALIGNMENT);
102102

103103
pool->metadata.pool_size = pool_size;
104104
pool->metadata.data_ptr = data_ptr;
@@ -149,7 +149,7 @@ void *umf_ba_linear_alloc(umf_ba_linear_pool_t *pool, size_t size) {
149149
void *data_ptr = &new_pool->data;
150150
size_t size_left =
151151
new_pool->pool_size - offsetof(umf_ba_next_linear_pool_t, data);
152-
utils_align_ptr_size(&data_ptr, &size_left, MEMORY_ALIGNMENT);
152+
utils_align_ptr_up_size_down(&data_ptr, &size_left, MEMORY_ALIGNMENT);
153153

154154
pool->metadata.data_ptr = data_ptr;
155155
pool->metadata.size_left = size_left;

src/provider/provider_devdax_memory.c

Lines changed: 56 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ umf_memory_provider_ops_t *umfDevDaxMemoryProviderOps(void) {
3131
#include "utils_concurrency.h"
3232
#include "utils_log.h"
3333

34-
#define NODESET_STR_BUF_LEN 1024
34+
#define DEVDAX_PAGE_SIZE_2MB ((size_t)(2 * 1024 * 1024)) // == 2 MB
3535

3636
#define TLS_MSG_BUF_LEN 1024
3737

@@ -228,15 +228,20 @@ static umf_result_t devdax_alloc(void *provider, size_t size, size_t alignment,
228228
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
229229
}
230230

231-
// alignment must be a power of two and a multiple of sizeof(void *)
232-
if (alignment &&
233-
((alignment & (alignment - 1)) || (alignment % sizeof(void *)))) {
234-
LOG_ERR("wrong alignment: %zu (not a power of 2 or a multiple of "
235-
"sizeof(void *))",
236-
alignment);
231+
// alignment must be a power of two and a multiple or a divider of the page size
232+
if (alignment && ((alignment & (alignment - 1)) ||
233+
((alignment % DEVDAX_PAGE_SIZE_2MB) &&
234+
(DEVDAX_PAGE_SIZE_2MB % alignment)))) {
235+
LOG_ERR("wrong alignment: %zu (not a power of 2 or a multiple or a "
236+
"divider of the page size (%zu))",
237+
alignment, DEVDAX_PAGE_SIZE_2MB);
237238
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
238239
}
239240

241+
if (IS_NOT_ALIGNED(alignment, DEVDAX_PAGE_SIZE_2MB)) {
242+
alignment = ALIGN_UP(alignment, DEVDAX_PAGE_SIZE_2MB);
243+
}
244+
240245
devdax_memory_provider_t *devdax_provider =
241246
(devdax_memory_provider_t *)provider;
242247

@@ -300,7 +305,7 @@ static umf_result_t devdax_get_recommended_page_size(void *provider,
300305
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
301306
}
302307

303-
*page_size = utils_get_page_size();
308+
*page_size = DEVDAX_PAGE_SIZE_2MB;
304309

305310
return UMF_RESULT_SUCCESS;
306311
}
@@ -369,9 +374,11 @@ static umf_result_t devdax_allocation_merge(void *provider, void *lowPtr,
369374
}
370375

371376
typedef struct devdax_ipc_data_t {
372-
char dd_path[PATH_MAX]; // path to the /dev/dax
373-
size_t dd_size; // size of the /dev/dax
374-
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
375382
} devdax_ipc_data_t;
376383

377384
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) {
386393

387394
static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr,
388395
size_t size, void *providerIpcData) {
389-
(void)size; // unused
390-
391396
if (provider == NULL || ptr == NULL || providerIpcData == NULL) {
392397
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
393398
}
@@ -396,11 +401,12 @@ static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr,
396401
(devdax_memory_provider_t *)provider;
397402

398403
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;
399407
devdax_ipc_data->offset =
400408
(size_t)((uintptr_t)ptr - (uintptr_t)devdax_provider->base);
401-
strncpy(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX - 1);
402-
devdax_ipc_data->dd_path[PATH_MAX - 1] = '\0';
403-
devdax_ipc_data->dd_size = devdax_provider->size;
409+
devdax_ipc_data->length = size;
404410

405411
return UMF_RESULT_SUCCESS;
406412
}
@@ -416,16 +422,9 @@ static umf_result_t devdax_put_ipc_handle(void *provider,
416422
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;
417423

418424
// verify the path of the /dev/dax
419-
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) {
425+
if (strncmp(devdax_ipc_data->path, devdax_provider->path, PATH_MAX)) {
420426
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)",
421-
devdax_provider->path, devdax_ipc_data->dd_path);
422-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
423-
}
424-
425-
// verify the size of the /dev/dax
426-
if (devdax_ipc_data->dd_size != devdax_provider->size) {
427-
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)",
428-
devdax_provider->size, devdax_ipc_data->dd_size);
427+
devdax_provider->path, devdax_ipc_data->path);
429428
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
430429
}
431430

@@ -438,58 +437,54 @@ static umf_result_t devdax_open_ipc_handle(void *provider,
438437
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
439438
}
440439

441-
devdax_memory_provider_t *devdax_provider =
442-
(devdax_memory_provider_t *)provider;
443440
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;
444441

445-
// verify it is the same devdax - first verify the path
446-
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) {
447-
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)",
448-
devdax_provider->path, devdax_ipc_data->dd_path);
449-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
450-
}
451-
452-
// verify the size of the /dev/dax
453-
if (devdax_ipc_data->dd_size != devdax_provider->size) {
454-
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)",
455-
devdax_provider->size, devdax_ipc_data->dd_size);
456-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
457-
}
458-
459-
umf_result_t ret = UMF_RESULT_SUCCESS;
460-
int fd = utils_devdax_open(devdax_provider->path);
442+
int fd = utils_devdax_open(devdax_ipc_data->path);
461443
if (fd == -1) {
462-
LOG_PERR("opening a devdax (%s) failed", devdax_provider->path);
444+
LOG_PERR("opening the devdax (%s) failed", devdax_ipc_data->path);
463445
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
464446
}
465447

466448
unsigned map_sync_flag = 0;
467449
utils_translate_mem_visibility_flag(UMF_MEM_MAP_SYNC, &map_sync_flag);
468450

451+
// It is just a workaround for case when
452+
// devdax_alloc() was called with the size argument
453+
// that is not a multiplier of DEVDAX_PAGE_SIZE_2MB.
454+
size_t offset_aligned = devdax_ipc_data->offset;
455+
size_t length_aligned = devdax_ipc_data->length;
456+
utils_align_ptr_down_size_up((void **)&offset_aligned, &length_aligned,
457+
DEVDAX_PAGE_SIZE_2MB);
458+
469459
// mmap /dev/dax with the MAP_SYNC xor MAP_SHARED flag (if MAP_SYNC fails)
470-
char *base = utils_mmap_file(NULL, devdax_provider->size,
471-
devdax_provider->protection, map_sync_flag, fd,
472-
0 /* offset */);
473-
if (base == NULL) {
460+
char *addr =
461+
utils_mmap_file(NULL, length_aligned, devdax_ipc_data->protection,
462+
map_sync_flag, fd, offset_aligned);
463+
if (addr == NULL) {
474464
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED,
475465
errno);
466+
476467
LOG_PERR("devdax mapping failed (path: %s, size: %zu, protection: %i, "
477-
"fd: %i)",
478-
devdax_provider->path, devdax_provider->size,
479-
devdax_provider->protection, fd);
480-
ret = UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
468+
"fd: %i, offset: %zu)",
469+
devdax_ipc_data->path, length_aligned,
470+
devdax_ipc_data->protection, fd, offset_aligned);
471+
472+
*ptr = NULL;
473+
(void)utils_close_fd(fd);
474+
475+
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
481476
}
482477

483478
LOG_DEBUG("devdax mapped (path: %s, size: %zu, protection: %i, fd: %i, "
484-
"offset: %zu)",
485-
devdax_provider->path, devdax_provider->size,
486-
devdax_provider->protection, fd, devdax_ipc_data->offset);
479+
"offset: %zu) to address %p",
480+
devdax_ipc_data->path, length_aligned,
481+
devdax_ipc_data->protection, fd, offset_aligned, addr);
487482

488-
(void)utils_close_fd(fd);
483+
*ptr = addr;
489484

490-
*ptr = base + devdax_ipc_data->offset;
485+
(void)utils_close_fd(fd);
491486

492-
return ret;
487+
return UMF_RESULT_SUCCESS;
493488
}
494489

495490
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,
498493
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
499494
}
500495

501-
devdax_memory_provider_t *devdax_provider =
502-
(devdax_memory_provider_t *)provider;
496+
size = ALIGN_UP(size, DEVDAX_PAGE_SIZE_2MB);
503497

504498
errno = 0;
505-
int ret = utils_munmap(devdax_provider->base, devdax_provider->size);
499+
int ret = utils_munmap(ptr, size);
506500
// ignore error when size == 0
507501
if (ret && (size > 0)) {
508502
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_FREE_FAILED,
509503
errno);
510-
LOG_PERR("memory unmapping failed");
504+
LOG_PERR("memory unmapping failed (ptr: %p, size: %zu)", ptr, size);
511505

512506
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
513507
}

src/utils/utils_common.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,42 @@
1212
#include "utils_assert.h"
1313
#include "utils_common.h"
1414

15-
// align a pointer and a size
16-
void utils_align_ptr_size(void **ptr, size_t *size, size_t alignment) {
15+
// align a pointer up and a size down
16+
void utils_align_ptr_up_size_down(void **ptr, size_t *size, size_t alignment) {
1717
uintptr_t p = (uintptr_t)*ptr;
1818
size_t s = *size;
1919

20-
// align pointer to 'alignment' bytes and adjust the size
20+
// align the pointer up to 'alignment' bytes and adjust the size down
2121
size_t rest = p & (alignment - 1);
2222
if (rest) {
23-
p += alignment - rest;
23+
p = ALIGN_UP(p, alignment);
2424
s -= alignment - rest;
2525
}
2626

27-
ASSERT((p & (alignment - 1)) == 0);
28-
ASSERT((s & (alignment - 1)) == 0);
27+
ASSERT(IS_ALIGNED(p, alignment));
28+
ASSERT(IS_ALIGNED(s, alignment));
29+
30+
*ptr = (void *)p;
31+
*size = s;
32+
}
33+
34+
// align a pointer down and a size up (for mmap()/munmap())
35+
void utils_align_ptr_down_size_up(void **ptr, size_t *size, size_t alignment) {
36+
uintptr_t p = (uintptr_t)*ptr;
37+
size_t s = *size;
38+
39+
// align the pointer down to 'alignment' bytes and adjust the size up
40+
size_t rest = p & (alignment - 1);
41+
if (rest) {
42+
p = ALIGN_DOWN(p, alignment);
43+
s += rest;
44+
}
45+
46+
// align the size up to 'alignment' bytes
47+
s = ALIGN_UP(s, alignment);
48+
49+
ASSERT(IS_ALIGNED(p, alignment));
50+
ASSERT(IS_ALIGNED(s, alignment));
2951

3052
*ptr = (void *)p;
3153
*size = s;

src/utils/utils_common.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,11 @@ int utils_is_running_in_proxy_lib(void);
8282

8383
size_t utils_get_page_size(void);
8484

85-
// align a pointer and a size
86-
void utils_align_ptr_size(void **ptr, size_t *size, size_t alignment);
85+
// align a pointer up and a size down
86+
void utils_align_ptr_up_size_down(void **ptr, size_t *size, size_t alignment);
87+
88+
// align a pointer down and a size up (for mmap()/munmap())
89+
void utils_align_ptr_down_size_up(void **ptr, size_t *size, size_t alignment);
8790

8891
// get the current process ID
8992
int utils_getpid(void);

test/provider_devdax_memory.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,13 @@ INSTANTIATE_TEST_SUITE_P(devdaxProviderTest, umfProviderTest,
190190

191191
TEST_P(umfProviderTest, create_destroy) {}
192192

193-
TEST_P(umfProviderTest, alloc_page64_align_0) {
194-
test_alloc_free_success(provider.get(), page_plus_64, 0, PURGE_NONE);
193+
TEST_P(umfProviderTest, alloc_page_align_0) {
194+
test_alloc_free_success(provider.get(), page_size, 0, PURGE_NONE);
195+
}
196+
197+
TEST_P(umfProviderTest, alloc_2page_align_page_size) {
198+
test_alloc_free_success(provider.get(), 2 * page_size, page_size,
199+
PURGE_NONE);
195200
}
196201

197202
TEST_P(umfProviderTest, alloc_page64_align_page_div_2) {
@@ -200,11 +205,11 @@ TEST_P(umfProviderTest, alloc_page64_align_page_div_2) {
200205
}
201206

202207
TEST_P(umfProviderTest, purge_lazy) {
203-
test_alloc_free_success(provider.get(), page_plus_64, 0, PURGE_LAZY);
208+
test_alloc_free_success(provider.get(), page_size, 0, PURGE_LAZY);
204209
}
205210

206211
TEST_P(umfProviderTest, purge_force) {
207-
test_alloc_free_success(provider.get(), page_plus_64, 0, PURGE_FORCE);
212+
test_alloc_free_success(provider.get(), page_size, 0, PURGE_FORCE);
208213
}
209214

210215
// negative tests using test_alloc_failure
@@ -231,7 +236,8 @@ TEST_P(umfProviderTest, alloc_3_pages_WRONG_ALIGNMENT_3_pages) {
231236
}
232237

233238
TEST_P(umfProviderTest, alloc_WRONG_SIZE) {
234-
test_alloc_failure(provider.get(), -1, 0,
239+
size_t size = (size_t)(-1) & ~(page_size - 1);
240+
test_alloc_failure(provider.get(), size, 0,
235241
UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC,
236242
UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED);
237243
}

0 commit comments

Comments
 (0)