summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2012-10-18 09:32:52 +0000
committerKeith Bostic <keith@wiredtiger.com>2012-10-19 08:58:51 +0000
commitbf1cd98682b3eb44e4a2794fe2a4bd8c264a4957 (patch)
treeb8ac55c926150649d26cb62db8933e6ae2f923ae
parentd4b67b853f78b10ea340f7e0c810abcb1fdc9dcc (diff)
downloadmongo-bf1cd98682b3eb44e4a2794fe2a4bd8c264a4957.tar.gz
Generalize the code to check for a block appearing on the available or
discard lists if the upper-level engine "owns" it, in other words, if the upper-level engine is freeing a block or reading a block, it better not appear on a list of block-manager "owned" blocks.
-rw-r--r--src/block/block_ext.c58
-rw-r--r--src/block/block_read.c27
-rw-r--r--src/include/extern.h8
3 files changed, 60 insertions, 33 deletions
diff --git a/src/block/block_ext.c b/src/block/block_ext.c
index 98915809d66..c2596823951 100644
--- a/src/block/block_ext.c
+++ b/src/block/block_ext.c
@@ -200,12 +200,12 @@ __block_off_insert(
#ifdef HAVE_DIAGNOSTIC
/*
- * __wt_block_off_match --
+ * __block_off_match --
* Return if any part of a specified range appears on a specified extent
* list.
*/
-int
-__wt_block_off_match(WT_EXTLIST *el, off_t off, off_t size)
+static int
+__block_off_match(WT_EXTLIST *el, off_t off, off_t size)
{
WT_EXT *before, *after;
@@ -219,6 +219,39 @@ __wt_block_off_match(WT_EXTLIST *el, off_t off, off_t size)
return (1);
return (0);
}
+
+/*
+ * __wt_block_misplaced --
+ * Complain if a block appears on the available or discard lists.
+ */
+int
+__wt_block_misplaced(WT_SESSION_IMPL *session,
+ WT_BLOCK *block, const char *tag, off_t offset, uint32_t size)
+{
+ const char *name;
+
+ name = NULL;
+
+ /*
+ * Verify a block the btree engine thinks it "owns" doesn't appear on
+ * the available or discard lists (it might reasonably be on the alloc
+ * list, if it was allocated since the last checkpoint). The engine
+ * "owns" a block if it's trying to read or free the block, and those
+ * functions make this check.
+ */
+ __wt_spin_lock(session, &block->live_lock);
+ if (__block_off_match(&block->live.avail, offset, size))
+ name = "available";
+ else if (__block_off_match(&block->live.discard, offset, size))
+ name = "discard";
+ __wt_spin_unlock(session, &block->live_lock);
+ if (name != NULL)
+ WT_RET_MSG(session, WT_ERROR,
+ "%s failed: %" PRIuMAX "/%" PRIu32 " is on the %s list",
+ tag, (uintmax_t)offset, size, name);
+
+ return (0);
+}
#endif
/*
@@ -458,20 +491,23 @@ __wt_block_free(WT_SESSION_IMPL *session,
WT_BLOCK *block, const uint8_t *addr, uint32_t addr_size)
{
WT_DECL_RET;
- off_t off;
+ off_t offset;
uint32_t cksum, size;
WT_UNUSED(addr_size);
WT_BSTAT_INCR(session, free);
/* Crack the cookie. */
- WT_RET(__wt_block_buffer_to_addr(block, addr, &off, &size, &cksum));
+ WT_RET(__wt_block_buffer_to_addr(block, addr, &offset, &size, &cksum));
WT_VERBOSE_RET(session, block,
- "free %" PRIdMAX "/%" PRIdMAX, (intmax_t)off, (intmax_t)size);
+ "free %" PRIdMAX "/%" PRIdMAX, (intmax_t)offset, (intmax_t)size);
+#ifdef HAVE_DIAGNOSTIC
+ WT_RET(__wt_block_misplaced(session, block, "free", offset, size));
+#endif
__wt_spin_lock(session, &block->live_lock);
- ret = __wt_block_off_free(session, block, off, (off_t)size);
+ ret = __wt_block_off_free(session, block, offset, (off_t)size);
__wt_spin_unlock(session, &block->live_lock);
return (ret);
@@ -483,7 +519,7 @@ __wt_block_free(WT_SESSION_IMPL *session,
*/
int
__wt_block_off_free(
- WT_SESSION_IMPL *session, WT_BLOCK *block, off_t off, off_t size)
+ WT_SESSION_IMPL *session, WT_BLOCK *block, off_t offset, off_t size)
{
WT_DECL_RET;
@@ -498,12 +534,12 @@ __wt_block_off_free(
* list.
*/
if ((ret = __wt_block_off_remove_overlap(
- session, &block->live.alloc, off, size)) == 0)
+ session, &block->live.alloc, offset, size)) == 0)
ret = __block_merge(
- session, &block->live.avail, off, (off_t)size);
+ session, &block->live.avail, offset, (off_t)size);
else if (ret == WT_NOTFOUND)
ret = __block_merge(
- session, &block->live.discard, off, (off_t)size);
+ session, &block->live.discard, offset, (off_t)size);
return (ret);
}
diff --git a/src/block/block_read.c b/src/block/block_read.c
index 56df2663fa8..b88d7f5424b 100644
--- a/src/block/block_read.c
+++ b/src/block/block_read.c
@@ -54,27 +54,14 @@ __wt_block_read_off(WT_SESSION_IMPL *session, WT_BLOCK *block,
#ifdef HAVE_DIAGNOSTIC
/*
* In diagnostic mode, verify the block we're about to read isn't on
- * either the available or discard lists (it might be on some other
- * checkpoint's lists, but this check has proved valuable in finding
- * problems). We don't check during salvage, it's quite possible
- * we're trying to read an overflow page that was freed long ago.
+ * either the available or discard lists.
+ *
+ * Don't check during salvage, it's possible we're reading an already
+ * freed overflow page.
*/
- if (!F_ISSET(session, WT_SESSION_SALVAGE_QUIET_ERR)) {
- const char *name = NULL;
- __wt_spin_lock(session, &block->live_lock);
- if (__wt_block_off_match(&block->live.avail, offset, size))
- name = "available";
- else if (
- __wt_block_off_match(&block->live.discard, offset, size))
- name = "discard";
- __wt_spin_unlock(session, &block->live_lock);
- if (name != NULL) {
- WT_RET_MSG(session, WT_ERROR,
- "read failed: %" PRIuMAX "/%" PRIu32 " is on "
- "the %s list",
- (uintmax_t)offset, size, name);
- }
- }
+ if (!F_ISSET(session, WT_SESSION_SALVAGE_QUIET_ERR))
+ WT_RET(
+ __wt_block_misplaced(session, block, "read", offset, size));
#endif
/*
diff --git a/src/include/extern.h b/src/include/extern.h
index 802d5360104..ded49ce3632 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -57,7 +57,11 @@ extern int __wt_block_compact_page_skip(WT_SESSION_IMPL *session,
const uint8_t *addr,
uint32_t addr_size,
int *skipp);
-extern int __wt_block_off_match(WT_EXTLIST *el, off_t off, off_t size);
+extern int __wt_block_misplaced(WT_SESSION_IMPL *session,
+ WT_BLOCK *block,
+ const char *tag,
+ off_t offset,
+ uint32_t size);
extern int __wt_block_off_remove_overlap( WT_SESSION_IMPL *session,
WT_EXTLIST *el,
off_t off,
@@ -76,7 +80,7 @@ extern int __wt_block_free(WT_SESSION_IMPL *session,
uint32_t addr_size);
extern int __wt_block_off_free( WT_SESSION_IMPL *session,
WT_BLOCK *block,
- off_t off,
+ off_t offset,
off_t size);
extern int __wt_block_extlist_check( WT_SESSION_IMPL *session,
WT_EXTLIST *al,