From 00fc38bf24a979035a9527ba7db9fa3e28f0a964 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Wed, 30 Apr 2025 13:17:44 +0000 Subject: [PATCH 01/13] DAOS-17322 ddb: DTX aggregation with ddb Cleanup of SCons file. Signed-off-by: Cedric Koch-Hofer --- src/utils/ddb/tests/SConscript | 58 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/utils/ddb/tests/SConscript b/src/utils/ddb/tests/SConscript index dc29dc8f848..3cf6297893c 100644 --- a/src/utils/ddb/tests/SConscript +++ b/src/utils/ddb/tests/SConscript @@ -6,25 +6,17 @@ def scons(): """Execute build""" Import('env', 'prereqs') + # ---------------------- + # Common build configs denv = env.Clone() - - # Add runtime paths for daos libraries denv.AppendUnique(RPATH_FULL=['$PREFIX/lib64/daos_srv']) - denv.AppendUnique(RPATH_FULL=['$PREFIX/lib64']) - - prereqs.require(denv, 'argobots', 'protobufc', 'pmdk', 'spdk') - # for ddb includes denv.AppendUnique(CPPPATH=[Dir('../').srcnode()]) denv.AppendUnique(LIBPATH=[Dir('../')]) - # Add include directory for vos internal headers denv.AppendUnique(CPPPATH=[Dir('../../../vos/').srcnode()]) denv.AppendUnique(CPPPATH=[Dir('../../../vos/')]) - denv.AppendUnique(CPPDEFINES='_GNU_SOURCE') - libs = ['vos', 'daos_common_pmem', 'abt', 'gurt', 'uuid', 'bio', 'cart', - 'cmocka', 'ddb'] # spdk libraries spdk_libs = ['rte_bus_pci', 'rte_eal', 'rte_kvargs', 'rte_mbuf', 'rte_mempool_ring', 'rte_mempool', 'rte_pci', 'rte_power', 'rte_ring', 'spdk_bdev_aio', @@ -33,36 +25,44 @@ def scons(): 'spdk_init', 'spdk_init', 'spdk_json', 'spdk_json', 'spdk_jsonrpc', 'spdk_log', 'spdk_log', 'spdk_log', 'spdk_notify', 'spdk_nvme', 'spdk_nvme', 'spdk_rpc', 'spdk_sock', 'spdk_thread', 'spdk_thread', 'spdk_trace', 'spdk_util', 'spdk_vmd'] + + # ---------------------- + # Build integration test + tenv = denv.Clone() + tenv.AppendUnique(CPPDEFINES='_GNU_SOURCE') + # Add runtime paths for daos libraries + tenv.AppendUnique(RPATH_FULL=['$PREFIX/lib64']) + prereqs.require(tenv, 'argobots', 'protobufc', 'pmdk', 'spdk') + + libs = ['vos', 'uuid', 'daos_common_pmem', 'abt', 'gurt', 'bio', 'cart', 'cmocka', 'ddb'] src = ['ddb_cmd_options_tests.c', 'ddb_commands_print_tests.c', 'ddb_commands_tests.c', 'ddb_main_tests.c', 'ddb_parse_tests.c', 'ddb_path_tests.c', 'ddb_test_driver.c', 'ddb_vos_tests.c'] - ddb_tests = denv.d_program('ddb_tests', [src], LIBS=libs + spdk_libs) + ddb_tests = tenv.d_program('ddb_tests', src, LIBS=libs + spdk_libs) - denv.Install('$PREFIX/bin/', ddb_tests) + tenv.Install('$PREFIX/bin/', ddb_tests) - # Build unit tests - denv = env.Clone() - prereqs.require(denv, 'argobots', 'spdk', 'pmdk') - libs = ['uuid', 'daos_common_pmem', 'gurt', 'vea', 'abt', 'bio', 'cmocka', 'pthread', 'pmemobj'] - denv.AppendUnique(RPATH_FULL=['$PREFIX/lib64/daos_srv']) - denv.AppendUnique(CPPPATH=[Dir('../').srcnode()]) - denv.AppendUnique(CPPPATH=[Dir('../../../vos/').srcnode()]) - denv.AppendUnique(CPPPATH=[Dir('../../../bio/').srcnode()]) + # --------------- + # Build unit test + tenv = denv.Clone() + tenv.AppendUnique(CPPPATH=[Dir('../../../bio/').srcnode()]) + tenv.Append(CPPDEFINES=['-DDAOS_PMEM_BUILD']) + prereqs.require(tenv, 'argobots', 'spdk', 'pmdk') # Required for dtx_act_discard_invalid tests. # This function is validated by its respective unit tests. - denv.AppendUnique(LINKFLAGS=['-Wl,--wrap=vos_dtx_discard_invalid']) + tenv.AppendUnique(LINKFLAGS=['-Wl,--wrap=vos_dtx_discard_invalid']) - denv.Append(CPPDEFINES=['-DDAOS_PMEM_BUILD']) - vos_src = Glob('../../../vos/*.c') - - mock_src = Glob('../../../dtx/tests/*_mock.c') + libs = ['uuid', 'daos_common_pmem', 'gurt', 'vea', 'abt', 'bio', 'cmocka', 'pthread', 'pmemobj'] + src = ['ddb_ut.c', 'ddb_vos_ut.c'] + # vos and mock object files to wrap vos symbols + vos_obj = tenv.Object(Glob('../../../vos/*.c')) + mock_obj = tenv.Object(Glob('../../../dtx/tests/*_mock.c')) # Pylint does not like the exclude keyword below, but it works. # pylint: disable=unexpected-keyword-arg - ddb_src = Glob('../*.c', exclude=['../ddb_entry.c']) - src = ['ddb_ut.c', 'ddb_vos_ut.c'] - ddb_ut = denv.d_program('ddb_ut', src + vos_src + mock_src + ddb_src, LIBS=libs + spdk_libs) + ddb_obj = tenv.Object(Glob('../*.c', exclude=['../ddb_entry.c'])) + ddb_ut = tenv.d_program('ddb_ut', src + vos_obj + mock_obj + ddb_obj, LIBS=libs + spdk_libs) - denv.Install('$PREFIX/bin/', ddb_ut) + tenv.Install('$PREFIX/bin/', ddb_ut) if __name__ == "SCons.Script": From 3ee405ab5bb14e3efba14ed9728b426a02c70b68 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Wed, 30 Apr 2025 13:17:44 +0000 Subject: [PATCH 02/13] DAOS-17322 ddb: DTX aggregation with ddb Miscellaneous fixes detected by clangd. Signed-off-by: Cedric Koch-Hofer --- src/utils/ddb/ddb_commands.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/utils/ddb/ddb_commands.c b/src/utils/ddb/ddb_commands.c index 63359f75696..e6ed54d79e6 100644 --- a/src/utils/ddb/ddb_commands.c +++ b/src/utils/ddb/ddb_commands.c @@ -477,7 +477,7 @@ ddb_run_dtx_dump(struct ddb_ctx *ctx, struct dtx_dump_options *opt) itp_free(&itp); return rc; } - ddb_printf(ctx, "%d Active Entries\n", args.entry_count); + ddb_printf(ctx, "%" PRIu32 " Active Entries\n", args.entry_count); } if (both || opt->committed) { args.entry_count = 0; @@ -487,7 +487,7 @@ ddb_run_dtx_dump(struct ddb_ctx *ctx, struct dtx_dump_options *opt) itp_free(&itp); return rc; } - ddb_printf(ctx, "%d Committed Entries\n", args.entry_count); + ddb_printf(ctx, "%" PRIu32 " Committed Entries\n", args.entry_count); } dv_cont_close(&coh); @@ -874,12 +874,12 @@ ddb_run_vea_update(struct ddb_ctx *ctx, struct vea_update_options *opt) } offset = parse_uint32_t(opt->offset); - if (offset <= 0) { + if (offset == 0) { ddb_errorf(ctx, "'%s' is not a valid offset\n", opt->offset); return -DER_INVAL; } blk_cnt = parse_uint32_t(opt->blk_cnt); - if (blk_cnt <= 0) { + if (blk_cnt == 0) { ddb_errorf(ctx, "'%s' is not a valid block size\n", opt->blk_cnt); return -DER_INVAL; } @@ -888,7 +888,7 @@ ddb_run_vea_update(struct ddb_ctx *ctx, struct vea_update_options *opt) if (!SUCCESS(rc)) return rc; - ddb_printf(ctx, "Adding free region to vea {%lu, %d}\n", offset, blk_cnt); + ddb_printf(ctx, "Adding free region to vea {%" PRIu64 ", %" PRIu32 "}\n", offset, blk_cnt); rc = dv_vea_free_region(ctx->dc_poh, offset, blk_cnt); if (!SUCCESS(rc)) ddb_errorf(ctx, "Unable to add new free region: "DF_RC"\n", DP_RC(rc)); @@ -1122,7 +1122,7 @@ dtx_active_entry_discard_invalid(struct dv_dtx_active_entry *entry, void *cb_arg ddb_errorf(ctx, "Error: " DF_RC "\n", DP_RC(rc)); } - return 0; + return rc; } int From 0be6e7ec8b3ca8f84dd12c60c719f589367eddf0 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Wed, 30 Apr 2025 13:17:44 +0000 Subject: [PATCH 03/13] DAOS-17322 ddb: DTX aggregation with ddb Add the following new command to ddb: - dtx_stat: Print statistics on DTX entries Signed-off-by: Cedric Koch-Hofer --- src/control/cmd/ddb/commands_wrapper.go | 9 ++ src/control/cmd/ddb/ddb_commands.go | 15 +++ src/utils/ddb/ddb.c | 111 ++++++++++++++----- src/utils/ddb/ddb.h | 114 ++++++++++++-------- src/utils/ddb/ddb_commands.c | 106 ++++++++++++++++++ src/utils/ddb/ddb_parse.c | 25 +++++ src/utils/ddb/ddb_parse.h | 5 + src/utils/ddb/tests/ddb_cmd_options_tests.c | 44 +++++--- src/utils/ddb/tests/ddb_cmocka.h | 52 +++++++++ src/utils/ddb/tests/ddb_commands_tests.c | 30 ++++++ src/utils/ddb/tests/ddb_parse_tests.c | 31 ++++++ 11 files changed, 460 insertions(+), 82 deletions(-) diff --git a/src/control/cmd/ddb/commands_wrapper.go b/src/control/cmd/ddb/commands_wrapper.go index 95aa9aa3847..95d7b8aff86 100644 --- a/src/control/cmd/ddb/commands_wrapper.go +++ b/src/control/cmd/ddb/commands_wrapper.go @@ -290,3 +290,12 @@ func ddbDevReplace(ctx *DdbContext, db_path string, old_devid string, new_devid /* Run the c code command */ return daosError(C.ddb_run_dev_replace(&ctx.ctx, &options)) } + +func ddbDtxStat(ctx *DdbContext, path string) error { + /* Set up the options */ + options := C.struct_dtx_stat_options{} + options.path = C.CString(path) + defer freeString(options.path) + /* Run the c code command */ + return daosError(C.ddb_run_dtx_stat(&ctx.ctx, &options)) +} diff --git a/src/control/cmd/ddb/ddb_commands.go b/src/control/cmd/ddb/ddb_commands.go index dfbc0e20ace..0230ad010dd 100644 --- a/src/control/cmd/ddb/ddb_commands.go +++ b/src/control/cmd/ddb/ddb_commands.go @@ -381,4 +381,19 @@ the path must include the extent, otherwise, it must not.`, }, Completer: nil, }) + // Command dtx_stat + app.AddCommand(&grumble.Command{ + Name: "dtx_stat", + Aliases: nil, + Help: "Stat on DTX entries", + LongHelp: "Print statistic on the DTX entries", + HelpGroup: "vos", + Args: func(a *grumble.Args) { + a.String("path", "VOS tree path to query.") + }, + Run: func(c *grumble.Context) error { + return ddbDtxStat(ctx, c.Args.String("path")) + }, + Completer: nil, + }) } diff --git a/src/utils/ddb/ddb.c b/src/utils/ddb/ddb.c index 1135b500904..1afa7c6cf16 100644 --- a/src/utils/ddb/ddb.c +++ b/src/utils/ddb/ddb.c @@ -8,39 +8,44 @@ #include #include #include +#include +#include #include "ddb.h" +#include "daos/common.h" +#include "daos_errno.h" #include "ddb_common.h" #include "ddb_parse.h" -#define MAX_COMMAND_LEN 1024 - -#define same(a, b) (strcmp((a), (b)) == 0) -#define COMMAND_NAME_HELP "help" -#define COMMAND_NAME_QUIT "quit" -#define COMMAND_NAME_LS "ls" -#define COMMAND_NAME_OPEN "open" -#define COMMAND_NAME_VERSION "version" -#define COMMAND_NAME_CLOSE "close" -#define COMMAND_NAME_SUPERBLOCK_DUMP "superblock_dump" -#define COMMAND_NAME_VALUE_DUMP "value_dump" -#define COMMAND_NAME_RM "rm" -#define COMMAND_NAME_VALUE_LOAD "value_load" -#define COMMAND_NAME_ILOG_DUMP "ilog_dump" -#define COMMAND_NAME_ILOG_COMMIT "ilog_commit" -#define COMMAND_NAME_ILOG_CLEAR "ilog_clear" -#define COMMAND_NAME_DTX_DUMP "dtx_dump" -#define COMMAND_NAME_DTX_CMT_CLEAR "dtx_cmt_clear" -#define COMMAND_NAME_SMD_SYNC "smd_sync" -#define COMMAND_NAME_VEA_DUMP "vea_dump" -#define COMMAND_NAME_VEA_UPDATE "vea_update" -#define COMMAND_NAME_DTX_ACT_COMMIT "dtx_act_commit" -#define COMMAND_NAME_DTX_ACT_ABORT "dtx_act_abort" -#define COMMAND_NAME_FEATURE "feature" -#define COMMAND_NAME_RM_POOL "rm_pool" +#define MAX_COMMAND_LEN 1024 + +#define same(a, b) (strcmp((a), (b)) == 0) +#define COMMAND_NAME_HELP "help" +#define COMMAND_NAME_QUIT "quit" +#define COMMAND_NAME_LS "ls" +#define COMMAND_NAME_OPEN "open" +#define COMMAND_NAME_VERSION "version" +#define COMMAND_NAME_CLOSE "close" +#define COMMAND_NAME_SUPERBLOCK_DUMP "superblock_dump" +#define COMMAND_NAME_VALUE_DUMP "value_dump" +#define COMMAND_NAME_RM "rm" +#define COMMAND_NAME_VALUE_LOAD "value_load" +#define COMMAND_NAME_ILOG_DUMP "ilog_dump" +#define COMMAND_NAME_ILOG_COMMIT "ilog_commit" +#define COMMAND_NAME_ILOG_CLEAR "ilog_clear" +#define COMMAND_NAME_DTX_DUMP "dtx_dump" +#define COMMAND_NAME_DTX_CMT_CLEAR "dtx_cmt_clear" +#define COMMAND_NAME_SMD_SYNC "smd_sync" +#define COMMAND_NAME_VEA_DUMP "vea_dump" +#define COMMAND_NAME_VEA_UPDATE "vea_update" +#define COMMAND_NAME_DTX_ACT_COMMIT "dtx_act_commit" +#define COMMAND_NAME_DTX_ACT_ABORT "dtx_act_abort" +#define COMMAND_NAME_FEATURE "feature" +#define COMMAND_NAME_RM_POOL "rm_pool" #define COMMAND_NAME_DTX_ACT_DISCARD_INVALID "dtx_act_discard_invalid" #define COMMAND_NAME_DEV_LIST "dev_list" #define COMMAND_NAME_DEV_REPLACE "dev_replace" +#define COMMAND_NAME_DTX_STAT "dtx_stat" /* Parse command line options for the 'ls' command */ static int @@ -814,6 +819,42 @@ dev_replace_option_parse(struct ddb_ctx *ctx, struct dev_replace_options *cmd_ar return 0; } +/* Parse command line options for the 'dtx_stat' command */ +static int +dtx_stat_option_parse(struct ddb_ctx *ctx, struct dtx_stat_options *cmd_args, uint32_t argc, + char **argv) +{ + char *options_short = ""; + int index = 0; + struct option options_long[] = {{NULL}}; + + memset(cmd_args, 0, sizeof(*cmd_args)); + + /* Restart getopt */ + optind = 1; + opterr = 0; + if (getopt_long(argc, argv, options_short, options_long, &index) != -1) { + ddb_printf(ctx, "Unknown option: '%c'\n", optopt); + return -DER_INVAL; + } + + index = optind; + if (argc - index > 0) { + cmd_args->path = argv[index]; + index++; + } else { + ddb_print(ctx, "Expected argument 'path'\n"); + return -DER_INVAL; + } + + if (argc - index > 0) { + ddb_printf(ctx, "Unexpected argument: %s\n", argv[index]); + return -DER_INVAL; + } + + return 0; +} + int ddb_parse_cmd_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct ddb_cmd_info *info) { @@ -935,6 +976,11 @@ ddb_parse_cmd_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct ddb_c argv); } + if (same(cmd, COMMAND_NAME_DTX_STAT)) { + info->dci_cmd = DDB_CMD_DTX_STAT; + return dtx_stat_option_parse(ctx, &info->dci_cmd_option.dci_dtx_stat, argc, argv); + } + ddb_errorf(ctx, "'%s' is not a valid command. Available commands are:" "'help', " @@ -960,7 +1006,8 @@ ddb_parse_cmd_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct ddb_c "'feature', " "'rm_pool', " "'dev_list', " - "'dev_replace'\n", + "'dev_replace', " + "'dtx_stat'\n", cmd); return -DER_INVAL; @@ -1136,6 +1183,10 @@ ddb_run_cmd(struct ddb_ctx *ctx, const char *cmd_str) rc = ddb_run_dev_replace(ctx, &info.dci_cmd_option.dci_dev_replace); break; + case DDB_CMD_DTX_STAT: + rc = ddb_run_dtx_stat(ctx, &info.dci_cmd_option.dci_dtx_stat); + break; + case DDB_CMD_UNKNOWN: ddb_error(ctx, "Unknown command\n"); rc = -DER_INVAL; @@ -1341,6 +1392,13 @@ ddb_commands_help(struct ddb_ctx *ctx) ddb_print(ctx, " -n, --new_dev\n"); ddb_print(ctx, "\tSpecify the new device UUID\n"); ddb_print(ctx, "\n"); + + /* Command: dtx_stat */ + ddb_print(ctx, "dtx_stat \n"); + ddb_print(ctx, "\tPrint statistic on the DTX entries.\n"); + ddb_print(ctx, " \n"); + ddb_print(ctx, "\tVOS tree path to query.\n"); + ddb_print(ctx, "\n"); } void @@ -1408,4 +1466,5 @@ ddb_program_help(struct ddb_ctx *ctx) ddb_print(ctx, " rm_pool Remove pool shard\n"); ddb_print(ctx, " dev_list List all devices\n"); ddb_print(ctx, " dev_replace Replace an old device with a new unused device\n"); + ddb_print(ctx, " dtx_stat Stat on DTX entries\n"); } diff --git a/src/utils/ddb/ddb.h b/src/utils/ddb/ddb.h index 86c00825efe..8cbf80bd385 100644 --- a/src/utils/ddb/ddb.h +++ b/src/utils/ddb/ddb.h @@ -7,8 +7,8 @@ #ifndef __DDB_RUN_CMDS_H #define __DDB_RUN_CMDS_H - #include +#include typedef int (*ddb_io_line_cb)(void *cb_args, char *line, uint32_t str_len); @@ -121,6 +121,7 @@ enum ddb_cmd { DDB_CMD_DTX_ACT_DISCARD_INVALID = 23, DDB_CMD_DEV_LIST = 24, DDB_CMD_DEV_REPLACE = 25, + DDB_CMD_DTX_STAT = 26, }; /* option and argument structures for commands that need them */ @@ -209,54 +210,79 @@ struct dev_replace_options { char *new_devid; }; +struct dtx_stat_options { + char *path; +}; + struct ddb_cmd_info { enum ddb_cmd dci_cmd; union { - struct ls_options dci_ls; - struct open_options dci_open; - struct value_dump_options dci_value_dump; - struct rm_options dci_rm; - struct value_load_options dci_value_load; - struct ilog_dump_options dci_ilog_dump; - struct ilog_commit_options dci_ilog_commit; - struct ilog_clear_options dci_ilog_clear; - struct dtx_dump_options dci_dtx_dump; + struct ls_options dci_ls; + struct open_options dci_open; + struct value_dump_options dci_value_dump; + struct rm_options dci_rm; + struct value_load_options dci_value_load; + struct ilog_dump_options dci_ilog_dump; + struct ilog_commit_options dci_ilog_commit; + struct ilog_clear_options dci_ilog_clear; + struct dtx_dump_options dci_dtx_dump; struct dtx_cmt_clear_options dci_dtx_cmt_clear; - struct smd_sync_options dci_smd_sync; - struct vea_update_options dci_vea_update; - struct feature_options dci_feature; - struct rm_pool_options dci_rm_pool; - struct dtx_act_options dci_dtx_act; - struct dev_list_options dci_dev_list; - struct dev_replace_options dci_dev_replace; + struct smd_sync_options dci_smd_sync; + struct vea_update_options dci_vea_update; + struct feature_options dci_feature; + struct rm_pool_options dci_rm_pool; + struct dtx_act_options dci_dtx_act; + struct dev_list_options dci_dev_list; + struct dev_replace_options dci_dev_replace; + struct dtx_stat_options dci_dtx_stat; } dci_cmd_option; }; -int ddb_parse_cmd_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct ddb_cmd_info *info); +int +ddb_parse_cmd_args(struct ddb_ctx *ctx, uint32_t argc, char **argv, struct ddb_cmd_info *info); int ddb_parse_cmd_str(struct ddb_ctx *ctx, const char *cmd_str, bool *open); int - ddb_run_cmd(struct ddb_ctx *ctx, const char *cmd_str); +ddb_run_cmd(struct ddb_ctx *ctx, const char *cmd_str); /* Run commands ... */ -int ddb_run_help(struct ddb_ctx *ctx); -int ddb_run_quit(struct ddb_ctx *ctx); -int ddb_run_ls(struct ddb_ctx *ctx, struct ls_options *opt); -bool ddb_pool_is_open(struct ddb_ctx *ctx); -int ddb_run_open(struct ddb_ctx *ctx, struct open_options *opt); -int ddb_run_version(struct ddb_ctx *ctx); -int ddb_run_close(struct ddb_ctx *ctx); -int ddb_run_superblock_dump(struct ddb_ctx *ctx); -int ddb_run_value_dump(struct ddb_ctx *ctx, struct value_dump_options *opt); -int ddb_run_rm(struct ddb_ctx *ctx, struct rm_options *opt); -int ddb_run_value_load(struct ddb_ctx *ctx, struct value_load_options *opt); -int ddb_run_ilog_dump(struct ddb_ctx *ctx, struct ilog_dump_options *opt); -int ddb_run_ilog_commit(struct ddb_ctx *ctx, struct ilog_commit_options *opt); -int ddb_run_ilog_clear(struct ddb_ctx *ctx, struct ilog_clear_options *opt); -int ddb_run_dtx_dump(struct ddb_ctx *ctx, struct dtx_dump_options *opt); -int ddb_run_dtx_cmt_clear(struct ddb_ctx *ctx, struct dtx_cmt_clear_options *opt); -int ddb_run_smd_sync(struct ddb_ctx *ctx, struct smd_sync_options *opt); -int ddb_run_vea_dump(struct ddb_ctx *ctx); -int ddb_run_vea_update(struct ddb_ctx *ctx, struct vea_update_options *opt); +int +ddb_run_help(struct ddb_ctx *ctx); +int +ddb_run_quit(struct ddb_ctx *ctx); +int +ddb_run_ls(struct ddb_ctx *ctx, struct ls_options *opt); +bool +ddb_pool_is_open(struct ddb_ctx *ctx); +int +ddb_run_open(struct ddb_ctx *ctx, struct open_options *opt); +int +ddb_run_version(struct ddb_ctx *ctx); +int +ddb_run_close(struct ddb_ctx *ctx); +int +ddb_run_superblock_dump(struct ddb_ctx *ctx); +int +ddb_run_value_dump(struct ddb_ctx *ctx, struct value_dump_options *opt); +int +ddb_run_rm(struct ddb_ctx *ctx, struct rm_options *opt); +int +ddb_run_value_load(struct ddb_ctx *ctx, struct value_load_options *opt); +int +ddb_run_ilog_dump(struct ddb_ctx *ctx, struct ilog_dump_options *opt); +int +ddb_run_ilog_commit(struct ddb_ctx *ctx, struct ilog_commit_options *opt); +int +ddb_run_ilog_clear(struct ddb_ctx *ctx, struct ilog_clear_options *opt); +int +ddb_run_dtx_dump(struct ddb_ctx *ctx, struct dtx_dump_options *opt); +int +ddb_run_dtx_cmt_clear(struct ddb_ctx *ctx, struct dtx_cmt_clear_options *opt); +int +ddb_run_smd_sync(struct ddb_ctx *ctx, struct smd_sync_options *opt); +int +ddb_run_vea_dump(struct ddb_ctx *ctx); +int +ddb_run_vea_update(struct ddb_ctx *ctx, struct vea_update_options *opt); int ddb_run_dtx_act_commit(struct ddb_ctx *ctx, struct dtx_act_options *opt); int @@ -269,13 +295,17 @@ ddb_feature_string2flags(struct ddb_ctx *ctx, const char *string, uint64_t *comp int ddb_run_rm_pool(struct ddb_ctx *ctx, struct rm_pool_options *opt); int - ddb_run_dtx_act_discard_invalid(struct ddb_ctx *ctx, struct dtx_act_options *opt); +ddb_run_dtx_act_discard_invalid(struct ddb_ctx *ctx, struct dtx_act_options *opt); int ddb_run_dev_list(struct ddb_ctx *ctx, struct dev_list_options *opt); int - ddb_run_dev_replace(struct ddb_ctx *ctx, struct dev_replace_options *opt); +ddb_run_dev_replace(struct ddb_ctx *ctx, struct dev_replace_options *opt); +int +ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt); -void ddb_program_help(struct ddb_ctx *ctx); -void ddb_commands_help(struct ddb_ctx *ctx); +void +ddb_program_help(struct ddb_ctx *ctx); +void +ddb_commands_help(struct ddb_ctx *ctx); #endif /* __DDB_RUN_CMDS_H */ diff --git a/src/utils/ddb/ddb_commands.c b/src/utils/ddb/ddb_commands.c index e6ed54d79e6..772202564a1 100644 --- a/src/utils/ddb/ddb_commands.c +++ b/src/utils/ddb/ddb_commands.c @@ -7,6 +7,11 @@ #include #include +#include +#include + +#include "daos_errno.h" +#include "daos_types.h" #include "ddb_common.h" #include "ddb_parse.h" #include "ddb.h" @@ -14,6 +19,8 @@ #include "ddb_printer.h" #include "daos.h" #include "ddb_tree_path.h" +#include "gurt/common.h" +#include "gurt/debug.h" #define ilog_path_required_error_message "Path to object, dkey, or akey required\n" #define error_msg_write_mode_only "Can only modify the VOS tree in 'write mode'\n" @@ -1258,3 +1265,102 @@ ddb_run_dev_replace(struct ddb_ctx *ctx, struct dev_replace_options *opt) return rc; } + +enum { TIMESPEC_FMT_SIZE = sizeof("1970-01-01 00:00:00.000000000") }; + +static int +timespec2str(struct timespec *tspec, char *buf, size_t buf_size) +{ + struct tm date; + size_t buf_len; + int rc; + + tzset(); + if (localtime_r(&(tspec->tv_sec), &date) == NULL) + return d_errno2der(errno); + + if (strftime(buf, buf_size, "%F %T", &date) == 0) + return -DER_INVAL; + + buf_len = strnlen(buf, buf_size); + D_ASSERT(buf_len < buf_size); + + rc = snprintf(&buf[buf_len], buf_size - buf_len, ".%09ld", tspec->tv_nsec); + if (rc < 0) + return -DER_INVAL; + if (rc >= buf_size - buf_len) + return -DER_TRUNC; + + return -DER_SUCCESS; +} + +static int +dtx_print_time_stat(struct ddb_ctx *ctx, char *stat_name, uint64_t epoch, char *align) +{ + struct timespec tspec; + char buf[TIMESPEC_FMT_SIZE]; + int rc; + + rc = d_hlc2timespec(epoch, &tspec); + if (!SUCCESS(rc)) { + ddb_errorf(ctx, "Conversion error of the DTX stat %s: " DF_RC "\n", stat_name, + DP_RC(rc)); + return rc; + } + rc = timespec2str(&tspec, buf, TIMESPEC_FMT_SIZE); + if (!SUCCESS(rc)) { + ddb_errorf(ctx, "Conversion error of the DTX stat %s: " DF_RC "\n", stat_name, + DP_RC(rc)); + return rc; + } + ddb_printf(ctx, "\t- %s time:%s%s, %" PRIu64 "\n", stat_name, align, buf, epoch); + + return -DER_SUCCESS; +} + +int +ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt) +{ + struct dv_indexed_tree_path itp = {0}; + daos_handle_t coh = {0}; + struct dtx_stat stat; + int rc; + + rc = init_path(ctx, opt->path, &itp); + if (!SUCCESS(rc)) + goto done; + + if (!itp_has_cont(&itp)) { + rc = -DER_INVAL; + goto done; + } + + rc = dv_cont_open(ctx->dc_poh, itp_cont(&itp), &coh); + if (!SUCCESS(rc)) + goto done; + + rc = vos_dtx_cmt_reindex(coh); + if (rc < 0) { + ddb_errorf(ctx, "DTX entries Statistic refresh failed: " DF_RC, DP_RC(rc)); + goto done; + } + vos_dtx_stat(coh, &stat, 0); + + ddb_print(ctx, "DTX entries statistics of "); + itp_print_full(ctx, &itp); + ddb_print(ctx, "\n"); + ddb_printf(ctx, "\t- Number of committed DTX of the container:\t%" PRIu32 "\n", + stat.dtx_cont_cmt_count); + ddb_printf(ctx, "\t- Number of committed DTX of the pool:\t\t%" PRIu32 "\n", + stat.dtx_pool_cmt_count); + rc = + dtx_print_time_stat(ctx, "DTX newest aggregated", stat.dtx_newest_aggregated, "\t\t\t"); + if (!SUCCESS(rc)) + goto done; + +done: + itp_free(&itp); + dv_cont_close(&coh); + + return rc; +} diff --git a/src/utils/ddb/ddb_parse.c b/src/utils/ddb/ddb_parse.c index 2e55615d016..a6034aef581 100644 --- a/src/utils/ddb/ddb_parse.c +++ b/src/utils/ddb/ddb_parse.c @@ -1,5 +1,6 @@ /** * (C) Copyright 2019-2024 Intel Corporation. + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -7,6 +8,7 @@ #include #include #include +#include "daos_errno.h" #include "ddb_common.h" #include "ddb_parse.h" @@ -477,3 +479,26 @@ ddb_parse_key(const char *input, daos_key_t *key) key_parse_typed(input, key) : key_parse_str(input, key); } + +int +ddb_date2epoch(const char *date, uint64_t *epoch) +{ + struct tm date_tm; + struct timespec date_tspec; + char *endptr; + + if (date == NULL || epoch == NULL) + return -DER_INVAL; + + memset(&date_tm, 0, sizeof(struct tm)); + endptr = strptime(date, "%Y-%m-%d %H:%M:%S", &date_tm); + if (endptr == NULL || *endptr != '\0') + return -DER_INVAL; + + memset(&date_tspec, 0, sizeof(struct timespec)); + date_tspec.tv_sec = mktime(&date_tm); + if (date_tspec.tv_sec == (time_t)-1) + return daos_errno2der(errno); + + return d_timespec2hlc(date_tspec, epoch); +} diff --git a/src/utils/ddb/ddb_parse.h b/src/utils/ddb/ddb_parse.h index fcd28754445..93b7ef7c064 100644 --- a/src/utils/ddb/ddb_parse.h +++ b/src/utils/ddb/ddb_parse.h @@ -1,5 +1,6 @@ /** * (C) Copyright 2019-2024 Intel Corporation. + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -50,4 +51,8 @@ int ddb_parse_key(const char *input, daos_key_t *key); */ int ddb_parse_dtx_id(const char *dtx_id_str, struct dtx_id *dtx_id); +/* Parse a string representing a date into an epoch */ +int +ddb_date2epoch(const char *date, uint64_t *epoch); + #endif /** __DAOS_DDB_PARSE_H */ diff --git a/src/utils/ddb/tests/ddb_cmd_options_tests.c b/src/utils/ddb/tests/ddb_cmd_options_tests.c index 9481748af0a..1086594a948 100644 --- a/src/utils/ddb/tests/ddb_cmd_options_tests.c +++ b/src/utils/ddb/tests/ddb_cmd_options_tests.c @@ -297,6 +297,21 @@ dtx_act_abort_options_parsing(void **state) assert_non_null(options->dtx_id); } +static void +dtx_stat_parsing(void **state) +{ + struct ddb_cmd_info info = {0}; + struct dtx_stat_options *options = &info.dci_cmd_option.dci_dtx_stat; + + /* test invalid arguments and options */ + test_run_inval_cmd("dtx_stat", "path", "extra"); /* too many argument */ + test_run_inval_cmd("dtx_stat", "-z"); /* invalid option */ + + /* test all arguments */ + test_run_cmd(&info, "dtx_stat", "path"); + assert_non_null(options->path); +} + /* * ----------------------------------------------- * Execute @@ -307,20 +322,21 @@ int ddb_cmd_options_tests_run() { static const struct CMUnitTest tests[] = { - TEST(ls_options_parsing), - TEST(open_options_parsing), - TEST(value_dump_options_parsing), - TEST(rm_options_parsing), - TEST(value_load_options_parsing), - TEST(ilog_dump_options_parsing), - TEST(ilog_commit_options_parsing), - TEST(ilog_clear_options_parsing), - TEST(dtx_dump_options_parsing), - TEST(dtx_cmt_clear_options_parsing), - TEST(smd_sync_options_parsing), - TEST(vea_update_options_parsing), - TEST(dtx_act_commit_options_parsing), - TEST(dtx_act_abort_options_parsing), + TEST(ls_options_parsing), + TEST(open_options_parsing), + TEST(value_dump_options_parsing), + TEST(rm_options_parsing), + TEST(value_load_options_parsing), + TEST(ilog_dump_options_parsing), + TEST(ilog_commit_options_parsing), + TEST(ilog_clear_options_parsing), + TEST(dtx_dump_options_parsing), + TEST(dtx_cmt_clear_options_parsing), + TEST(smd_sync_options_parsing), + TEST(vea_update_options_parsing), + TEST(dtx_act_commit_options_parsing), + TEST(dtx_act_abort_options_parsing), + TEST(dtx_stat_parsing), }; return cmocka_run_group_tests_name("DDB commands option parsing tests", tests, diff --git a/src/utils/ddb/tests/ddb_cmocka.h b/src/utils/ddb/tests/ddb_cmocka.h index dd38715e376..1605fbf87bf 100644 --- a/src/utils/ddb/tests/ddb_cmocka.h +++ b/src/utils/ddb/tests/ddb_cmocka.h @@ -1,5 +1,6 @@ /** * (C) Copyright 2022 Intel Corporation. + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -7,8 +8,10 @@ #ifndef DAOS_DDB_CMOCKA_H #define DAOS_DDB_CMOCKA_H #include +#include #include #include +#include #include #define assert_uuid_equal(a, b) \ @@ -69,4 +72,53 @@ #define assert_invalid(x) assert_rc_equal(-DER_INVAL, (x)) #define assert_nonexist(x) assert_rc_equal(-DER_NONEXIST, (x)) +/* XXX Needs of testing _buf to avoid false positive error from gcc: '%s' directive argument is null + * [-Werror=format-overflow=] */ +#define assert_regex_match(str, regex) \ + do { \ + char *_str_dup; \ + char *_token; \ + regex_t _preg; \ + int _rc = regcomp(&_preg, regex, REG_NOSUB | REG_EXTENDED); \ + if (_rc != 0) { \ + char *_buf; \ + size_t _buf_size = regerror(_rc, &_preg, NULL, 0); \ + D_ALLOC_ARRAY(_buf, _buf_size); \ + assert_non_null(_buf); \ + regerror(_rc, &_preg, _buf, _buf_size); \ + if (_buf) \ + print_error("ERROR: invalid regex '%s': %s\n", regex, _buf); \ + D_FREE(_buf); \ + regfree(&_preg); \ + fail(); \ + } \ + D_STRNDUP(_str_dup, str, strlen(str)); \ + assert_non_null(_str_dup); \ + _token = strtok(_str_dup, "\n"); \ + while (_token != NULL) { \ + _rc = regexec(&_preg, _token, 0, NULL, 0); \ + if (_rc == 0) \ + break; \ + if (_rc != REG_NOMATCH) { \ + char *_buf; \ + size_t _buf_size = regerror(_rc, &_preg, NULL, 0); \ + D_ALLOC_ARRAY(_buf, _buf_size); \ + assert_non_null(_buf); \ + regerror(_rc, &_preg, _buf, _buf_size); \ + if (_buf) \ + print_error("ERROR: invalid regex '%s': %s\n", regex, \ + _buf); \ + D_FREE(_buf); \ + regfree(&_preg); \ + D_FREE(_str_dup); \ + fail(); \ + } \ + _token = strtok(NULL, "\n"); \ + } \ + D_FREE(_str_dup); \ + regfree(&_preg); \ + if (_rc == REG_NOMATCH) \ + fail_msg("'%s' regex not matched in '%s'", regex, str); \ + } while (0) + #endif /* DAOS_DDB_CMOCKA_H */ diff --git a/src/utils/ddb/tests/ddb_commands_tests.c b/src/utils/ddb/tests/ddb_commands_tests.c index b0fdbf5ad89..35f2ba07595 100644 --- a/src/utils/ddb/tests/ddb_commands_tests.c +++ b/src/utils/ddb/tests/ddb_commands_tests.c @@ -4,7 +4,15 @@ * * SPDX-License-Identifier: BSD-2-Clause-Patent */ +#include +#include +#include +#include +#include + +#include "gurt/common.h" #include +#include "daos/common.h" #include #include #include @@ -397,6 +405,27 @@ feature_cmd_tests(void **state) assert_success(ddb_run_feature(&g_ctx, &opt)); } +static void +dtx_stat_tests(void **state) +{ + struct dt_vos_pool_ctx *tctx = *state; + struct ddb_ctx ctx = {0}; + struct dtx_stat_options opt = {0}; + + ctx.dc_poh = tctx->dvt_poh; + ctx.dc_io_ft.ddb_print_message = dvt_fake_print; + ctx.dc_io_ft.ddb_print_error = dvt_fake_print; + ctx.dc_write_mode = false; + opt.path = "[0]"; + dvt_fake_print_reset(); + assert_success(ddb_run_dtx_stat(&ctx, &opt)); + assert_regex_match( + dvt_fake_print_buffer, + "^[[:blank:]]+- Number of committed DTX of the container:[[:blank:]]+1$"); + assert_regex_match(dvt_fake_print_buffer, + "^[[:blank:]]+- DTX newest aggregated time:.+, 0$"); +} + /* * -------------------------------------------------------------- * End test functions @@ -447,6 +476,7 @@ ddb_commands_tests_run() TEST(dump_ilog_cmd_tests), TEST(dump_superblock_cmd_tests), TEST(dump_dtx_cmd_tests), + TEST(dtx_stat_tests), TEST(rm_cmd_tests), TEST(load_cmd_tests), TEST(rm_ilog_cmd_tests), diff --git a/src/utils/ddb/tests/ddb_parse_tests.c b/src/utils/ddb/tests/ddb_parse_tests.c index 155b9c1bcc4..e7bb8b93f4c 100644 --- a/src/utils/ddb/tests/ddb_parse_tests.c +++ b/src/utils/ddb/tests/ddb_parse_tests.c @@ -1,5 +1,6 @@ /** * (C) Copyright 2022-2024 Intel Corporation. + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -8,6 +9,7 @@ #include #include #include +#include "daos_errno.h" #include "ddb_cmocka.h" #include "ddb_test_driver.h" @@ -348,6 +350,34 @@ pool_flags_tests(void **state) assert_rc_equal(-DER_INVAL, rc); } +static void +date2epoch_tests(void **state) +{ + uint64_t epoch = -1; + int rc; + + rc = ddb_date2epoch(NULL, &epoch); + assert_rc_equal(rc, -DER_INVAL); + assert_int_equal(epoch, -1); + rc = ddb_date2epoch("1970-01-01 00:00:00", NULL); + assert_rc_equal(rc, -DER_INVAL); + assert_int_equal(epoch, -1); + rc = ddb_date2epoch(NULL, NULL); + assert_rc_equal(rc, -DER_INVAL); + assert_int_equal(epoch, -1); + rc = ddb_date2epoch("foo", NULL); + assert_rc_equal(rc, -DER_INVAL); + assert_int_equal(epoch, -1); + rc = ddb_date2epoch("0000-00-00 00:00:00", &epoch); + assert_rc_equal(rc, -DER_INVAL); + assert_int_equal(epoch, -1); + + rc = ddb_date2epoch("1970-01-01 00:00:00", &epoch); + assert_success(rc); + assert_int_equal(rc, -DER_SUCCESS); + assert_int_equal(epoch, 0x9aa0d62878400000ull); +} + /* * ----------------------------------------------- * Execute @@ -360,6 +390,7 @@ ddb_parse_tests_run() static const struct CMUnitTest tests[] = { TEST(vos_file_parts_tests), TEST(string_to_argv_tests), TEST(parse_args_tests), TEST(parse_dtx_id_tests), TEST(keys_are_parsed_correctly), TEST(pool_flags_tests), + TEST(date2epoch_tests), }; return cmocka_run_group_tests_name("DDB helper parsing function tests", tests, NULL, NULL); From 983d9d42a814d14e9570951fe8f3f531c6ac628a Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 8 Sep 2025 07:05:02 +0000 Subject: [PATCH 04/13] DAOS-17322 ddb: DTX aggregation with ddb Integrate reviewers comments: - Remove useless test - Remove useless strlen - Use static initialisation instead of explicit initialisation. Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/utils/ddb/ddb_commands.c | 6 ++---- src/utils/ddb/ddb_parse.c | 6 ++---- src/utils/ddb/tests/ddb_cmocka.h | 7 ++----- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/utils/ddb/ddb_commands.c b/src/utils/ddb/ddb_commands.c index bc2bb334ecc..8ea0be1248f 100644 --- a/src/utils/ddb/ddb_commands.c +++ b/src/utils/ddb/ddb_commands.c @@ -1296,12 +1296,10 @@ timespec2str(struct timespec *tspec, char *buf, size_t buf_size) if (localtime_r(&(tspec->tv_sec), &date) == NULL) return d_errno2der(errno); - if (strftime(buf, buf_size, "%F %T", &date) == 0) + buf_len = strftime(buf, buf_size, "%F %T", &date); + if (buf_len == 0) return -DER_INVAL; - buf_len = strnlen(buf, buf_size); - D_ASSERT(buf_len < buf_size); - rc = snprintf(&buf[buf_len], buf_size - buf_len, ".%09ld", tspec->tv_nsec); if (rc < 0) return -DER_INVAL; diff --git a/src/utils/ddb/ddb_parse.c b/src/utils/ddb/ddb_parse.c index a6034aef581..9bbdc5e3b16 100644 --- a/src/utils/ddb/ddb_parse.c +++ b/src/utils/ddb/ddb_parse.c @@ -483,19 +483,17 @@ ddb_parse_key(const char *input, daos_key_t *key) int ddb_date2epoch(const char *date, uint64_t *epoch) { - struct tm date_tm; - struct timespec date_tspec; + struct tm date_tm = {0}; + struct timespec date_tspec = {0}; char *endptr; if (date == NULL || epoch == NULL) return -DER_INVAL; - memset(&date_tm, 0, sizeof(struct tm)); endptr = strptime(date, "%Y-%m-%d %H:%M:%S", &date_tm); if (endptr == NULL || *endptr != '\0') return -DER_INVAL; - memset(&date_tspec, 0, sizeof(struct timespec)); date_tspec.tv_sec = mktime(&date_tm); if (date_tspec.tv_sec == (time_t)-1) return daos_errno2der(errno); diff --git a/src/utils/ddb/tests/ddb_cmocka.h b/src/utils/ddb/tests/ddb_cmocka.h index 1605fbf87bf..9ab32577f92 100644 --- a/src/utils/ddb/tests/ddb_cmocka.h +++ b/src/utils/ddb/tests/ddb_cmocka.h @@ -86,8 +86,7 @@ D_ALLOC_ARRAY(_buf, _buf_size); \ assert_non_null(_buf); \ regerror(_rc, &_preg, _buf, _buf_size); \ - if (_buf) \ - print_error("ERROR: invalid regex '%s': %s\n", regex, _buf); \ + print_error("ERROR: invalid regex '%s': %s\n", regex, _buf); \ D_FREE(_buf); \ regfree(&_preg); \ fail(); \ @@ -105,9 +104,7 @@ D_ALLOC_ARRAY(_buf, _buf_size); \ assert_non_null(_buf); \ regerror(_rc, &_preg, _buf, _buf_size); \ - if (_buf) \ - print_error("ERROR: invalid regex '%s': %s\n", regex, \ - _buf); \ + print_error("ERROR: invalid regex '%s': %s\n", regex, _buf); \ D_FREE(_buf); \ regfree(&_preg); \ D_FREE(_str_dup); \ From 77e3c2166b2e2f0362f3e097fdcea7872a5df5f4 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 8 Sep 2025 07:05:02 +0000 Subject: [PATCH 05/13] DAOS-17322 ddb: DTX aggregation with ddb Integrate reviewers comments: - fix invalid regfree() Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/utils/ddb/tests/ddb_cmocka.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils/ddb/tests/ddb_cmocka.h b/src/utils/ddb/tests/ddb_cmocka.h index 9ab32577f92..828a71dd0a8 100644 --- a/src/utils/ddb/tests/ddb_cmocka.h +++ b/src/utils/ddb/tests/ddb_cmocka.h @@ -82,13 +82,12 @@ int _rc = regcomp(&_preg, regex, REG_NOSUB | REG_EXTENDED); \ if (_rc != 0) { \ char *_buf; \ - size_t _buf_size = regerror(_rc, &_preg, NULL, 0); \ + size_t _buf_size = regerror(_rc, NULL, NULL, 0); \ D_ALLOC_ARRAY(_buf, _buf_size); \ assert_non_null(_buf); \ - regerror(_rc, &_preg, _buf, _buf_size); \ + regerror(_rc, NULL, _buf, _buf_size); \ print_error("ERROR: invalid regex '%s': %s\n", regex, _buf); \ D_FREE(_buf); \ - regfree(&_preg); \ fail(); \ } \ D_STRNDUP(_str_dup, str, strlen(str)); \ From 2b72e15fc56df06a9fb47368512eb34898570287 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 8 Sep 2025 07:05:02 +0000 Subject: [PATCH 06/13] DAOS-17322 ddb: DTX aggregation with ddb Integrate reviewers comments: - Print stat for all containers Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/control/cmd/ddb/ddb_commands.go | 2 +- src/utils/ddb/ddb.c | 12 +-- src/utils/ddb/ddb_commands.c | 101 ++++++++++++++++---- src/utils/ddb/tests/ddb_cmd_options_tests.c | 4 + src/utils/ddb/tests/ddb_commands_tests.c | 9 ++ 5 files changed, 101 insertions(+), 27 deletions(-) diff --git a/src/control/cmd/ddb/ddb_commands.go b/src/control/cmd/ddb/ddb_commands.go index 0230ad010dd..27968cf5fec 100644 --- a/src/control/cmd/ddb/ddb_commands.go +++ b/src/control/cmd/ddb/ddb_commands.go @@ -389,7 +389,7 @@ the path must include the extent, otherwise, it must not.`, LongHelp: "Print statistic on the DTX entries", HelpGroup: "vos", Args: func(a *grumble.Args) { - a.String("path", "VOS tree path to query.") + a.String("path", "Optional, VOS tree path to query.", grumble.Default("")) }, Run: func(c *grumble.Context) error { return ddbDtxStat(ctx, c.Args.String("path")) diff --git a/src/utils/ddb/ddb.c b/src/utils/ddb/ddb.c index 1afa7c6cf16..ac3a72fb0b9 100644 --- a/src/utils/ddb/ddb.c +++ b/src/utils/ddb/ddb.c @@ -839,12 +839,10 @@ dtx_stat_option_parse(struct ddb_ctx *ctx, struct dtx_stat_options *cmd_args, ui } index = optind; - if (argc - index > 0) { + cmd_args->path = NULL; + if (argc - index > 0 && *argv[index] != '\0') { cmd_args->path = argv[index]; index++; - } else { - ddb_print(ctx, "Expected argument 'path'\n"); - return -DER_INVAL; } if (argc - index > 0) { @@ -1394,10 +1392,10 @@ ddb_commands_help(struct ddb_ctx *ctx) ddb_print(ctx, "\n"); /* Command: dtx_stat */ - ddb_print(ctx, "dtx_stat \n"); + ddb_print(ctx, "dtx_stat [path]\n"); ddb_print(ctx, "\tPrint statistic on the DTX entries.\n"); - ddb_print(ctx, " \n"); - ddb_print(ctx, "\tVOS tree path to query.\n"); + ddb_print(ctx, " [path]\n"); + ddb_print(ctx, "\tOptional, VOS tree path to query.\n"); ddb_print(ctx, "\n"); } diff --git a/src/utils/ddb/ddb_commands.c b/src/utils/ddb/ddb_commands.c index 8ea0be1248f..805369acbb1 100644 --- a/src/utils/ddb/ddb_commands.c +++ b/src/utils/ddb/ddb_commands.c @@ -11,6 +11,7 @@ #include #include "daos_errno.h" +#include "daos_srv/vos_types.h" #include "daos_types.h" #include "ddb_common.h" #include "ddb_parse.h" @@ -1333,24 +1334,20 @@ dtx_print_time_stat(struct ddb_ctx *ctx, char *stat_name, uint64_t epoch, char * return -DER_SUCCESS; } -int -ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt) -{ - struct dv_indexed_tree_path itp = {0}; - daos_handle_t coh = {0}; - struct dtx_stat stat; - int rc; - - rc = init_path(ctx, opt->path, &itp); - if (!SUCCESS(rc)) - goto done; +struct dtx_stat_args { + struct ddb_ctx *ctx; + struct dtx_stat_options *opt; + uint32_t cont_seen; +}; - if (!itp_has_cont(&itp)) { - rc = -DER_INVAL; - goto done; - } +static int +dtx_stat(struct ddb_ctx *ctx, struct dv_indexed_tree_path *itp) +{ + struct dtx_stat stat; + daos_handle_t coh = {0}; + int rc; - rc = dv_cont_open(ctx->dc_poh, itp_cont(&itp), &coh); + rc = dv_cont_open(ctx->dc_poh, itp_cont(itp), &coh); if (!SUCCESS(rc)) goto done; @@ -1362,7 +1359,7 @@ ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt) vos_dtx_stat(coh, &stat, 0); ddb_print(ctx, "DTX entries statistics of "); - itp_print_full(ctx, &itp); + itp_print_full(ctx, itp); ddb_print(ctx, "\n"); ddb_printf(ctx, "\t- Number of committed DTX of the container:\t%" PRIu32 "\n", stat.dtx_cont_cmt_count); @@ -1372,10 +1369,76 @@ ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt) dtx_print_time_stat(ctx, "DTX newest aggregated", stat.dtx_newest_aggregated, "\t\t\t"); if (!SUCCESS(rc)) goto done; - done: - itp_free(&itp); dv_cont_close(&coh); return rc; } + +static int +dtx_stat_cb(daos_handle_t ih, vos_iter_entry_t *entry, vos_iter_type_t type, + vos_iter_param_t *param, void *cb_arg, unsigned int *acts) +{ + struct ddb_ctx *ctx; + struct dv_indexed_tree_path itp = {0}; + struct dtx_stat_args *args; + int rc; + + if (type != VOS_ITER_COUUID) + return 0; + + args = (struct dtx_stat_args *)cb_arg; + ctx = args->ctx; + + itp_set_cont(&itp, entry->ie_couuid, args->cont_seen); + ++args->cont_seen; + + rc = dtx_stat(ctx, &itp); + itp_free(&itp); + + return rc; +} + +int +ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt) +{ + vos_iter_param_t param = {0}; + struct dtx_stat_args args = {0}; + int rc; + + if (daos_handle_is_inval(ctx->dc_poh)) { + ddb_error(ctx, "Not connected to a pool. Use 'open' to connect to a pool.\n"); + return -DER_NONEXIST; + } + + if (opt->path != NULL && opt->path[0] != '\0') { + struct dv_indexed_tree_path itp = {0}; + + rc = init_path(ctx, opt->path, &itp); + if (!SUCCESS(rc)) + goto done; + + if (!itp_has_cont(&itp)) { + rc = -DER_INVAL; + goto done; + } + + rc = dtx_stat(ctx, &itp); +done: + itp_free(&itp); + return rc; + } + + args.ctx = ctx; + args.opt = opt; + param.ip_hdl = ctx->dc_poh; + param.ip_epr.epr_hi = DAOS_EPOCH_MAX; + do { + struct vos_iter_anchors anchors = {0}; + + rc = vos_iterate(¶m, VOS_ITER_COUUID, false, &anchors, NULL, dtx_stat_cb, &args, + NULL); + } while (rc > 0); + + return rc; +} diff --git a/src/utils/ddb/tests/ddb_cmd_options_tests.c b/src/utils/ddb/tests/ddb_cmd_options_tests.c index 1086594a948..199099abc77 100644 --- a/src/utils/ddb/tests/ddb_cmd_options_tests.c +++ b/src/utils/ddb/tests/ddb_cmd_options_tests.c @@ -310,6 +310,10 @@ dtx_stat_parsing(void **state) /* test all arguments */ test_run_cmd(&info, "dtx_stat", "path"); assert_non_null(options->path); + + /* test all arguments */ + test_run_cmd(&info, "dtx_stat"); + assert_null(options->path); } /* diff --git a/src/utils/ddb/tests/ddb_commands_tests.c b/src/utils/ddb/tests/ddb_commands_tests.c index 35f2ba07595..336474950a3 100644 --- a/src/utils/ddb/tests/ddb_commands_tests.c +++ b/src/utils/ddb/tests/ddb_commands_tests.c @@ -424,6 +424,15 @@ dtx_stat_tests(void **state) "^[[:blank:]]+- Number of committed DTX of the container:[[:blank:]]+1$"); assert_regex_match(dvt_fake_print_buffer, "^[[:blank:]]+- DTX newest aggregated time:.+, 0$"); + + opt.path = ""; + dvt_fake_print_reset(); + assert_success(ddb_run_dtx_stat(&ctx, &opt)); + assert_regex_match( + dvt_fake_print_buffer, + "^[[:blank:]]+- Number of committed DTX of the container:[[:blank:]]+1$"); + assert_regex_match(dvt_fake_print_buffer, + "^[[:blank:]]+- DTX newest aggregated time:.+, 0$"); } /* From 3ff2b3a9cdfbffa80d0d15b330e5a3844d2c0d36 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 8 Sep 2025 07:05:02 +0000 Subject: [PATCH 07/13] DAOS-17322 ddb: DTX aggregation with ddb Integrate reviewers comments: - Replace vos_dtx_cmt_reindex() with iterate on vos_dtx_blob_df Other updates: - Fix number of committed entries per pool Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/include/daos_srv/vos.h | 10 +++++++ src/utils/ddb/ddb_commands.c | 36 +++++++++++++++--------- src/utils/ddb/tests/ddb_commands_tests.c | 2 ++ src/utils/ddb/tests/ddb_test_driver.h | 3 +- src/vos/vos_dtx.c | 36 ++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/include/daos_srv/vos.h b/src/include/daos_srv/vos.h index c4238bbc933..c0c3b472e01 100644 --- a/src/include/daos_srv/vos.h +++ b/src/include/daos_srv/vos.h @@ -1777,4 +1777,14 @@ vos_pin_objects(daos_handle_t coh, daos_unit_oid_t oids[], int count, struct vos bool vos_oi_exist(daos_handle_t coh, daos_unit_oid_t oid); +/** + * Return the number of DTX committed entries of a container. + * + * \param[in] coh container open handle. + * + * \return Number of DTX committed entries. + */ +uint32_t +vos_dtx_get_cmt_cnt(daos_handle_t coh); + #endif /* __VOS_API_H */ diff --git a/src/utils/ddb/ddb_commands.c b/src/utils/ddb/ddb_commands.c index 805369acbb1..a96edd1bd9d 100644 --- a/src/utils/ddb/ddb_commands.c +++ b/src/utils/ddb/ddb_commands.c @@ -1338,37 +1338,34 @@ struct dtx_stat_args { struct ddb_ctx *ctx; struct dtx_stat_options *opt; uint32_t cont_seen; + uint32_t cmt_cnt; }; static int -dtx_stat(struct ddb_ctx *ctx, struct dv_indexed_tree_path *itp) +dtx_stat(struct ddb_ctx *ctx, struct dv_indexed_tree_path *itp, uint32_t *cnt) { struct dtx_stat stat; daos_handle_t coh = {0}; + uint32_t cnt_tmp; int rc; rc = dv_cont_open(ctx->dc_poh, itp_cont(itp), &coh); if (!SUCCESS(rc)) goto done; - rc = vos_dtx_cmt_reindex(coh); - if (rc < 0) { - ddb_errorf(ctx, "DTX entries Statistic refresh failed: " DF_RC, DP_RC(rc)); - goto done; - } + cnt_tmp = vos_dtx_get_cmt_cnt(coh); vos_dtx_stat(coh, &stat, 0); ddb_print(ctx, "DTX entries statistics of "); itp_print_full(ctx, itp); ddb_print(ctx, "\n"); - ddb_printf(ctx, "\t- Number of committed DTX of the container:\t%" PRIu32 "\n", - stat.dtx_cont_cmt_count); - ddb_printf(ctx, "\t- Number of committed DTX of the pool:\t\t%" PRIu32 "\n", - stat.dtx_pool_cmt_count); + ddb_printf(ctx, "\t- Number of committed DTX of the container:\t%" PRIu32 "\n", cnt_tmp); rc = dtx_print_time_stat(ctx, "DTX newest aggregated", stat.dtx_newest_aggregated, "\t\t\t"); if (!SUCCESS(rc)) goto done; + if (cnt != NULL) + *cnt = cnt_tmp; done: dv_cont_close(&coh); @@ -1382,10 +1379,13 @@ dtx_stat_cb(daos_handle_t ih, vos_iter_entry_t *entry, vos_iter_type_t type, struct ddb_ctx *ctx; struct dv_indexed_tree_path itp = {0}; struct dtx_stat_args *args; + uint32_t cnt; int rc; - if (type != VOS_ITER_COUUID) - return 0; + if (type != VOS_ITER_COUUID) { + rc = -DER_SUCCESS; + goto done; + } args = (struct dtx_stat_args *)cb_arg; ctx = args->ctx; @@ -1393,7 +1393,12 @@ dtx_stat_cb(daos_handle_t ih, vos_iter_entry_t *entry, vos_iter_type_t type, itp_set_cont(&itp, entry->ie_couuid, args->cont_seen); ++args->cont_seen; - rc = dtx_stat(ctx, &itp); + rc = dtx_stat(ctx, &itp, &cnt); + if (!SUCCESS(rc)) + goto done; + args->cmt_cnt += cnt; + +done: itp_free(&itp); return rc; @@ -1423,7 +1428,7 @@ ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt) goto done; } - rc = dtx_stat(ctx, &itp); + rc = dtx_stat(ctx, &itp, NULL); done: itp_free(&itp); return rc; @@ -1439,6 +1444,9 @@ ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt) rc = vos_iterate(¶m, VOS_ITER_COUUID, false, &anchors, NULL, dtx_stat_cb, &args, NULL); } while (rc > 0); + if (rc == 0) + ddb_printf(ctx, "Number of committed DTX of the pool:\t\t\t%" PRIu32 "\n", + args.cmt_cnt); return rc; } diff --git a/src/utils/ddb/tests/ddb_commands_tests.c b/src/utils/ddb/tests/ddb_commands_tests.c index 336474950a3..3e61649ec2b 100644 --- a/src/utils/ddb/tests/ddb_commands_tests.c +++ b/src/utils/ddb/tests/ddb_commands_tests.c @@ -433,6 +433,8 @@ dtx_stat_tests(void **state) "^[[:blank:]]+- Number of committed DTX of the container:[[:blank:]]+1$"); assert_regex_match(dvt_fake_print_buffer, "^[[:blank:]]+- DTX newest aggregated time:.+, 0$"); + assert_regex_match(dvt_fake_print_buffer, + "^Number of committed DTX of the pool:[[:blank:]]+1$"); } /* diff --git a/src/utils/ddb/tests/ddb_test_driver.h b/src/utils/ddb/tests/ddb_test_driver.h index e5cc649d0d6..4573a395e82 100644 --- a/src/utils/ddb/tests/ddb_test_driver.h +++ b/src/utils/ddb/tests/ddb_test_driver.h @@ -1,5 +1,6 @@ /** * (C) Copyright 2022-2024 Intel Corporation. + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -77,7 +78,7 @@ int ddb_test_pool_setup(struct dt_vos_pool_ctx *tctx); extern uint32_t dvt_fake_print_called; extern bool dvt_fake_print_just_count; -#define DVT_FAKE_PRINT_BUFFER_SIZE (1024) +#define DVT_FAKE_PRINT_BUFFER_SIZE (2048) extern char dvt_fake_print_buffer[DVT_FAKE_PRINT_BUFFER_SIZE]; int dvt_fake_print(const char *fmt, ...); void dvt_fake_print_reset(void); diff --git a/src/vos/vos_dtx.c b/src/vos/vos_dtx.c index 7838f9c6048..175a14030a1 100644 --- a/src/vos/vos_dtx.c +++ b/src/vos/vos_dtx.c @@ -4006,3 +4006,39 @@ vos_dtx_local_end(struct dtx_handle *dth, int result) return result; } + +uint32_t +vos_dtx_get_cmt_cnt(daos_handle_t coh) +{ + struct umem_instance *umm; + struct vos_container *cont; + struct vos_dtx_blob_df *dbd; + int i; + uint32_t cnt; + + cont = vos_hdl2cont(coh); + D_ASSERT(cont != NULL); + + umm = vos_cont2umm(cont); + dbd = umem_off2ptr(umm, cont->vc_cmt_dtx_reindex_pos); + if (dbd == NULL) + return 0; + + D_ASSERTF(dbd->dbd_magic == DTX_CMT_BLOB_MAGIC, "Corrupted committed DTX blob (2) %x\n", + dbd->dbd_magic); + + cnt = 0; + for (i = 0; i < dbd->dbd_count; i++) { + struct vos_dtx_cmt_ent_df *dce_df; + + dce_df = &dbd->dbd_committed_data[i]; + if (daos_is_zero_dti(&dce_df->dce_xid) || dce_df->dce_epoch == 0) { + D_WARN("Skip invalid committed DTX entry\n"); + continue; + } + + cnt++; + } + + return cnt; +} From 7c96b6a4fdf1becb96e503d1e4e4f27a92d881c0 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 8 Sep 2025 07:05:02 +0000 Subject: [PATCH 08/13] DAOS-17322 ddb: DTX aggregation with ddb - Fix code formating issues - Workaround to manage false positive Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/utils/ddb/ddb.c | 2 +- src/utils/ddb/tests/ddb_cmocka.h | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/utils/ddb/ddb.c b/src/utils/ddb/ddb.c index ac3a72fb0b9..fb5f5021004 100644 --- a/src/utils/ddb/ddb.c +++ b/src/utils/ddb/ddb.c @@ -838,7 +838,7 @@ dtx_stat_option_parse(struct ddb_ctx *ctx, struct dtx_stat_options *cmd_args, ui return -DER_INVAL; } - index = optind; + index = optind; cmd_args->path = NULL; if (argc - index > 0 && *argv[index] != '\0') { cmd_args->path = argv[index]; diff --git a/src/utils/ddb/tests/ddb_cmocka.h b/src/utils/ddb/tests/ddb_cmocka.h index 828a71dd0a8..a5948b6a048 100644 --- a/src/utils/ddb/tests/ddb_cmocka.h +++ b/src/utils/ddb/tests/ddb_cmocka.h @@ -86,7 +86,8 @@ D_ALLOC_ARRAY(_buf, _buf_size); \ assert_non_null(_buf); \ regerror(_rc, NULL, _buf, _buf_size); \ - print_error("ERROR: invalid regex '%s': %s\n", regex, _buf); \ + if (_buf) \ + print_error("ERROR: invalid regex '%s': %s\n", regex, _buf); \ D_FREE(_buf); \ fail(); \ } \ @@ -103,7 +104,9 @@ D_ALLOC_ARRAY(_buf, _buf_size); \ assert_non_null(_buf); \ regerror(_rc, &_preg, _buf, _buf_size); \ - print_error("ERROR: invalid regex '%s': %s\n", regex, _buf); \ + if (_buf) \ + print_error("ERROR: invalid regex '%s': %s\n", regex, \ + _buf); \ D_FREE(_buf); \ regfree(&_preg); \ D_FREE(_str_dup); \ From adcd6df431f6d63600d6b7430d72187f75043e1b Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 15 Sep 2025 12:39:48 +0000 Subject: [PATCH 09/13] DAOS-17322 ddb: DTX aggregation with ddb Integrate reviewers comments: - Use vos_cont_df::cd_dtx_committed_head instead of vos_cont_df::cd_dtx_committed_head - Iterate over the dbd linked list - Do not check DTX entries consistency Other updates: - Add unit tests for the vos_dtx_get_cmt_cnt() function. Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/dtx/tests/SConscript | 1 + src/dtx/tests/dts_count.c | 113 ++++++++++++++++++++++++++++++++++++++ src/dtx/tests/dtx_ut.c | 7 ++- src/vos/tests/vts_dtx.c | 37 ++++++++----- src/vos/vos_dtx.c | 25 +++------ 5 files changed, 148 insertions(+), 35 deletions(-) create mode 100644 src/dtx/tests/dts_count.c diff --git a/src/dtx/tests/SConscript b/src/dtx/tests/SConscript index f949838ee42..1a97b9bdff0 100644 --- a/src/dtx/tests/SConscript +++ b/src/dtx/tests/SConscript @@ -61,6 +61,7 @@ def scons(): 'sched_mock.c', 'srv_mock.c', 'srv_module_mock.c', + 'dts_count.c' ] dtx_ut = tenv.d_program('dtx_ut', test_src + vos_src, LIBS=libraries) diff --git a/src/dtx/tests/dts_count.c b/src/dtx/tests/dts_count.c new file mode 100644 index 00000000000..f6eb149edd2 --- /dev/null +++ b/src/dtx/tests/dts_count.c @@ -0,0 +1,113 @@ +/** + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP. + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + */ +#define D_LOGFAC DD_FAC(tests) + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "vos_internal.h" + +/* mocks */ + +#define DTX_CMT_BLOB_MAGIC 0x2502191c +#define DBD_COUNT 0x3 +#define DBD_BLOB_DF_CAP 0x8 + +static struct vos_pool Pool; +static struct vos_container Cont; +static struct vos_cont_df ContDf; +static struct vos_dtx_blob_df *Dbds; +static umem_off_t DbdsOff[DBD_COUNT]; +static daos_handle_t Coh; + +/* setup & teardown */ + +static int +test_setup(void **unused) +{ + int i; + + memset(&Pool, 0, sizeof(Pool)); + memset(&Cont, 0, sizeof(Cont)); + memset(&ContDf, 0, sizeof(ContDf)); + + D_ALLOC(Dbds, DBD_COUNT * (sizeof(struct vos_dtx_blob_df) + + DBD_BLOB_DF_CAP * sizeof(struct vos_dtx_cmt_ent_df))); + for (i = 0; i < DBD_COUNT; i++) { + Dbds[i].dbd_magic = DTX_CMT_BLOB_MAGIC; + Dbds[i].dbd_cap = DBD_BLOB_DF_CAP; + DbdsOff[i] = umem_ptr2off(&Pool.vp_umm, &Dbds[i]); + Dbds[i].dbd_next = + (i == DBD_COUNT - 1) ? UMOFF_NULL : umem_ptr2off(&Pool.vp_umm, &Dbds[i + 1]); + Dbds[i].dbd_prev = (i == 0) ? UMOFF_NULL : umem_ptr2off(&Pool.vp_umm, &Dbds[i - 1]); + Dbds[i].dbd_count = (i + 1) * 2; + assert_true(Dbds[i].dbd_count <= DBD_BLOB_DF_CAP); + } + + Cont.vc_pool = &Pool; + Cont.vc_cont_df = &ContDf; + ContDf.cd_dtx_committed_head = DbdsOff[0]; + ContDf.cd_dtx_committed_tail = DbdsOff[DBD_COUNT - 1]; + Coh.cookie = (uint64_t)&Cont; + + return 0; +} + +static int +test_teardown(void **unused) +{ + D_FREE(Dbds); + + return 0; +} + +/* tests */ + +static void +test_asserts(void **unused) +{ + daos_handle_t hdl_null = {0}; + + /* Missing argument. */ + expect_assert_failure(vos_dtx_get_cmt_cnt(hdl_null)); + + /* Corrupted dbd */ + Dbds[1].dbd_magic = 42; + expect_assert_failure(vos_dtx_get_cmt_cnt(Coh)); +} + +static void +test_count(void **unused) +{ + uint32_t cnt; + + cnt = vos_dtx_get_cmt_cnt(Coh); + assert_int_equal(cnt, DBD_COUNT * (DBD_COUNT + 1)); +} + +/* compilation unit's entry point */ +#define TEST(name, func) {name ": vos_dtx_get_cmt_cnt - " #func, func, test_setup, test_teardown} + +static const struct CMUnitTest vos_dtx_count_tests_all[] = { + TEST("DTX600", test_asserts), + TEST("DTX601", test_count), +}; + +int +run_dtx_count_tests(void) +{ + const char *test_name = "vos_dtx_get_cmt_cnt"; + + return cmocka_run_group_tests_name(test_name, vos_dtx_count_tests_all, NULL, NULL); +} diff --git a/src/dtx/tests/dtx_ut.c b/src/dtx/tests/dtx_ut.c index e608c6c6964..dcccb713161 100644 --- a/src/dtx/tests/dtx_ut.c +++ b/src/dtx/tests/dtx_ut.c @@ -21,6 +21,8 @@ int run_structs_tests(void); int run_discard_invalid_tests(void); +int +run_dtx_count_tests(void); static void print_usage() @@ -40,6 +42,7 @@ run_all_tests(int keys) failed += run_structs_tests(); failed += run_discard_invalid_tests(); + failed += run_dtx_count_tests(); return failed; } @@ -77,7 +80,7 @@ main(int argc, char **argv) #if CMOCKA_FILTER_SUPPORTED == 1 /** requires cmocka 1.1.5 */ cmocka_set_skip_filter(optarg); #else - D_PRINT("filter not enabled"); + D_PRINT("filter not enabled\n"); #endif break; @@ -92,7 +95,7 @@ main(int argc, char **argv) printf("Test filter: %s\n", filter); } #else - D_PRINT("filter not enabled"); + D_PRINT("filter not enabled\n"); #endif break; default: diff --git a/src/vos/tests/vts_dtx.c b/src/vos/tests/vts_dtx.c index 00e5d85fedf..08792addc98 100644 --- a/src/vos/tests/vts_dtx.c +++ b/src/vos/tests/vts_dtx.c @@ -791,21 +791,22 @@ dtx_17(void **state) static void dtx_18(void **state) { - struct io_test_args *args = *state; - struct dtx_id xid[10]; - daos_iod_t iod = { 0 }; - d_sg_list_t sgl = { 0 }; - daos_recx_t rex = { 0 }; - daos_key_t dkey; - daos_key_t akey; - d_iov_t val_iov; - uint64_t epoch; - char dkey_buf[UPDATE_DKEY_SIZE]; - char akey_buf[UPDATE_AKEY_SIZE]; - char update_buf[UPDATE_BUF_SIZE]; - char fetch_buf[UPDATE_BUF_SIZE]; - int rc; - int i; + struct io_test_args *args = *state; + struct dtx_id xid[10]; + daos_iod_t iod = {0}; + d_sg_list_t sgl = {0}; + daos_recx_t rex = {0}; + daos_key_t dkey; + daos_key_t akey; + d_iov_t val_iov; + uint64_t epoch; + uint32_t cnt; + char dkey_buf[UPDATE_DKEY_SIZE]; + char akey_buf[UPDATE_AKEY_SIZE]; + char update_buf[UPDATE_BUF_SIZE]; + char fetch_buf[UPDATE_BUF_SIZE]; + int rc; + int i; /* Assume I am the leader. */ for (i = 0; i < 10; i++) { @@ -841,10 +842,16 @@ dtx_18(void **state) sleep(3); + cnt = vos_dtx_get_cmt_cnt(args->ctx.tc_co_hdl); + assert_rc_equal(cnt, 10); + /* Aggregate the DTXs. */ rc = vos_dtx_aggregate(args->ctx.tc_co_hdl); assert_rc_equal(rc, 0); + cnt = vos_dtx_get_cmt_cnt(args->ctx.tc_co_hdl); + assert_rc_equal(cnt, 0); + for (i = 0; i < 10; i++) { rc = vos_dtx_check(args->ctx.tc_co_hdl, &xid[i], NULL, NULL, NULL, false); assert_rc_equal(rc, -DER_NONEXIST); diff --git a/src/vos/vos_dtx.c b/src/vos/vos_dtx.c index 175a14030a1..83359608a7b 100644 --- a/src/vos/vos_dtx.c +++ b/src/vos/vos_dtx.c @@ -4013,31 +4013,20 @@ vos_dtx_get_cmt_cnt(daos_handle_t coh) struct umem_instance *umm; struct vos_container *cont; struct vos_dtx_blob_df *dbd; - int i; uint32_t cnt; cont = vos_hdl2cont(coh); D_ASSERT(cont != NULL); - umm = vos_cont2umm(cont); - dbd = umem_off2ptr(umm, cont->vc_cmt_dtx_reindex_pos); - if (dbd == NULL) - return 0; - - D_ASSERTF(dbd->dbd_magic == DTX_CMT_BLOB_MAGIC, "Corrupted committed DTX blob (2) %x\n", - dbd->dbd_magic); - cnt = 0; - for (i = 0; i < dbd->dbd_count; i++) { - struct vos_dtx_cmt_ent_df *dce_df; - - dce_df = &dbd->dbd_committed_data[i]; - if (daos_is_zero_dti(&dce_df->dce_xid) || dce_df->dce_epoch == 0) { - D_WARN("Skip invalid committed DTX entry\n"); - continue; - } + umm = vos_cont2umm(cont); + dbd = umem_off2ptr(umm, cont->vc_cont_df->cd_dtx_committed_head); + while (dbd != NULL) { + D_ASSERTF(dbd->dbd_magic == DTX_CMT_BLOB_MAGIC, + "Corrupted committed DTX blob (2) %x\n", dbd->dbd_magic); + cnt += dbd->dbd_count; - cnt++; + dbd = umem_off2ptr(umm, dbd->dbd_next); } return cnt; From bc2c785b6a7ea1bc95985d258b05ca75f58c93fe Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 15 Sep 2025 12:39:48 +0000 Subject: [PATCH 10/13] DAOS-17322 ddb: DTX aggregation with ddb Fix clang format issue. Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/dtx/tests/dts_count.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dtx/tests/dts_count.c b/src/dtx/tests/dts_count.c index f6eb149edd2..c28abf00999 100644 --- a/src/dtx/tests/dts_count.c +++ b/src/dtx/tests/dts_count.c @@ -97,7 +97,10 @@ test_count(void **unused) } /* compilation unit's entry point */ -#define TEST(name, func) {name ": vos_dtx_get_cmt_cnt - " #func, func, test_setup, test_teardown} +#define TEST(name, func) \ + { \ + name ": vos_dtx_get_cmt_cnt - " #func, func, test_setup, test_teardown \ + } static const struct CMUnitTest vos_dtx_count_tests_all[] = { TEST("DTX600", test_asserts), From 49be495544400aadef9cd55e6338e973c434d739 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 15 Sep 2025 12:39:48 +0000 Subject: [PATCH 11/13] DAOS-17322 ddb: DTX aggregation with ddb Integrate reviewers comments: - Change assert into error code. - Fix C coding standard. - Fix iterator management. - Fix coding standard issue - Fix DTX blob offset Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/dtx/tests/dts_count.c | 96 ++++++++++++++++++++++++------------ src/include/daos_srv/vos.h | 7 +-- src/utils/ddb/ddb_commands.c | 15 +++--- src/vos/tests/vts_dtx.c | 10 ++-- src/vos/vos_dtx.c | 35 +++++++++---- 5 files changed, 109 insertions(+), 54 deletions(-) diff --git a/src/dtx/tests/dts_count.c b/src/dtx/tests/dts_count.c index c28abf00999..aaf12ff6d0d 100644 --- a/src/dtx/tests/dts_count.c +++ b/src/dtx/tests/dts_count.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "vos_internal.h" @@ -23,13 +24,15 @@ #define DTX_CMT_BLOB_MAGIC 0x2502191c #define DBD_COUNT 0x3 #define DBD_BLOB_DF_CAP 0x8 +#define CELL_SIZE \ + sizeof(struct vos_dtx_blob_df) + DBD_BLOB_DF_CAP * sizeof(struct vos_dtx_cmt_ent_df) -static struct vos_pool Pool; -static struct vos_container Cont; -static struct vos_cont_df ContDf; -static struct vos_dtx_blob_df *Dbds; -static umem_off_t DbdsOff[DBD_COUNT]; -static daos_handle_t Coh; +static struct vos_pool mock_pool; +static struct vos_container mock_cont; +static struct vos_cont_df mock_cont_df; +static struct vos_dtx_blob_df *mock_dbds; +static umem_off_t mock_dbds_off[DBD_COUNT]; +static daos_handle_t mock_coh; /* setup & teardown */ @@ -38,28 +41,48 @@ test_setup(void **unused) { int i; - memset(&Pool, 0, sizeof(Pool)); - memset(&Cont, 0, sizeof(Cont)); - memset(&ContDf, 0, sizeof(ContDf)); + memset(&mock_pool, 0, sizeof(mock_pool)); + memset(&mock_cont, 0, sizeof(mock_cont)); + memset(&mock_cont_df, 0, sizeof(mock_cont_df)); - D_ALLOC(Dbds, DBD_COUNT * (sizeof(struct vos_dtx_blob_df) + - DBD_BLOB_DF_CAP * sizeof(struct vos_dtx_cmt_ent_df))); + D_ALLOC(mock_dbds, DBD_COUNT * CELL_SIZE); for (i = 0; i < DBD_COUNT; i++) { - Dbds[i].dbd_magic = DTX_CMT_BLOB_MAGIC; - Dbds[i].dbd_cap = DBD_BLOB_DF_CAP; - DbdsOff[i] = umem_ptr2off(&Pool.vp_umm, &Dbds[i]); - Dbds[i].dbd_next = - (i == DBD_COUNT - 1) ? UMOFF_NULL : umem_ptr2off(&Pool.vp_umm, &Dbds[i + 1]); - Dbds[i].dbd_prev = (i == 0) ? UMOFF_NULL : umem_ptr2off(&Pool.vp_umm, &Dbds[i - 1]); - Dbds[i].dbd_count = (i + 1) * 2; - assert_true(Dbds[i].dbd_count <= DBD_BLOB_DF_CAP); + struct vos_dtx_blob_df *dbd; + + dbd = (struct vos_dtx_blob_df *)((uint64_t)(&mock_dbds[0]) + i * CELL_SIZE); + dbd->dbd_magic = DTX_CMT_BLOB_MAGIC; + dbd->dbd_cap = DBD_BLOB_DF_CAP; + if (i == DBD_COUNT - 1) + dbd->dbd_next = UMOFF_NULL; + else { + uint64_t tmp; + struct vos_dtx_blob_df *next; + + tmp = (uint64_t)(&mock_dbds[0]) + (i + 1) * CELL_SIZE; + next = (struct vos_dtx_blob_df *)tmp; + dbd->dbd_next = umem_ptr2off(&mock_pool.vp_umm, next); + } + if (i == 0) + dbd->dbd_prev = UMOFF_NULL; + else { + uint64_t tmp; + struct vos_dtx_blob_df *prev; + + tmp = (uint64_t)(&dbd[0]) + (i - 1) * CELL_SIZE; + prev = (struct vos_dtx_blob_df *)tmp; + dbd->dbd_prev = umem_ptr2off(&mock_pool.vp_umm, prev); + } + dbd->dbd_count = (i + 1) * 2; + assert_true(dbd->dbd_count <= DBD_BLOB_DF_CAP); + + mock_dbds_off[i] = umem_ptr2off(&mock_pool.vp_umm, dbd); } - Cont.vc_pool = &Pool; - Cont.vc_cont_df = &ContDf; - ContDf.cd_dtx_committed_head = DbdsOff[0]; - ContDf.cd_dtx_committed_tail = DbdsOff[DBD_COUNT - 1]; - Coh.cookie = (uint64_t)&Cont; + mock_cont.vc_pool = &mock_pool; + mock_cont.vc_cont_df = &mock_cont_df; + mock_cont_df.cd_dtx_committed_head = mock_dbds_off[0]; + mock_cont_df.cd_dtx_committed_tail = mock_dbds_off[DBD_COUNT - 1]; + mock_coh.cookie = (uint64_t)&mock_cont; return 0; } @@ -67,7 +90,7 @@ test_setup(void **unused) static int test_teardown(void **unused) { - D_FREE(Dbds); + D_FREE(mock_dbds); return 0; } @@ -77,22 +100,33 @@ test_teardown(void **unused) static void test_asserts(void **unused) { - daos_handle_t hdl_null = {0}; + daos_handle_t hdl_null = {0}; + struct vos_dtx_blob_df *dbd; + uint32_t cnt; + int rc; - /* Missing argument. */ - expect_assert_failure(vos_dtx_get_cmt_cnt(hdl_null)); + /* Invalid arguments. */ + rc = vos_dtx_get_cmt_cnt(hdl_null, &cnt); + assert_rc_equal(rc, -DER_INVAL); + rc = vos_dtx_get_cmt_cnt(mock_coh, NULL); + assert_rc_equal(rc, -DER_INVAL); /* Corrupted dbd */ - Dbds[1].dbd_magic = 42; - expect_assert_failure(vos_dtx_get_cmt_cnt(Coh)); + dbd = (struct vos_dtx_blob_df *)((uint64_t)(&mock_dbds[0]) + CELL_SIZE); + dbd->dbd_magic = 42; + rc = vos_dtx_get_cmt_cnt(mock_coh, &cnt); + assert_rc_equal(rc, -DER_INVAL); } static void test_count(void **unused) { uint32_t cnt; + int rc; - cnt = vos_dtx_get_cmt_cnt(Coh); + /* Container with several DTX entries table */ + rc = vos_dtx_get_cmt_cnt(mock_coh, &cnt); + assert_rc_equal(rc, -DER_SUCCESS); assert_int_equal(cnt, DBD_COUNT * (DBD_COUNT + 1)); } diff --git a/src/include/daos_srv/vos.h b/src/include/daos_srv/vos.h index c0c3b472e01..1b798b5c4c9 100644 --- a/src/include/daos_srv/vos.h +++ b/src/include/daos_srv/vos.h @@ -1781,10 +1781,11 @@ vos_oi_exist(daos_handle_t coh, daos_unit_oid_t oid); * Return the number of DTX committed entries of a container. * * \param[in] coh container open handle. + * \param[out] cnt number of DTX committed entries. * - * \return Number of DTX committed entries. + * \return 0 on success, error otherwise. */ -uint32_t -vos_dtx_get_cmt_cnt(daos_handle_t coh); +int +vos_dtx_get_cmt_cnt(daos_handle_t coh, uint32_t *cnt); #endif /* __VOS_API_H */ diff --git a/src/utils/ddb/ddb_commands.c b/src/utils/ddb/ddb_commands.c index a96edd1bd9d..12e91c22c70 100644 --- a/src/utils/ddb/ddb_commands.c +++ b/src/utils/ddb/ddb_commands.c @@ -1353,7 +1353,9 @@ dtx_stat(struct ddb_ctx *ctx, struct dv_indexed_tree_path *itp, uint32_t *cnt) if (!SUCCESS(rc)) goto done; - cnt_tmp = vos_dtx_get_cmt_cnt(coh); + rc = vos_dtx_get_cmt_cnt(coh, &cnt_tmp); + if (!SUCCESS(rc)) + goto done; vos_dtx_stat(coh, &stat, 0); ddb_print(ctx, "DTX entries statistics of "); @@ -1391,7 +1393,7 @@ dtx_stat_cb(daos_handle_t ih, vos_iter_entry_t *entry, vos_iter_type_t type, ctx = args->ctx; itp_set_cont(&itp, entry->ie_couuid, args->cont_seen); - ++args->cont_seen; + ++(args->cont_seen); rc = dtx_stat(ctx, &itp, &cnt); if (!SUCCESS(rc)) @@ -1407,9 +1409,10 @@ dtx_stat_cb(daos_handle_t ih, vos_iter_entry_t *entry, vos_iter_type_t type, int ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt) { - vos_iter_param_t param = {0}; - struct dtx_stat_args args = {0}; - int rc; + vos_iter_param_t param = {0}; + struct dtx_stat_args args = {0}; + struct vos_iter_anchors anchors = {0}; + int rc; if (daos_handle_is_inval(ctx->dc_poh)) { ddb_error(ctx, "Not connected to a pool. Use 'open' to connect to a pool.\n"); @@ -1439,8 +1442,6 @@ ddb_run_dtx_stat(struct ddb_ctx *ctx, struct dtx_stat_options *opt) param.ip_hdl = ctx->dc_poh; param.ip_epr.epr_hi = DAOS_EPOCH_MAX; do { - struct vos_iter_anchors anchors = {0}; - rc = vos_iterate(¶m, VOS_ITER_COUUID, false, &anchors, NULL, dtx_stat_cb, &args, NULL); } while (rc > 0); diff --git a/src/vos/tests/vts_dtx.c b/src/vos/tests/vts_dtx.c index 08792addc98..e22fb4d402a 100644 --- a/src/vos/tests/vts_dtx.c +++ b/src/vos/tests/vts_dtx.c @@ -842,15 +842,17 @@ dtx_18(void **state) sleep(3); - cnt = vos_dtx_get_cmt_cnt(args->ctx.tc_co_hdl); - assert_rc_equal(cnt, 10); + rc = vos_dtx_get_cmt_cnt(args->ctx.tc_co_hdl, &cnt); + assert_rc_equal(rc, -DER_SUCCESS); + assert_int_equal(cnt, 10); /* Aggregate the DTXs. */ rc = vos_dtx_aggregate(args->ctx.tc_co_hdl); assert_rc_equal(rc, 0); - cnt = vos_dtx_get_cmt_cnt(args->ctx.tc_co_hdl); - assert_rc_equal(cnt, 0); + rc = vos_dtx_get_cmt_cnt(args->ctx.tc_co_hdl, &cnt); + assert_rc_equal(rc, -DER_SUCCESS); + assert_int_equal(cnt, 0); for (i = 0; i < 10; i++) { rc = vos_dtx_check(args->ctx.tc_co_hdl, &xid[i], NULL, NULL, NULL, false); diff --git a/src/vos/vos_dtx.c b/src/vos/vos_dtx.c index 83359608a7b..ef3121d85d4 100644 --- a/src/vos/vos_dtx.c +++ b/src/vos/vos_dtx.c @@ -4007,27 +4007,44 @@ vos_dtx_local_end(struct dtx_handle *dth, int result) return result; } -uint32_t -vos_dtx_get_cmt_cnt(daos_handle_t coh) +int +vos_dtx_get_cmt_cnt(daos_handle_t coh, uint32_t *cnt) { struct umem_instance *umm; struct vos_container *cont; struct vos_dtx_blob_df *dbd; - uint32_t cnt; + uint32_t tmp; + int rc; cont = vos_hdl2cont(coh); - D_ASSERT(cont != NULL); + if (cont == NULL) { + rc = -DER_INVAL; + goto out; + } + if (cnt == NULL) { + rc = -DER_INVAL; + goto out; + } - cnt = 0; + tmp = 0; umm = vos_cont2umm(cont); dbd = umem_off2ptr(umm, cont->vc_cont_df->cd_dtx_committed_head); while (dbd != NULL) { - D_ASSERTF(dbd->dbd_magic == DTX_CMT_BLOB_MAGIC, - "Corrupted committed DTX blob (2) %x\n", dbd->dbd_magic); - cnt += dbd->dbd_count; + if (dbd->dbd_magic != DTX_CMT_BLOB_MAGIC) { + D_ERROR("Committed DTX blob with bad magic: container=" DF_UUID + ", wait=%#x, get=%#x\n", + DP_UUID(cont->vc_id), DTX_CMT_BLOB_MAGIC, dbd->dbd_magic); + rc = -DER_INVAL; + goto out; + } + tmp += dbd->dbd_count; dbd = umem_off2ptr(umm, dbd->dbd_next); } - return cnt; + *cnt = tmp; + rc = -DER_SUCCESS; + +out: + return rc; } From 9d81546029cce9c1f57d2a2476e41a1fd59d13bb Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 15 Sep 2025 12:39:48 +0000 Subject: [PATCH 12/13] DAOS-17322 ddb: DTX aggregation with ddb Integrate reviewers comments: - Replace -DER_SUCCESS with 0 - Use multiple allocation Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/dtx/tests/dts_count.c | 58 +++++++++++---------------- src/utils/ddb/ddb_commands.c | 6 +-- src/utils/ddb/tests/ddb_parse_tests.c | 2 +- src/vos/tests/vts_dtx.c | 4 +- src/vos/vos_dtx.c | 2 +- 5 files changed, 31 insertions(+), 41 deletions(-) diff --git a/src/dtx/tests/dts_count.c b/src/dtx/tests/dts_count.c index aaf12ff6d0d..ce25ea4723a 100644 --- a/src/dtx/tests/dts_count.c +++ b/src/dtx/tests/dts_count.c @@ -30,7 +30,7 @@ static struct vos_pool mock_pool; static struct vos_container mock_cont; static struct vos_cont_df mock_cont_df; -static struct vos_dtx_blob_df *mock_dbds; +static struct vos_dtx_blob_df *mock_dbds[DBD_COUNT]; static umem_off_t mock_dbds_off[DBD_COUNT]; static daos_handle_t mock_coh; @@ -45,37 +45,26 @@ test_setup(void **unused) memset(&mock_cont, 0, sizeof(mock_cont)); memset(&mock_cont_df, 0, sizeof(mock_cont_df)); - D_ALLOC(mock_dbds, DBD_COUNT * CELL_SIZE); for (i = 0; i < DBD_COUNT; i++) { - struct vos_dtx_blob_df *dbd; + D_ALLOC(mock_dbds[i], CELL_SIZE); + assert_non_null(mock_dbds[i]); + } - dbd = (struct vos_dtx_blob_df *)((uint64_t)(&mock_dbds[0]) + i * CELL_SIZE); - dbd->dbd_magic = DTX_CMT_BLOB_MAGIC; - dbd->dbd_cap = DBD_BLOB_DF_CAP; + for (i = 0; i < DBD_COUNT; i++) { + mock_dbds[i]->dbd_magic = DTX_CMT_BLOB_MAGIC; + mock_dbds[i]->dbd_cap = DBD_BLOB_DF_CAP; if (i == DBD_COUNT - 1) - dbd->dbd_next = UMOFF_NULL; - else { - uint64_t tmp; - struct vos_dtx_blob_df *next; - - tmp = (uint64_t)(&mock_dbds[0]) + (i + 1) * CELL_SIZE; - next = (struct vos_dtx_blob_df *)tmp; - dbd->dbd_next = umem_ptr2off(&mock_pool.vp_umm, next); - } + mock_dbds[i]->dbd_next = UMOFF_NULL; + else + mock_dbds[i]->dbd_next = umem_ptr2off(&mock_pool.vp_umm, mock_dbds[i + 1]); if (i == 0) - dbd->dbd_prev = UMOFF_NULL; - else { - uint64_t tmp; - struct vos_dtx_blob_df *prev; - - tmp = (uint64_t)(&dbd[0]) + (i - 1) * CELL_SIZE; - prev = (struct vos_dtx_blob_df *)tmp; - dbd->dbd_prev = umem_ptr2off(&mock_pool.vp_umm, prev); - } - dbd->dbd_count = (i + 1) * 2; - assert_true(dbd->dbd_count <= DBD_BLOB_DF_CAP); - - mock_dbds_off[i] = umem_ptr2off(&mock_pool.vp_umm, dbd); + mock_dbds[i]->dbd_prev = UMOFF_NULL; + else + mock_dbds[i]->dbd_prev = umem_ptr2off(&mock_pool.vp_umm, mock_dbds[i - 1]); + mock_dbds[i]->dbd_count = (i + 1) * 2; + assert_true(mock_dbds[i]->dbd_count <= DBD_BLOB_DF_CAP); + + mock_dbds_off[i] = umem_ptr2off(&mock_pool.vp_umm, mock_dbds[i]); } mock_cont.vc_pool = &mock_pool; @@ -90,7 +79,10 @@ test_setup(void **unused) static int test_teardown(void **unused) { - D_FREE(mock_dbds); + int i; + + for (i = 0; i < DBD_COUNT; i++) + D_FREE(mock_dbds[i]); return 0; } @@ -101,7 +93,6 @@ static void test_asserts(void **unused) { daos_handle_t hdl_null = {0}; - struct vos_dtx_blob_df *dbd; uint32_t cnt; int rc; @@ -112,9 +103,8 @@ test_asserts(void **unused) assert_rc_equal(rc, -DER_INVAL); /* Corrupted dbd */ - dbd = (struct vos_dtx_blob_df *)((uint64_t)(&mock_dbds[0]) + CELL_SIZE); - dbd->dbd_magic = 42; - rc = vos_dtx_get_cmt_cnt(mock_coh, &cnt); + mock_dbds[1]->dbd_magic = 42; + rc = vos_dtx_get_cmt_cnt(mock_coh, &cnt); assert_rc_equal(rc, -DER_INVAL); } @@ -126,7 +116,7 @@ test_count(void **unused) /* Container with several DTX entries table */ rc = vos_dtx_get_cmt_cnt(mock_coh, &cnt); - assert_rc_equal(rc, -DER_SUCCESS); + assert_rc_equal(rc, 0); assert_int_equal(cnt, DBD_COUNT * (DBD_COUNT + 1)); } diff --git a/src/utils/ddb/ddb_commands.c b/src/utils/ddb/ddb_commands.c index 12e91c22c70..1ff733b3162 100644 --- a/src/utils/ddb/ddb_commands.c +++ b/src/utils/ddb/ddb_commands.c @@ -1307,7 +1307,7 @@ timespec2str(struct timespec *tspec, char *buf, size_t buf_size) if (rc >= buf_size - buf_len) return -DER_TRUNC; - return -DER_SUCCESS; + return 0; } static int @@ -1331,7 +1331,7 @@ dtx_print_time_stat(struct ddb_ctx *ctx, char *stat_name, uint64_t epoch, char * } ddb_printf(ctx, "\t- %s time:%s%s, %" PRIu64 "\n", stat_name, align, buf, epoch); - return -DER_SUCCESS; + return 0; } struct dtx_stat_args { @@ -1385,7 +1385,7 @@ dtx_stat_cb(daos_handle_t ih, vos_iter_entry_t *entry, vos_iter_type_t type, int rc; if (type != VOS_ITER_COUUID) { - rc = -DER_SUCCESS; + rc = 0; goto done; } diff --git a/src/utils/ddb/tests/ddb_parse_tests.c b/src/utils/ddb/tests/ddb_parse_tests.c index e7bb8b93f4c..fdc1b025927 100644 --- a/src/utils/ddb/tests/ddb_parse_tests.c +++ b/src/utils/ddb/tests/ddb_parse_tests.c @@ -374,7 +374,7 @@ date2epoch_tests(void **state) rc = ddb_date2epoch("1970-01-01 00:00:00", &epoch); assert_success(rc); - assert_int_equal(rc, -DER_SUCCESS); + assert_int_equal(rc, 0); assert_int_equal(epoch, 0x9aa0d62878400000ull); } diff --git a/src/vos/tests/vts_dtx.c b/src/vos/tests/vts_dtx.c index e22fb4d402a..944fdc0f744 100644 --- a/src/vos/tests/vts_dtx.c +++ b/src/vos/tests/vts_dtx.c @@ -843,7 +843,7 @@ dtx_18(void **state) sleep(3); rc = vos_dtx_get_cmt_cnt(args->ctx.tc_co_hdl, &cnt); - assert_rc_equal(rc, -DER_SUCCESS); + assert_rc_equal(rc, 0); assert_int_equal(cnt, 10); /* Aggregate the DTXs. */ @@ -851,7 +851,7 @@ dtx_18(void **state) assert_rc_equal(rc, 0); rc = vos_dtx_get_cmt_cnt(args->ctx.tc_co_hdl, &cnt); - assert_rc_equal(rc, -DER_SUCCESS); + assert_rc_equal(rc, 0); assert_int_equal(cnt, 0); for (i = 0; i < 10; i++) { diff --git a/src/vos/vos_dtx.c b/src/vos/vos_dtx.c index ef3121d85d4..7801bf7830d 100644 --- a/src/vos/vos_dtx.c +++ b/src/vos/vos_dtx.c @@ -4043,7 +4043,7 @@ vos_dtx_get_cmt_cnt(daos_handle_t coh, uint32_t *cnt) } *cnt = tmp; - rc = -DER_SUCCESS; + rc = 0; out: return rc; From 29583d025eab84476baf92e193e76d801e5ff581 Mon Sep 17 00:00:00 2001 From: Cedric Koch-Hofer Date: Mon, 15 Sep 2025 12:39:48 +0000 Subject: [PATCH 13/13] DAOS-17322 ddb: DTX aggregation with ddb Fix clang format issue Features: aggregation Signed-off-by: Cedric Koch-Hofer --- src/dtx/tests/dts_count.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dtx/tests/dts_count.c b/src/dtx/tests/dts_count.c index ce25ea4723a..3e6b823caf2 100644 --- a/src/dtx/tests/dts_count.c +++ b/src/dtx/tests/dts_count.c @@ -92,9 +92,9 @@ test_teardown(void **unused) static void test_asserts(void **unused) { - daos_handle_t hdl_null = {0}; - uint32_t cnt; - int rc; + daos_handle_t hdl_null = {0}; + uint32_t cnt; + int rc; /* Invalid arguments. */ rc = vos_dtx_get_cmt_cnt(hdl_null, &cnt);