Skip to content

[WIP] Add IPC tests (umfIpcTest) to the devdax provider #839

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

Closed
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
59 changes: 0 additions & 59 deletions .github/workflows/pr_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,64 +16,5 @@ permissions:
contents: read

jobs:
CodeChecks:
uses: ./.github/workflows/reusable_checks.yml
DocsBuild:
uses: ./.github/workflows/reusable_docs_build.yml
FastBuild:
name: Fast builds
needs: [CodeChecks, DocsBuild]
uses: ./.github/workflows/reusable_fast.yml
Build:
name: Basic builds
needs: [FastBuild]
uses: ./.github/workflows/reusable_basic.yml
DevDax:
needs: [FastBuild]
uses: ./.github/workflows/reusable_dax.yml
Sanitizers:
needs: [FastBuild]
uses: ./.github/workflows/reusable_sanitizers.yml
Qemu:
needs: [FastBuild]
uses: ./.github/workflows/reusable_qemu.yml
Benchmarks:
needs: [Build]
uses: ./.github/workflows/reusable_benchmarks.yml
ProxyLib:
needs: [Build]
uses: ./.github/workflows/reusable_proxy_lib.yml
GPU:
needs: [Build]
uses: ./.github/workflows/reusable_gpu.yml
Valgrind:
needs: [Build]
uses: ./.github/workflows/reusable_valgrind.yml
MultiNuma:
needs: [Build]
uses: ./.github/workflows/reusable_multi_numa.yml
Coverage:
# total coverage (on upstream only)
if: github.repository == 'oneapi-src/unified-memory-framework'
needs: [Build, DevDax, GPU, MultiNuma, Qemu, ProxyLib]
uses: ./.github/workflows/reusable_coverage.yml
secrets: inherit
with:
trigger: "${{github.event_name}}"
Coverage_partial:
# partial coverage (on forks)
if: github.repository != 'oneapi-src/unified-memory-framework'
needs: [Build, Qemu, ProxyLib]
uses: ./.github/workflows/reusable_coverage.yml
CodeQL:
needs: [Build]
permissions:
contents: read
security-events: write
uses: ./.github/workflows/reusable_codeql.yml
Trivy:
needs: [Build]
permissions:
contents: read
security-events: write
uses: ./.github/workflows/reusable_trivy.yml
29 changes: 11 additions & 18 deletions .github/workflows/reusable_dax.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
if: github.repository == 'oneapi-src/unified-memory-framework'
strategy:
matrix:
build_type: [Debug, Release]
build_type: [Debug]
shared_library: ['ON', 'OFF']

runs-on: ["DSS-DEVDAX", "DSS-Ubuntu"]
Expand Down Expand Up @@ -92,11 +92,20 @@ jobs:
- name: Build UMF
run: cmake --build ${{env.BUILD_DIR}} --config ${{matrix.build_type}} -j $(nproc)

- name: Run the DEVDAX tests
- name: Run the DEVDAX test test/umf_test-provider_devdax_memory
working-directory: ${{env.BUILD_DIR}}
run: >
UMF_TESTS_DEVDAX_PATH="/dev/dax${{env.DEVDAX_NAMESPACE}}"
UMF_TESTS_DEVDAX_SIZE="$(ndctl list --namespace=namespace${{env.DEVDAX_NAMESPACE}} | grep size | cut -d':' -f2 | cut -d',' -f1)"
UMF_LOG="level:debug;flush:debug;output:stderr;pid:yes"
./test/umf_test-provider_devdax_memory

- name: Run all DEVDAX tests
working-directory: ${{env.BUILD_DIR}}
run: >
UMF_TESTS_DEVDAX_PATH="/dev/dax${{env.DEVDAX_NAMESPACE}}"
UMF_TESTS_DEVDAX_SIZE="$(ndctl list --namespace=namespace${{env.DEVDAX_NAMESPACE}} | grep size | cut -d':' -f2 | cut -d',' -f1)"
UMF_LOG="level:debug;flush:debug;output:stderr;pid:yes"
ctest -C ${{matrix.build_type}} -R devdax -V

