Pages are remaining in swap cache after process exits.

Larry Woodman (woodman@missioncriticallinux.com)
Thu, 02 Dec 1999 11:39:00 -0500


This is a multi-part message in MIME format.
--------------FF8483A4ECC318C0A83D0D23
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

We are seeing a problem where large virtual memory allocations fail
after the system
has been up for a while and has been under heavy loads. What is
happening is one
process malloc()s a large buffer, modifies that buffer then sleeps.
Then other processes
run and overcommit memory so the sleeping process gets swapped out.
Later the sleeping
process wakes up and reads from the buffer, causing lots of swapins and
since the pages
are read they stay in the swap cache. When this process exits many of
those pages
stay in the swap cache and the swap space remains allocated. At this
point other large
memory allocations can fail because vm_enough_memory() cant include the
swap space
that remains allocated due to the dead process's pages in the swap
cache. Does the system
rely on shrink_mmap() running before these pages are removed from the
swap cache???

I fixed this problem on my system by removing the private pages from the
swap cache
when a process exits with the following 2.3.29 patch, is there a better
way to do this???

Larry Woodman
www.missioncriticallinux.com

--------------FF8483A4ECC318C0A83D0D23
Content-Type: text/plain; charset=us-ascii;
name="patch-2.3.29.exit"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="patch-2.3.29.exit"

--- mm/swap_state.c.sav Wed Dec 1 18:20:23 1999
+++ mm/swap_state.c Thu Dec 2 11:39:36 1999
@@ -204,7 +204,7 @@
* If we are the only user, then free up the swap cache.
*/
lock_page(page);
- if (PageSwapCache(page) && !is_page_shared(page)) {
+ if (PageSwapCache(page) && can_remove_page(page)) {
delete_from_swap_cache_nolock(page);
page_cache_release(page);
}
--- include/linux/swap.h.sav Wed Dec 1 12:28:42 1999
+++ include/linux/swap.h Thu Dec 2 12:27:00 1999
@@ -152,6 +152,20 @@
return count > 1;
}

+static inline int can_remove_page(struct page *page)
+{
+ unsigned int count;
+ if (PageReserved(page))
+ return 0;
+ /* removable pages have page_count==2 or 3 and swap_count==1 */
+ count = page_count(page) + swap_count(page) - 2;
+
+ /* if shrink_mmap didnt free the buffers yet */
+ if (page->buffers) count--;
+
+ return count <= 1;
+}
+
extern spinlock_t pagemap_lru_lock;

/*

--------------FF8483A4ECC318C0A83D0D23--

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