Re: 2.4.18(19) swapcache oops

Andrew Morton (akpm@zip.com.au)
Thu, 15 Aug 2002 13:05:41 -0700


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/