summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Gorrod <alexander.gorrod@mongodb.com>2015-11-26 15:47:10 +1100
committerAlex Gorrod <alexander.gorrod@mongodb.com>2015-11-26 15:47:10 +1100
commit4e1844c6a28ce5b60ea6a44b81bd04a3f5457940 (patch)
treed6baf14195968d33d84ba4035126947be8a643fa /src
parentcace179242802786b9ecbdb5f229389c517dd531 (diff)
parent714ae53068b767f64b90dae503a82dc063f9a25f (diff)
downloadmongo-4e1844c6a28ce5b60ea6a44b81bd04a3f5457940.tar.gz
Merge pull request #2324 from wiredtiger/wt-2230-multi-split-error-path
WT-2230: multi-split error path
Diffstat (limited to 'src')
-rw-r--r--src/btree/bt_discard.c26
-rw-r--r--src/btree/bt_split.c8
-rw-r--r--src/include/extern.h2
3 files changed, 24 insertions, 12 deletions
diff --git a/src/btree/bt_discard.c b/src/btree/bt_discard.c
index 277cdc60522..13bd943f803 100644
--- a/src/btree/bt_discard.c
+++ b/src/btree/bt_discard.c
@@ -231,7 +231,7 @@ __free_page_int(WT_SESSION_IMPL *session, WT_PAGE *page)
*/
void
__wt_free_ref(
- WT_SESSION_IMPL *session, WT_PAGE *page, WT_REF *ref, bool free_pages)
+ WT_SESSION_IMPL *session, WT_REF *ref, int page_type, bool free_pages)
{
WT_IKEY *ikey;
@@ -250,8 +250,15 @@ __wt_free_ref(
__wt_page_out(session, &ref->page);
}
- /* Free any key allocation. */
- switch (page->type) {
+ /*
+ * Optionally free row-store WT_REF key allocation. Historic versions of
+ * this code looked in a passed-in page argument, but that is dangerous,
+ * some of our error-path callers create WT_REF structures without ever
+ * setting WT_REF.home or having a parent page to which the WT_REF will
+ * be linked. Those WT_REF structures invariably have instantiated keys,
+ * (they obviously cannot be on-page keys), and we must free the memory.
+ */
+ switch (page_type) {
case WT_PAGE_ROW_INT:
case WT_PAGE_ROW_LEAF:
if ((ikey = __wt_ref_key_instantiated(ref)) != NULL)
@@ -259,8 +266,12 @@ __wt_free_ref(
break;
}
- /* Free any address allocation. */
- if (ref->addr != NULL && __wt_off_page(page, ref->addr)) {
+ /*
+ * 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);
}
@@ -276,7 +287,7 @@ __wt_free_ref(
/*
* __wt_free_ref_index --
- * Discard a page index and it's references.
+ * Discard a page index and its references.
*/
void
__wt_free_ref_index(WT_SESSION_IMPL *session,
@@ -288,7 +299,8 @@ __wt_free_ref_index(WT_SESSION_IMPL *session,
return;
for (i = 0; i < pindex->entries; ++i)
- __wt_free_ref(session, page, pindex->index[i], free_pages);
+ __wt_free_ref(
+ session, pindex->index[i], page->type, free_pages);
__wt_free(session, pindex);
}
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c
index 92ed2b3e559..35c3bfea711 100644
--- a/src/btree/bt_split.c
+++ b/src/btree/bt_split.c
@@ -1527,7 +1527,7 @@ __split_multi_inmem_final(WT_PAGE *orig, WT_MULTI *multi)
* Discard allocated pages after failure.
*/
static void
-__split_multi_inmem_fail(WT_SESSION_IMPL *session, WT_REF *ref)
+__split_multi_inmem_fail(WT_SESSION_IMPL *session, WT_PAGE *orig, WT_REF *ref)
{
/*
* We failed creating new in-memory pages. For error-handling reasons,
@@ -1537,7 +1537,7 @@ __split_multi_inmem_fail(WT_SESSION_IMPL *session, WT_REF *ref)
*/
if (ref->page != NULL) {
F_SET_ATOMIC(ref->page, WT_PAGE_UPDATE_IGNORE);
- __wt_free_ref(session, ref->page, ref, true);
+ __wt_free_ref(session, ref, orig->type, true);
}
}
@@ -1962,7 +1962,7 @@ __split_multi(WT_SESSION_IMPL *session, WT_REF *ref, bool closing)
if (0) {
err: for (i = 0; i < new_entries; ++i)
- __split_multi_inmem_fail(session, ref_new[i]);
+ __split_multi_inmem_fail(session, page, ref_new[i]);
}
__wt_free(session, ref_new);
@@ -2072,6 +2072,6 @@ __wt_split_rewrite(WT_SESSION_IMPL *session, WT_REF *ref)
return (0);
-err: __split_multi_inmem_fail(session, &new);
+err: __split_multi_inmem_fail(session, page, &new);
return (ret);
}
diff --git a/src/include/extern.h b/src/include/extern.h
index 3cbbb7b0072..af8a7aa70e9 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -122,7 +122,7 @@ extern bool __wt_delete_page_skip(WT_SESSION_IMPL *session, WT_REF *ref, bool vi
extern int __wt_delete_page_instantiate(WT_SESSION_IMPL *session, WT_REF *ref);
extern void __wt_ref_out(WT_SESSION_IMPL *session, WT_REF *ref);
extern void __wt_page_out(WT_SESSION_IMPL *session, WT_PAGE **pagep);
-extern void __wt_free_ref( WT_SESSION_IMPL *session, WT_PAGE *page, WT_REF *ref, bool free_pages);
+extern void __wt_free_ref( WT_SESSION_IMPL *session, WT_REF *ref, int page_type, bool free_pages);
extern void __wt_free_ref_index(WT_SESSION_IMPL *session, WT_PAGE *page, WT_PAGE_INDEX *pindex, bool free_pages);
extern void __wt_free_update_list(WT_SESSION_IMPL *session, WT_UPDATE *upd);
extern int __wt_btree_open(WT_SESSION_IMPL *session, const char *op_cfg[]);