diff options
author | Keith Bostic <keith@wiredtiger.com> | 2012-10-18 09:32:52 +0000 |
---|---|---|
committer | Keith Bostic <keith@wiredtiger.com> | 2012-10-19 08:58:51 +0000 |
commit | bf1cd98682b3eb44e4a2794fe2a4bd8c264a4957 (patch) | |
tree | b8ac55c926150649d26cb62db8933e6ae2f923ae | |
parent | d4b67b853f78b10ea340f7e0c810abcb1fdc9dcc (diff) | |
download | mongo-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.c | 58 | ||||
-rw-r--r-- | src/block/block_read.c | 27 | ||||
-rw-r--r-- | src/include/extern.h | 8 |
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, |