Skip to content

Use libcoarse in the file and the devdax providers #932

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

Merged
merged 5 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 72 additions & 76 deletions src/provider/provider_devdax_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ umf_result_t umfDevDaxMemoryProviderParamsSetProtection(
#else // !defined(_WIN32) && !defined(UMF_NO_HWLOC)

#include "base_alloc_global.h"
#include "coarse.h"
#include "libumf.h"
#include "utils_common.h"
#include "utils_concurrency.h"
Expand All @@ -74,6 +75,7 @@ typedef struct devdax_memory_provider_t {
size_t offset; // offset in the file used for memory mapping
utils_mutex_t lock; // lock of ptr and offset
unsigned protection; // combination of OS-specific protection flags
coarse_t *coarse; // coarse library handle
} devdax_memory_provider_t;

// DevDax Memory provider settings struct
Expand Down Expand Up @@ -133,6 +135,12 @@ devdax_translate_params(umf_devdax_memory_provider_params_t *in_params,
return UMF_RESULT_SUCCESS;
}

static umf_result_t devdax_allocation_split_cb(void *provider, void *ptr,
size_t totalSize,
size_t firstSize);
static umf_result_t devdax_allocation_merge_cb(void *provider, void *lowPtr,
void *highPtr, size_t totalSize);

static umf_result_t devdax_initialize(void *params, void **provider) {
umf_result_t ret;

Expand Down Expand Up @@ -161,21 +169,42 @@ static umf_result_t devdax_initialize(void *params, void **provider) {

memset(devdax_provider, 0, sizeof(*devdax_provider));

ret = devdax_translate_params(in_params, devdax_provider);
coarse_params_t coarse_params = {0};
coarse_params.provider = devdax_provider;
coarse_params.page_size = DEVDAX_PAGE_SIZE_2MB;
// The alloc callback is not available in case of the devdax provider
// because it is a fixed-size memory provider
// and the entire devdax memory is added as a single block
// to the coarse library.
coarse_params.cb.alloc = NULL;
coarse_params.cb.free = NULL; // not available for the devdax provider
coarse_params.cb.split = devdax_allocation_split_cb;
coarse_params.cb.merge = devdax_allocation_merge_cb;

coarse_t *coarse = NULL;
ret = coarse_new(&coarse_params, &coarse);
if (ret != UMF_RESULT_SUCCESS) {
LOG_ERR("coarse_new() failed");
goto err_free_devdax_provider;
}

devdax_provider->coarse = coarse;

ret = devdax_translate_params(in_params, devdax_provider);
if (ret != UMF_RESULT_SUCCESS) {
goto err_coarse_delete;
}

devdax_provider->size = in_params->size;
if (utils_copy_path(in_params->path, devdax_provider->path, PATH_MAX)) {
goto err_free_devdax_provider;
goto err_coarse_delete;
}

int fd = utils_devdax_open(in_params->path);
if (fd == -1) {
LOG_ERR("cannot open the device DAX: %s", in_params->path);
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT;
goto err_free_devdax_provider;
goto err_coarse_delete;
}

bool is_dax = false;
Expand All @@ -189,23 +218,26 @@ static umf_result_t devdax_initialize(void *params, void **provider) {
LOG_PDEBUG("mapping the devdax failed (path=%s, size=%zu)",
in_params->path, devdax_provider->size);
ret = UMF_RESULT_ERROR_UNKNOWN;
goto err_free_devdax_provider;
goto err_coarse_delete;
}

if (!is_dax) {
LOG_ERR("mapping the devdax with MAP_SYNC failed: %s", in_params->path);
ret = UMF_RESULT_ERROR_UNKNOWN;

if (devdax_provider->base) {
utils_munmap(devdax_provider->base, devdax_provider->size);
}

goto err_free_devdax_provider;
goto err_unmap_devdax;
}

LOG_DEBUG("devdax memory mapped (path=%s, size=%zu, addr=%p)",
in_params->path, devdax_provider->size, devdax_provider->base);

// add the entire devdax memory as a single block
ret = coarse_add_memory_fixed(coarse, devdax_provider->base,
devdax_provider->size);
if (ret != UMF_RESULT_SUCCESS) {
LOG_ERR("adding memory block failed");
goto err_unmap_devdax;
}

if (utils_mutex_init(&devdax_provider->lock) == NULL) {
LOG_ERR("lock init failed");
ret = UMF_RESULT_ERROR_UNKNOWN;
Expand All @@ -217,7 +249,11 @@ static umf_result_t devdax_initialize(void *params, void **provider) {
return UMF_RESULT_SUCCESS;

err_unmap_devdax:
utils_munmap(devdax_provider->base, devdax_provider->size);
if (devdax_provider->base) {
utils_munmap(devdax_provider->base, devdax_provider->size);
}
err_coarse_delete:
coarse_delete(devdax_provider->coarse);
err_free_devdax_provider:
umf_ba_global_free(devdax_provider);
return ret;
Expand All @@ -227,78 +263,15 @@ static void devdax_finalize(void *provider) {
devdax_memory_provider_t *devdax_provider = provider;
utils_mutex_destroy_not_free(&devdax_provider->lock);
utils_munmap(devdax_provider->base, devdax_provider->size);
coarse_delete(devdax_provider->coarse);
umf_ba_global_free(devdax_provider);
}

static int devdax_alloc_aligned(size_t length, size_t alignment, void *base,
size_t size, utils_mutex_t *lock,
void **out_addr, size_t *offset) {
assert(out_addr);

if (utils_mutex_lock(lock)) {
LOG_ERR("locking file offset failed");
return -1;
}

uintptr_t ptr = (uintptr_t)base + *offset;
uintptr_t rest_of_div = alignment ? (ptr % alignment) : 0;

if (alignment > 0 && rest_of_div > 0) {
ptr += alignment - rest_of_div;
}

size_t new_offset = ptr - (uintptr_t)base + length;

if (new_offset > size) {
utils_mutex_unlock(lock);
LOG_ERR("cannot allocate more memory than the device DAX size: %zu",
size);
return -1;
}

*offset = new_offset;
*out_addr = (void *)ptr;

utils_mutex_unlock(lock);

return 0;
}

static umf_result_t devdax_alloc(void *provider, size_t size, size_t alignment,
void **resultPtr) {
int ret;

// 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;

void *addr = NULL;
errno = 0;
ret = devdax_alloc_aligned(size, alignment, devdax_provider->base,
devdax_provider->size, &devdax_provider->lock,
&addr, &devdax_provider->offset);
if (ret) {
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED, 0);
LOG_ERR("memory allocation failed");
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
}

*resultPtr = addr;

return UMF_RESULT_SUCCESS;
return coarse_alloc(devdax_provider->coarse, size, alignment, resultPtr);
}

static void devdax_get_last_native_error(void *provider, const char **ppMessage,
Expand Down Expand Up @@ -384,6 +357,14 @@ static const char *devdax_get_name(void *provider) {
static umf_result_t devdax_allocation_split(void *provider, void *ptr,
size_t totalSize,
size_t firstSize) {
devdax_memory_provider_t *devdax_provider =
(devdax_memory_provider_t *)provider;
return coarse_split(devdax_provider->coarse, ptr, totalSize, firstSize);
}

static umf_result_t devdax_allocation_split_cb(void *provider, void *ptr,
size_t totalSize,
size_t firstSize) {
(void)provider;
(void)ptr;
(void)totalSize;
Expand All @@ -393,6 +374,14 @@ static umf_result_t devdax_allocation_split(void *provider, void *ptr,

static umf_result_t devdax_allocation_merge(void *provider, void *lowPtr,
void *highPtr, size_t totalSize) {
devdax_memory_provider_t *devdax_provider =
(devdax_memory_provider_t *)provider;
return coarse_merge(devdax_provider->coarse, lowPtr, highPtr, totalSize);
}

static umf_result_t devdax_allocation_merge_cb(void *provider, void *lowPtr,
void *highPtr,
size_t totalSize) {
(void)provider;
(void)lowPtr;
(void)highPtr;
Expand Down Expand Up @@ -527,6 +516,12 @@ static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr,
return UMF_RESULT_SUCCESS;
}

static umf_result_t devdax_free(void *provider, void *ptr, size_t size) {
devdax_memory_provider_t *devdax_provider =
(devdax_memory_provider_t *)provider;
return coarse_free(devdax_provider->coarse, ptr, size);
}

static umf_memory_provider_ops_t UMF_DEVDAX_MEMORY_PROVIDER_OPS = {
.version = UMF_VERSION_CURRENT,
.initialize = devdax_initialize,
Expand All @@ -536,6 +531,7 @@ static umf_memory_provider_ops_t UMF_DEVDAX_MEMORY_PROVIDER_OPS = {
.get_recommended_page_size = devdax_get_recommended_page_size,
.get_min_page_size = devdax_get_min_page_size,
.get_name = devdax_get_name,
.ext.free = devdax_free,
.ext.purge_lazy = devdax_purge_lazy,
.ext.purge_force = devdax_purge_force,
.ext.allocation_merge = devdax_allocation_merge,
Expand Down
61 changes: 57 additions & 4 deletions src/provider/provider_file_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ umf_result_t umfFileMemoryProviderParamsSetVisibility(
#else // !defined(_WIN32) && !defined(UMF_NO_HWLOC)

#include "base_alloc_global.h"
#include "coarse.h"
#include "critnib.h"
#include "libumf.h"
#include "utils_common.h"
Expand Down Expand Up @@ -101,6 +102,8 @@ typedef struct file_memory_provider_t {
// It is needed mainly in the get_ipc_handle and open_ipc_handle hooks
// to mmap a specific part of a file.
critnib *fd_offset_map;

coarse_t *coarse; // coarse library handle
} file_memory_provider_t;

// File Memory Provider settings struct
Expand Down Expand Up @@ -166,6 +169,14 @@ file_translate_params(umf_file_memory_provider_params_t *in_params,
return UMF_RESULT_SUCCESS;
}

static umf_result_t file_alloc_cb(void *provider, size_t size, size_t alignment,
void **resultPtr);
static umf_result_t file_allocation_split_cb(void *provider, void *ptr,
size_t totalSize,
size_t firstSize);
static umf_result_t file_allocation_merge_cb(void *provider, void *lowPtr,
void *highPtr, size_t totalSize);

static umf_result_t file_initialize(void *params, void **provider) {
umf_result_t ret;

Expand Down Expand Up @@ -233,10 +244,27 @@ static umf_result_t file_initialize(void *params, void **provider) {
file_provider->page_size = utils_get_page_size();
}

coarse_params_t coarse_params = {0};
coarse_params.provider = file_provider;
coarse_params.page_size = file_provider->page_size;
coarse_params.cb.alloc = file_alloc_cb;
coarse_params.cb.free = NULL; // not available for the file provider
coarse_params.cb.split = file_allocation_split_cb;
coarse_params.cb.merge = file_allocation_merge_cb;

coarse_t *coarse = NULL;
ret = coarse_new(&coarse_params, &coarse);
if (ret != UMF_RESULT_SUCCESS) {
LOG_ERR("coarse_new() failed");
goto err_close_fd;
}

file_provider->coarse = coarse;

if (utils_mutex_init(&file_provider->lock) == NULL) {
LOG_ERR("lock init failed");
ret = UMF_RESULT_ERROR_UNKNOWN;
goto err_close_fd;
goto err_coarse_delete;
}

file_provider->fd_offset_map = critnib_new();
Expand All @@ -261,6 +289,8 @@ static umf_result_t file_initialize(void *params, void **provider) {
critnib_delete(file_provider->fd_offset_map);
err_mutex_destroy_not_free:
utils_mutex_destroy_not_free(&file_provider->lock);
err_coarse_delete:
coarse_delete(file_provider->coarse);
err_close_fd:
utils_close_fd(file_provider->fd);
err_free_file_provider:
Expand All @@ -285,6 +315,7 @@ static void file_finalize(void *provider) {
utils_close_fd(file_provider->fd);
critnib_delete(file_provider->fd_offset_map);
critnib_delete(file_provider->mmaps);
coarse_delete(file_provider->coarse);
umf_ba_global_free(file_provider);
}

Expand Down Expand Up @@ -443,6 +474,12 @@ static umf_result_t file_alloc_aligned(file_memory_provider_t *file_provider,

static umf_result_t file_alloc(void *provider, size_t size, size_t alignment,
void **resultPtr) {
file_memory_provider_t *file_provider = (file_memory_provider_t *)provider;
return coarse_alloc(file_provider->coarse, size, alignment, resultPtr);
}

static umf_result_t file_alloc_cb(void *provider, size_t size, size_t alignment,
void **resultPtr) {
umf_result_t umf_result;
int ret;

Expand Down Expand Up @@ -568,10 +605,15 @@ static const char *file_get_name(void *provider) {
return "FILE";
}

// This function is supposed to be thread-safe, so it should NOT be called concurrently
// with file_allocation_merge() with the same pointer.
static umf_result_t file_allocation_split(void *provider, void *ptr,
size_t totalSize, size_t firstSize) {
file_memory_provider_t *file_provider = (file_memory_provider_t *)provider;
return coarse_split(file_provider->coarse, ptr, totalSize, firstSize);
}

static umf_result_t file_allocation_split_cb(void *provider, void *ptr,
size_t totalSize,
size_t firstSize) {
(void)totalSize;

file_memory_provider_t *file_provider = (file_memory_provider_t *)provider;
Expand Down Expand Up @@ -601,9 +643,14 @@ static umf_result_t file_allocation_split(void *provider, void *ptr,
return UMF_RESULT_SUCCESS;
}

// It should NOT be called concurrently with file_allocation_split() with the same pointer.
static umf_result_t file_allocation_merge(void *provider, void *lowPtr,
void *highPtr, size_t totalSize) {
file_memory_provider_t *file_provider = (file_memory_provider_t *)provider;
return coarse_merge(file_provider->coarse, lowPtr, highPtr, totalSize);
}

static umf_result_t file_allocation_merge_cb(void *provider, void *lowPtr,
void *highPtr, size_t totalSize) {
(void)lowPtr;
(void)totalSize;

Expand Down Expand Up @@ -768,6 +815,11 @@ static umf_result_t file_close_ipc_handle(void *provider, void *ptr,
return UMF_RESULT_SUCCESS;
}

static umf_result_t file_free(void *provider, void *ptr, size_t size) {
file_memory_provider_t *file_provider = (file_memory_provider_t *)provider;
return coarse_free(file_provider->coarse, ptr, size);
}

static umf_memory_provider_ops_t UMF_FILE_MEMORY_PROVIDER_OPS = {
.version = UMF_VERSION_CURRENT,
.initialize = file_initialize,
Expand All @@ -777,6 +829,7 @@ static umf_memory_provider_ops_t UMF_FILE_MEMORY_PROVIDER_OPS = {
.get_recommended_page_size = file_get_recommended_page_size,
.get_min_page_size = file_get_min_page_size,
.get_name = file_get_name,
.ext.free = file_free,
.ext.purge_lazy = file_purge_lazy,
.ext.purge_force = file_purge_force,
.ext.allocation_merge = file_allocation_merge,
Expand Down
Loading
Loading