Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(811)

Unified Diff: net/disk_cache/backend_impl.cc

Issue 155951: Disk cache: Fix handling of invalid entries that are detected... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/disk_cache/backend_impl.h ('k') | net/disk_cache/backend_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/disk_cache/backend_impl.cc
===================================================================
--- net/disk_cache/backend_impl.cc (revision 21084)
+++ net/disk_cache/backend_impl.cc (working copy)
@@ -147,6 +147,12 @@
}
if (*current_group <= 5) {
+#if defined(UNIT_TEST)
+ // The unit test controls directly what to test.
+ *current_group = 0;
+ return true;
+#endif
+
// Re-load the two groups.
int option = base::RandInt(0, 9);
@@ -1177,7 +1183,7 @@
if (!error) {
// It is important to call DestroyInvalidEntry after removing this
// entry from the table.
- DestroyInvalidEntry(address, cache_entry);
+ DestroyInvalidEntry(cache_entry);
cache_entry = NULL;
} else {
Trace("NewEntry failed on MatchEntry 0x%x", address.value());
@@ -1252,7 +1258,7 @@
OpenFollowingEntryFromList(forward, iterator->list,
&iterator->nodes[i], &temp);
} else {
- temp = GetEnumeratedEntry(iterator->nodes[i]);
+ temp = GetEnumeratedEntry(iterator->nodes[i], false);
}
entries[i].swap(&temp); // The entry was already addref'd.
@@ -1308,7 +1314,7 @@
Rankings::ScopedRankingsBlock next(&rankings_, next_block);
*from_entry = NULL;
- *next_entry = GetEnumeratedEntry(next.get());
+ *next_entry = GetEnumeratedEntry(next.get(), false);
if (!*next_entry)
return false;
@@ -1316,41 +1322,29 @@
return true;
}
-EntryImpl* BackendImpl::GetEnumeratedEntry(CacheRankingsBlock* next) {
+EntryImpl* BackendImpl::GetEnumeratedEntry(CacheRankingsBlock* next,
+ bool to_evict) {
if (!next)
return NULL;
- scoped_refptr<EntryImpl> entry;
- EntryImpl* temp = NULL;
-
- if (next->Data()->pointer) {
- entry = reinterpret_cast<EntryImpl*>(next->Data()->pointer);
- entry.swap(&temp);
- return temp;
- }
-
+ EntryImpl* entry;
bool dirty;
- if (NewEntry(Addr(next->Data()->contents), &temp, &dirty))
+ if (NewEntry(Addr(next->Data()->contents), &entry, &dirty))
return NULL;
- entry.swap(&temp);
if (dirty) {
- // We cannot trust this entry. Call MatchEntry to go through the regular
- // path and take the appropriate action.
- std::string key = entry->GetKey();
- uint32 hash = entry->GetHash();
- entry = NULL; // Release the entry.
- temp = MatchEntry(key, hash, false);
- if (temp)
- temp->Release();
+ // We cannot trust this entry. This code also releases the reference.
+ DestroyInvalidEntryFromEnumeration(entry);
+ return NULL;
+ }
+ // There is no need to store the entry to disk if we want to delete it.
+ if (!to_evict && !entry->Update()) {
+ entry->Release();
return NULL;
}
- if (!entry->Update())
- return NULL;
- entry.swap(&temp);
- return temp;
+ return entry;
}
bool BackendImpl::ResurrectEntry(EntryImpl* deleted_entry, Entry** entry) {
@@ -1372,7 +1366,7 @@
return true;
}
-void BackendImpl::DestroyInvalidEntry(Addr address, EntryImpl* entry) {
+void BackendImpl::DestroyInvalidEntry(EntryImpl* entry) {
LOG(WARNING) << "Destroying invalid entry.";
Trace("Destroying invalid entry 0x%p", entry);
@@ -1386,6 +1380,42 @@
stats_.OnEvent(Stats::INVALID_ENTRY);
}
+// This is kind of ugly. The entry may or may not be part of the cache index
+// table, and it may even have corrupt fields. If we just doom it, we may end up
+// deleting it twice (if all fields are right, and when looking up the parent of
+// chained entries wee see this one... and we delete it because it is dirty). If
+// we ignore it, we may leave it here forever. So we're going to attempt to
+// delete it through the provided object, without touching the index table
+// (because we cannot jus call MatchEntry()), and also attempt to delete it from
+// the table through the key: this may find a new entry (too bad), or an entry
+// that was just deleted and consider it a very corrupt entry.
+void BackendImpl::DestroyInvalidEntryFromEnumeration(EntryImpl* entry) {
+ std::string key = entry->GetKey();
+ entry->SetPointerForInvalidEntry(GetCurrentEntryId());
+ CacheAddr next_entry = entry->entry()->Data()->next;
+ if (!next_entry) {
+ DestroyInvalidEntry(entry);
+ entry->Release();
+ }
+ DoomEntry(key);
+
+ if (!next_entry)
+ return;
+
+ // We have a chained entry so instead of destroying first this entry and then
+ // anything with this key, we just called DoomEntry() first. If that call
+ // deleted everything, |entry| has invalid data. Let's see if there is
+ // something else to do. We started with just a rankings node (we come from
+ // an enumeration), so that one may still be there.
+ CacheRankingsBlock* rankings = entry->rankings();
+ rankings->Load();
+ if (rankings->Data()->contents) {
+ // We still have something. Clean this up.
+ DestroyInvalidEntry(entry);
+ }
+ entry->Release();
+}
+
void BackendImpl::AddStorageSize(int32 bytes) {
data_->header.num_bytes += bytes;
DCHECK(data_->header.num_bytes >= 0);
« no previous file with comments | « net/disk_cache/backend_impl.h ('k') | net/disk_cache/backend_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698