diff options
author | Ruby Chen <ruby.chen@mongodb.com> | 2023-03-22 04:27:57 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-03-22 05:05:26 +0000 |
commit | c7fee1fd452fd7ca41d34edc8dcae9bdccf9cb07 (patch) | |
tree | e23ed9a10b24da453ea964db4d3423cacfbf7f24 /src/third_party/wiredtiger/src/block/block_ckpt.c | |
parent | 819f18006151ae7998f492a88c29c1b6fb2eeb3f (diff) | |
download | mongo-c7fee1fd452fd7ca41d34edc8dcae9bdccf9cb07.tar.gz |
Import wiredtiger: 116fc475915a3e372c1b79f4462b48f386e43db6 from branch mongodb-master
ref: ea3fd8a50b..116fc47591
for: 7.0.0-rc0
WT-10763 Don't load the wrong extent lists in __wt_block_checkpoint_load
Diffstat (limited to 'src/third_party/wiredtiger/src/block/block_ckpt.c')
-rw-r--r-- | src/third_party/wiredtiger/src/block/block_ckpt.c | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/src/third_party/wiredtiger/src/block/block_ckpt.c b/src/third_party/wiredtiger/src/block/block_ckpt.c index a89cb7c63dd..5aa945b9350 100644 --- a/src/third_party/wiredtiger/src/block/block_ckpt.c +++ b/src/third_party/wiredtiger/src/block/block_ckpt.c @@ -12,8 +12,37 @@ static int __ckpt_process(WT_SESSION_IMPL *, WT_BLOCK *, WT_CKPT *); static int __ckpt_update(WT_SESSION_IMPL *, WT_BLOCK *, WT_CKPT *, WT_CKPT *, WT_BLOCK_CKPT *); /* + * __block_extlist_setup -- + * Initialize the extent lists in a checkpoint structure. + */ +static int +__block_extlist_setup(WT_SESSION_IMPL *session, WT_BLOCK_CKPT *ci, const char *name) +{ + WT_RET(__wt_block_extlist_init(session, &ci->alloc, name, "alloc", false)); + WT_RET(__wt_block_extlist_init(session, &ci->avail, name, "avail", true)); + WT_RET(__wt_block_extlist_init(session, &ci->discard, name, "discard", false)); + WT_RET(__wt_block_extlist_init(session, &ci->ckpt_avail, name, "ckpt_avail", true)); + + return (0); +} + +/* + * __block_extlist_reset -- + * Discard and reinitialize the extent lists in a checkpoint structure + */ +static int +__block_extlist_reset(WT_SESSION_IMPL *session, WT_BLOCK_CKPT *ci, const char *name) +{ + __wt_block_ckpt_destroy(session, ci); + WT_RET(__block_extlist_setup(session, ci, name)); + + return (0); +} + +/* * __wt_block_ckpt_init -- - * Initialize a checkpoint structure. + * Return the address cookie for the root page of a checkpoint. Also initialize extent lists if + * we are loading the live checkpoint in a writable file. */ int __wt_block_ckpt_init(WT_SESSION_IMPL *session, WT_BLOCK_CKPT *ci, const char *name) @@ -23,17 +52,13 @@ __wt_block_ckpt_init(WT_SESSION_IMPL *session, WT_BLOCK_CKPT *ci, const char *na ci->version = WT_BM_CHECKPOINT_VERSION; ci->root_offset = WT_BLOCK_INVALID_OFFSET; - WT_RET(__wt_block_extlist_init(session, &ci->alloc, name, "alloc", false)); - WT_RET(__wt_block_extlist_init(session, &ci->avail, name, "avail", true)); - WT_RET(__wt_block_extlist_init(session, &ci->discard, name, "discard", false)); - WT_RET(__wt_block_extlist_init(session, &ci->ckpt_avail, name, "ckpt_avail", true)); - - return (0); + return (__block_extlist_setup(session, ci, name)); } /* * __wt_block_checkpoint_load -- - * Load a checkpoint. + * Return the address cookie for the root page of a checkpoint. Also initialize its extent lists + * if loading the live checkpoint from a writeable file. */ int __wt_block_checkpoint_load(WT_SESSION_IMPL *session, WT_BLOCK *block, const uint8_t *addr, @@ -90,23 +115,42 @@ __wt_block_checkpoint_load(WT_SESSION_IMPL *session, WT_BLOCK *block, const uint WT_ERR(__wt_block_ckpt_unpack(session, block, addr, addr_size, ci)); /* Verify sets up next. */ - if (block->verify) + if (block->verify) { + /* + * FIXME: We may need to change how we setup for verify when it supports tiered tables. + * Until then, an attempt to verify a tiered table should return before getting here. + */ + WT_ASSERT(session, block->objectid == 0 && ci->root_objectid == 0); WT_ERR(__wt_verify_ckpt_load(session, block, ci)); + } /* Read any root page. */ if (ci->root_offset != WT_BLOCK_INVALID_OFFSET) { + /* A checkpoint shouldn't point to an object created after this one. */ + WT_ASSERT(session, block->objectid >= ci->root_objectid); + endp = root_addr; WT_ERR(__wt_block_addr_pack( block, &endp, ci->root_objectid, ci->root_offset, ci->root_size, ci->root_checksum)); *root_addr_sizep = WT_PTRDIFF(endp, root_addr); } - /* - * Rolling a checkpoint forward requires the avail list, the blocks from which we can - * allocate. - */ - if (!checkpoint) + if (!checkpoint) { + /* + * The checkpoint address may point to an earlier object. If so, the object backing this + * block handle doesn't have valid data -- i.e., it must have been written after the + * checkpoint we are opening. So we discard the incorrect extent lists and reinitialize + * them to be empty. + */ + if (block->objectid != ci->root_objectid) + __block_extlist_reset(session, ci, "live"); + + /* + * Rolling a checkpoint forward requires the avail list, the blocks from which we can + * allocate. + */ WT_ERR(__wt_block_extlist_read_avail(session, block, &ci->avail, ci->file_size)); + } } /* @@ -168,7 +212,8 @@ __wt_block_checkpoint_unload(WT_SESSION_IMPL *session, WT_BLOCK *block, bool che /* * __wt_block_ckpt_destroy -- - * Clear a checkpoint structure. + * Clear a checkpoint structure. Free the extent lists, but leave the rest of the state intact + * in case the caller is re-using it. */ void __wt_block_ckpt_destroy(WT_SESSION_IMPL *session, WT_BLOCK_CKPT *ci) |