diff --git a/src/common/btree.c b/src/common/btree.c index 021d369ee5f..21b3b478e45 100644 --- a/src/common/btree.c +++ b/src/common/btree.c @@ -170,7 +170,7 @@ struct btr_context { static int btr_class_init(umem_off_t root_off, struct btr_root *root, unsigned int tree_class, uint64_t *tree_feats, struct umem_attr *uma, daos_handle_t coh, void *priv, - btr_report_fn_t report_fn, void *report_arg, struct btr_instance *tins); + report_fn_t report_fn, void *report_arg, struct btr_instance *tins); static struct btr_record *btr_node_rec_at(struct btr_context *tcx, umem_off_t nd_off, unsigned int at); @@ -318,11 +318,6 @@ btr_ops(struct btr_context *tcx) return tcx->tc_tins.ti_ops; } -static inline void -report_fn_nop(void *arg, enum btr_report_type type, const char *fmt, ...) -{ -} - /** * Create a btree context (in volatile memory). * @@ -4596,7 +4591,7 @@ btr_class_feats_init(unsigned int tree_class, uint64_t *tree_feats, struct btr_c static int btr_class_init(umem_off_t root_off, struct btr_root *root, unsigned int tree_class, uint64_t *tree_feats, struct umem_attr *uma, daos_handle_t coh, void *priv, - btr_report_fn_t report_fn, void *report_arg, struct btr_instance *tins) + report_fn_t report_fn, void *report_arg, struct btr_instance *tins) { struct btr_class *tc; int rc; @@ -4624,29 +4619,28 @@ btr_class_init(umem_off_t root_off, struct btr_root *root, unsigned int tree_cla /* XXX should be multi-thread safe */ if (tree_class >= BTR_TYPE_MAX || DAOS_FAIL_CHECK(DAOS_FAULT_BTREE_OPEN_INV_CLASS)) { - report_fn(report_arg, BTR_REPORT_ERROR, TREE_CLASS_STR INVALID_CLASS_FMT, - tree_class); + report_fn(report_arg, REPORT_ERROR, TREE_CLASS_STR INVALID_CLASS_FMT, tree_class); D_DEBUG(DB_TRACE, INVALID_CLASS_FMT, tree_class); return -DER_INVAL; } tc = &btr_class_registered[tree_class]; if (tc->tc_ops == NULL || DAOS_FAIL_CHECK(DAOS_FAULT_BTREE_OPEN_UNREG_CLASS)) { - report_fn(report_arg, BTR_REPORT_ERROR, TREE_CLASS_STR UNREGISTERED_CLASS_FMT, + report_fn(report_arg, REPORT_ERROR, TREE_CLASS_STR UNREGISTERED_CLASS_FMT, tree_class); D_DEBUG(DB_TRACE, UNREGISTERED_CLASS_FMT, tree_class); return -DER_NONEXIST; } - report_fn(report_arg, BTR_REPORT_MSG, TREE_CLASS_STR OK_STR); + report_fn(report_arg, REPORT_MSG, TREE_CLASS_STR OK_STR); rc = btr_class_feats_init(tree_class, tree_feats, tc); if (rc != DER_SUCCESS) { - report_fn(report_arg, BTR_REPORT_ERROR, TREE_FEATURES_STR UNSUPPORTED_FEATURES_FMT, + report_fn(report_arg, REPORT_ERROR, TREE_FEATURES_STR UNSUPPORTED_FEATURES_FMT, *tree_feats, tc->tc_feats); D_ERROR(UNSUPPORTED_FEATURES_FMT, *tree_feats, tc->tc_feats); return rc; } - report_fn(report_arg, BTR_REPORT_MSG, TREE_FEATURES_STR OK_STR); + report_fn(report_arg, REPORT_MSG, TREE_FEATURES_STR OK_STR); tins->ti_ops = tc->tc_ops; return rc; @@ -4761,6 +4755,17 @@ dbtree_overhead_get(int alloc_overhead, unsigned int tclass, uint64_t otype, return 0; } +static int +btr_rec_check(struct btr_context *tcx, struct btr_record *rec, report_fn_t report_fn, + void *report_arg) +{ + if (!btr_ops(tcx)->to_rec_check) { + return -DER_NOSYS; + } + + return btr_ops(tcx)->to_rec_check(&tcx->tc_tins, rec, report_fn, report_arg); +} + #define CK_BTREE_NODE_FMT "Node (off=%#lx)... " #define CK_BTREE_NODE_MALFORMED_STR "malformed - " #define CK_BTREE_NON_ZERO_PADDING_FMT CK_BTREE_NODE_MALFORMED_STR "tn_pad_32 != 0 (%#" PRIx32 ")" @@ -4769,15 +4774,16 @@ dbtree_overhead_get(int alloc_overhead, unsigned int tclass, uint64_t otype, /** * Validate the integrity of the btree node. * - * \param[in] nd Node to check. - * \param[in] nd_off Node's offset. - * \param[in] ck Checker. + * \param[in] nd Node to check. + * \param[in] nd_off Node's offset. + * \param[in] report_fn Report function. + * \param[in] report_arg Argument for the report function. * * \retval DER_SUCCESS The node is correct. * \retval -DER_NOTYPE The node is malformed. */ static int -btr_node_check(struct btr_node *nd, umem_off_t nd_off, btr_report_fn_t report_fn, void *report_arg, +btr_node_check(struct btr_node *nd, umem_off_t nd_off, report_fn_t report_fn, void *report_arg, bool error_on_non_zero_padding) { uint16_t unknown_flags; @@ -4786,7 +4792,7 @@ btr_node_check(struct btr_node *nd, umem_off_t nd_off, btr_report_fn_t report_fn unknown_flags = nd->tn_flags & ~(BTR_NODE_LEAF | BTR_NODE_ROOT); if (unknown_flags != 0) { - report_fn(report_arg, BTR_REPORT_ERROR, + report_fn(report_arg, REPORT_ERROR, CK_BTREE_NODE_MALFORMED_STR "unknown flags (%#" PRIx16 ")", unknown_flags); return -DER_NOTYPE; @@ -4794,12 +4800,12 @@ btr_node_check(struct btr_node *nd, umem_off_t nd_off, btr_report_fn_t report_fn if (nd->tn_pad_32 != 0) { if (error_on_non_zero_padding) { - report_fn(report_arg, BTR_REPORT_ERROR, + report_fn(report_arg, REPORT_ERROR, CK_BTREE_NODE_FMT CK_BTREE_NON_ZERO_PADDING_FMT, nd_off, nd->tn_pad_32); return -DER_NOTYPE; } else { - report_fn(report_arg, BTR_REPORT_WARNING, + report_fn(report_arg, REPORT_WARNING, CK_BTREE_NODE_FMT CK_BTREE_NON_ZERO_PADDING_FMT, nd_off, nd->tn_pad_32); } @@ -4807,16 +4813,16 @@ btr_node_check(struct btr_node *nd, umem_off_t nd_off, btr_report_fn_t report_fn if (nd->tn_gen != 0) { if (error_on_non_zero_padding) { - report_fn(report_arg, BTR_REPORT_ERROR, + report_fn(report_arg, REPORT_ERROR, CK_BTREE_NODE_FMT CK_BTREE_NON_ZERO_GEN_FMT, nd_off, nd->tn_gen); return -DER_NOTYPE; } else { - report_fn(report_arg, BTR_REPORT_WARNING, + report_fn(report_arg, REPORT_WARNING, CK_BTREE_NODE_FMT CK_BTREE_NON_ZERO_GEN_FMT, nd_off, nd->tn_gen); } } - report_fn(report_arg, BTR_REPORT_MSG, CK_BTREE_NODE_FMT OK_STR, nd_off); + report_fn(report_arg, REPORT_MSG, CK_BTREE_NODE_FMT OK_STR, nd_off); return DER_SUCCESS; } @@ -4835,7 +4841,8 @@ struct node_info { * Validate the integrity of a btree. * * \param[in] tcx Btree context. - * \param[in] ck Checker. + * \param[in] report_fn Report function. + * \param[in] report_arg Argument for the report function. * * \retval DER_SUCCESS The tree is correct. * \retval -DER_NOTYPE The tree is malformed. @@ -4843,7 +4850,7 @@ struct node_info { * \retval -DER_* Possibly other errors. */ static int -btr_nodes_check(struct btr_context *tcx, btr_report_fn_t report_fn, void *report_arg, +btr_nodes_check(struct btr_context *tcx, report_fn_t report_fn, void *report_arg, bool error_on_non_zero_padding) { D_LIST_HEAD(node_list); @@ -4851,12 +4858,13 @@ btr_nodes_check(struct btr_context *tcx, btr_report_fn_t report_fn, void *report struct node_info *ni_tmp; umem_off_t nd_off; struct btr_node *nd; + struct btr_record *rec; int rc = DER_SUCCESS; D_ASSERT(report_fn != NULL); if (btr_root_empty(tcx)) { - report_fn(report_arg, BTR_REPORT_MSG, "Empty tree\n"); + report_fn(report_arg, REPORT_MSG, "Empty tree\n"); return DER_SUCCESS; } @@ -4880,16 +4888,30 @@ btr_nodes_check(struct btr_context *tcx, btr_report_fn_t report_fn, void *report break; } + /** check records' consistency */ + report_fn(report_arg, REPORT_INDENT_INC, NULL); + for (int at = 0; at < nd->tn_keyn; ++at) { + rec = btr_node_rec_at(tcx, nd_off, at); + rc = btr_rec_check(tcx, rec, report_fn, report_arg); + if (rc != DER_SUCCESS) { + break; + } + } + report_fn(report_arg, REPORT_INDENT_DEC, NULL); + if (rc != DER_SUCCESS) { + break; + } + /** a leaf has no child nodes */ if (btr_node_is_leaf(tcx, nd_off)) { continue; } /** - * append the node's children to the front of the nodes' list + * Append the node's children to the front of the nodes' list. * - * Note: This makes the traversal depth-first. Given the limited depth of a typical - * DAOS tree, this approach should help reduce resource usage. + * Note: This makes the traversal depth-first. Given the limited depth of a + * typical DAOS tree, this approach should help reduce resource usage. */ for (int at = 0; at < nd->tn_keyn; ++at) { D_ALLOC_PTR(ni); @@ -4911,13 +4933,16 @@ btr_nodes_check(struct btr_context *tcx, btr_report_fn_t report_fn, void *report /** * Check a btree. * - * \param[in] root Address of the tree root. - * \param[in] uma Memory class attributes. - * \param[in] ck Checker. + * \param[in] root Address of the tree root. + * \param[in] uma Memory class attributes. + * \param[in] priv Private data for the tree class. + * \param[in] report_fn Report function. + * \param[in] report_arg Argument for the report function. + * \param[in] error_on_non_zero_padding Trigger an error on non-zero padding. */ int -dbtree_check_inplace(struct btr_root *root, struct umem_attr *uma, btr_report_fn_t report_fn, - void *report_arg, bool error_on_non_zero_padding) +dbtree_check_inplace(struct btr_root *root, struct umem_attr *uma, void *priv, + report_fn_t report_fn, void *report_arg, bool error_on_non_zero_padding) { struct btr_context tcx = {0}; uint64_t tree_feats = -1; @@ -4927,7 +4952,7 @@ dbtree_check_inplace(struct btr_root *root, struct umem_attr *uma, btr_report_fn D_ASSERT(uma != NULL); D_ASSERT(report_fn != NULL); - rc = btr_class_init(UMOFF_NULL, root, -1, &tree_feats, uma, DAOS_HDL_INVAL, NULL, report_fn, + rc = btr_class_init(UMOFF_NULL, root, -1, &tree_feats, uma, DAOS_HDL_INVAL, priv, report_fn, report_arg, &tcx.tc_tins); if (rc != DER_SUCCESS) { return rc; diff --git a/src/include/daos/btree.h b/src/include/daos/btree.h index 9b9b243d9bb..d143717a395 100644 --- a/src/include/daos/btree.h +++ b/src/include/daos/btree.h @@ -1,6 +1,6 @@ /** * (C) Copyright 2016-2024 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -16,6 +16,7 @@ #include #include #include +#include /** * KV record of the btree. @@ -409,7 +410,21 @@ typedef struct { * \a return Allocated node address (offset within the pool) */ umem_off_t (*to_node_alloc)(struct btr_instance *tins, int size); - + /** + * Optional: + * Check the consistency of the given record. + * + * \param tins [IN] Tree instance which contains the root umem + * offset and memory class etc. + * \param rec [IN] Record to be checked. + * \param report_fn [IN] Report function. + * \param report_arg [IN] Argument for the report function. + * + * \retval DER_SUCCESS Success. + * \retval -DER_* Errors returned by the fetch callback or the consistency check. + */ + int (*to_rec_check)(struct btr_instance *tins, struct btr_record *rec, + report_fn_t report_fn, void *report_arg); } btr_ops_t; /** @@ -543,15 +558,10 @@ int dbtree_open_inplace(struct btr_root *root, struct umem_attr *uma, daos_handle_t *toh); int dbtree_open_inplace_ex(struct btr_root *root, struct umem_attr *uma, daos_handle_t coh, void *priv, daos_handle_t *toh); -enum btr_report_type { - BTR_REPORT_ERROR, - BTR_REPORT_WARNING, - BTR_REPORT_MSG, -}; -typedef void (*btr_report_fn_t)(void *arg, enum btr_report_type type, const char *fmt, ...); + int - dbtree_check_inplace(struct btr_root *root, struct umem_attr *uma, btr_report_fn_t report_fn, - void *report_arg, bool error_on_non_zero_padding); + dbtree_check_inplace(struct btr_root *root, struct umem_attr *uma, void *priv, + report_fn_t report_fn, void *report_arg, bool error_on_non_zero_padding); int dbtree_close(daos_handle_t toh); int dbtree_destroy(daos_handle_t toh, void *args); int dbtree_drain(daos_handle_t toh, int *credits, void *args, bool *destroyed); diff --git a/src/include/daos/common.h b/src/include/daos/common.h index 823105224bf..7354a4ea791 100644 --- a/src/include/daos/common.h +++ b/src/include/daos/common.h @@ -982,6 +982,7 @@ enum { #define DAOS_FAULT_DAE_INV_FLAGS (DAOS_FAIL_SYS_TEST_GROUP_LOC | 0x306) #define DAOS_FAULT_DAE_ALLOC (DAOS_FAIL_SYS_TEST_GROUP_LOC | 0x307) #define DAOS_FAULT_DBD_COUNT (DAOS_FAIL_SYS_TEST_GROUP_LOC | 0x308) +#define DAOS_FAULT_OBJ_ILOG_MAGIC (DAOS_FAIL_SYS_TEST_GROUP_LOC | 0x309) #define DAOS_DTX_SKIP_PREPARE DAOS_DTX_SPEC_LEADER diff --git a/src/include/daos/report.h b/src/include/daos/report.h new file mode 100644 index 00000000000..a4fada422b7 --- /dev/null +++ b/src/include/daos/report.h @@ -0,0 +1,28 @@ +/** + * (C) Copyright 2026 Hewlett Packard Enterprise Development LP + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + */ + +#ifndef __DAOS_REPORT_H__ +#define __DAOS_REPORT_H__ + +enum report_opts { + REPORT_ERROR, + REPORT_WARNING, + REPORT_MSG, + /** flags occupy the highest bits */ + REPORT_NO_PREFIX = (1 << 29), + REPORT_INDENT_INC = (1 << 30), + REPORT_INDENT_DEC = (1 << 31), + REPORT_FLAGS_MASK = (REPORT_NO_PREFIX | REPORT_INDENT_INC | REPORT_INDENT_DEC), +}; + +typedef void (*report_fn_t)(void *arg, enum report_opts opts, const char *fmt, ...); + +static inline void +report_fn_nop(void *arg, enum report_opts ops, const char *fmt, ...) +{ +} + +#endif /* __DAOS_REPORT_H__ */ diff --git a/src/include/daos_srv/checker.h b/src/include/daos_srv/checker.h index faef94e5f25..45b316b35fd 100644 --- a/src/include/daos_srv/checker.h +++ b/src/include/daos_srv/checker.h @@ -82,37 +82,57 @@ ck_common_printf(struct checker *ck, const char *fmt, ...) } /** - * Print a btree report as a checker message. + * Print a report as a checker message. + * + * \p fmt == NULL indicates that no message will be printed, and the \p arg checker object will be + * adjusted according to \p opts e.g. increasing or decreasing the indentation level. * * \param[in] arg Checker. - * \param[in] type Btree report type. + * \param[in] opts Report options. * \param[in] fmt Format. * \param[in] ... Format's arguments. */ static inline void -ck_report(void *arg, enum btr_report_type type, const char *fmt, ...) +ck_report(void *arg, enum report_opts opts, const char *fmt, ...) { - struct checker *ck = arg; + struct checker *ck = arg; + const char *prefix = (opts & REPORT_NO_PREFIX) ? "" : ck->ck_prefix; va_list args; + if (fmt == NULL) { + switch (opts) { + case REPORT_INDENT_INC: + ck->ck_level++; + ck->ck_indent_set(ck); + return; + case REPORT_INDENT_DEC: + ck->ck_level--; + ck->ck_indent_set(ck); + return; + default: + D_ASSERTF(0, "Unknown report options: %x\n", opts); + } + return; + } + va_start(args, fmt); - switch (type) { - case BTR_REPORT_ERROR: - ck_common_printf(ck, "%s%s", ck->ck_prefix, CHECKER_ERROR_INFIX); + switch (opts & ~REPORT_FLAGS_MASK) { + case REPORT_ERROR: + ck_common_printf(ck, "%s%s", prefix, CHECKER_ERROR_INFIX); ck->ck_vprintf(ck, fmt, args); break; - case BTR_REPORT_WARNING: - ck_common_printf(ck, "%s%s", ck->ck_prefix, CHECKER_WARNING_INFIX); + case REPORT_WARNING: + ck_common_printf(ck, "%s%s", prefix, CHECKER_WARNING_INFIX); ck->ck_vprintf(ck, fmt, args); ck->ck_warnings_num++; break; - case BTR_REPORT_MSG: - ck_common_printf(ck, "%s", ck->ck_prefix); + case REPORT_MSG: + ck_common_printf(ck, "%s", prefix); ck->ck_vprintf(ck, fmt, args); break; default: - D_ASSERTF(0, "Unknown report type: %x\n", type); + D_ASSERTF(0, "Unknown report type: %x\n", opts); } va_end(args); diff --git a/src/utils/dlck/cmds/dlck_cmd_check.c b/src/utils/dlck/cmds/dlck_cmd_check.c index c3cc0cdd7f7..d299bb9784c 100644 --- a/src/utils/dlck/cmds/dlck_cmd_check.c +++ b/src/utils/dlck/cmds/dlck_cmd_check.c @@ -64,12 +64,11 @@ cont_process(daos_handle_t ih, vos_iter_entry_t *entry, vos_iter_type_t type, int rc; rc = vos_cont_open_ex(param->ip_hdl, entry->ie_couuid, ck, &coh); + CONT_REPORT_RESULT(main_ck, xa->xs->tgt_id, entry->ie_couuid, rc, ck->ck_warnings_num); if (rc == DER_SUCCESS) { (void)vos_cont_close(coh); } - CONT_REPORT_RESULT(main_ck, xa->xs->tgt_id, entry->ie_couuid, rc, ck->ck_warnings_num); - /** continue checking other containers even if this one failed */ return 0; } diff --git a/src/utils/dlck/tests/fault_injection_dlck.yaml b/src/utils/dlck/tests/fault_injection_dlck.yaml index 3a3f05b782d..15d879980da 100644 --- a/src/utils/dlck/tests/fault_injection_dlck.yaml +++ b/src/utils/dlck/tests/fault_injection_dlck.yaml @@ -45,3 +45,4 @@ fault_config: # - id: 131846 # DAOS_FAULT_DAE_INV_FLAGS # - id: 131847 # DAOS_FAULT_DAE_ALLOC # - id: 131848 # DAOS_FAULT_DBD_COUNT + # - id: 131849 # DAOS_FAULT_OBJ_ILOG_MAGIC diff --git a/src/vos/ilog.c b/src/vos/ilog.c index 8af1ddf0814..82850f501ff 100644 --- a/src/vos/ilog.c +++ b/src/vos/ilog.c @@ -1648,13 +1648,21 @@ ilog_version_get(daos_handle_t loh) return ilog_mag2ver(lctx->ic_root->lr_magic); } -bool -ilog_root_is_valid(struct ilog_df *ilog_df) +int +ilog_root_is_valid(struct ilog_df *ilog_df, report_fn_t report_fn, void *report_arg) { struct ilog_root *root = (struct ilog_root *)ilog_df; D_ASSERT(root != NULL); - return ILOG_MAGIC_VALID(root->lr_magic); + report_fn(report_arg, REPORT_MSG, "ILOG... "); + if (!ILOG_MAGIC_VALID(root->lr_magic) || DAOS_FAIL_CHECK(DAOS_FAULT_OBJ_ILOG_MAGIC)) { + report_fn(report_arg, REPORT_ERROR | REPORT_NO_PREFIX, + "invalid magic (%#" PRIx32 ").\n", root->lr_magic); + return -DER_DF_INVAL; + } + report_fn(report_arg, REPORT_MSG | REPORT_NO_PREFIX, CHECKER_OK_INFIX ".\n"); + + return DER_SUCCESS; } bool diff --git a/src/vos/ilog.h b/src/vos/ilog.h index 3fdff8524a5..a14ab9d256e 100644 --- a/src/vos/ilog.h +++ b/src/vos/ilog.h @@ -1,6 +1,6 @@ /** * (C) Copyright 2019-2024 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP. + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP. * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -344,11 +344,14 @@ ilog_is_punch(const struct ilog_entry *entry) * Validate ilog's root. * * \param[in] ilog_df + * \param[in] report_fn Report function. + * \param[in] report_arg Argument for the report function. * - * \return true if the root is valid. + * \retval DER_SUCCESS On success. + * \retval -DER_DF_INVAL Invalid ilog magic. */ -bool -ilog_root_is_valid(struct ilog_df *ilog_df); +int +ilog_root_is_valid(struct ilog_df *ilog_df, report_fn_t report_fn, void *report_arg); /** Validate the provided ilog. * diff --git a/src/vos/vos_container.c b/src/vos/vos_container.c index f5f52b9ab17..be91a642c45 100644 --- a/src/vos/vos_container.c +++ b/src/vos/vos_container.c @@ -147,14 +147,23 @@ cont_df_rec_update(struct btr_instance *tins, struct btr_record *rec, return 0; } +static int +cont_df_rec_check(struct btr_instance *tins, struct btr_record *rec, report_fn_t report_fn, + void *report_arg) +{ + /** NOP. The container is checked on open. */ + return 0; +} + static btr_ops_t vct_ops = { - .to_rec_msize = cont_df_rec_msize, - .to_hkey_size = cont_df_hkey_size, - .to_hkey_gen = cont_df_hkey_gen, - .to_rec_alloc = cont_df_rec_alloc, - .to_rec_free = cont_df_rec_free, - .to_rec_fetch = cont_df_rec_fetch, - .to_rec_update = cont_df_rec_update, + .to_rec_msize = cont_df_rec_msize, + .to_hkey_size = cont_df_hkey_size, + .to_hkey_gen = cont_df_hkey_gen, + .to_rec_alloc = cont_df_rec_alloc, + .to_rec_free = cont_df_rec_free, + .to_rec_fetch = cont_df_rec_fetch, + .to_rec_update = cont_df_rec_update, + .to_rec_check = cont_df_rec_check, }; static int @@ -450,9 +459,9 @@ vos_cont_open_ex(daos_handle_t poh, uuid_t co_uuid, struct checker *ck, daos_han CK_APPENDL_OK(ck); CK_PRINT(ck, CK_OBJ_TREE_STR "...\n"); - CK_INDENT(ck, - rc = dbtree_check_inplace(&args.ca_cont_df->cd_obj_root, &pool->vp_uma, - ck_report, ck, error_on_non_zero_padding)); + CK_INDENT(ck, rc = dbtree_check_inplace(&args.ca_cont_df->cd_obj_root, + &pool->vp_uma, pool, ck_report, ck, + error_on_non_zero_padding)); CK_PRINTL_RC(ck, rc, CK_OBJ_TREE_STR); if (rc != DER_SUCCESS) { D_GOTO(exit, rc); diff --git a/src/vos/vos_gc.c b/src/vos/vos_gc.c index 2c4e54e11bb..5ccb45e5992 100644 --- a/src/vos/vos_gc.c +++ b/src/vos/vos_gc.c @@ -1516,8 +1516,8 @@ gc_open_bkt(struct umem_attr *uma, struct vos_gc_bkt_df *bkt_df, struct checker if (IS_CHECKER(ck)) { CK_PRINT(ck, CK_GC_TREE_STR "...\n"); - CK_INDENT(ck, rc = dbtree_check_inplace(&bkt_df->gd_bins_root, uma, ck_report, ck, - error_on_non_zero_padding)); + CK_INDENT(ck, rc = dbtree_check_inplace(&bkt_df->gd_bins_root, uma, NULL, ck_report, + ck, error_on_non_zero_padding)); CK_PRINTL_RC(ck, rc, CK_GC_TREE_STR); if (rc != DER_SUCCESS) { return rc; diff --git a/src/vos/vos_obj_index.c b/src/vos/vos_obj_index.c index 328dc77fdf4..d46018f91a2 100644 --- a/src/vos/vos_obj_index.c +++ b/src/vos/vos_obj_index.c @@ -217,16 +217,57 @@ oi_node_alloc(struct btr_instance *tins, int size) return umem_zalloc(&tins->ti_umm, size); } +#define REP_OBJECT_FMT "Object (oid=" DF_UOID ")... " + +static int +oi_rec_check(struct btr_instance *tins, struct btr_record *rec, report_fn_t report_fn, + void *report_arg) +{ + d_iov_t val_iov; + struct vos_obj_df *obj; + int rc; + + report_fn(report_arg, REPORT_MSG, "Record fetch (off=%#lx)... ", rec->rec_off); + rc = tins->ti_ops->to_rec_fetch(tins, rec, NULL, &val_iov); + if (rc != DER_SUCCESS) { + report_fn(report_arg, REPORT_ERROR | REPORT_NO_PREFIX, DF_RC "\n", DP_RC(rc)); + return rc; + } + report_fn(report_arg, REPORT_MSG | REPORT_NO_PREFIX, CHECKER_OK_INFIX ".\n"); + + D_ASSERT(val_iov.iov_buf != NULL); + D_ASSERT(val_iov.iov_len == vos_obj_df_size((struct vos_pool *)tins->ti_priv)); + + obj = val_iov.iov_buf; + + report_fn(report_arg, REPORT_INDENT_INC, NULL); + report_fn(report_arg, REPORT_MSG, REP_OBJECT_FMT "\n", DP_UOID(obj->vo_id)); + report_fn(report_arg, REPORT_INDENT_INC, NULL); + rc = ilog_root_is_valid(&obj->vo_ilog, report_fn, report_arg); + report_fn(report_arg, REPORT_INDENT_DEC, NULL); + if (rc == DER_SUCCESS) { + report_fn(report_arg, REPORT_MSG, REP_OBJECT_FMT CHECKER_OK_INFIX ".\n", + DP_UOID(obj->vo_id)); + } else { + report_fn(report_arg, REPORT_ERROR, REP_OBJECT_FMT DF_RC ".\n", DP_UOID(obj->vo_id), + DP_RC(rc)); + } + report_fn(report_arg, REPORT_INDENT_DEC, NULL); + + return rc; +} + static btr_ops_t oi_btr_ops = { - .to_rec_msize = oi_rec_msize, - .to_hkey_size = oi_hkey_size, - .to_hkey_gen = oi_hkey_gen, - .to_hkey_cmp = oi_hkey_cmp, - .to_rec_alloc = oi_rec_alloc, - .to_rec_free = oi_rec_free, - .to_rec_fetch = oi_rec_fetch, - .to_rec_update = oi_rec_update, - .to_node_alloc = oi_node_alloc, + .to_rec_msize = oi_rec_msize, + .to_hkey_size = oi_hkey_size, + .to_hkey_gen = oi_hkey_gen, + .to_hkey_cmp = oi_hkey_cmp, + .to_rec_alloc = oi_rec_alloc, + .to_rec_free = oi_rec_free, + .to_rec_fetch = oi_rec_fetch, + .to_rec_update = oi_rec_update, + .to_node_alloc = oi_node_alloc, + .to_rec_check = oi_rec_check, }; bool diff --git a/src/vos/vos_pool.c b/src/vos/vos_pool.c index 6e1e118713e..fea565bf089 100644 --- a/src/vos/vos_pool.c +++ b/src/vos/vos_pool.c @@ -1693,7 +1693,7 @@ pool_open_post(struct umem_pool **p_ph, struct vos_pool_df *pool_df, unsigned in if (IS_CHECKER(ck)) { CK_PRINT(ck, CK_CONT_TREE_STR "...\n"); - CK_INDENT(ck, rc = dbtree_check_inplace(&pool_df->pd_cont_root, &pool->vp_uma, + CK_INDENT(ck, rc = dbtree_check_inplace(&pool_df->pd_cont_root, &pool->vp_uma, pool, ck_report, ck, error_on_non_zero_padding)); CK_PRINTL_RC(ck, rc, CK_CONT_TREE_STR); if (rc != DER_SUCCESS) {