summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2015-12-01 14:32:50 +1100
committerMichael Cahill <michael.cahill@mongodb.com>2015-12-01 14:32:50 +1100
commite2a91fe5f6a9401c64a85ffeff4090940ec1e6e1 (patch)
tree6746f226087fb8e37756fa223ebdbdd110fc106f /src
parent264ec216effa832977bab41cfe095bb8292f5f3c (diff)
downloadmongo-e2a91fe5f6a9401c64a85ffeff4090940ec1e6e1.tar.gz
WT-2251 Free addresses when we discard deleted page references.
There was a lot of repeated code to check for offpage and free ref->addr, create an inlined function.
Diffstat (limited to 'src')
-rw-r--r--src/btree/bt_discard.c6
-rw-r--r--src/btree/bt_slvg.c6
-rw-r--r--src/btree/bt_split.c1
-rw-r--r--src/evict/evict_page.c10
-rw-r--r--src/include/btree.i16
-rw-r--r--src/reconcile/rec_write.c14
6 files changed, 24 insertions, 29 deletions
diff --git a/src/btree/bt_discard.c b/src/btree/bt_discard.c
index 7cd97831044..54d9761c487 100644
--- a/src/btree/bt_discard.c
+++ b/src/btree/bt_discard.c
@@ -269,11 +269,7 @@ __wt_free_ref(
* Free any address allocation; if there's no linked WT_REF page, it
* must be allocated.
*/
- if (ref->addr != NULL &&
- (ref->home == NULL || __wt_off_page(ref->home, ref->addr))) {
- __wt_free(session, ((WT_ADDR *)ref->addr)->addr);
- __wt_free(session, ref->addr);
- }
+ __wt_ref_free_addr(session, ref);
/* Free any page-deleted information. */
if (ref->page_del != NULL) {
diff --git a/src/btree/bt_slvg.c b/src/btree/bt_slvg.c
index 80e467b5707..39a5e5c4f91 100644
--- a/src/btree/bt_slvg.c
+++ b/src/btree/bt_slvg.c
@@ -1290,8 +1290,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);
+ __wt_ref_free_addr(session, ref);
ref->addr = NULL;
/* Write the new version of the leaf page to disk. */
@@ -2013,8 +2012,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);
+ __wt_ref_free_addr(session, ref);
ref->addr = NULL;
/* Write the new version of the leaf page to disk. */
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c
index a0dfbf32cad..862a683645e 100644
--- a/src/btree/bt_split.c
+++ b/src/btree/bt_split.c
@@ -895,6 +895,7 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
*/
WT_ASSERT(session, next_ref->page_del == NULL);
+ __wt_ref_free_addr(session, next_ref);
WT_TRET(__split_safe_free(
session, split_gen, exclusive, next_ref, sizeof(WT_REF)));
parent_decr += sizeof(WT_REF);
diff --git a/src/evict/evict_page.c b/src/evict/evict_page.c
index 26ea9117fae..6d02c5cec49 100644
--- a/src/evict/evict_page.c
+++ b/src/evict/evict_page.c
@@ -250,10 +250,7 @@ __evict_page_dirty_update(WT_SESSION_IMPL *session, WT_REF *ref, bool closing)
switch (mod->rec_result) {
case WT_PM_REC_EMPTY: /* Page is empty */
/* Discard the parent's address. */
- if (ref->addr != NULL && __wt_off_page(parent, ref->addr)) {
- __wt_free(session, ((WT_ADDR *)ref->addr)->addr);
- __wt_free(session, ref->addr);
- }
+ __wt_ref_free_addr(session, ref);
/*
* Update the parent to reference a deleted page. The fact that
@@ -308,10 +305,7 @@ __evict_page_dirty_update(WT_SESSION_IMPL *session, WT_REF *ref, bool closing)
return (EBUSY);
/* Discard the parent's address. */
- if (ref->addr != NULL && __wt_off_page(parent, ref->addr)) {
- __wt_free(session, ((WT_ADDR *)ref->addr)->addr);
- __wt_free(session, ref->addr);
- }
+ __wt_ref_free_addr(session, ref);
/*
* Update the parent to reference the replacement page.
diff --git a/src/include/btree.i b/src/include/btree.i
index 3f8dc08a1da..9db88440225 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -466,6 +466,22 @@ __wt_off_page(WT_PAGE *page, const void *p)
}
/*
+ * __wt_ref_free_addr --
+ * Free the address in a reference, if necessary.
+ */
+static inline void
+__wt_ref_free_addr(WT_SESSION_IMPL *session, WT_REF *ref)
+{
+ if (ref->addr != NULL) {
+ if (ref->home == NULL || __wt_off_page(ref->home, ref->addr)) {
+ __wt_free(session, ((WT_ADDR *)ref->addr)->addr);
+ __wt_free(session, ref->addr);
+ } else
+ ref->addr = NULL;
+ }
+}
+
+/*
* __wt_ref_key --
* Return a reference to a row-store internal page key as cheaply as
* possible.
diff --git a/src/reconcile/rec_write.c b/src/reconcile/rec_write.c
index 8bf81eafac2..0e1e7498568 100644
--- a/src/reconcile/rec_write.c
+++ b/src/reconcile/rec_write.c
@@ -1395,12 +1395,7 @@ __rec_child_deleted(WT_SESSION_IMPL *session,
__wt_txn_visible_all(session, page_del->txnid))) {
WT_RET(__wt_ref_info(session, ref, &addr, &addr_size, NULL));
WT_RET(__rec_block_free(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_ref_free_addr(session, ref);
}
/*
@@ -5434,12 +5429,7 @@ __rec_write_wrapup(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page)
WT_RET(__wt_ref_info(
session, ref, &addr, &addr_size, NULL));
WT_RET(__rec_block_free(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_ref_free_addr(session, ref);
}
break;
case WT_PM_REC_EMPTY: /* Page deleted */