summaryrefslogtreecommitdiffstats
path: root/net/disk_cache
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-23 18:16:12 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-23 18:16:12 +0000
commit447fa25ee582852c0ccd4a57184251aeabfd91df (patch)
treef6246d980fac30e46acedf2059fb57edf2dd85a3 /net/disk_cache
parent7288d88d422c26a3185f52324c05d9d34d6807c6 (diff)
downloadchromium_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.cc107
-rw-r--r--net/disk_cache/rankings.h3
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.