diff --git a/src/common/pmemcommon.inc b/src/common/pmemcommon.inc index 93b14eab47..3e124c1cf3 100644 --- a/src/common/pmemcommon.inc +++ b/src/common/pmemcommon.inc @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2017-2023, Intel Corporation +# Copyright 2025, Hewlett Packard Enterprise Development LP # # src/pmemcommon.inc -- common SOURCE definitions for PMDK libraries # @@ -21,6 +22,7 @@ SOURCE +=\ $(COMMON)/rand.c\ $(COMMON)/set.c\ $(COMMON)/shutdown_state.c\ + $(COMMON)/shutdown_state_helper.c\ $(COMMON)/uuid.c\ $(COMMON)/uuid_linux.c\ $(PMEM2)/pmem2_utils.c\ diff --git a/src/common/shutdown_state.c b/src/common/shutdown_state.c index 8dd6cf533b..49e9caad9a 100644 --- a/src/common/shutdown_state.c +++ b/src/common/shutdown_state.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: BSD-3-Clause /* Copyright 2017-2024, Intel Corporation */ +/* Copyright 2025, Hewlett Packard Enterprise Development LP */ /* * shutdown_state.c -- unsafe shudown detection @@ -17,13 +18,10 @@ #include "bad_blocks.h" #include "../libpmem2/pmem2_utils.h" -#define FLUSH_SDS(sds, rep) \ - if ((rep) != NULL) os_part_deep_common(rep, 0, sds, sizeof(*(sds)), 1) - /* - * shutdown_state_checksum -- (internal) counts SDS checksum and flush it + * shutdown_state_checksum -- counts SDS checksum and flush it */ -static void +void shutdown_state_checksum(struct shutdown_state *sds, struct pool_replica *rep) { LOG(3, "sds %p", sds); @@ -159,24 +157,6 @@ shutdown_state_clear_dirty(struct shutdown_state *sds, struct pool_replica *rep) shutdown_state_checksum(sds, rep); } -/* - * shutdown_state_reinit -- (internal) reinitializes shutdown_state struct - */ -static void -shutdown_state_reinit(struct shutdown_state *curr_sds, - struct shutdown_state *pool_sds, struct pool_replica *rep) -{ - LOG(3, "curr_sds %p, pool_sds %p", curr_sds, pool_sds); - shutdown_state_init(pool_sds, rep); - pool_sds->uuid = htole64(curr_sds->uuid); - pool_sds->usc = htole64(curr_sds->usc); - pool_sds->dirty = 0; - - FLUSH_SDS(pool_sds, rep); - - shutdown_state_checksum(pool_sds, rep); -} - /* * shutdown_state_check -- compares and fixes shutdown state */ @@ -186,15 +166,26 @@ shutdown_state_check(struct shutdown_state *curr_sds, { LOG(3, "curr_sds %p, pool_sds %p", curr_sds, pool_sds); + /* + * This is likely to occur only when the pool is being opened for + * the first time after the SHUTDOWN_STATE feature has been enabled on + * the pool, for example, via (lib)pmempool. + * Please do not confuse this with establishing SDS during creation. + */ if (util_is_zeroed(pool_sds, sizeof(*pool_sds)) && !util_is_zeroed(curr_sds, sizeof(*curr_sds))) { + CORE_LOG_WARNING( + "Enabling ADR failure detection, assuming pool consistency up to this point."); shutdown_state_reinit(curr_sds, pool_sds, rep); return 0; } + bool is_uuid_correct = + le64toh(pool_sds->uuid) == le64toh(curr_sds->uuid); + bool is_uuid_usc_correct = le64toh(pool_sds->usc) == le64toh(curr_sds->usc) && - le64toh(pool_sds->uuid) == le64toh(curr_sds->uuid); + is_uuid_correct; bool is_checksum_correct = util_checksum(pool_sds, sizeof(*pool_sds), &pool_sds->checksum, 0, 0); @@ -204,7 +195,7 @@ shutdown_state_check(struct shutdown_state *curr_sds, if (!is_checksum_correct) { /* the program was killed during opening or closing the pool */ CORE_LOG_WARNING( - "incorrect checksum - SDS will be reinitialized"); + "The pool was not opened/closed properly - reinitializing ADR failure detection."); shutdown_state_reinit(curr_sds, pool_sds, rep); return 0; } @@ -217,19 +208,23 @@ shutdown_state_check(struct shutdown_state *curr_sds, * but there wasn't an ADR failure */ CORE_LOG_WARNING( - "the pool was not closed - SDS will be reinitialized"); + "The ADR failure was detected but the pool was closed properly - reinitializing ADR failure detection."); shutdown_state_reinit(curr_sds, pool_sds, rep); return 0; } if (dirty == 0) { - /* an ADR failure but the pool was closed */ - CORE_LOG_WARNING( - "an ADR failure was detected but the pool was closed - SDS will be reinitialized"); + if (is_uuid_correct) + CORE_LOG_WARNING( + "The ADR failure was detected but the pool was closed properly - reinitializing ADR failure detection."); + else + CORE_LOG_HARK( + "The pool has moved to a new location but it was closed properly - reinitializing ADR failure detection."); shutdown_state_reinit(curr_sds, pool_sds, rep); return 0; } - /* an ADR failure - the pool might be corrupted */ - ERR_WO_ERRNO( - "an ADR failure was detected, the pool might be corrupted"); + + ERR_WO_ERRNO("%s, the pool might be corrupted.", is_uuid_correct ? + "The ADR failure was detected" : + "The pool has moved to a new location while it was not closed properly"); return 1; } diff --git a/src/common/shutdown_state.h b/src/common/shutdown_state.h index 1f9fa4ce8b..4267e60f0e 100644 --- a/src/common/shutdown_state.h +++ b/src/common/shutdown_state.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause */ /* Copyright 2017-2020, Intel Corporation */ +/* Copyright 2025, Hewlett Packard Enterprise Development LP */ /* * shutdown_state.h -- unsafe shudown detection @@ -23,6 +24,9 @@ struct shutdown_state { uint64_t checksum; }; +#define FLUSH_SDS(sds, rep) \ + if ((rep) != NULL) os_part_deep_common(rep, 0, sds, sizeof(*(sds)), 1) + int shutdown_state_init(struct shutdown_state *sds, struct pool_replica *rep); int shutdown_state_add_part(struct shutdown_state *sds, int fd, struct pool_replica *rep); @@ -34,6 +38,12 @@ void shutdown_state_clear_dirty(struct shutdown_state *sds, int shutdown_state_check(struct shutdown_state *curr_sds, struct shutdown_state *pool_sds, struct pool_replica *rep); +void shutdown_state_reinit(struct shutdown_state *curr_sds, + struct shutdown_state *pool_sds, struct pool_replica *rep); + +void shutdown_state_checksum(struct shutdown_state *sds, + struct pool_replica *rep); + #ifdef __cplusplus } #endif diff --git a/src/common/shutdown_state_helper.c b/src/common/shutdown_state_helper.c new file mode 100644 index 0000000000..2bf5322895 --- /dev/null +++ b/src/common/shutdown_state_helper.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2025, Hewlett Packard Enterprise Development LP */ + +/* + * shutdown_state_helper.c -- implementation of shutdown_state_reinit + */ + +#include "out.h" +#include "os_deep.h" +#include "set.h" + +/* + * shutdown_state_reinit -- reinitializes shutdown_state struct + */ +void +shutdown_state_reinit(struct shutdown_state *curr_sds, + struct shutdown_state *pool_sds, struct pool_replica *rep) +{ + LOG(3, "curr_sds %p, pool_sds %p", curr_sds, pool_sds); + shutdown_state_init(pool_sds, rep); + pool_sds->uuid = htole64(curr_sds->uuid); + pool_sds->usc = htole64(curr_sds->usc); + pool_sds->dirty = 0; + + FLUSH_SDS(pool_sds, rep); + + shutdown_state_checksum(pool_sds, rep); +} diff --git a/src/test/Makefile b/src/test/Makefile index 5d39101d81..c3bd32990e 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -148,6 +148,7 @@ OTHER_TESTS = \ util_poolset_size\ util_ravl\ util_sds\ + util_sds_check\ util_uuid_generate\ util_vec\ util_vecq\ diff --git a/src/test/Makefile.inc b/src/test/Makefile.inc index dc07375cb4..875bbfe672 100644 --- a/src/test/Makefile.inc +++ b/src/test/Makefile.inc @@ -246,6 +246,7 @@ OBJS +=\ $(TOP)/src/nondebug/common/pool_hdr.o\ $(TOP)/src/nondebug/common/set.o\ $(TOP)/src/nondebug/common/shutdown_state.o\ + $(TOP)/src/nondebug/common/shutdown_state_helper.o\ $(TOP)/src/nondebug/common/util.o\ $(TOP)/src/nondebug/common/util_posix.o\ $(TOP)/src/nondebug/common/uuid.o\ @@ -287,6 +288,7 @@ OBJS +=\ $(TOP)/src/debug/common/pool_hdr.o\ $(TOP)/src/debug/common/set.o\ $(TOP)/src/debug/common/shutdown_state.o\ + $(TOP)/src/debug/common/shutdown_state_helper.o\ $(TOP)/src/debug/common/uuid.o\ $(TOP)/src/debug/common/uuid_linux.o\ $(TOP)/src/debug/libpmem2/pmem2_utils.o\ diff --git a/src/test/core_log_max/call_all.c.generated b/src/test/core_log_max/call_all.c.generated index 87024dfe7c..b18eae048c 100644 --- a/src/test/core_log_max/call_all.c.generated +++ b/src/test/core_log_max/call_all.c.generated @@ -181,13 +181,13 @@ call_all_ERR_WO_ERRNO(void) // src/common/set_badblocks.c ERR_WO_ERRNO("part file contains bad blocks -- '%s'", _s); // src/common/shutdown_state.c - ERR_WO_ERRNO("cannot read uuid of %d", _d); - // src/common/shutdown_state.c - ERR_WO_ERRNO("an ADR failure was detected, the pool might be corrupted"); + ERR_WO_ERRNO("%s, the pool might be corrupted.", _s); // src/common/shutdown_state.c ERR_WO_ERRNO("Cannot read unsafe shutdown count. For more information please check https://github.com/pmem/pmdk/issues/4207"); // src/common/shutdown_state.c ERR_WO_ERRNO("cannot read uuid of %d", _d); + // src/common/shutdown_state.c + ERR_WO_ERRNO("cannot read uuid of %d", _d); // src/libpmem/libpmem.c ERR_WO_ERRNO("libpmem major version mismatch (need %u, found %u)", _u, _u); // src/libpmem/libpmem.c @@ -462,11 +462,13 @@ call_all_CORE_LOG_WARNING(void) // src/common/set.c CORE_LOG_WARNING("file permissions changed during pool initialization, file: %s (%o)", _s, _u); // src/common/shutdown_state.c - CORE_LOG_WARNING("incorrect checksum - SDS will be reinitialized"); + CORE_LOG_WARNING("Enabling ADR failure detection, assuming pool consistency up to this point."); + // src/common/shutdown_state.c + CORE_LOG_WARNING("The pool was not opened/closed properly - reinitializing ADR failure detection."); // src/common/shutdown_state.c - CORE_LOG_WARNING("the pool was not closed - SDS will be reinitialized"); + CORE_LOG_WARNING("The ADR failure was detected but the pool was closed properly - reinitializing ADR failure detection."); // src/common/shutdown_state.c - CORE_LOG_WARNING("an ADR failure was detected but the pool was closed - SDS will be reinitialized"); + CORE_LOG_WARNING("The ADR failure was detected but the pool was closed properly - reinitializing ADR failure detection."); // src/libpmemobj/heap.c CORE_LOG_WARNING("failed to allocate memory block runtime tracking info"); // src/libpmemobj/heap.c diff --git a/src/test/core_log_max/core_log_max.c b/src/test/core_log_max/core_log_max.c index 71ef599aac..33365ab2a0 100644 --- a/src/test/core_log_max/core_log_max.c +++ b/src/test/core_log_max/core_log_max.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: BSD-3-Clause /* Copyright 2024, Intel Corporation */ +/* Copyright 2025, Hewlett Packard Enterprise Development LP */ /* * core_log_max.c -- unit test to verify max size of log buffers @@ -119,7 +120,7 @@ test_ERR_W_ERRNO(const struct test_case *tc, int argc, char *argv[]) return NO_ARGS_CONSUMED; } -#define TOTAL_MESSAGE_NUM_EXPECTED 213 +#define TOTAL_MESSAGE_NUM_EXPECTED 214 static int Max_message_len = 0; static int Total_message_num = 0; static char The_longest_message[BIG_BUF_SIZE]; diff --git a/src/test/util_sds/Makefile b/src/test/util_sds/Makefile index 67adab7622..9ed8af0a6d 100644 --- a/src/test/util_sds/Makefile +++ b/src/test/util_sds/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2015-2020, Intel Corporation +# Copyright 2025, Hewlett Packard Enterprise Development LP # # src/test/util_sds/Makefile -- shutdown_tests unit test @@ -11,6 +12,7 @@ vpath %.c $(TOP)/src/common/ TARGET = util_sds OBJS = util_sds.o\ shutdown_state.o\ + shutdown_state_helper.o\ ut_pmem2_config.o\ ut_pmem2_source.o\ ut_pmem2_utils.o diff --git a/src/test/util_sds/grep1.log.match b/src/test/util_sds/grep1.log.match index e69de29bb2..19a52cb124 100644 --- a/src/test/util_sds/grep1.log.match +++ b/src/test/util_sds/grep1.log.match @@ -0,0 +1 @@ +: <2> [shutdown_state.c:$(N) shutdown_state_check] Enabling ADR failure detection, assuming pool consistency up to this point. diff --git a/src/test/util_sds/grep2.log.match b/src/test/util_sds/grep2.log.match index e69de29bb2..19a52cb124 100644 --- a/src/test/util_sds/grep2.log.match +++ b/src/test/util_sds/grep2.log.match @@ -0,0 +1 @@ +: <2> [shutdown_state.c:$(N) shutdown_state_check] Enabling ADR failure detection, assuming pool consistency up to this point. diff --git a/src/test/util_sds/grep3.log.match b/src/test/util_sds/grep3.log.match index aa153f3b5d..65fdd3a5a2 100644 --- a/src/test/util_sds/grep3.log.match +++ b/src/test/util_sds/grep3.log.match @@ -1 +1 @@ -: <2> [shutdown_state.c:$(N) shutdown_state_check] an ADR failure was detected but the pool was closed - SDS will be reinitialized +: <1> [shutdown_state.c:$(N) shutdown_state_check] The pool has moved to a new location but it was closed properly - reinitializing ADR failure detection. diff --git a/src/test/util_sds/grep5.log.match b/src/test/util_sds/grep5.log.match index 1926c20d1e..64f8dea763 100644 --- a/src/test/util_sds/grep5.log.match +++ b/src/test/util_sds/grep5.log.match @@ -1 +1 @@ -: <2> [shutdown_state.c:$(N) shutdown_state_check] the pool was not closed - SDS will be reinitialized +: <2> [shutdown_state.c:$(N) shutdown_state_check] The ADR failure was detected but the pool was closed properly - reinitializing ADR failure detection. diff --git a/src/test/util_sds/grep6.log.match b/src/test/util_sds/grep6.log.match index 8d26418c32..3b7821ca80 100644 --- a/src/test/util_sds/grep6.log.match +++ b/src/test/util_sds/grep6.log.match @@ -1 +1 @@ -: <1> [shutdown_state.c:$(N) shutdown_state_check] an ADR failure was detected, the pool might be corrupted +: <1> [shutdown_state.c:$(N) shutdown_state_check] The pool has moved to a new location while it was not closed properly, the pool might be corrupted. diff --git a/src/test/util_sds/grep7.log.match b/src/test/util_sds/grep7.log.match index 8d26418c32..60fff6cfdd 100644 --- a/src/test/util_sds/grep7.log.match +++ b/src/test/util_sds/grep7.log.match @@ -1 +1 @@ -: <1> [shutdown_state.c:$(N) shutdown_state_check] an ADR failure was detected, the pool might be corrupted +: <1> [shutdown_state.c:$(N) shutdown_state_check] The ADR failure was detected, the pool might be corrupted. diff --git a/src/test/util_sds_check/.gitignore b/src/test/util_sds_check/.gitignore new file mode 100644 index 0000000000..e9b41bcd7f --- /dev/null +++ b/src/test/util_sds_check/.gitignore @@ -0,0 +1 @@ +util_sds_check diff --git a/src/test/util_sds_check/Makefile b/src/test/util_sds_check/Makefile new file mode 100644 index 0000000000..4299abdc80 --- /dev/null +++ b/src/test/util_sds_check/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2025, Hewlett Packard Enterprise Development LP + +# +# src/test/util_sds_check/Makefile -- shutdown_state_check unit test +# +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +TARGET = util_sds_check +OBJS = util_sds_check.o + +LIBPMEM=y +LIBPMEMCOMMON=internal-debug + +include ../Makefile.inc + +LDFLAGS += $(call extract_funcs, util_sds_check.c) diff --git a/src/test/util_sds_check/TEST0 b/src/test/util_sds_check/TEST0 new file mode 100755 index 0000000000..14ff63eb3c --- /dev/null +++ b/src/test/util_sds_check/TEST0 @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2025, Hewlett Packard Enterprise Development LP + +# +# src/test/util_sds_check/TEST0 -- unittest for shutdown_state_check +# + +. ../unittest/unittest.sh + +require_test_type short + +require_fs_type none + +require_build_type debug + +setup + +expect_normal_exit ./util_sds_check test_dirty_clear + +check + +pass diff --git a/src/test/util_sds_check/TEST1 b/src/test/util_sds_check/TEST1 new file mode 100755 index 0000000000..f2417575af --- /dev/null +++ b/src/test/util_sds_check/TEST1 @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2025, Hewlett Packard Enterprise Development LP + +# +# src/test/util_sds_check/TEST1 -- unittest for shutdown_state_check +# + +. ../unittest/unittest.sh + +require_test_type short + +require_fs_type none + +require_build_type debug + +setup + +expect_normal_exit ./util_sds_check test_invalid_checksum + +check + +pass diff --git a/src/test/util_sds_check/TEST2 b/src/test/util_sds_check/TEST2 new file mode 100755 index 0000000000..54cc7aeceb --- /dev/null +++ b/src/test/util_sds_check/TEST2 @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2025, Hewlett Packard Enterprise Development LP + +# +# src/test/util_sds_check/TEST2 -- unittest for shutdown_state_check +# + +. ../unittest/unittest.sh + +require_test_type short + +require_fs_type none + +require_build_type debug + +setup + +expect_normal_exit ./util_sds_check test_dirty_set + +check + +pass diff --git a/src/test/util_sds_check/TEST3 b/src/test/util_sds_check/TEST3 new file mode 100755 index 0000000000..958df6eb8b --- /dev/null +++ b/src/test/util_sds_check/TEST3 @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2025, Hewlett Packard Enterprise Development LP + +# +# src/test/util_sds_check/TEST3 -- unittest for shutdown_state_check +# + +. ../unittest/unittest.sh + +require_test_type short + +require_fs_type none + +require_build_type debug + +setup + +expect_normal_exit ./util_sds_check test_invalid_uuid + +check + +pass diff --git a/src/test/util_sds_check/TEST4 b/src/test/util_sds_check/TEST4 new file mode 100755 index 0000000000..79d1e9acc8 --- /dev/null +++ b/src/test/util_sds_check/TEST4 @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2025, Hewlett Packard Enterprise Development LP + +# +# src/test/util_sds_check/TEST4 -- unittest for shutdown_state_check +# + +. ../unittest/unittest.sh + +require_test_type short + +require_fs_type none + +require_build_type debug + +setup + +expect_normal_exit ./util_sds_check test_invalid_uuid_set_dirty + +check + +pass diff --git a/src/test/util_sds_check/TEST5 b/src/test/util_sds_check/TEST5 new file mode 100755 index 0000000000..ccf7de34d6 --- /dev/null +++ b/src/test/util_sds_check/TEST5 @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2025, Hewlett Packard Enterprise Development LP + +# +# src/test/util_sds_check/TEST5 -- unittest for shutdown_state_check +# + +. ../unittest/unittest.sh + +require_test_type short + +require_fs_type none + +require_build_type debug + +setup + +expect_normal_exit ./util_sds_check test_invalid_usc + +check + +pass diff --git a/src/test/util_sds_check/TEST6 b/src/test/util_sds_check/TEST6 new file mode 100755 index 0000000000..aa9038ec35 --- /dev/null +++ b/src/test/util_sds_check/TEST6 @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2025, Hewlett Packard Enterprise Development LP + +# +# src/test/util_sds_check/TEST6 -- unittest for shutdown_state_check +# + +. ../unittest/unittest.sh + +require_test_type short + +require_fs_type none + +require_build_type debug + +setup + +expect_normal_exit ./util_sds_check test_invalid_usc_set_dirty + +check + +pass diff --git a/src/test/util_sds_check/TEST7 b/src/test/util_sds_check/TEST7 new file mode 100755 index 0000000000..beed80e62d --- /dev/null +++ b/src/test/util_sds_check/TEST7 @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2025, Hewlett Packard Enterprise Development LP + +# +# src/test/util_sds_check/TEST7 -- unittest for shutdown_state_check +# + +. ../unittest/unittest.sh + +require_test_type short + +require_fs_type none + +require_build_type debug + +setup + +expect_normal_exit ./util_sds_check test_happy_day + +check + +pass diff --git a/src/test/util_sds_check/out0.log.match b/src/test/util_sds_check/out0.log.match new file mode 100644 index 0000000000..31270abc1b --- /dev/null +++ b/src/test/util_sds_check/out0.log.match @@ -0,0 +1,7 @@ +util_sds_check$(nW)TEST0: START: util_sds_check + $(nW)util_sds_check test_dirty_clear +src version: $(nW) +compiled with support for shutdown state +compiled with libndctl $(nW) +Enabling ADR failure detection, assuming pool consistency up to this point. +util_sds_check$(nW)TEST0: DONE diff --git a/src/test/util_sds_check/out1.log.match b/src/test/util_sds_check/out1.log.match new file mode 100644 index 0000000000..c9575de573 --- /dev/null +++ b/src/test/util_sds_check/out1.log.match @@ -0,0 +1,7 @@ +util_sds_check$(nW)TEST1: START: util_sds_check + $(nW)util_sds_check test_invalid_checksum +src version: $(nW) +compiled with support for shutdown state +compiled with libndctl $(nW) +The pool was not opened/closed properly - reinitializing ADR failure detection. +util_sds_check$(nW)TEST1: DONE diff --git a/src/test/util_sds_check/out2.log.match b/src/test/util_sds_check/out2.log.match new file mode 100644 index 0000000000..8e878eb850 --- /dev/null +++ b/src/test/util_sds_check/out2.log.match @@ -0,0 +1,7 @@ +util_sds_check$(nW)TEST2: START: util_sds_check + $(nW)util_sds_check test_dirty_set +src version: $(nW) +compiled with support for shutdown state +compiled with libndctl $(nW) +The ADR failure was detected but the pool was closed properly - reinitializing ADR failure detection. +util_sds_check$(nW)TEST2: DONE diff --git a/src/test/util_sds_check/out3.log.match b/src/test/util_sds_check/out3.log.match new file mode 100644 index 0000000000..6b65326c5b --- /dev/null +++ b/src/test/util_sds_check/out3.log.match @@ -0,0 +1,7 @@ +util_sds_check$(nW)TEST3: START: util_sds_check + $(nW)util_sds_check test_invalid_uuid +src version: $(nW) +compiled with support for shutdown state +compiled with libndctl $(nW) +The pool has moved to a new location but it was closed properly - reinitializing ADR failure detection. +util_sds_check$(nW)TEST3: DONE diff --git a/src/test/util_sds_check/out4.log.match b/src/test/util_sds_check/out4.log.match new file mode 100644 index 0000000000..d2c1062320 --- /dev/null +++ b/src/test/util_sds_check/out4.log.match @@ -0,0 +1,7 @@ +util_sds_check$(nW)TEST4: START: util_sds_check + $(nW)util_sds_check test_invalid_uuid_set_dirty +src version: $(nW) +compiled with support for shutdown state +compiled with libndctl $(nW) +The pool has moved to a new location while it was not closed properly, the pool might be corrupted. +util_sds_check$(nW)TEST4: DONE diff --git a/src/test/util_sds_check/out5.log.match b/src/test/util_sds_check/out5.log.match new file mode 100644 index 0000000000..7a7f21f0d1 --- /dev/null +++ b/src/test/util_sds_check/out5.log.match @@ -0,0 +1,7 @@ +util_sds_check$(nW)TEST5: START: util_sds_check + $(nW)util_sds_check test_invalid_usc +src version: $(nW) +compiled with support for shutdown state +compiled with libndctl $(nW) +The ADR failure was detected but the pool was closed properly - reinitializing ADR failure detection. +util_sds_check$(nW)TEST5: DONE diff --git a/src/test/util_sds_check/out6.log.match b/src/test/util_sds_check/out6.log.match new file mode 100644 index 0000000000..f650dbbbb8 --- /dev/null +++ b/src/test/util_sds_check/out6.log.match @@ -0,0 +1,7 @@ +util_sds_check$(nW)TEST6: START: util_sds_check + $(nW)util_sds_check test_invalid_usc_set_dirty +src version: $(nW) +compiled with support for shutdown state +compiled with libndctl $(nW) +The ADR failure was detected, the pool might be corrupted. +util_sds_check$(nW)TEST6: DONE diff --git a/src/test/util_sds_check/out7.log.match b/src/test/util_sds_check/out7.log.match new file mode 100644 index 0000000000..b6ea82698e --- /dev/null +++ b/src/test/util_sds_check/out7.log.match @@ -0,0 +1,6 @@ +util_sds_check$(nW)TEST7: START: util_sds_check + $(nW)util_sds_check test_happy_day +src version: $(nW) +compiled with support for shutdown state +compiled with libndctl $(nW) +util_sds_check$(nW)TEST7: DONE diff --git a/src/test/util_sds_check/util_sds_check.c b/src/test/util_sds_check/util_sds_check.c new file mode 100644 index 0000000000..2ae4926891 --- /dev/null +++ b/src/test/util_sds_check/util_sds_check.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2025, Hewlett Packard Enterprise Development LP */ + +/* + * util_sds_check.c -- unit test for the shutdown_state_check() function + */ + +#include "util_sds_check.h" + +/* pool_sds - SDS read from the pool header (persistent) */ +static struct shutdown_state Pool_sds; +/* + * curr_sds - SDS calculated ad hoc considering all the involved PMem DIMMs + * their UUIDs and USCs (volatile) + */ +static struct shutdown_state Curr_sds; +static struct pool_replica Rep; + +FUNC_MOCK(shutdown_state_reinit, void, struct shutdown_state *curr_sds, + struct shutdown_state *pool_sds, struct pool_replica *rep) +FUNC_MOCK_RUN_DEFAULT { + UT_ASSERTeq(curr_sds, &Curr_sds); + UT_ASSERTeq(pool_sds, &Pool_sds); + UT_ASSERTeq(rep, &Rep); +} +FUNC_MOCK_END + +/* + * The persistent SDS turned out to be zeroed out + * whereas based on the pool structure it should be not. + */ +static int +test_dirty_clear() +{ + SET_SDS(Pool_sds, SDS_ZERO); + SET_SDS(Curr_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + + int ret = shutdown_state_check(&Curr_sds, &Pool_sds, &Rep); + UT_ASSERTeq(ret, 0); + UT_ASSERTeq(RCOUNTER(shutdown_state_reinit), 1); + + return NO_ARGS_CONSUMED; +} + +/* Pool_sds having an invalid checksum. */ +static int +test_invalid_checksum() +{ + SET_SDS(Pool_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + /* Pool_sds.checksum left zeroed out (invalid) */ + SET_SDS(Curr_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + + int ret = shutdown_state_check(&Curr_sds, &Pool_sds, &Rep); + UT_ASSERTeq(ret, 0); + UT_ASSERTeq(RCOUNTER(shutdown_state_reinit), 1); + + return NO_ARGS_CONSUMED; +} + +/* + * Test with curr_sds and pool_sds having the same values + * except for the dirty field. + */ +static int +test_dirty_set() +{ + SET_SDS(Pool_sds, SDS_CUSTOM(USC, UUID, DIRTY_SET)); + shutdown_state_checksum(&Pool_sds, &Rep); + SET_SDS(Curr_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + + int ret = shutdown_state_check(&Curr_sds, &Pool_sds, &Rep); + UT_ASSERTeq(ret, 0); + UT_ASSERTeq(RCOUNTER(shutdown_state_reinit), 1); + + return NO_ARGS_CONSUMED; +} + +/* Pool_sds and Curr_sds having different uuid. */ +static int +test_invalid_uuid() +{ + SET_SDS(Pool_sds, SDS_CUSTOM(USC, UUID ^ INVALID_VALUE, DIRTY_CLEAR)); + shutdown_state_checksum(&Pool_sds, &Rep); + SET_SDS(Curr_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + + int ret = shutdown_state_check(&Curr_sds, &Pool_sds, &Rep); + UT_ASSERTeq(ret, 0); + UT_ASSERTeq(RCOUNTER(shutdown_state_reinit), 1); + + return NO_ARGS_CONSUMED; +} + +/* + * Pool_sds and Curr_sds having different uuid and + * Pool_sds.dirty is set. + */ +static int +test_invalid_uuid_set_dirty() +{ + SET_SDS(Pool_sds, SDS_CUSTOM(USC, UUID ^ INVALID_VALUE, DIRTY_SET)); + shutdown_state_checksum(&Pool_sds, &Rep); + SET_SDS(Curr_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + + int ret = shutdown_state_check(&Curr_sds, &Pool_sds, &Rep); + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(RCOUNTER(shutdown_state_reinit), 0); + + return NO_ARGS_CONSUMED; +} + +/* Pool_sds and Curr_sds having different USC and the same UUID. */ +static int +test_invalid_usc() +{ + SET_SDS(Pool_sds, SDS_CUSTOM(USC ^ INVALID_VALUE, UUID, DIRTY_CLEAR)); + shutdown_state_checksum(&Pool_sds, &Rep); + SET_SDS(Curr_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + + int ret = shutdown_state_check(&Curr_sds, &Pool_sds, &Rep); + UT_ASSERTeq(ret, 0); + UT_ASSERTeq(RCOUNTER(shutdown_state_reinit), 1); + + return NO_ARGS_CONSUMED; +} + +/* + * Pool_sds and Curr_sds having different USC, the same UUID and + * Pool_sds.dirty is set. + */ +static int +test_invalid_usc_set_dirty() +{ + SET_SDS(Pool_sds, SDS_CUSTOM(USC ^ INVALID_VALUE, UUID, DIRTY_SET)); + shutdown_state_checksum(&Pool_sds, &Rep); + SET_SDS(Curr_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + + int ret = shutdown_state_check(&Curr_sds, &Pool_sds, &Rep); + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(RCOUNTER(shutdown_state_reinit), 0); + + return NO_ARGS_CONSUMED; +} + +/* Pool_sds and Curr_sds having identical values (dirty==0). */ +static int +test_happy_day() +{ + SET_SDS(Pool_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + shutdown_state_checksum(&Pool_sds, &Rep); + SET_SDS(Curr_sds, SDS_CUSTOM(USC, UUID, DIRTY_CLEAR)); + + int ret = shutdown_state_check(&Curr_sds, &Pool_sds, &Rep); + UT_ASSERTeq(ret, 0); + UT_ASSERTeq(RCOUNTER(shutdown_state_reinit), 0); + + return NO_ARGS_CONSUMED; +} + +static struct test_case test_cases[] = { + TEST_CASE(test_dirty_clear), + TEST_CASE(test_invalid_checksum), + TEST_CASE(test_dirty_set), + TEST_CASE(test_invalid_uuid), + TEST_CASE(test_invalid_uuid_set_dirty), + TEST_CASE(test_invalid_usc), + TEST_CASE(test_invalid_usc_set_dirty), + TEST_CASE(test_happy_day), +}; + +#define NTESTS ARRAY_SIZE(test_cases) + +static void +log_function(enum core_log_level level, const char *file_name, + unsigned line_no, const char *function_name, const char *message) +{ + UT_OUT("%s", message); +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "util_sds_check"); + core_log_set_function(log_function); + TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); + DONE(NULL); +} diff --git a/src/test/util_sds_check/util_sds_check.h b/src/test/util_sds_check/util_sds_check.h new file mode 100644 index 0000000000..8a03d61975 --- /dev/null +++ b/src/test/util_sds_check/util_sds_check.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright 2025, Hewlett Packard Enterprise Development LP */ + +/* + * util_sds_check.h -- header for unit test + */ + +#include "unittest.h" +#include "shutdown_state.h" +#include "set.h" + +#define NO_ARGS_CONSUMED 0 + +#define DIRTY_SET 1 +#define DIRTY_CLEAR 0 + +/* Invalid value for all test cases */ +#define INVALID_VALUE 0x60bab3f082b07f57 +#define UUID 0xbe4919b3edce624a +#define USC 0x14796ef67d593c7b + +#define SDS_CUSTOM(my_usc, my_uuid, my_dirty) \ +{ \ + .usc = my_usc, \ + .uuid = my_uuid, \ + .dirty = my_dirty, \ + .reserved = {0}, \ + .checksum = 0 \ +} + +#define SDS_ZERO {0} + +#define SET_SDS(DST, VALUE) \ +do { \ + struct shutdown_state sds_src = VALUE; \ + memcpy(&DST, &sds_src, sizeof(struct shutdown_state)); \ +} while (0)