Possible memory ordering bug in page reclaim?

From: Nick Piggin
Date: Fri Oct 14 2005 - 22:28:53 EST


Is there anything that prevents PageDirty from theoretically being
speculatively loaded before page_count here? (see patch)

It would result in pagecache corruption in the following situation:

1 2
find_get_page();
write to page write_lock(tree_lock);
SetPageDirty(); if (page_count != 2
put_page(); || PageDirty())

Now I'm worried that 2 might see PageDirty *before* SetPageDirty in
1, and page_count *after* put_page in 1.

Or am I seeing things that aren't there?

Thanks,

--
SUSE Labs, Novell Inc.

Index: linux-2.6/mm/vmscan.c
===================================================================
--- linux-2.6.orig/mm/vmscan.c
+++ linux-2.6/mm/vmscan.c
@@ -511,7 +511,12 @@ static int shrink_list(struct list_head
* PageDirty _after_ making sure that the page is freeable and
* not in use by anybody. (pagecache + us == 2)
*/
- if (page_count(page) != 2 || PageDirty(page)) {
+ if (page_count(page) != 2) {
+ write_unlock_irq(&mapping->tree_lock);
+ goto keep_locked;
+ }
+ smp_rmb();
+ if (PageDirty(page)) {
write_unlock_irq(&mapping->tree_lock);
goto keep_locked;
}