mdbx: fix/refine mdbx_walk_tree() for working with invalid/corrupted DB.

Change-Id: I2594b785f675319027ff129d12683c4392e6e2f4
This commit is contained in:
Leonid Yuriev 2020-09-18 23:12:14 +03:00
parent e762442917
commit 73647a5e46

View File

@ -17750,12 +17750,12 @@ static MDBX_page_type_t walk_page_type(const MDBX_page *mp) {
} }
/* Depth-first tree traversal. */ /* Depth-first tree traversal. */
static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno, static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, const pgno_t pgno,
const char *name, int deep, const char *name, int deep,
txnid_t parent_txnid) { txnid_t parent_txnid) {
assert(pgno != P_INVALID); assert(pgno != P_INVALID);
MDBX_page *mp = nullptr; MDBX_page *mp = nullptr;
int err = mdbx_page_get(ctx->mw_cursor, pgno, &mp, NULL, parent_txnid); int rc, err = mdbx_page_get(ctx->mw_cursor, pgno, &mp, NULL, parent_txnid);
if (err == MDBX_SUCCESS) if (err == MDBX_SUCCESS)
err = mdbx_page_check(ctx->mw_cursor, mp, 0); err = mdbx_page_check(ctx->mw_cursor, mp, 0);
@ -17772,6 +17772,7 @@ static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
payload_size; payload_size;
size_t align_bytes = 0; size_t align_bytes = 0;
if (err == MDBX_SUCCESS) {
/* LY: Don't use mask here, e.g bitwise /* LY: Don't use mask here, e.g bitwise
* (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP). * (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP).
* Pages should not me marked dirty/loose or otherwise. */ * Pages should not me marked dirty/loose or otherwise. */
@ -17786,6 +17787,7 @@ static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
case P_LEAF | P_LEAF2: case P_LEAF | P_LEAF2:
break; break;
} }
}
for (int i = 0; err == MDBX_SUCCESS && i < nentries; for (int i = 0; err == MDBX_SUCCESS && i < nentries;
align_bytes += ((payload_size + align_bytes) & 1), i++) { align_bytes += ((payload_size + align_bytes) & 1), i++) {
@ -17833,9 +17835,11 @@ static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
pagesize = pgno2bytes(ctx->mw_txn->mt_env, npages); pagesize = pgno2bytes(ctx->mw_txn->mt_env, npages);
const size_t over_unused = pagesize - over_payload - over_header; const size_t over_unused = pagesize - over_payload - over_header;
err = ctx->mw_visitor(large_pgno, npages, ctx->mw_user, deep, name, rc = ctx->mw_visitor(large_pgno, npages, ctx->mw_user, deep, name,
pagesize, MDBX_page_large, err, 1, over_payload, pagesize, MDBX_page_large, err, 1, over_payload,
over_header, over_unused); over_header, over_unused);
if (unlikely(rc != MDBX_SUCCESS))
return (rc == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : rc;
} break; } break;
case F_SUBDATA /* sub-db */: { case F_SUBDATA /* sub-db */: {
@ -17893,10 +17897,11 @@ static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
} }
} }
err = rc = ctx->mw_visitor(pgno, 0, ctx->mw_user, deep + 1, name, node_ds(node),
ctx->mw_visitor(pgno, 0, ctx->mw_user, deep + 1, name, node_ds(node),
subtype, err, nsubkeys, subpayload_size, subtype, err, nsubkeys, subpayload_size,
subheader_size, subunused_size + subalign_bytes); subheader_size, subunused_size + subalign_bytes);
if (unlikely(rc != MDBX_SUCCESS))
return (rc == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : rc;
header_size += subheader_size; header_size += subheader_size;
unused_size += subunused_size; unused_size += subunused_size;
payload_size += subpayload_size; payload_size += subpayload_size;
@ -17908,12 +17913,11 @@ static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
} }
} }
err = ctx->mw_visitor(mp->mp_pgno, 1, ctx->mw_user, deep, name, rc = ctx->mw_visitor(pgno, 1, ctx->mw_user, deep, name,
ctx->mw_txn->mt_env->me_psize, type, err, nentries, ctx->mw_txn->mt_env->me_psize, type, err, nentries,
payload_size, header_size, unused_size + align_bytes); payload_size, header_size, unused_size + align_bytes);
if (unlikely(rc != MDBX_SUCCESS))
if (unlikely(err != MDBX_SUCCESS)) return (rc == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : rc;
return (err == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : err;
for (int i = 0; err == MDBX_SUCCESS && i < nentries; i++) { for (int i = 0; err == MDBX_SUCCESS && i < nentries; i++) {
if (type == MDBX_page_dupfixed_leaf) if (type == MDBX_page_dupfixed_leaf)