- name: Run the FSDAX tests
Expand All @@ -105,19 +114,3 @@ jobs:
UMF_TESTS_FSDAX_PATH=${{env.UMF_TESTS_FSDAX_PATH}} UMF_TESTS_FSDAX_PATH_2=${{env.UMF_TESTS_FSDAX_PATH_2}} ctest -C ${{matrix.build_type}} -R umf-provider_file_memory -V
UMF_TESTS_FSDAX_PATH=${{env.UMF_TESTS_FSDAX_PATH}} UMF_TESTS_FSDAX_PATH_2=${{env.UMF_TESTS_FSDAX_PATH_2}} ctest -C ${{matrix.build_type}} -R umf_example_dram_and_fsdax -V
UMF_TESTS_FSDAX_PATH=${{env.UMF_TESTS_FSDAX_PATH}} UMF_TESTS_FSDAX_PATH_2=${{env.UMF_TESTS_FSDAX_PATH_2}} ctest -C ${{matrix.build_type}} -R umf-ipc_file_prov_fsdax -V

- name: Check coverage
if: ${{ matrix.build_type == 'Debug' }}
working-directory: ${{env.BUILD_DIR}}
run: |
export COVERAGE_FILE_NAME=${{env.COVERAGE_NAME}}-shared-${{matrix.shared_library}}
echo "COVERAGE_FILE_NAME: $COVERAGE_FILE_NAME"
../scripts/coverage/coverage_capture.sh $COVERAGE_FILE_NAME
mkdir -p ${{env.COVERAGE_DIR}}
mv ./$COVERAGE_FILE_NAME ${{env.COVERAGE_DIR}}

- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
if: ${{ matrix.build_type == 'Debug' }}
with:
name: ${{env.COVERAGE_NAME}}-shared-${{matrix.shared_library}}
path: ${{env.COVERAGE_DIR}}
6 changes: 4 additions & 2 deletions src/base_alloc/base_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ umf_ba_pool_t *umf_ba_create(size_t size) {
char *data_ptr = (char *)&pool->data;
size_t size_left = pool_size - offsetof(umf_ba_pool_t, data);

utils_align_ptr_size((void **)&data_ptr, &size_left, MEMORY_ALIGNMENT);
utils_align_ptr_up_size_down((void **)&data_ptr, &size_left,
MEMORY_ALIGNMENT);

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

utils_align_ptr_size((void **)&data_ptr, &size_left, MEMORY_ALIGNMENT);
utils_align_ptr_up_size_down((void **)&data_ptr, &size_left,
MEMORY_ALIGNMENT);
ba_divide_memory_into_chunks(pool, data_ptr, size_left);
}

