Commit 9bdedfce authored by Andrew Morton's avatar Andrew Morton Committed by Oleg Drokin

[PATCH] Fix a race between __page_cache_release() and shrink_cache()

__page_cache_release() needs to recheck the page count inside the LRU
lock, because shrink_cache() may have found the page on the LRU and
incremented its refcount again.

Which is carefully documented over __pagevec_release().  Duh.
parent ac31cf70
...@@ -81,15 +81,18 @@ void __page_cache_release(struct page *page) ...@@ -81,15 +81,18 @@ void __page_cache_release(struct page *page)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&_pagemap_lru_lock, flags); spin_lock_irqsave(&_pagemap_lru_lock, flags);
if (!TestClearPageLRU(page)) if (TestClearPageLRU(page)) {
BUG(); if (PageActive(page))
if (PageActive(page)) del_page_from_active_list(page);
del_page_from_active_list(page); else
else del_page_from_inactive_list(page);
del_page_from_inactive_list(page); }
if (page_count(page) != 0)
page = NULL;
spin_unlock_irqrestore(&_pagemap_lru_lock, flags); spin_unlock_irqrestore(&_pagemap_lru_lock, flags);
} }
__free_pages_ok(page, 0); if (page)
__free_pages_ok(page, 0);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment