Messages in this thread Patch in this message | | | Date | Thu, 15 Aug 2002 13:05:41 -0700 | From | Andrew Morton <> | Subject | Re: 2.4.18(19) swapcache oops |
| |
Hugh Dickins wrote: > > On Thu, 15 Aug 2002 j-nomura@ce.jp.nec.com wrote: > > > > I'm using 2.4.18 kernel and suspect there are swapcache race. > > I looked into 2.4.19 patch but could not find the fix to it. > > I see a benign race but no oops. >
But look at lru_cache_add():
void lru_cache_add(struct page * page) { if (!TestSetPageLRU(page)) { /* window here */ spin_lock(&pagemap_lru_lock); add_page_to_inactive_list(page); spin_unlock(&pagemap_lru_lock); } }
It sets PG_lru before adding the page to the LRU.
static inline void activate_page_nolock(struct page * page) { if (PageLRU(page) && !PageActive(page)) { del_page_from_inactive_list(page); add_page_to_active_list(page); } }
void activate_page(struct page * page) { spin_lock(&pagemap_lru_lock); activate_page_nolock(page); spin_unlock(&pagemap_lru_lock); }
So if activate_page gets the lock inside that window, it will delete a page from the LRU which isn't on it (memory corruption). Then activate_page will set PG_active and will drop the lock.
lru_cache_add gets the lock, runs add_page_to_inactive_list which BUGs over PG_active.
--- 2.4.19/mm/swap.c~lru-race Thu Aug 15 13:03:48 2002 +++ 2.4.19-akpm/mm/swap.c Thu Aug 15 13:04:19 2002 @@ -57,9 +57,10 @@ void activate_page(struct page * page) */ void lru_cache_add(struct page * page) { - if (!TestSetPageLRU(page)) { + if (!PageLRU(page)) { spin_lock(&pagemap_lru_lock); - add_page_to_inactive_list(page); + if (!TestSetPageLRU(page)) + add_page_to_inactive_list(page); spin_unlock(&pagemap_lru_lock); } } . - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |