diff options
author | Michael Cahill <michael.cahill@mongodb.com> | 2015-12-02 22:13:33 +1100 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2015-12-02 22:13:47 +1100 |
commit | eb8bc24a0d36b673022faa83976a4b33bc8f676b (patch) | |
tree | e14db1a16010a86f89241c85bc9b3015d2aace52 | |
parent | a5ddbdfcd2ab0e05f31fa56af8e9e9a887d63dc1 (diff) | |
download | mongo-eb8bc24a0d36b673022faa83976a4b33bc8f676b.tar.gz |
Import wiredtiger-wiredtiger-mongodb-3.0.7-20-g27d0cbd.tar.gz from wiredtiger branch mongodb-3.0
ref: deb2d81..27d0cbd
6feaa28 WT-2251 Fix leaf of deleted page addresses.
1da2d3a SERVER-21568 Fix a use-after-free.
4228295 SERVER-21553 Free blocks during reverse splits.
0398515 WT-2241 Use a lock to protect transaction ID allocation.
06a5c7b WT-2237 Avoid yields if we race allocating transaction IDs.
16a418b WT-2237 Have threads publish unique transaction IDs so that updates always become visible immediately on commit.
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_delete.c | 12 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_discard.c | 5 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_slvg.c | 8 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_split.c | 64 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_walk.c | 4 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/evict/evict_page.c | 14 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/include/btree.i | 55 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/include/txn.h | 1 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/include/txn.i | 117 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/lsm/lsm_tree.c | 4 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/reconcile/rec_track.c | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/reconcile/rec_write.c | 44 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/txn/txn.c | 7 |
13 files changed, 191 insertions, 146 deletions
diff --git a/src/third_party/wiredtiger/src/btree/bt_delete.c b/src/third_party/wiredtiger/src/btree/bt_delete.c index 7313e31267f..e19085830bd 100644 --- a/src/third_party/wiredtiger/src/btree/bt_delete.c +++ b/src/third_party/wiredtiger/src/btree/bt_delete.c @@ -250,6 +250,18 @@ __wt_delete_page_skip(WT_SESSION_IMPL *session, WT_REF *ref, bool visible_all) __wt_txn_visible_all(session, ref->page_del->txnid) : __wt_txn_visible(session, ref->page_del->txnid)); + /* + * The page_del structure can be freed as soon as the delete is stable: + * it is only read when the ref state is WT_REF_DELETED. It is worth + * checking every time we come through because once this is freed, we + * no longer need synchronization to check the ref. + */ + if (skip && ref->page_del != NULL && (visible_all || + __wt_txn_visible_all(session, ref->page_del->txnid))) { + __wt_free(session, ref->page_del->update_list); + __wt_free(session, ref->page_del); + } + WT_PUBLISH(ref->state, WT_REF_DELETED); return (skip); } diff --git a/src/third_party/wiredtiger/src/btree/bt_discard.c b/src/third_party/wiredtiger/src/btree/bt_discard.c index c876da6309c..30e19147e12 100644 --- a/src/third_party/wiredtiger/src/btree/bt_discard.c +++ b/src/third_party/wiredtiger/src/btree/bt_discard.c @@ -252,10 +252,7 @@ __wt_free_ref( } /* Free any address allocation. */ - if (ref->addr != NULL && __wt_off_page(page, ref->addr)) { - __wt_free(session, ((WT_ADDR *)ref->addr)->addr); - __wt_free(session, ref->addr); - } + __wt_ref_addr_free(session, ref); /* Free any page-deleted information. */ if (ref->page_del != NULL) { diff --git a/src/third_party/wiredtiger/src/btree/bt_slvg.c b/src/third_party/wiredtiger/src/btree/bt_slvg.c index 89355baeb5c..e4e611f947a 100644 --- a/src/third_party/wiredtiger/src/btree/bt_slvg.c +++ b/src/third_party/wiredtiger/src/btree/bt_slvg.c @@ -1299,9 +1299,7 @@ __slvg_col_build_leaf(WT_SESSION_IMPL *session, WT_TRACK *trk, WT_REF *ref) * would have been lost.) Clear the reference addr so eviction doesn't * free the underlying blocks. */ - __wt_free(session, ((WT_ADDR *)ref->addr)->addr); - __wt_free(session, ref->addr); - ref->addr = NULL; + __wt_ref_addr_free(session, ref); /* Write the new version of the leaf page to disk. */ WT_ERR(__slvg_modify_init(session, page)); @@ -2008,9 +2006,7 @@ __slvg_row_build_leaf( * would have been lost.) Clear the reference addr so eviction doesn't * free the underlying blocks. */ - __wt_free(session, ((WT_ADDR *)ref->addr)->addr); - __wt_free(session, ref->addr); - ref->addr = NULL; + __wt_ref_addr_free(session, ref); /* Write the new version of the leaf page to disk. */ WT_ERR(__slvg_modify_init(session, page)); diff --git a/src/third_party/wiredtiger/src/btree/bt_split.c b/src/third_party/wiredtiger/src/btree/bt_split.c index 6f31ff89aa7..6e0436bb01f 100644 --- a/src/third_party/wiredtiger/src/btree/bt_split.c +++ b/src/third_party/wiredtiger/src/btree/bt_split.c @@ -502,7 +502,7 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent) * array, a thread might see a freed WT_REF. Set the eviction * transaction requirement for the newly created internal pages. */ - child->modify->mod_split_txn = __wt_txn_new_id(session); + child->modify->mod_split_txn = __wt_txn_id_alloc(session, false); /* * The newly allocated child's page index references the same @@ -1030,6 +1030,16 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, #endif /* + * Page-delete information is only read when the WT_REF state is + * WT_REF_DELETED. The page-delete memory wasn't added to the + * parent's footprint, ignore it here. + */ + if (ref->page_del != NULL) { + __wt_free(session, ref->page_del->update_list); + __wt_free(session, ref->page_del); + } + + /* * Reset the page's original WT_REF field to split. Threads cursoring * through the tree were blocked because that WT_REF state was set to * locked. This update changes the locked state to split, unblocking @@ -1090,19 +1100,15 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, session, split_gen, 0, ikey, size)); parent_decr += size; } - /* - * The page_del structure can be freed immediately: it - * is only read when the ref state is WT_REF_DELETED. - * The size of the structure wasn't added to the parent, - * don't decrement. - */ - if (next_ref->page_del != NULL) { - __wt_free(session, - next_ref->page_del->update_list); - __wt_free(session, next_ref->page_del); - } } + /* + * If this page was fast-truncated, any attached structure + * should have been freed before now. + */ + WT_ASSERT(session, next_ref->page_del == NULL); + + WT_TRET(__wt_ref_block_free(session, next_ref)); WT_TRET(__split_safe_free( session, split_gen, 0, next_ref, sizeof(WT_REF))); parent_decr += sizeof(WT_REF); @@ -1213,21 +1219,30 @@ __split_insert(WT_SESSION_IMPL *session, WT_REF *ref) * The first page in the split is the current page, but we still have * to create a replacement WT_REF, the original WT_REF will be set to * split status and eventually freed. + * + * The new WT_REF is not quite identical: we have to instantiate a key, + * and the new reference is visible to readers once the split completes. + * + * The key-instantiation code checks for races, leave the key fields + * zeroed we don't trigger them. + * + * Don't copy any deleted page state: we may be splitting a page that + * was instantiated after a truncate and that history should not be + * carried onto these new child pages. */ WT_ERR(__wt_calloc_one(session, &split_ref[0])); child = split_ref[0]; - *child = *ref; + child->page = ref->page; + child->home = ref->home; + child->pindex_hint = ref->pindex_hint; + child->state = WT_REF_MEM; + child->addr = ref->addr; /* - * The new WT_REF is not quite identical: we have to instantiate a key, - * and the new reference is visible to readers once the split completes. - * - * The key-instantiation code checks for races, clear the key fields so - * we don't trigger them. + * The address has moved to the replacement WT_REF. Make sure it isn't + * freed when the original ref is discarded. */ - child->key.recno = 0; - child->key.ikey = NULL; - child->state = WT_REF_MEM; + ref->addr = NULL; /* * Copy the first key from the original page into first ref in the new @@ -1383,7 +1398,7 @@ __split_insert(WT_SESSION_IMPL *session, WT_REF *ref) * threads will not try to forcibly evict the page again until * all concurrent transactions commit. */ - page->modify->inmem_split_txn = __wt_txn_new_id(session); + page->modify->inmem_split_txn = __wt_txn_id_alloc(session, false); /* * Update the page accounting. @@ -1429,6 +1444,11 @@ __split_insert(WT_SESSION_IMPL *session, WT_REF *ref) return (0); err: if (split_ref[0] != NULL) { + /* + * The address was moved to the replacement WT_REF, restore it. + */ + ref->addr = split_ref[0]->addr; + __wt_free(session, split_ref[0]->key.ikey); __wt_free(session, split_ref[0]); } diff --git a/src/third_party/wiredtiger/src/btree/bt_walk.c b/src/third_party/wiredtiger/src/btree/bt_walk.c index 8e0f4036b79..c7d83d8dfff 100644 --- a/src/third_party/wiredtiger/src/btree/bt_walk.c +++ b/src/third_party/wiredtiger/src/btree/bt_walk.c @@ -244,7 +244,8 @@ ascend: /* * If we see any child states other than deleted, the * page isn't empty. */ - if (ref->state != WT_REF_DELETED) + if (ref->state != WT_REF_DELETED && + !LF_ISSET(WT_READ_TRUNCATE)) empty_internal = false; if (LF_ISSET(WT_READ_CACHE)) { @@ -270,6 +271,7 @@ ascend: /* WT_ERR(__wt_delete_page(session, ref, &skip)); if (skip) break; + empty_internal = false; } else if (LF_ISSET(WT_READ_COMPACT)) { /* * Skip deleted pages, rewriting them doesn't diff --git a/src/third_party/wiredtiger/src/evict/evict_page.c b/src/third_party/wiredtiger/src/evict/evict_page.c index 9de66922931..046d8bb3eba 100644 --- a/src/third_party/wiredtiger/src/evict/evict_page.c +++ b/src/third_party/wiredtiger/src/evict/evict_page.c @@ -222,19 +222,14 @@ __evict_page_dirty_update(WT_SESSION_IMPL *session, WT_REF *ref, bool closing) { WT_ADDR *addr; WT_DECL_RET; - WT_PAGE *parent; WT_PAGE_MODIFY *mod; - parent = ref->home; mod = ref->page->modify; + WT_ASSERT(session, ref->addr == NULL); + switch (mod->rec_result) { case WT_PM_REC_EMPTY: /* Page is empty */ - if (ref->addr != NULL && __wt_off_page(parent, ref->addr)) { - __wt_free(session, ((WT_ADDR *)ref->addr)->addr); - __wt_free(session, ref->addr); - } - /* * Update the parent to reference a deleted page. The fact that * reconciliation left the page "empty" means there's no older @@ -261,11 +256,6 @@ __evict_page_dirty_update(WT_SESSION_IMPL *session, WT_REF *ref, bool closing) WT_RET(__wt_split_multi(session, ref, closing)); break; case WT_PM_REC_REPLACE: /* 1-for-1 page swap */ - if (ref->addr != NULL && __wt_off_page(parent, ref->addr)) { - __wt_free(session, ((WT_ADDR *)ref->addr)->addr); - __wt_free(session, ref->addr); - } - /* * Update the parent to reference the replacement page. * diff --git a/src/third_party/wiredtiger/src/include/btree.i b/src/third_party/wiredtiger/src/include/btree.i index 1c416c99e13..4029b29d207 100644 --- a/src/third_party/wiredtiger/src/include/btree.i +++ b/src/third_party/wiredtiger/src/include/btree.i @@ -1008,6 +1008,61 @@ __wt_page_can_split(WT_SESSION_IMPL *session, WT_PAGE *page) } /* + * __wt_ref_addr_free -- + * Free the address in a reference, if necessary. + */ +static inline void +__wt_ref_addr_free(WT_SESSION_IMPL *session, WT_REF *ref) + { + if (ref->addr == NULL) + return; + + if (ref->home == NULL || __wt_off_page(ref->home, ref->addr)) { + __wt_free(session, ((WT_ADDR *)ref->addr)->addr); + __wt_free(session, ref->addr); + } + ref->addr = NULL; +} + +/* + * __wt_btree_block_free -- + * Helper function to free a block from the current tree. + */ +static inline int +__wt_btree_block_free( + WT_SESSION_IMPL *session, const uint8_t *addr, size_t addr_size) +{ + WT_BM *bm; + WT_BTREE *btree; + + btree = S2BT(session); + bm = btree->bm; + + return (bm->free(bm, session, addr, addr_size)); +} + +/* + * __wt_ref_block_free -- + * Free the on-disk block for a reference and clear the address. + */ +static inline int +__wt_ref_block_free(WT_SESSION_IMPL *session, WT_REF *ref) +{ + const uint8_t *addr; + size_t addr_size; + + if (ref->addr == NULL) + return (0); + + WT_RET(__wt_ref_info(session, ref, &addr, &addr_size, NULL)); + WT_RET(__wt_btree_block_free(session, addr, addr_size)); + + /* Clear the address (so we don't free it twice). */ + __wt_ref_addr_free(session, ref); + return (0); +} + +/* * __wt_page_can_evict -- * Check whether a page can be evicted. */ diff --git a/src/third_party/wiredtiger/src/include/txn.h b/src/third_party/wiredtiger/src/include/txn.h index 0d5f337fff0..9f9f282bfa4 100644 --- a/src/third_party/wiredtiger/src/include/txn.h +++ b/src/third_party/wiredtiger/src/include/txn.h @@ -34,6 +34,7 @@ struct WT_COMPILER_TYPE_ALIGN(WT_CACHE_LINE_ALIGNMENT) __wt_txn_state { }; struct __wt_txn_global { + WT_SPINLOCK id_lock; volatile uint64_t current; /* Current transaction ID. */ /* The oldest running transaction ID (may race). */ diff --git a/src/third_party/wiredtiger/src/include/txn.i b/src/third_party/wiredtiger/src/include/txn.i index 73d7f1f0518..d7d958e801e 100644 --- a/src/third_party/wiredtiger/src/include/txn.i +++ b/src/third_party/wiredtiger/src/include/txn.i @@ -280,23 +280,6 @@ __wt_txn_autocommit_check(WT_SESSION_IMPL *session) } /* - * __wt_txn_new_id -- - * Allocate a new transaction ID. - */ -static inline uint64_t -__wt_txn_new_id(WT_SESSION_IMPL *session) -{ - /* - * We want the global value to lead the allocated values, so that any - * allocated transaction ID eventually becomes globally visible. When - * there are no transactions running, the oldest_id will reach the - * global current ID, so we want post-increment semantics. Our atomic - * add primitive does pre-increment, so adjust the result here. - */ - return (__wt_atomic_addv64(&S2C(session)->txn_global.current, 1) - 1); -} - -/* * __wt_txn_idle_cache_check -- * If there is no transaction active in this thread and we haven't checked * if the cache is full, do it now. If we have to block for eviction, @@ -323,6 +306,54 @@ __wt_txn_idle_cache_check(WT_SESSION_IMPL *session) } /* + * __wt_txn_id_alloc -- + * Allocate a new transaction ID. + */ +static inline uint64_t +__wt_txn_id_alloc(WT_SESSION_IMPL *session, bool publish) +{ + WT_TXN_GLOBAL *txn_global; + uint64_t id; + + txn_global = &S2C(session)->txn_global; + + /* + * Allocating transaction IDs involves several steps. + * + * Firstly, we do an atomic increment to allocate a unique ID. The + * field we increment is not used anywhere else. + * + * Then we optionally publish the allocated ID into the global + * transaction table. It is critical that this becomes visible before + * the global current value moves past our ID, or some concurrent + * reader could get a snapshot that makes our changes visible before we + * commit. + * + * Lastly, we spin to update the current ID. This is the only place + * that the current ID is updated, and it is in the same cache line as + * the field we allocate from, so we should usually succeed on the + * first try. + * + * We want the global value to lead the allocated values, so that any + * allocated transaction ID eventually becomes globally visible. When + * there are no transactions running, the oldest_id will reach the + * global current ID, so we want post-increment semantics. Our atomic + * add primitive does pre-increment, so adjust the result here. + */ + __wt_spin_lock(session, &txn_global->id_lock); + id = txn_global->current; + + if (publish) { + session->txn.id = id; + WT_PUBLISH(WT_SESSION_TXN_STATE(session)->id, id); + } + + ++txn_global->current; + __wt_spin_unlock(session, &txn_global->id_lock); + return (id); +} + +/* * __wt_txn_id_check -- * A transaction is going to do an update, start an auto commit * transaction if required and allocate a transaction ID. @@ -330,57 +361,27 @@ __wt_txn_idle_cache_check(WT_SESSION_IMPL *session) static inline int __wt_txn_id_check(WT_SESSION_IMPL *session) { - WT_CONNECTION_IMPL *conn; WT_TXN *txn; - WT_TXN_GLOBAL *txn_global; - WT_TXN_STATE *txn_state; txn = &session->txn; WT_ASSERT(session, F_ISSET(txn, WT_TXN_RUNNING)); + if (F_ISSET(txn, WT_TXN_HAS_ID)) + return (0); + /* If the transaction is idle, check that the cache isn't full. */ WT_RET(__wt_txn_idle_cache_check(session)); - if (!F_ISSET(txn, WT_TXN_HAS_ID)) { - conn = S2C(session); - txn_global = &conn->txn_global; - txn_state = WT_SESSION_TXN_STATE(session); + (void)__wt_txn_id_alloc(session, true); - WT_ASSERT(session, txn_state->id == WT_TXN_NONE); - - /* - * Allocate a transaction ID. - * - * We use an atomic compare and swap to ensure that we get a - * unique ID that is published before the global counter is - * updated. - * - * If two threads race to allocate an ID, only the latest ID - * will proceed. The winning thread can be sure its snapshot - * contains all of the earlier active IDs. Threads that race - * and get an earlier ID may not appear in the snapshot, but - * they will loop and allocate a new ID before proceeding to - * make any updates. - * - * This potentially wastes transaction IDs when threads race to - * begin transactions: that is the price we pay to keep this - * path latch free. - */ - do { - txn_state->id = txn->id = txn_global->current; - } while (!__wt_atomic_casv64( - &txn_global->current, txn->id, txn->id + 1) || - WT_TXNID_LT(txn->id, txn_global->last_running)); - - /* - * If we have used 64-bits of transaction IDs, there is nothing - * more we can do. - */ - if (txn->id == WT_TXN_ABORTED) - WT_RET_MSG(session, ENOMEM, "Out of transaction IDs"); - F_SET(txn, WT_TXN_HAS_ID); - } + /* + * If we have used 64-bits of transaction IDs, there is nothing + * more we can do. + */ + if (txn->id == WT_TXN_ABORTED) + WT_RET_MSG(session, ENOMEM, "Out of transaction IDs"); + F_SET(txn, WT_TXN_HAS_ID); return (0); } diff --git a/src/third_party/wiredtiger/src/lsm/lsm_tree.c b/src/third_party/wiredtiger/src/lsm/lsm_tree.c index 0680d98bdde..d3979da0da1 100644 --- a/src/third_party/wiredtiger/src/lsm/lsm_tree.c +++ b/src/third_party/wiredtiger/src/lsm/lsm_tree.c @@ -858,7 +858,7 @@ __wt_lsm_tree_switch(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree) */ if (last_chunk != NULL && last_chunk->switch_txn == WT_TXN_NONE && !F_ISSET(last_chunk, WT_LSM_CHUNK_ONDISK)) - last_chunk->switch_txn = __wt_txn_new_id(session); + last_chunk->switch_txn = __wt_txn_id_alloc(session, false); /* * If a maximum number of chunks are configured, drop the any chunks @@ -1257,7 +1257,7 @@ __wt_lsm_compact(WT_SESSION_IMPL *session, const char *name, bool *skipp) if (lsm_tree->nchunks > 0 && (chunk = lsm_tree->chunk[lsm_tree->nchunks - 1]) != NULL) { if (chunk->switch_txn == WT_TXN_NONE) - chunk->switch_txn = __wt_txn_new_id(session); + chunk->switch_txn = __wt_txn_id_alloc(session, false); /* * If we have a chunk, we want to look for it to be on-disk. * So we need to add a reference to keep it available. diff --git a/src/third_party/wiredtiger/src/reconcile/rec_track.c b/src/third_party/wiredtiger/src/reconcile/rec_track.c index 36e85713421..17ad1c5fdc4 100644 --- a/src/third_party/wiredtiger/src/reconcile/rec_track.c +++ b/src/third_party/wiredtiger/src/reconcile/rec_track.c @@ -820,7 +820,7 @@ __wt_ovfl_txnc_add(WT_SESSION_IMPL *session, WT_PAGE *page, txnc->value_offset = WT_PTRDIFF32(p, txnc); txnc->value_size = WT_STORE_SIZE(value_size); memcpy(p, value, value_size); - txnc->current = __wt_txn_new_id(session); + txnc->current = __wt_txn_id_alloc(session, false); __wt_cache_page_inmem_incr( session, page, WT_OVFL_SIZE(txnc, WT_OVFL_TXNC)); diff --git a/src/third_party/wiredtiger/src/reconcile/rec_write.c b/src/third_party/wiredtiger/src/reconcile/rec_write.c index 73b7f4968e9..67b43057c8a 100644 --- a/src/third_party/wiredtiger/src/reconcile/rec_write.c +++ b/src/third_party/wiredtiger/src/reconcile/rec_write.c @@ -1066,10 +1066,7 @@ static int __rec_child_deleted(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_REF *ref, WT_CHILD_STATE *statep) { - WT_BM *bm; WT_PAGE_DELETED *page_del; - size_t addr_size; - const uint8_t *addr; page_del = ref->page_del; @@ -1117,17 +1114,8 @@ __rec_child_deleted(WT_SESSION_IMPL *session, */ if (ref->addr != NULL && (page_del == NULL || - __wt_txn_visible_all(session, page_del->txnid))) { - WT_RET(__wt_ref_info(session, ref, &addr, &addr_size, NULL)); - bm = S2BT(session)->bm; - WT_RET(bm->free(bm, session, addr, addr_size)); - - if (__wt_off_page(ref->home, ref->addr)) { - __wt_free(session, ((WT_ADDR *)ref->addr)->addr); - __wt_free(session, ref->addr); - } - ref->addr = NULL; - } + __wt_txn_visible_all(session, page_del->txnid))) + WT_RET(__wt_ref_block_free(session, ref)); /* * If the original page is gone, we can skip the slot on the internal @@ -4790,13 +4778,11 @@ __rec_row_leaf_insert(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins) static int __rec_split_discard(WT_SESSION_IMPL *session, WT_PAGE *page) { - WT_BM *bm; WT_DECL_RET; WT_PAGE_MODIFY *mod; WT_MULTI *multi; uint32_t i; - bm = S2BT(session)->bm; mod = page->modify; /* @@ -4816,7 +4802,7 @@ __rec_split_discard(WT_SESSION_IMPL *session, WT_PAGE *page) if (multi->addr.reuse) multi->addr.addr = NULL; else { - WT_RET(bm->free(bm, session, + WT_RET(__wt_btree_block_free(session, multi->addr.addr, multi->addr.size)); __wt_free(session, multi->addr.addr); } @@ -4862,8 +4848,6 @@ __rec_write_wrapup(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) WT_MULTI *multi; WT_PAGE_MODIFY *mod; WT_REF *ref; - size_t addr_size; - const uint8_t *addr; btree = S2BT(session); bm = btree->bm; @@ -4888,21 +4872,7 @@ __rec_write_wrapup(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) */ if (__wt_ref_is_root(ref)) break; - if (ref->addr != NULL) { - /* - * Free the page and clear the address (so we don't free - * it twice). - */ - WT_RET(__wt_ref_info( - session, ref, &addr, &addr_size, NULL)); - WT_RET(bm->free(bm, session, addr, addr_size)); - if (__wt_off_page(ref->home, ref->addr)) { - __wt_free( - session, ((WT_ADDR *)ref->addr)->addr); - __wt_free(session, ref->addr); - } - ref->addr = NULL; - } + WT_RET(__wt_ref_block_free(session, ref)); break; case WT_PM_REC_EMPTY: /* Page deleted */ break; @@ -4921,7 +4891,7 @@ __rec_write_wrapup(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) * are checkpoints, and must be explicitly dropped. */ if (!__wt_ref_is_root(ref)) - WT_RET(bm->free(bm, session, + WT_RET(__wt_btree_block_free(session, mod->mod_replace.addr, mod->mod_replace.size)); /* Discard the replacement page's address. */ @@ -5126,14 +5096,12 @@ err: __wt_scr_free(session, &tkey); static int __rec_write_wrapup_err(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) { - WT_BM *bm; WT_BOUNDARY *bnd; WT_DECL_RET; WT_MULTI *multi; WT_PAGE_MODIFY *mod; uint32_t i; - bm = S2BT(session)->bm; mod = page->modify; /* @@ -5164,7 +5132,7 @@ __rec_write_wrapup_err(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) if (bnd->addr.reuse) bnd->addr.addr = NULL; else { - WT_TRET(bm->free(bm, session, + WT_TRET(__wt_btree_block_free(session, bnd->addr.addr, bnd->addr.size)); __wt_free(session, bnd->addr.addr); } diff --git a/src/third_party/wiredtiger/src/txn/txn.c b/src/third_party/wiredtiger/src/txn/txn.c index eb2b621f315..f9af9589172 100644 --- a/src/third_party/wiredtiger/src/txn/txn.c +++ b/src/third_party/wiredtiger/src/txn/txn.c @@ -597,6 +597,9 @@ __wt_txn_global_init(WT_SESSION_IMPL *session, const char *cfg[]) txn_global->current = txn_global->last_running = txn_global->oldest_id = WT_TXN_FIRST; + WT_RET(__wt_spin_init(session, + &txn_global->id_lock, "transaction id lock")); + WT_RET(__wt_calloc_def( session, conn->session_size, &txn_global->states)); for (i = 0, s = txn_global->states; i < conn->session_size; i++, s++) @@ -618,6 +621,6 @@ __wt_txn_global_destroy(WT_SESSION_IMPL *session) conn = S2C(session); txn_global = &conn->txn_global; - if (txn_global != NULL) - __wt_free(session, txn_global->states); + __wt_spin_destroy(session, &txn_global->id_lock); + __wt_free(session, txn_global->states); } |