diff --git a/.github/workflows/dax.yml b/.github/workflows/dax.yml new file mode 100644 index 000000000..889825eaa --- /dev/null +++ b/.github/workflows/dax.yml @@ -0,0 +1,101 @@ +# +# This workflow builds and tests the DEVDAX memory provider +# and the file memory provider with FSDAX. +# It requires: +# - a DAX device (e.g. /dev/dax0.0) and +# - a FSDAX device (e.g. /dev/pmem1) +# configured and mounted in the OS. +# +# The DAX device should be specified using the +# UMF_TESTS_DEVDAX_PATH and UMF_TESTS_DEVDAX_SIZE environment variables. +# +# The FSDAX device should be mounted in the OS (e.g. /mnt/pmem1) +# and the UMF_TESTS_FSDAX_PATH environment variable +# should contain a path to a file o this FSDAX device. +# + +name: Dax + +on: [workflow_call] + +permissions: + contents: read + +env: + DEVDAX_NAMESPACE : "0.0" + FSDAX_NAMESPACE : "1.0" + FSDAX_PMEM: "pmem1" + UMF_TESTS_FSDAX_PATH: "/mnt/pmem1/file" + BUILD_DIR : "${{github.workspace}}/build" + INSTL_DIR : "${{github.workspace}}/../install-dir" + +jobs: + dax: + name: Build + # run only on upstream; forks may not have a DAX device + if: github.repository == 'oneapi-src/unified-memory-framework' + strategy: + matrix: + build_type: [Debug, Release] + shared_library: ['ON', 'OFF'] + + runs-on: ["DSS-DEVDAX", "DSS-Ubuntu"] + steps: + - name: Check configuration of the DEVDAX + run: | + echo DEVDAX_NAMESPACE="${{env.DEVDAX_NAMESPACE}}" + ndctl list --namespace=namespace${{env.DEVDAX_NAMESPACE}} --device-dax + ls -al /dev/dax${{env.DEVDAX_NAMESPACE}} + echo UMF_TESTS_DEVDAX_PATH="/dev/dax${{env.DEVDAX_NAMESPACE}}" + echo UMF_TESTS_DEVDAX_SIZE="$(ndctl list --namespace=namespace${{env.DEVDAX_NAMESPACE}} | grep size | cut -d':' -f2 | cut -d',' -f1)" + + - name: Check configuration of the FSDAX + run: | + echo FSDAX_NAMESPACE="${{env.FSDAX_NAMESPACE}}" + echo UMF_TESTS_FSDAX_PATH="${{env.UMF_TESTS_FSDAX_PATH}}" + ndctl list --namespace=namespace${{env.FSDAX_NAMESPACE}} + ls -al /dev/${{env.FSDAX_PMEM}} /mnt/${{env.FSDAX_PMEM}} + mount | grep -e "/dev/${{env.FSDAX_PMEM}}" + touch ${{env.UMF_TESTS_FSDAX_PATH}} + rm -f ${{env.UMF_TESTS_FSDAX_PATH}} + + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + + - name: Configure build + run: > + cmake + -B ${{env.BUILD_DIR}} + -DCMAKE_INSTALL_PREFIX="${{env.INSTL_DIR}}" + -DCMAKE_BUILD_TYPE=${{matrix.build_type}} + -DCMAKE_C_COMPILER=gcc + -DCMAKE_CXX_COMPILER=g++ + -DUMF_BUILD_SHARED_LIBRARY=${{matrix.shared_library}} + -DUMF_BUILD_BENCHMARKS=OFF + -DUMF_BUILD_TESTS=ON + -DUMF_BUILD_GPU_TESTS=OFF + -DUMF_BUILD_GPU_EXAMPLES=OFF + -DUMF_FORMAT_CODE_STYLE=OFF + -DUMF_DEVELOPER_MODE=ON + -DUMF_BUILD_LIBUMF_POOL_DISJOINT=ON + -DUMF_BUILD_LIBUMF_POOL_JEMALLOC=ON + -DUMF_BUILD_LEVEL_ZERO_PROVIDER=OFF + -DUMF_TESTS_FAIL_ON_SKIP=ON + + - name: Build UMF + run: cmake --build ${{env.BUILD_DIR}} --config ${{matrix.build_type}} -j $(nproc) + + - name: Run the 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)" + ctest -C ${{matrix.build_type}} -R devdax -V + + - name: Run the FSDAX tests + working-directory: ${{env.BUILD_DIR}} + run: > + UMF_TESTS_FSDAX_PATH=${{env.UMF_TESTS_FSDAX_PATH}} + ctest -C ${{matrix.build_type}} -R umf-provider_file_memory -V diff --git a/.github/workflows/devdax.yml b/.github/workflows/devdax.yml deleted file mode 100644 index e8a4dc3bd..000000000 --- a/.github/workflows/devdax.yml +++ /dev/null @@ -1,70 +0,0 @@ -# This workflow builds and tests the devdax memory provider. -# It requires a DAX device (e.g. /dev/dax0.0) configured in the OS. -# This DAX device should be specified using the -# UMF_TESTS_DEVDAX_PATH and UMF_TESTS_DEVDAX_SIZE environment variables. - -name: DevDax - -on: [workflow_call] - -permissions: - contents: read - -env: - UMF_TESTS_DEVDAX_NAMESPACE : "0.0" - BUILD_DIR : "${{github.workspace}}/build" - INSTL_DIR : "${{github.workspace}}/../install-dir" - -jobs: - devdax: - name: Build - # run only on upstream; forks may not have a DAX device - if: github.repository == 'oneapi-src/unified-memory-framework' - strategy: - matrix: - build_type: [Debug, Release] - shared_library: ['ON', 'OFF'] - - runs-on: ["DSS-DEVDAX", "DSS-Ubuntu"] - steps: - - name: Check if the devdax exists, print out UMF_TESTS_DEVDAX_PATH and UMF_TESTS_DEVDAX_SIZE - run: | - ndctl list -N --device-dax - ls -al /dev/dax${UMF_TESTS_DEVDAX_NAMESPACE} - echo UMF_TESTS_DEVDAX_PATH="/dev/dax${UMF_TESTS_DEVDAX_NAMESPACE}" - echo UMF_TESTS_DEVDAX_SIZE="$(ndctl list --namespace=namespace${UMF_TESTS_DEVDAX_NAMESPACE} | grep size | cut -d':' -f2 | cut -d',' -f1)" - - - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - fetch-depth: 0 - - - name: Configure build - run: > - cmake - -B ${{env.BUILD_DIR}} - -DCMAKE_INSTALL_PREFIX="${{env.INSTL_DIR}}" - -DCMAKE_BUILD_TYPE=${{matrix.build_type}} - -DCMAKE_C_COMPILER=gcc - -DCMAKE_CXX_COMPILER=g++ - -DUMF_BUILD_SHARED_LIBRARY=${{matrix.shared_library}} - -DUMF_BUILD_BENCHMARKS=OFF - -DUMF_BUILD_TESTS=ON - -DUMF_BUILD_GPU_TESTS=OFF - -DUMF_BUILD_GPU_EXAMPLES=OFF - -DUMF_FORMAT_CODE_STYLE=OFF - -DUMF_DEVELOPER_MODE=ON - -DUMF_BUILD_LIBUMF_POOL_DISJOINT=ON - -DUMF_BUILD_LIBUMF_POOL_JEMALLOC=ON - -DUMF_BUILD_LEVEL_ZERO_PROVIDER=OFF - -DUMF_TESTS_FAIL_ON_SKIP=ON - - - name: Build UMF - run: cmake --build ${{env.BUILD_DIR}} --config ${{matrix.build_type}} -j $(nproc) - - - name: Run only devdax tests - working-directory: ${{env.BUILD_DIR}} - run: > - UMF_TESTS_DEVDAX_PATH="/dev/dax${UMF_TESTS_DEVDAX_NAMESPACE}" - UMF_TESTS_DEVDAX_SIZE="$(ndctl list --namespace=namespace${UMF_TESTS_DEVDAX_NAMESPACE} | grep size | cut -d':' -f2 | cut -d',' -f1)" - ctest -C ${{matrix.build_type}} -R devdax -V diff --git a/.github/workflows/pr_push.yml b/.github/workflows/pr_push.yml index 02b7adf9f..c921eced6 100644 --- a/.github/workflows/pr_push.yml +++ b/.github/workflows/pr_push.yml @@ -88,7 +88,7 @@ jobs: uses: ./.github/workflows/basic.yml DevDax: needs: [FastBuild] - uses: ./.github/workflows/devdax.yml + uses: ./.github/workflows/dax.yml Sanitizers: needs: [FastBuild] uses: ./.github/workflows/sanitizers.yml diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt index 4f88fd7d8..6cffe5cfe 100644 --- a/test/common/CMakeLists.txt +++ b/test/common/CMakeLists.txt @@ -9,6 +9,10 @@ set(COMMON_SOURCES provider_null.c provider_trace.c) +if(LINUX) + set(COMMON_SOURCES ${COMMON_SOURCES} test_helpers_linux.c) +endif(LINUX) + add_umf_library( NAME umf_test_common TYPE STATIC diff --git a/test/common/test_helpers_linux.c b/test/common/test_helpers_linux.c new file mode 100644 index 000000000..9f7606b09 --- /dev/null +++ b/test/common/test_helpers_linux.c @@ -0,0 +1,67 @@ +// Copyright (C) 2024 Intel Corporation +// Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// This file contains tests for UMF pool API + +#include +#include +#include +#include +#include +#include + +#include "test_helpers_linux.h" + +// Check if the file given by the 'path' argument was mapped with the MAP_SYNC flag: +// 1) Open and read the /proc/self/smaps file. +// 2) Look for the section of the 'path' file. +// 3) Check if the VmFlags of the 'path' file contains the "sf" flag +// marking that the file was mapped with the MAP_SYNC flag. +bool is_mapped_with_MAP_SYNC(char *path, char *buf, size_t size_buf) { + memset(buf, 0, size_buf); + + int fd = open("/proc/self/smaps", O_RDONLY); + if (fd == -1) { + return false; + } + + // number of bytes read from the file + ssize_t nbytes = 1; + // string starting from the path of the smaps + char *smaps = NULL; + + // Read the "/proc/self/smaps" file + // until the path of the smaps is found + // or EOF is reached. + while (nbytes > 0 && smaps == NULL) { + memset(buf, 0, nbytes); // erase previous data + nbytes = read(fd, buf, size_buf); + // look for the path of the smaps + smaps = strstr(buf, path); + } + + // String starting from the "sf" flag + // marking that memory was mapped with the MAP_SYNC flag. + char *sf_flag = NULL; + + if (smaps) { + // look for the "VmFlags:" string + char *VmFlags = strstr(smaps, "VmFlags:"); + if (VmFlags) { + // look for the EOL + char *eol = strstr(VmFlags, "\n"); + if (eol) { + // End the VmFlags string at EOL. + *eol = 0; + // Now the VmFlags string contains only one line with all VmFlags. + + // Look for the "sf" flag in VmFlags + // marking that memory was mapped + // with the MAP_SYNC flag. + sf_flag = strstr(VmFlags, "sf"); + } + } + } + + return (sf_flag != NULL); +} diff --git a/test/common/test_helpers_linux.h b/test/common/test_helpers_linux.h new file mode 100644 index 000000000..7755408b7 --- /dev/null +++ b/test/common/test_helpers_linux.h @@ -0,0 +1,21 @@ +// Copyright (C) 2024 Intel Corporation +// Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// This file contains helpers for tests for UMF pool API + +#ifndef UMF_TEST_HELPERS_LINUX_H +#define UMF_TEST_HELPERS_LINUX_H 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool is_mapped_with_MAP_SYNC(char *path, char *buf, size_t size_buf); + +#ifdef __cplusplus +} +#endif + +#endif /* UMF_TEST_HELPERS_LINUX_H */ diff --git a/test/provider_devdax_memory.cpp b/test/provider_devdax_memory.cpp index 1fdd53b08..6ed5f241e 100644 --- a/test/provider_devdax_memory.cpp +++ b/test/provider_devdax_memory.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #ifndef _WIN32 +#include "test_helpers_linux.h" #include #include #include @@ -11,6 +12,7 @@ #include "base.hpp" #include "cpp_helpers.hpp" +#include "test_helpers.h" #include #include @@ -137,10 +139,6 @@ static void test_alloc_failure(umf_memory_provider_handle_t provider, // TESTS // Test checking if devdax was mapped with the MAP_SYNC flag: -// 1) Open and read the /proc/self/smaps file. -// 2) Look for the section of the devdax (the /dev/daxX.Y path). -// 3) Check if the VmFlags of the /dev/daxX.Y contains the "sf" flag -// marking that the devdax was mapped with the MAP_SYNC flag. TEST_F(test, test_if_mapped_with_MAP_SYNC) { umf_memory_provider_handle_t hProvider = nullptr; umf_result_t umf_result; @@ -167,48 +165,8 @@ TEST_F(test, test_if_mapped_with_MAP_SYNC) { umf_result = umfMemoryProviderAlloc(hProvider, size, 0, (void **)&buf); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); ASSERT_NE(buf, nullptr); - memset(buf, 0, size); - - int fd = open("/proc/self/smaps", O_RDONLY); - ASSERT_NE(fd, -1); - - // number of bytes read from the file - ssize_t nbytes = 1; - // string starting from the path of the devdax - char *devdax = nullptr; - - // Read the "/proc/self/smaps" file - // until the path of the devdax is found - // or EOF is reached. - while (nbytes > 0 && devdax == nullptr) { - memset(buf, 0, nbytes); // erase previous data - nbytes = read(fd, buf, size); - // look for the path of the devdax - devdax = strstr(buf, path); - } - // String starting from the "sf" flag - // marking that memory was mapped with the MAP_SYNC flag. - char *sf_flag = nullptr; - - if (devdax) { - // look for the "VmFlags:" string - char *VmFlags = strstr(devdax, "VmFlags:"); - if (VmFlags) { - // look for the EOL - char *eol = strstr(VmFlags, "\n"); - if (eol) { - // End the VmFlags string at EOL. - *eol = 0; - // Now the VmFlags string contains only one line with all VmFlags. - - // Look for the "sf" flag in VmFlags - // marking that memory was mapped - // with the MAP_SYNC flag. - sf_flag = strstr(VmFlags, "sf"); - } - } - } + bool flag_found = is_mapped_with_MAP_SYNC(path, buf, size); umf_result = umfMemoryProviderFree(hProvider, buf, size); ASSERT_EQ(umf_result, UMF_RESULT_ERROR_NOT_SUPPORTED); @@ -216,7 +174,7 @@ TEST_F(test, test_if_mapped_with_MAP_SYNC) { umfMemoryProviderDestroy(hProvider); // fail test if the "sf" flag was not found - ASSERT_NE(sf_flag, nullptr); + ASSERT_EQ(flag_found, true); } // positive tests using test_alloc_free_success diff --git a/test/provider_file_memory.cpp b/test/provider_file_memory.cpp index 3903febe7..3ec7b849e 100644 --- a/test/provider_file_memory.cpp +++ b/test/provider_file_memory.cpp @@ -6,6 +6,9 @@ #include "cpp_helpers.hpp" #include "test_helpers.h" +#ifndef _WIN32 +#include "test_helpers_linux.h" +#endif #include #include @@ -121,6 +124,41 @@ static void test_alloc_failure(umf_memory_provider_handle_t provider, // TESTS +// Test checking if FSDAX was mapped with the MAP_SYNC flag: +TEST_F(test, test_if_mapped_with_MAP_SYNC) { + umf_memory_provider_handle_t hProvider = nullptr; + umf_result_t umf_result; + + char *path = getenv("UMF_TESTS_FSDAX_PATH"); + if (path == nullptr || path[0] == 0) { + GTEST_SKIP() << "Test skipped, UMF_TESTS_FSDAX_PATH is not set"; + } + + auto params = umfFileMemoryProviderParamsDefault(path); + params.visibility = UMF_MEM_MAP_SYNC; + + umf_result = umfMemoryProviderCreate(umfFileMemoryProviderOps(), ¶ms, + &hProvider); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + ASSERT_NE(hProvider, nullptr); + + char *buf; + size_t size = 2 * 1024 * 1024; // 2MB + umf_result = umfMemoryProviderAlloc(hProvider, size, 0, (void **)&buf); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + ASSERT_NE(buf, nullptr); + + bool flag_found = is_mapped_with_MAP_SYNC(path, buf, size); + + umf_result = umfMemoryProviderFree(hProvider, buf, size); + ASSERT_EQ(umf_result, UMF_RESULT_ERROR_NOT_SUPPORTED); + + umfMemoryProviderDestroy(hProvider); + + // fail test if the "sf" flag was not found + ASSERT_EQ(flag_found, true); +} + // positive tests using test_alloc_free_success umf_file_memory_provider_params_t get_file_params_shared(char *path) {