Re: pre12 VM doubts and patch

Andrea Arcangeli (andrea@suse.de)
Wed, 19 Sep 2001 23:28:18 +0200


On Wed, Sep 19, 2001 at 08:42:39PM +0100, Hugh Dickins wrote:
> --- 2.4.10-pre12/mm/swap_state.c Wed Sep 19 14:05:54 2001
> +++ linux/mm/swap_state.c Mon Sep 17 06:30:26 2001
> @@ -23,6 +23,17 @@
> */
> static int swap_writepage(struct page *page)
> {
> + /* One for the page cache, one for this user, one for page->buffers */
> + if (page_count(page) > 2 + !!page->buffers)

this is racy, you have to spin_lock(&pagecache_lock) before you can
expect the page_count() stays constant. then after you checked the page
has count == 1, you must atomically drop it from the pagecache so it's
not visible anymore to the swapin lookups.

Another way to fix the race is to change lookup_swap_cache to do
find_lock_page instead of find_get_page, and then check the page is
still a swapcachepage after you got it locked (that was the old way,
somebody changed it and introduced the race, I like lookup_swap_cache to
use find_get_page so I dropped such check to fix it, it was a minor
optimization but yes probably worthwhile to reintroduce after addressing
this race in one of the two ways described).

It is also buggy, if something it should be "page_count(page) != 1" (not
!= 2).

> + goto in_use;
> + if (swap_count(page) > 1)
> + goto in_use;
> +
> + delete_from_swap_cache_nolock(page);
> + UnlockPage(page);
> + return 0;
> +
> +in_use:
> rw_swap_page(WRITE, page);
> return 0;
> }

Andrea
-
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/