From: Tom Yu Date: Tue, 19 Feb 2008 18:29:15 +0000 (+0000) Subject: pull up r20222 from trunk X-Git-Tag: krb5-1.6.4-beta1~8 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=ef551a94b6379b4de528ea7fc1ba4da25df4b9ee;p=krb5.git pull up r20222 from trunk r20222@cathode-dark-space: tlyu | 2008-02-07 02:07:06 -0500 ticket: new target_version: 1.6.4 tags: pullup subject: more tests for libdb btree page split on zero index component: krb5-kdc Enhance btree debugging output somewhat to limit key printout to the key length if the key is not null-terminated. Add additional test case for the zero-index page split bug; test case can create a corrupted btree database with records unreachable by random access but reachable by sequential access. Requires recompiling with CPPFLAGS='-DDEBUG -DDEBUG_IDX0SPLIT' to correctly model mpool page reuse that would be present in production conditions. (CPPFLAGS=-DDEBUG would otherwise explicitly overwrite the contents of reused pages.) ticket: 5888 version_fixed: 1.6.4 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@20233 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_debug.c b/src/plugins/kdb/db2/libdb2/btree/bt_debug.c index d36256b3a..b302ca60d 100644 --- a/src/plugins/kdb/db2/libdb2/btree/bt_debug.c +++ b/src/plugins/kdb/db2/libdb2/btree/bt_debug.c @@ -257,7 +257,8 @@ __bt_dpage(dbp, h) *(db_pgno_t *)bl->bytes, *(u_int32_t *)(bl->bytes + sizeof(db_pgno_t))); else if (bl->ksize) - (void)fprintf(tracefp, "%s/", bl->bytes); + (void)fprintf(tracefp, "%.*s/", + (int)bl->ksize, bl->bytes); if (bl->flags & P_BIGDATA) (void)fprintf(tracefp, "big data page %lu size %u", diff --git a/src/plugins/kdb/db2/libdb2/mpool/mpool.c b/src/plugins/kdb/db2/libdb2/mpool/mpool.c index 56f2749a9..3b0be3f55 100644 --- a/src/plugins/kdb/db2/libdb2/mpool/mpool.c +++ b/src/plugins/kdb/db2/libdb2/mpool/mpool.c @@ -377,7 +377,7 @@ mpool_bkt(mp) head = &mp->hqh[HASHKEY(bp->pgno)]; CIRCLEQ_REMOVE(head, bp, hq); CIRCLEQ_REMOVE(&mp->lqh, bp, q); -#ifdef DEBUG +#if defined(DEBUG) && !defined(DEBUG_IDX0SPLIT) { void *spage; spage = bp->page; memset(bp, 0xff, sizeof(BKT) + mp->pagesize); diff --git a/src/plugins/kdb/db2/libdb2/test/run.test b/src/plugins/kdb/db2/libdb2/test/run.test index 377d6f794..d029862d1 100644 --- a/src/plugins/kdb/db2/libdb2/test/run.test +++ b/src/plugins/kdb/db2/libdb2/test/run.test @@ -34,7 +34,7 @@ main() bindir=/bin/. if [ $# -eq 0 ]; then - for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20 40; do + for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20 40 41; do test$t done else @@ -45,7 +45,7 @@ main() [0-9]*) test$1;; btree) - for t in 1 2 3 7 8 9 10 12 13 40; do + for t in 1 2 3 7 8 9 10 12 13 40 41; do test$t done;; hash) @@ -793,4 +793,112 @@ keylen+datalen=$kdsize failed" $e } +# Extremely tricky test attempting to replicate some unusual database +# corruption seen in the field: pieces of the database becoming +# inaccessible to random access, sequential access, or both. The +# hypothesis is that at least some of these are triggered by the bug +# in page splits on index 0 with a particular exact keylen+datalen. +# (See Test 40.) For psize=4096, this size is exactly 2024. + +# The order of operations here relies on very specific knowledge of +# the internals of the btree access method in order to place records +# at specific offsets in a page and to create certain keys on internal +# pages. The to-be-split page immediately prior to the bug-triggering +# split has the following properties: +# +# * is not the leftmost leaf page +# * key on the parent page is compares less than the key of the item +# on index 0 +# * triggering record's key also compares greater than the key on the +# parent page + +# Additionally, we prime the mpool LRU chain so that the head page on +# the chain has the following properties: +# +# * record at index 0 is located where it will not get overwritten by +# items written to the right-hand page during the split +# * key of the record at index 0 compares less than the key of the +# bug-triggering record + +# If the page-split bug exists, this test appears to create a database +# where some records are inaccessible to a search, but still remain in +# the file and are accessible by sequential traversal. At least one +# record gets duplicated out of sequence. + +test41 () { + echo "Test 41: btree: no unsearchables due to page split on index 0" + # list of individual retrievals in a variable for easy reuse + list=`(for i in a b c d; do + for j in 990 998 999; do + echo g ${i}${j} 1024 + done + done; + echo g y997 2014 + for i in y z; do + for j in 998 999; do + echo g ${i}${j} 1024 + done + done)` + # Exact number for trigger condition accounts for newlines + # retained by dbtest with -ofile but not without; we use + # -ofile, so count newlines. keylen=5,datalen=5+2014 for + # psize=4096 here. + (cat - < $TMP2 + (echo "$list"; echo "$list") | awk '{ + s = $2; + for (i = 0; i < $3; i++) { + s = s "x"; + } + print s; + }' > $TMP1 + $PROG -o $TMP3 -i psize=4096 btree $TMP2 + if (cmp -s $TMP1 $TMP3); then : + else + echo "test41: btree: failed" + exit 1 + fi +} + main $*