SwapCache bug?

Mark Hemment (markhe@sco.COM)
Sun, 4 Apr 1999 17:02:17 +0100 (BST)


Hi Stephen/All,

I've been looking through Linux's memory management code for the first
time in 12mths, seeing what has changed. A line in swapfile.c, in the
func shrink_mmap(), looks suspicious. Not wrong, just not doing what is
expected of it;

if (PageSwapCache(page)) {
if (referenced && swap_count(page->offset) != 1)
continue;
delete_from_swap_cache(page);
return 1;
}

Taking "page" to refer to a shared anonymous page, which has two
mappings (say a stack page after a fork()). When swap_out() finds the
first loaded mapping for the page, it allocates a swap-page, adds the page
to the swap-cache (the swapper inode hash-chain), writes the page out,
and unloads the mapping.

After this, the page has a ref count of 2 (one for the remaining
mapping, and one for the swap-cache entry). The swap_map count is
2. Say, before swap_out() finds the second mapping, shrink_mmap() finds
the page. Assuming the page hasn't been recently referenced, the page
will be deleted from the swap-cache.

Is this what is intended? Shouldn't the page be left in the swap-cache
until the second (ie. all) mapping is found via swap_out()? Releasing
the page while there are more mappings around doesn't free memory, and
can cause more swap space to be consumed (writing multiple copies of the
same page - which I assumed the change in the page-cache was suppose to
prevent).

Should the second if() statement be changed to;

...
if (page->count != 1)
continue;
delete_from_swap_cache(page);
...

Am I missing something?

Also in do_wp_page(), what happens to a swap-cached page whose reference
count is greater than 2? There looks like a missing default case which
does a swap_free().

Finally, shouldn't swap_free() only update p->lowest_bit and
p->highest_bit when p->swap_map[offset] == 0?

Regards,
Mark

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/