Expand Down
4 changes: 2 additions & 2 deletions src/base_alloc/base_alloc_linear.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ umf_ba_linear_pool_t *umf_ba_linear_create(size_t pool_size) {
void *data_ptr = &pool->data;
size_t size_left = pool_size - offsetof(umf_ba_linear_pool_t, data);

utils_align_ptr_size(&data_ptr, &size_left, MEMORY_ALIGNMENT);
utils_align_ptr_up_size_down(&data_ptr, &size_left, MEMORY_ALIGNMENT);

pool->metadata.pool_size = pool_size;
pool->metadata.data_ptr = data_ptr;
Expand Down Expand Up @@ -149,7 +149,7 @@ void *umf_ba_linear_alloc(umf_ba_linear_pool_t *pool, size_t size) {
void *data_ptr = &new_pool->data;
size_t size_left =
new_pool->pool_size - offsetof(umf_ba_next_linear_pool_t, data);
utils_align_ptr_size(&data_ptr, &size_left, MEMORY_ALIGNMENT);
utils_align_ptr_up_size_down(&data_ptr, &size_left, MEMORY_ALIGNMENT);

pool->metadata.data_ptr = data_ptr;
pool->metadata.size_left = size_left;
Expand Down
106 changes: 52 additions & 54 deletions src/provider/provider_devdax_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ umf_memory_provider_ops_t *umfDevDaxMemoryProviderOps(void) {
#include "utils_concurrency.h"
#include "utils_log.h"

#define NODESET_STR_BUF_LEN 1024
// the default alignment for the devdax mode
#define DEVDAX_ALIGNMENT_2MB (2 * 1024 * 1024) // == 2 MB

#define TLS_MSG_BUF_LEN 1024

Expand Down Expand Up @@ -300,7 +301,8 @@ static umf_result_t devdax_get_recommended_page_size(void *provider,
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

*page_size = utils_get_page_size();
// the default alignment for the devdax mode
*page_size = DEVDAX_ALIGNMENT_2MB;

return UMF_RESULT_SUCCESS;
}
Expand Down Expand Up @@ -369,9 +371,11 @@ static umf_result_t devdax_allocation_merge(void *provider, void *lowPtr,
}

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

static umf_result_t devdax_get_ipc_handle_size(void *provider, size_t *size) {
Expand All @@ -386,8 +390,6 @@ static umf_result_t devdax_get_ipc_handle_size(void *provider, size_t *size) {

static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr,
size_t size, void *providerIpcData) {
(void)size; // unused

if (provider == NULL || ptr == NULL || providerIpcData == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
Expand All @@ -396,11 +398,12 @@ static umf_result_t devdax_get_ipc_handle(void *provider, const void *ptr,
(devdax_memory_provider_t *)provider;

devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;
strncpy(devdax_ipc_data->path, devdax_provider->path, PATH_MAX - 1);
devdax_ipc_data->path[PATH_MAX - 1] = '\0';
devdax_ipc_data->protection = devdax_provider->protection;
devdax_ipc_data->offset =
(size_t)((uintptr_t)ptr - (uintptr_t)devdax_provider->base);
strncpy(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX - 1);
devdax_ipc_data->dd_path[PATH_MAX - 1] = '\0';
devdax_ipc_data->dd_size = devdax_provider->size;
devdax_ipc_data->length = size;

return UMF_RESULT_SUCCESS;
}
Expand All @@ -416,16 +419,9 @@ static umf_result_t devdax_put_ipc_handle(void *provider,
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;

// verify the path of the /dev/dax
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) {
if (strncmp(devdax_ipc_data->path, devdax_provider->path, PATH_MAX)) {
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)",
devdax_provider->path, devdax_ipc_data->dd_path);
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

// verify the size of the /dev/dax
if (devdax_ipc_data->dd_size != devdax_provider->size) {
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)",
devdax_provider->size, devdax_ipc_data->dd_size);
devdax_provider->path, devdax_ipc_data->path);
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

Expand All @@ -438,58 +434,56 @@ static umf_result_t devdax_open_ipc_handle(void *provider,
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

devdax_memory_provider_t *devdax_provider =
(devdax_memory_provider_t *)provider;
devdax_ipc_data_t *devdax_ipc_data = (devdax_ipc_data_t *)providerIpcData;

// verify it is the same devdax - first verify the path
if (strncmp(devdax_ipc_data->dd_path, devdax_provider->path, PATH_MAX)) {
LOG_ERR("devdax path mismatch (local: %s, ipc: %s)",
devdax_provider->path, devdax_ipc_data->dd_path);
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

// verify the size of the /dev/dax
if (devdax_ipc_data->dd_size != devdax_provider->size) {
LOG_ERR("devdax size mismatch (local: %zu, ipc: %zu)",
devdax_provider->size, devdax_ipc_data->dd_size);
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

umf_result_t ret = UMF_RESULT_SUCCESS;
int fd = utils_devdax_open(devdax_provider->path);
int fd = utils_devdax_open(devdax_ipc_data->path);
if (fd == -1) {
LOG_PERR("opening a devdax (%s) failed", devdax_provider->path);
LOG_PERR("opening the devdax (%s) failed", devdax_ipc_data->path);
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

unsigned map_sync_flag = 0;
utils_translate_mem_visibility_flag(UMF_MEM_MAP_SYNC, &map_sync_flag);

// get the page size
size_t page_size;
(void)devdax_get_recommended_page_size(provider, devdax_ipc_data->length,
&page_size);

// length and offset passed to mmap() have to be page-aligned in case of /dev/dax device
size_t offset_aligned = devdax_ipc_data->offset;
size_t length_aligned = devdax_ipc_data->length;
utils_align_ptr_down_size_up((void **)&offset_aligned, &length_aligned,
page_size);

// mmap /dev/dax with the MAP_SYNC xor MAP_SHARED flag (if MAP_SYNC fails)
char *base = utils_mmap_file(NULL, devdax_provider->size,
devdax_provider->protection, map_sync_flag, fd,
0 /* offset */);
if (base == NULL) {
char *addr =
utils_mmap_file(NULL, length_aligned, devdax_ipc_data->protection,
map_sync_flag, fd, offset_aligned);
if (addr == NULL) {
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED,
errno);
LOG_PERR("devdax mapping failed (path: %s, size: %zu, protection: %i, "
"fd: %i)",
devdax_provider->path, devdax_provider->size,
devdax_provider->protection, fd);
ret = UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
"fd: %i, offset: %zu)",
devdax_ipc_data->path, length_aligned,
devdax_ipc_data->protection, fd, offset_aligned);

*ptr = NULL;
(void)utils_close_fd(fd);

return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
}

LOG_DEBUG("devdax mapped (path: %s, size: %zu, protection: %i, fd: %i, "
"offset: %zu)",
devdax_provider->path, devdax_provider->size,
devdax_provider->protection, fd, devdax_ipc_data->offset);
devdax_ipc_data->path, length_aligned,
devdax_ipc_data->protection, fd, offset_aligned);

(void)utils_close_fd(fd);
*ptr = addr + (devdax_ipc_data->offset - offset_aligned);

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

return ret;
return UMF_RESULT_SUCCESS;
}

static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr,
Expand All @@ -498,11 +492,15 @@ static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr,
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

devdax_memory_provider_t *devdax_provider =
(devdax_memory_provider_t *)provider;
// get the page size
size_t page_size;
(void)devdax_get_recommended_page_size(provider, size, &page_size);

// ptr and size passed to munmap() have to be page-aligned in case of /dev/dax device
utils_align_ptr_down_size_up(&ptr, &size, page_size);

errno = 0;
int ret = utils_munmap(devdax_provider->base, devdax_provider->size);
int ret = utils_munmap(ptr, size);
// ignore error when size == 0
if (ret && (size > 0)) {
devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_FREE_FAILED,
Expand Down
34 changes: 28 additions & 6 deletions src/utils/utils_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,42 @@
#include "utils_assert.h"
#include "utils_common.h"

// align a pointer and a size
void utils_align_ptr_size(void **ptr, size_t *size, size_t alignment) {
// align a pointer up and a size down
void utils_align_ptr_up_size_down(void **ptr, size_t *size, size_t alignment) {
uintptr_t p = (uintptr_t)*ptr;
size_t s = *size;

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

ASSERT((p & (alignment - 1)) == 0);
ASSERT((s & (alignment - 1)) == 0);
ASSERT(IS_ALIGNED(p, alignment));
ASSERT(IS_ALIGNED(s, alignment));

*ptr = (void *)p;
*size = s;
}

// align a pointer down and a size up (for mmap()/munmap())
void utils_align_ptr_down_size_up(void **ptr, size_t *size, size_t alignment) {
uintptr_t p = (uintptr_t)*ptr;
size_t s = *size;

// align the pointer down to 'alignment' bytes and adjust the size up
size_t rest = p & (alignment - 1);
if (rest) {
p = ALIGN_DOWN(p, alignment);
s += rest;
}

// align the size up to 'alignment' bytes
s = ALIGN_UP(s, alignment);

ASSERT(IS_ALIGNED(p, alignment));
ASSERT(IS_ALIGNED(s, alignment));

*ptr = (void *)p;
*size = s;
Expand Down
Loading