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/