diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-23 18:16:12 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-23 18:16:12 +0000 |
commit | 447fa25ee582852c0ccd4a57184251aeabfd91df (patch) | |
tree | f6246d980fac30e46acedf2059fb57edf2dd85a3 /net/disk_cache | |
parent | 7288d88d422c26a3185f52324c05d9d34d6807c6 (diff) | |
download | chromium_src-447fa25ee582852c0ccd4a57184251aeabfd91df.zip chromium_src-447fa25ee582852c0ccd4a57184251aeabfd91df.tar.gz chromium_src-447fa25ee582852c0ccd4a57184251aeabfd91df.tar.bz2 |
Disk cache: More histograms to track critical corruption.
BUG=none
TEST=none
Review URL: https://chromiumcodereview.appspot.com/10823302
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@153030 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/disk_cache')
-rw-r--r-- | net/disk_cache/rankings.cc | 107 | ||||
-rw-r--r-- | net/disk_cache/rankings.h | 3 |
2 files changed, 110 insertions, 0 deletions
diff --git a/net/disk_cache/rankings.cc b/net/disk_cache/rankings.cc index 109a32a..974931f 100644 --- a/net/disk_cache/rankings.cc +++ b/net/disk_cache/rankings.cc @@ -803,6 +803,8 @@ int Rankings::CheckList(List list) { if (rv == ERR_NO_ERROR) return head_items; + DetailedCheck(list); + Addr last3, last4; int tail_items; int rv2 = CheckListSection(list, last1, last2, false, // Tail to head. @@ -912,6 +914,111 @@ int Rankings::CheckListSection(List list, Addr end1, Addr end2, bool forward, } // TODO(rvargas): remove when we figure why we have corrupt heads. +// This is basically the same code as CheckListSection except that it starts +// at a random node and it iterates until it finds something looking like the +// last node. +int Rankings::CheckListSegment(Addr start, + bool forward, + Addr* last, + int* num_items) { + Addr current = start; + *last = current; + *num_items = 0; + if (!current.is_initialized()) + return ERR_NO_ERROR; + + if (!current.SanityCheckForRankings()) + return ERR_INVALID_HEAD; + + scoped_ptr<CacheRankingsBlock> node; + Addr prev_addr; + const int kMaxItemsToCheck = 100000; + do { + node.reset(new CacheRankingsBlock(backend_->File(current), current)); + node->Load(); + // The head may point to the wrong node so don't use SanityCheck(). + if (ExplodedSanityCheck(node.get())) + return ERR_INVALID_ENTRY; + + CacheAddr next = forward ? node->Data()->next : node->Data()->prev; + CacheAddr prev = forward ? node->Data()->prev : node->Data()->next; + + if (prev_addr.is_initialized() && prev != prev_addr.value()) + return ERR_INVALID_PREV; + + Addr next_addr(next); + if (!next_addr.SanityCheckForRankings()) + return ERR_INVALID_NEXT; + + prev_addr = current; + current = next_addr; + *last = current; + (*num_items)++; + + if (next_addr == prev_addr) + return ERR_NO_ERROR; + } while (*num_items < kMaxItemsToCheck); + return ERR_NO_ERROR; +} + +// TODO(rvargas): remove when we figure why we have corrupt heads. +void Rankings::DetailedCheck(List list) { + int rv = CheckHeadAndTail(list); + Addr last; + int num_items = 0; + int error = ERR_NO_ERROR; + if (rv == ERR_INVALID_PREV) { + error = CheckListSegment(heads_[list], false, &last, &num_items); + } else if (rv == ERR_INVALID_NEXT) { + error = CheckListSegment(tails_[list], true, &last, &num_items); + } else if (rv == ERR_INVALID_ENTRY) { + scoped_ptr<CacheRankingsBlock> head; + head.reset(new CacheRankingsBlock(backend_->File(heads_[list]), + heads_[list])); + head->Load(); + int result = ExplodedSanityCheck(head.get()); + if (!result) { + scoped_ptr<CacheRankingsBlock> tail; + tail.reset(new CacheRankingsBlock(backend_->File(tails_[list]), + tails_[list])); + tail->Load(); + result = ExplodedSanityCheck(tail.get()); + } + CACHE_UMA(CACHE_ERROR, "DetailedListCheckSanity", 0, result); + return; + } + CACHE_UMA(CACHE_ERROR, "DetailedListCheck", 0, -error); + CACHE_UMA(COUNTS, "DetailedListCheckCount", 0, num_items); +} + +// TODO(rvargas): remove when we figure why we have corrupt heads. +// This is basically SanityCheck(). +int Rankings::ExplodedSanityCheck(CacheRankingsBlock* node) { + int error = 0; + const int kBlockHashFailed = 1; + if (!node->VerifyHash()) + error = kBlockHashFailed; + + const RankingsNode* data = node->Data(); + const int kHasOnlyOneOfNextAndPrev = 2; + if ((!data->next && data->prev) || (data->next && !data->prev)) + error += kHasOnlyOneOfNextAndPrev; + + const int kHasNeitherNextNorPrev = 4; + if (!data->next && !data->prev) + error += kHasNeitherNextNorPrev; + + Addr next_addr(data->next); + Addr prev_addr(data->prev); + const int kFailsSanityCheck = 8; + if (!next_addr.SanityCheck() || next_addr.file_type() != RANKINGS || + !prev_addr.SanityCheck() || prev_addr.file_type() != RANKINGS) + error += kFailsSanityCheck; + + return error; +} + +// TODO(rvargas): remove when we figure why we have corrupt heads. void Rankings::QuickListCheck() { for (int i = 0; i < LAST_ELEMENT; i++) { int rv = CheckHeadAndTail(static_cast<List>(i)); diff --git a/net/disk_cache/rankings.h b/net/disk_cache/rankings.h index 94ab1fb..3f0fe51 100644 --- a/net/disk_cache/rankings.h +++ b/net/disk_cache/rankings.h @@ -179,6 +179,9 @@ class Rankings { // and the addresses of the last nodes visited. int CheckListSection(List list, Addr end1, Addr end2, bool forward, Addr* last, Addr* second_last, int* num_items); + int CheckListSegment(Addr start, bool forward, Addr* last, int* num_items); + void DetailedCheck(List list); + static int ExplodedSanityCheck(CacheRankingsBlock* node); void QuickListCheck(); // Returns an error code as appropriate. |