summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gorrod <alexander.gorrod@mongodb.com>2015-12-01 17:05:36 +1100
committerAlex Gorrod <alexg@wiredtiger.com>2015-12-02 05:46:18 +0000
commit6feaa2812e1c02fe4b74bcd6c6baeda9f310899b (patch)
treeb8361857a70cd3a7cb236707546e80907b36738f
parent1da2d3a517392d71e13b7ecdeaa97b01a2627d2d (diff)
downloadmongo-6feaa2812e1c02fe4b74bcd6c6baeda9f310899b.tar.gz
Merge pull request #2350 from wiredtiger/WT-2251-ref-addr-leak
(cherry picked from commit e731ef8ab) Conflicts: src/btree/bt_discard.c src/btree/bt_slvg.c src/btree/bt_split.c src/evict/evict_page.c src/reconcile/rec_write.c
-rw-r--r--src/btree/bt_split.c11
-rw-r--r--src/include/btree.i16
2 files changed, 27 insertions, 0 deletions
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c
index 5fc2c4cd89f..c77dfdcf5e3 100644
--- a/src/btree/bt_split.c
+++ b/src/btree/bt_split.c
@@ -1239,6 +1239,12 @@ __split_insert(WT_SESSION_IMPL *session, WT_REF *ref)
child->addr = ref->addr;
/*
+ * The address has moved to the replacement WT_REF. Make sure it isn't
+ * freed when the original ref is discarded.
+ */
+ ref->addr = NULL;
+
+ /*
* Copy the first key from the original page into first ref in the new
* parent. Pages created in memory always have a "smallest" insert
* list, so look there first. If we don't find one, get the first key
@@ -1438,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/include/btree.i b/src/include/btree.i
index 4029b29d207..271284f85a6 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -445,6 +445,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.