diff --git a/include/umf/providers/provider_devdax_memory.h b/include/umf/providers/provider_devdax_memory.h index 113d383727..0fb5218bcf 100644 --- a/include/umf/providers/provider_devdax_memory.h +++ b/include/umf/providers/provider_devdax_memory.h @@ -18,15 +18,43 @@ extern "C" { #define UMF_DEVDAX_RESULTS_START_FROM 2000 /// @endcond -/// @brief Memory provider settings struct -typedef struct umf_devdax_memory_provider_params_t { - /// path of the device DAX - char *path; - /// size of the device DAX in bytes - size_t size; - /// combination of 'umf_mem_protection_flags_t' flags - unsigned protection; -} umf_devdax_memory_provider_params_t; +struct umf_devdax_memory_provider_params_t; + +typedef struct umf_devdax_memory_provider_params_t + *umf_devdax_memory_provider_params_handle_t; + +/// @brief Create a struct to store parameters of the Devdax Memory Provider. +/// @param hParams [out] handle to the newly created parameters struct. +/// @param path [in] path of the device DAX. +/// @param size [in] size of the device DAX in bytes. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfDevDaxMemoryProviderParamsCreate( + umf_devdax_memory_provider_params_handle_t *hParams, const char *path, + size_t size); + +/// @brief Destroy parameters struct. +/// @param hParams [in] handle to the parameters of the Devdax Memory Provider. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfDevDaxMemoryProviderParamsDestroy( + umf_devdax_memory_provider_params_handle_t hParams); + +/// @brief Set a device DAX in the parameters struct. Overwrites the previous value. +/// It provides an ability to use the same instance of params to create multiple +/// instances of the provider for different DAX devices. +/// @param hParams [in] handle to the parameters of the Devdax Memory Provider. +/// @param path [in] path of the device DAX. +/// @param size [in] size of the device DAX in bytes. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfDevDaxMemoryProviderParamsSetDeviceDax( + umf_devdax_memory_provider_params_handle_t hParams, const char *path, + size_t size); + +/// @brief Set the protection flags in the parameters struct. +/// @param hParams [in] handle to the parameters of the Devdax Memory Provider. +/// @param protection [in] combination of 'umf_mem_protection_flags_t' flags. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfDevDaxMemoryProviderParamsSetProtection( + umf_devdax_memory_provider_params_handle_t hParams, unsigned protection); /// @brief Devdax Memory Provider operation results typedef enum umf_devdax_memory_provider_native_error { @@ -39,18 +67,6 @@ typedef enum umf_devdax_memory_provider_native_error { umf_memory_provider_ops_t *umfDevDaxMemoryProviderOps(void); -/// @brief Create default params for the devdax memory provider -static inline umf_devdax_memory_provider_params_t -umfDevDaxMemoryProviderParamsDefault(char *path, size_t size) { - umf_devdax_memory_provider_params_t params = { - path, /* path of the device DAX */ - size, /* size of the device DAX in bytes */ - UMF_PROTECTION_READ | UMF_PROTECTION_WRITE, /* protection */ - }; - - return params; -} - #ifdef __cplusplus } #endif diff --git a/src/libumf.def b/src/libumf.def index ae1ba68096..0b4588bb81 100644 --- a/src/libumf.def +++ b/src/libumf.def @@ -23,6 +23,10 @@ EXPORTS umfCUDAMemoryProviderParamsSetDevice umfCUDAMemoryProviderParamsSetMemoryType umfDevDaxMemoryProviderOps + umfDevDaxMemoryProviderParamsCreate + umfDevDaxMemoryProviderParamsDestroy + umfDevDaxMemoryProviderParamsSetDeviceDax + umfDevDaxMemoryProviderParamsSetProtection umfFree umfFileMemoryProviderOps umfFileMemoryProviderParamsCreate diff --git a/src/libumf.map b/src/libumf.map index 9231123846..41467bad59 100644 --- a/src/libumf.map +++ b/src/libumf.map @@ -17,6 +17,10 @@ UMF_1.0 { umfCUDAMemoryProviderParamsSetDevice; umfCUDAMemoryProviderParamsSetMemoryType; umfDevDaxMemoryProviderOps; + umfDevDaxMemoryProviderParamsCreate; + umfDevDaxMemoryProviderParamsDestroy; + umfDevDaxMemoryProviderParamsSetDeviceDax; + umfDevDaxMemoryProviderParamsSetProtection; umfFree; umfFileMemoryProviderOps; umfFileMemoryProviderParamsCreate; diff --git a/src/provider/provider_devdax_memory.c b/src/provider/provider_devdax_memory.c index 1179ed115b..32407acbba 100644 --- a/src/provider/provider_devdax_memory.c +++ b/src/provider/provider_devdax_memory.c @@ -24,9 +24,41 @@ umf_memory_provider_ops_t *umfDevDaxMemoryProviderOps(void) { return NULL; } +umf_result_t umfDevDaxMemoryProviderParamsCreate( + umf_devdax_memory_provider_params_handle_t *hParams, const char *path, + size_t size) { + (void)hParams; + (void)path; + (void)size; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfDevDaxMemoryProviderParamsDestroy( + umf_devdax_memory_provider_params_handle_t hParams) { + (void)hParams; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfDevDaxMemoryProviderParamsSetDeviceDax( + umf_devdax_memory_provider_params_handle_t hParams, const char *path, + size_t size) { + (void)hParams; + (void)path; + (void)size; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfDevDaxMemoryProviderParamsSetProtection( + umf_devdax_memory_provider_params_handle_t hParams, unsigned protection) { + (void)hParams; + (void)protection; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + #else // !defined(_WIN32) && !defined(UMF_NO_HWLOC) #include "base_alloc_global.h" +#include "libumf.h" #include "utils_common.h" #include "utils_concurrency.h" #include "utils_log.h" @@ -44,6 +76,13 @@ typedef struct devdax_memory_provider_t { unsigned protection; // combination of OS-specific protection flags } devdax_memory_provider_t; +// DevDax Memory provider settings struct +typedef struct umf_devdax_memory_provider_params_t { + char *path; + size_t size; + unsigned protection; +} umf_devdax_memory_provider_params_t; + typedef struct devdax_last_native_error_t { int32_t native_error; int errno_value; @@ -511,4 +550,110 @@ umf_memory_provider_ops_t *umfDevDaxMemoryProviderOps(void) { return &UMF_DEVDAX_MEMORY_PROVIDER_OPS; } +umf_result_t umfDevDaxMemoryProviderParamsCreate( + umf_devdax_memory_provider_params_handle_t *hParams, const char *path, + size_t size) { + libumfInit(); + if (hParams == NULL) { + LOG_ERR("DevDax Memory Provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + if (path == NULL) { + LOG_ERR("DevDax path is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + umf_devdax_memory_provider_params_handle_t params = + umf_ba_global_alloc(sizeof(*params)); + if (params == NULL) { + LOG_ERR( + "Allocating memory for the DevDax Memory Provider params failed"); + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + params->path = NULL; + params->size = 0; + params->protection = UMF_PROTECTION_READ | UMF_PROTECTION_WRITE; + + umf_result_t res = + umfDevDaxMemoryProviderParamsSetDeviceDax(params, path, size); + if (res != UMF_RESULT_SUCCESS) { + umf_ba_global_free(params); + return res; + } + + *hParams = params; + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfDevDaxMemoryProviderParamsDestroy( + umf_devdax_memory_provider_params_handle_t hParams) { + if (hParams != NULL) { + umf_ba_global_free(hParams->path); + umf_ba_global_free(hParams); + } + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfDevDaxMemoryProviderParamsSetDeviceDax( + umf_devdax_memory_provider_params_handle_t hParams, const char *path, + size_t size) { + if (hParams == NULL) { + LOG_ERR("DevDax Memory Provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + if (path == NULL) { + LOG_ERR("DevDax path is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + size_t path_len = strlen(path); + if (path_len == 0) { + LOG_ERR("DevDax path is empty"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + path_len += 1; // for the null terminator + char *new_path = umf_ba_global_alloc(path_len); + if (new_path == NULL) { + LOG_ERR("Allocating memory for the DevDax path failed"); + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + strncpy(new_path, path, path_len); + + umf_ba_global_free(hParams->path); + + hParams->path = new_path; + hParams->size = size; + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfDevDaxMemoryProviderParamsSetProtection( + umf_devdax_memory_provider_params_handle_t hParams, unsigned protection) { + if (hParams == NULL) { + LOG_ERR("DevDax Memory Provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + // verify that protection contains only valid bits set + // (UMF_PROTECTION_MAX-1) - highest possible bit + // (UMF_PROTECTION_MAX-1) << 1 - next after highest possible bit + // ((UMF_PROTECTION_MAX-1) << 1) - 1 - all valid bits set + const unsigned VALID_FLAGS_ALL = ((UMF_PROTECTION_MAX - 1) << 1) - 1; + if (protection & ~VALID_FLAGS_ALL || protection == 0) { + LOG_ERR("Incorrect memory protection flags: %u", protection); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + hParams->protection = protection; + + return UMF_RESULT_SUCCESS; +} + #endif // !defined(_WIN32) && !defined(UMF_NO_HWLOC) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6ce94654a9..bf9884dc98 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -343,6 +343,10 @@ else() NAME provider_file_memory_not_impl SRCS provider_file_memory_not_impl.cpp LIBS ${UMF_UTILS_FOR_TEST}) + add_umf_test( + NAME provider_devdax_memory_not_impl + SRCS provider_devdax_memory_not_impl.cpp + LIBS ${UMF_UTILS_FOR_TEST}) endif() if(UMF_DISABLE_HWLOC) diff --git a/test/ipc_devdax_prov_consumer.c b/test/ipc_devdax_prov_consumer.c index a8fd8211db..286b6de785 100644 --- a/test/ipc_devdax_prov_consumer.c +++ b/test/ipc_devdax_prov_consumer.c @@ -19,6 +19,7 @@ int main(int argc, char *argv[]) { return -1; } + int ret = 0; int port = atoi(argv[1]); char *path = getenv("UMF_TESTS_DEVDAX_PATH"); @@ -33,12 +34,22 @@ int main(int argc, char *argv[]) { return 0; } - umf_devdax_memory_provider_params_t devdax_params = - umfDevDaxMemoryProviderParamsDefault(path, atol(size)); + umf_devdax_memory_provider_params_handle_t devdax_params = NULL; + umf_result_t umf_result = + umfDevDaxMemoryProviderParamsCreate(&devdax_params, path, atol(size)); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "[consumer] ERROR: creating DevDax Memory Provider " + "params failed\n"); + return -1; + } void *pool_params = NULL; - return run_consumer(port, umfScalablePoolOps(), pool_params, - umfDevDaxMemoryProviderOps(), &devdax_params, memcopy, - NULL); + ret = run_consumer(port, umfScalablePoolOps(), pool_params, + umfDevDaxMemoryProviderOps(), devdax_params, memcopy, + NULL); + + umfDevDaxMemoryProviderParamsDestroy(devdax_params); + + return ret; } diff --git a/test/ipc_devdax_prov_producer.c b/test/ipc_devdax_prov_producer.c index 90afe64dde..479c1f9457 100644 --- a/test/ipc_devdax_prov_producer.c +++ b/test/ipc_devdax_prov_producer.c @@ -19,6 +19,7 @@ int main(int argc, char *argv[]) { return -1; } + int ret = 0; int port = atoi(argv[1]); char *path = getenv("UMF_TESTS_DEVDAX_PATH"); @@ -33,12 +34,22 @@ int main(int argc, char *argv[]) { return 0; } - umf_devdax_memory_provider_params_t devdax_params = - umfDevDaxMemoryProviderParamsDefault(path, atol(size)); + umf_devdax_memory_provider_params_handle_t devdax_params = NULL; + umf_result_t umf_result = + umfDevDaxMemoryProviderParamsCreate(&devdax_params, path, atol(size)); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "[producer] ERROR: creating DevDax Memory Provider " + "params failed\n"); + return -1; + } void *pool_params = NULL; - return run_producer(port, umfScalablePoolOps(), pool_params, - umfDevDaxMemoryProviderOps(), &devdax_params, memcopy, - NULL); + ret = run_producer(port, umfScalablePoolOps(), pool_params, + umfDevDaxMemoryProviderOps(), devdax_params, memcopy, + NULL); + + umfDevDaxMemoryProviderParamsDestroy(devdax_params); + + return ret; } diff --git a/test/poolFixtures.hpp b/test/poolFixtures.hpp index 995db981b4..e5ec85012c 100644 --- a/test/poolFixtures.hpp +++ b/test/poolFixtures.hpp @@ -69,27 +69,6 @@ struct umfPoolTest : umf_test::test, void SetUp() override { test::SetUp(); - auto [pool_ops, pool_params, provider_ops, provider_params, - coarse_params] = this->GetParam(); - (void)pool_ops; - (void)pool_params; - (void)provider_params; - (void)coarse_params; - - if (provider_ops == umfDevDaxMemoryProviderOps()) { - char *path = getenv("UMF_TESTS_DEVDAX_PATH"); - if (path == nullptr || path[0] == 0) { - GTEST_SKIP() - << "Test skipped, UMF_TESTS_DEVDAX_PATH is not set"; - } - - char *size = getenv("UMF_TESTS_DEVDAX_SIZE"); - if (size == nullptr || size[0] == 0) { - GTEST_SKIP() - << "Test skipped, UMF_TESTS_DEVDAX_SIZE is not set"; - } - } - pool = poolCreateExtUnique(this->GetParam()); } diff --git a/test/pools/jemalloc_coarse_devdax.cpp b/test/pools/jemalloc_coarse_devdax.cpp index ae98ecf4b1..350e053ab7 100644 --- a/test/pools/jemalloc_coarse_devdax.cpp +++ b/test/pools/jemalloc_coarse_devdax.cpp @@ -7,14 +7,39 @@ #include "pool_coarse.hpp" +using devdax_params_unique_handle_t = + std::unique_ptr; + +devdax_params_unique_handle_t create_devdax_params() { + char *path = getenv("UMF_TESTS_DEVDAX_PATH"); + char *size = getenv("UMF_TESTS_DEVDAX_SIZE"); + if (path == nullptr || path[0] == 0 || size == nullptr || size[0] == 0) { + return devdax_params_unique_handle_t( + nullptr, &umfDevDaxMemoryProviderParamsDestroy); + } + + umf_devdax_memory_provider_params_handle_t params = NULL; + umf_result_t res = + umfDevDaxMemoryProviderParamsCreate(¶ms, path, atol(size)); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error( + "Failed to create DevDax Memory Provider params"); + } + + return devdax_params_unique_handle_t(params, + &umfDevDaxMemoryProviderParamsDestroy); +} + auto coarseParams = umfCoarseMemoryProviderParamsDefault(); -auto devdaxParams = umfDevDaxMemoryProviderParamsDefault( - getenv("UMF_TESTS_DEVDAX_PATH"), getenv("UMF_TESTS_DEVDAX_SIZE") - ? atol(getenv("UMF_TESTS_DEVDAX_SIZE")) - : 0); +auto devdaxParams = create_devdax_params(); + +static std::vector poolParamsList = + devdaxParams.get() + ? std::vector{poolCreateExtParams{ + umfJemallocPoolOps(), nullptr, umfDevDaxMemoryProviderOps(), + devdaxParams.get(), &coarseParams}} + : std::vector{}; INSTANTIATE_TEST_SUITE_P(jemallocCoarseDevDaxTest, umfPoolTest, - ::testing::Values(poolCreateExtParams{ - umfJemallocPoolOps(), nullptr, - umfDevDaxMemoryProviderOps(), &devdaxParams, - &coarseParams})); + ::testing::ValuesIn(poolParamsList)); diff --git a/test/pools/scalable_coarse_devdax.cpp b/test/pools/scalable_coarse_devdax.cpp index b5da7d2422..1bf77c61ce 100644 --- a/test/pools/scalable_coarse_devdax.cpp +++ b/test/pools/scalable_coarse_devdax.cpp @@ -7,14 +7,39 @@ #include "pool_coarse.hpp" +using devdax_params_unique_handle_t = + std::unique_ptr; + +devdax_params_unique_handle_t create_devdax_params() { + char *path = getenv("UMF_TESTS_DEVDAX_PATH"); + char *size = getenv("UMF_TESTS_DEVDAX_SIZE"); + if (path == nullptr || path[0] == 0 || size == nullptr || size[0] == 0) { + return devdax_params_unique_handle_t( + nullptr, &umfDevDaxMemoryProviderParamsDestroy); + } + + umf_devdax_memory_provider_params_handle_t params = NULL; + umf_result_t res = + umfDevDaxMemoryProviderParamsCreate(¶ms, path, atol(size)); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error( + "Failed to create DevDax Memory Provider params"); + } + + return devdax_params_unique_handle_t(params, + &umfDevDaxMemoryProviderParamsDestroy); +} + auto coarseParams = umfCoarseMemoryProviderParamsDefault(); -auto devdaxParams = umfDevDaxMemoryProviderParamsDefault( - getenv("UMF_TESTS_DEVDAX_PATH"), getenv("UMF_TESTS_DEVDAX_SIZE") - ? atol(getenv("UMF_TESTS_DEVDAX_SIZE")) - : 0); +auto devdaxParams = create_devdax_params(); + +static std::vector poolParamsList = + devdaxParams.get() + ? std::vector{poolCreateExtParams{ + umfScalablePoolOps(), nullptr, umfDevDaxMemoryProviderOps(), + devdaxParams.get(), &coarseParams}} + : std::vector{}; INSTANTIATE_TEST_SUITE_P(scalableCoarseDevDaxTest, umfPoolTest, - ::testing::Values(poolCreateExtParams{ - umfScalablePoolOps(), nullptr, - umfDevDaxMemoryProviderOps(), &devdaxParams, - &coarseParams})); + ::testing::ValuesIn(poolParamsList)); diff --git a/test/provider_devdax_memory.cpp b/test/provider_devdax_memory.cpp index c41fb8769a..0fd0705da4 100644 --- a/test/provider_devdax_memory.cpp +++ b/test/provider_devdax_memory.cpp @@ -63,16 +63,6 @@ struct umfProviderTest : umf_test::test, ::testing::WithParamInterface { void SetUp() override { - char *path = getenv("UMF_TESTS_DEVDAX_PATH"); - if (path == nullptr || path[0] == 0) { - GTEST_SKIP() << "Test skipped, UMF_TESTS_DEVDAX_PATH is not set"; - } - - char *size = getenv("UMF_TESTS_DEVDAX_SIZE"); - if (size == nullptr || size[0] == 0) { - GTEST_SKIP() << "Test skipped, UMF_TESTS_DEVDAX_SIZE is not set"; - } - test::SetUp(); providerCreateExt(this->GetParam(), &provider); umf_result_t umf_result = umfMemoryProviderGetMinPageSize( @@ -154,9 +144,12 @@ TEST_F(test, test_if_mapped_with_MAP_SYNC) { } size_t size = atol(size_str); - auto params = umfDevDaxMemoryProviderParamsDefault(path, size); + umf_devdax_memory_provider_params_handle_t params = NULL; + umf_result = umfDevDaxMemoryProviderParamsCreate(¶ms, path, size); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + ASSERT_NE(params, nullptr); - umf_result = umfMemoryProviderCreate(umfDevDaxMemoryProviderOps(), ¶ms, + umf_result = umfMemoryProviderCreate(umfDevDaxMemoryProviderOps(), params, &hProvider); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); ASSERT_NE(hProvider, nullptr); @@ -179,15 +172,42 @@ TEST_F(test, test_if_mapped_with_MAP_SYNC) { // positive tests using test_alloc_free_success -auto defaultDevDaxParams = umfDevDaxMemoryProviderParamsDefault( - getenv("UMF_TESTS_DEVDAX_PATH"), - atol(getenv("UMF_TESTS_DEVDAX_SIZE") ? getenv("UMF_TESTS_DEVDAX_SIZE") - : "0")); +using devdax_params_unique_handle_t = + std::unique_ptr; + +devdax_params_unique_handle_t create_devdax_params() { + char *path = getenv("UMF_TESTS_DEVDAX_PATH"); + char *size = getenv("UMF_TESTS_DEVDAX_SIZE"); + if (path == nullptr || path[0] == 0 || size == nullptr || size[0] == 0) { + return devdax_params_unique_handle_t( + nullptr, &umfDevDaxMemoryProviderParamsDestroy); + } + + umf_devdax_memory_provider_params_handle_t params = NULL; + umf_result_t res = + umfDevDaxMemoryProviderParamsCreate(¶ms, path, atol(size)); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error( + "Failed to create DevDax Memory Provider params"); + } + + return devdax_params_unique_handle_t(params, + &umfDevDaxMemoryProviderParamsDestroy); +} + +auto defaultDevDaxParams = create_devdax_params(); + +static std::vector devdaxProviderTestParamsList = + defaultDevDaxParams.get() + ? std::vector{providerCreateExtParams{ + umfDevDaxMemoryProviderOps(), defaultDevDaxParams.get()}} + : std::vector{}; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(umfProviderTest); INSTANTIATE_TEST_SUITE_P(devdaxProviderTest, umfProviderTest, - ::testing::Values(providerCreateExtParams{ - umfDevDaxMemoryProviderOps(), - &defaultDevDaxParams})); + ::testing::ValuesIn(devdaxProviderTestParamsList)); TEST_P(umfProviderTest, create_destroy) {} @@ -306,47 +326,160 @@ TEST_P(umfProviderTest, purge_force_INVALID_POINTER) { UMF_DEVDAX_RESULT_ERROR_PURGE_FORCE_FAILED); } -// negative tests +// params tests + +TEST_F(test, params_protection_flag) { + umf_devdax_memory_provider_params_handle_t params = nullptr; + umf_result_t ret = + umfDevDaxMemoryProviderParamsCreate(¶ms, "/dev/dax0.0", 4096); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(params, nullptr); + + //test all valid combinations + for (unsigned protection = UMF_PROTECTION_NONE; + protection < (UMF_PROTECTION_MAX - 1) << 1; ++protection) { + ret = umfDevDaxMemoryProviderParamsSetProtection(params, protection); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + } + + umfDevDaxMemoryProviderParamsDestroy(params); +} + +// negative params tests + +TEST_F(test, params_invalid_protection_flag) { + umf_devdax_memory_provider_params_handle_t params = nullptr; + umf_result_t ret = + umfDevDaxMemoryProviderParamsCreate(¶ms, "/dev/dax0.0", 4096); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(params, nullptr); + + ret = umfDevDaxMemoryProviderParamsSetProtection(params, 0); + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + for (unsigned protection = UMF_PROTECTION_NONE; + protection < (UMF_PROTECTION_MAX - 1) << 1; ++protection) { + unsigned invalid_protection = protection | (UMF_PROTECTION_MAX << 1); + ret = umfDevDaxMemoryProviderParamsSetProtection(params, + invalid_protection); + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + } + + umfDevDaxMemoryProviderParamsDestroy(params); +} + +TEST_F(test, params_null_handle) { + auto ret = + umfDevDaxMemoryProviderParamsCreate(nullptr, "/dev/dax0.0", 4096); + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + ret = umfDevDaxMemoryProviderParamsDestroy(nullptr); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = + umfDevDaxMemoryProviderParamsSetDeviceDax(nullptr, "/dev/dax0.0", 4096); + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + ret = umfDevDaxMemoryProviderParamsSetProtection(nullptr, 1); + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); +} TEST_F(test, create_empty_path) { - umf_memory_provider_handle_t hProvider = nullptr; const char *path = ""; - auto wrong_params = - umfDevDaxMemoryProviderParamsDefault((char *)path, 4096); - auto ret = umfMemoryProviderCreate(umfDevDaxMemoryProviderOps(), - &wrong_params, &hProvider); - EXPECT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); - EXPECT_EQ(hProvider, nullptr); + umf_devdax_memory_provider_params_handle_t wrong_params = NULL; + auto ret = umfDevDaxMemoryProviderParamsCreate(&wrong_params, path, 4096); + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + ASSERT_EQ(wrong_params, nullptr); +} + +TEST_F(test, create_null_path) { + const char *path = nullptr; + umf_devdax_memory_provider_params_handle_t wrong_params = NULL; + auto ret = umfDevDaxMemoryProviderParamsCreate(&wrong_params, path, 4096); + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + ASSERT_EQ(wrong_params, nullptr); +} + +TEST_F(test, set_empty_path) { + const char *path = "tmp"; + const char *empty_path = ""; + umf_devdax_memory_provider_params_handle_t params = NULL; + auto ret = umfDevDaxMemoryProviderParamsCreate(¶ms, path, 4096); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(params, nullptr); + + ret = umfDevDaxMemoryProviderParamsSetDeviceDax(params, empty_path, 4096); + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + ret = umfDevDaxMemoryProviderParamsDestroy(params); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); +} + +TEST_F(test, set_null_path) { + const char *path = "tmp"; + const char *null_path = nullptr; + umf_devdax_memory_provider_params_handle_t params = NULL; + auto ret = umfDevDaxMemoryProviderParamsCreate(¶ms, path, 4096); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(params, nullptr); + + ret = umfDevDaxMemoryProviderParamsSetDeviceDax(params, null_path, 4096); + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + ret = umfDevDaxMemoryProviderParamsDestroy(params); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); } TEST_F(test, create_wrong_path) { umf_memory_provider_handle_t hProvider = nullptr; const char *path = "/tmp/dev/dax0.0"; - auto wrong_params = - umfDevDaxMemoryProviderParamsDefault((char *)path, 4096); - auto ret = umfMemoryProviderCreate(umfDevDaxMemoryProviderOps(), - &wrong_params, &hProvider); + umf_devdax_memory_provider_params_handle_t wrong_params = nullptr; + + auto ret = umfDevDaxMemoryProviderParamsCreate(&wrong_params, path, 4096); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(wrong_params, nullptr); + + ret = umfMemoryProviderCreate(umfDevDaxMemoryProviderOps(), wrong_params, + &hProvider); EXPECT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); EXPECT_EQ(hProvider, nullptr); + + ret = umfDevDaxMemoryProviderParamsDestroy(wrong_params); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); } TEST_F(test, create_wrong_path_not_exist) { umf_memory_provider_handle_t hProvider = nullptr; const char *path = "/dev/dax1.1"; - auto wrong_params = - umfDevDaxMemoryProviderParamsDefault((char *)path, 4096); - auto ret = umfMemoryProviderCreate(umfDevDaxMemoryProviderOps(), - &wrong_params, &hProvider); + umf_devdax_memory_provider_params_handle_t wrong_params = nullptr; + + auto ret = umfDevDaxMemoryProviderParamsCreate(&wrong_params, path, 4096); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(wrong_params, nullptr); + + ret = umfMemoryProviderCreate(umfDevDaxMemoryProviderOps(), wrong_params, + &hProvider); EXPECT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); EXPECT_EQ(hProvider, nullptr); + + ret = umfDevDaxMemoryProviderParamsDestroy(wrong_params); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); } TEST_F(test, create_wrong_size_0) { umf_memory_provider_handle_t hProvider = nullptr; const char *path = "/dev/dax0.0"; - auto wrong_params = umfDevDaxMemoryProviderParamsDefault((char *)path, 0); - auto ret = umfMemoryProviderCreate(umfDevDaxMemoryProviderOps(), - &wrong_params, &hProvider); + umf_devdax_memory_provider_params_handle_t wrong_params = nullptr; + + auto ret = umfDevDaxMemoryProviderParamsCreate(&wrong_params, path, 0); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(wrong_params, nullptr); + + ret = umfMemoryProviderCreate(umfDevDaxMemoryProviderOps(), wrong_params, + &hProvider); EXPECT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); EXPECT_EQ(hProvider, nullptr); + + ret = umfDevDaxMemoryProviderParamsDestroy(wrong_params); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); } diff --git a/test/provider_devdax_memory_ipc.cpp b/test/provider_devdax_memory_ipc.cpp index 071196c947..3941f66e90 100644 --- a/test/provider_devdax_memory_ipc.cpp +++ b/test/provider_devdax_memory_ipc.cpp @@ -15,38 +15,52 @@ using umf_test::test; -auto defaultDevDaxParams = umfDevDaxMemoryProviderParamsDefault( - getenv("UMF_TESTS_DEVDAX_PATH"), - atol(getenv("UMF_TESTS_DEVDAX_SIZE") ? getenv("UMF_TESTS_DEVDAX_SIZE") - : "0")); +using devdax_params_unique_handle_t = + std::unique_ptr; + +devdax_params_unique_handle_t create_devdax_params() { + char *path = getenv("UMF_TESTS_DEVDAX_PATH"); + char *size = getenv("UMF_TESTS_DEVDAX_SIZE"); + if (path == nullptr || path[0] == 0 || size == nullptr || size[0] == 0) { + return devdax_params_unique_handle_t( + nullptr, &umfDevDaxMemoryProviderParamsDestroy); + } + + umf_devdax_memory_provider_params_handle_t params = NULL; + umf_result_t res = + umfDevDaxMemoryProviderParamsCreate(¶ms, path, atol(size)); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error( + "Failed to create DevDax Memory Provider params"); + } + + return devdax_params_unique_handle_t(params, + &umfDevDaxMemoryProviderParamsDestroy); +} + +auto defaultDevDaxParams = create_devdax_params(); HostMemoryAccessor hostAccessor; static std::vector getIpcProxyPoolTestParamsList(void) { std::vector ipcProxyPoolTestParamsList = {}; - char *path = getenv("UMF_TESTS_DEVDAX_PATH"); - if (path == nullptr || path[0] == 0) { - // skipping the test, UMF_TESTS_DEVDAX_PATH is not set - return ipcProxyPoolTestParamsList; - } - - char *size = getenv("UMF_TESTS_DEVDAX_SIZE"); - if (size == nullptr || size[0] == 0) { - // skipping the test, UMF_TESTS_DEVDAX_SIZE is not set + if (!defaultDevDaxParams.get()) { + // return empty list to skip the test return ipcProxyPoolTestParamsList; } ipcProxyPoolTestParamsList = { {umfProxyPoolOps(), nullptr, umfDevDaxMemoryProviderOps(), - &defaultDevDaxParams, &hostAccessor, true}, + defaultDevDaxParams.get(), &hostAccessor, true}, #ifdef UMF_POOL_JEMALLOC_ENABLED {umfJemallocPoolOps(), nullptr, umfDevDaxMemoryProviderOps(), - &defaultDevDaxParams, &hostAccessor, false}, + defaultDevDaxParams.get(), &hostAccessor, false}, #endif #ifdef UMF_POOL_SCALABLE_ENABLED {umfScalablePoolOps(), nullptr, umfDevDaxMemoryProviderOps(), - &defaultDevDaxParams, &hostAccessor, false}, + defaultDevDaxParams.get(), &hostAccessor, false}, #endif }; diff --git a/test/provider_devdax_memory_not_impl.cpp b/test/provider_devdax_memory_not_impl.cpp new file mode 100644 index 0000000000..3b97443a08 --- /dev/null +++ b/test/provider_devdax_memory_not_impl.cpp @@ -0,0 +1,30 @@ +// 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 + +#include "base.hpp" + +#include + +using umf_test::test; + +TEST_F(test, devdax_provider_not_implemented) { + umf_devdax_memory_provider_params_handle_t params = nullptr; + umf_result_t umf_result = + umfDevDaxMemoryProviderParamsCreate(¶ms, "path", 4096); + EXPECT_EQ(umf_result, UMF_RESULT_ERROR_NOT_SUPPORTED); + EXPECT_EQ(params, nullptr); + + umf_result = umfDevDaxMemoryProviderParamsDestroy(nullptr); + EXPECT_EQ(umf_result, UMF_RESULT_ERROR_NOT_SUPPORTED); + + umf_result = + umfDevDaxMemoryProviderParamsSetDeviceDax(nullptr, "path", 4096); + EXPECT_EQ(umf_result, UMF_RESULT_ERROR_NOT_SUPPORTED); + + umf_result = umfDevDaxMemoryProviderParamsSetProtection(nullptr, 0); + EXPECT_EQ(umf_result, UMF_RESULT_ERROR_NOT_SUPPORTED); + + umf_memory_provider_ops_t *ops = umfDevDaxMemoryProviderOps(); + EXPECT_EQ(ops, nullptr); +}