4034947 anon_swap_adjust() should call kmem_reap() if availrmem is low.
authorstans
Wed, 24 May 2006 10:08:05 -0700
changeset 2048 8ceabdf91507
parent 2047 e21b6f0a829b
child 2049 b26d273ea4de
4034947 anon_swap_adjust() should call kmem_reap() if availrmem is low.
usr/src/uts/common/fs/zfs/arc.c
usr/src/uts/common/vm/page.h
usr/src/uts/common/vm/vm_anon.c
usr/src/uts/common/vm/vm_page.c
--- a/usr/src/uts/common/fs/zfs/arc.c	Wed May 24 09:39:06 2006 -0700
+++ b/usr/src/uts/common/fs/zfs/arc.c	Wed May 24 10:08:05 2006 -0700
@@ -1110,6 +1110,8 @@
 void
 arc_kmem_reclaim(void)
 {
+	uint64_t to_free;
+
 	/* Remove 12.5% */
 	/*
 	 * We need arc_reclaim_lock because we don't want multiple
@@ -1129,7 +1131,16 @@
 
 	mutex_enter(&arc_reclaim_lock);
 
-	atomic_add_64(&arc.c, -(arc.c >> 3));
+#ifdef _KERNEL
+	to_free = MAX(arc.c >> 3, ptob(needfree));
+#else
+	to_free = arc.c >> 3;
+#endif
+	if (arc.c > to_free)
+		atomic_add_64(&arc.c, -to_free);
+	else
+		arc.c = arc.c_min;
+
 	atomic_add_64(&arc.p, -(arc.p >> 3));
 	if (arc.c > arc.size)
 		arc.c = arc.size;
@@ -1150,6 +1161,10 @@
 	uint64_t extra;
 
 #ifdef _KERNEL
+
+	if (needfree)
+		return (1);
+
 	/*
 	 * take 'desfree' extra pages, so we reclaim sooner, rather than later
 	 */
--- a/usr/src/uts/common/vm/page.h	Wed May 24 09:39:06 2006 -0700
+++ b/usr/src/uts/common/vm/page.h	Wed May 24 10:08:05 2006 -0700
@@ -750,6 +750,7 @@
 void	page_settoxic(page_t *, uchar_t);
 
 int	page_mem_avail(pgcnt_t);
+int	page_reclaim_mem(pgcnt_t, pgcnt_t, int);
 
 void page_set_props(page_t *, uint_t);
 void page_clr_all_props(page_t *);
--- a/usr/src/uts/common/vm/vm_anon.c	Wed May 24 09:39:06 2006 -0700
+++ b/usr/src/uts/common/vm/vm_anon.c	Wed May 24 10:08:05 2006 -0700
@@ -792,6 +792,11 @@
 	 * swapfs_reserve is minimum of 4Mb or 1/16 of physmem.
 	 *
 	 */
+	mutex_exit(&anoninfo_lock);
+	(void) page_reclaim_mem(mswap_pages,
+	    swapfs_minfree + swapfs_reserve, 0);
+	mutex_enter(&anoninfo_lock);
+
 	mutex_enter(&freemem_lock);
 	if (availrmem > (swapfs_minfree + swapfs_reserve + mswap_pages) ||
 		(availrmem > (swapfs_minfree + mswap_pages) &&
@@ -3093,14 +3098,10 @@
 		 * if there is not enough unlocked mem swap we take missing
 		 * amount from phys swap and give it to mem swap
 		 */
-		mutex_enter(&freemem_lock);
-		if (availrmem < adjusted_swap + segspt_minfree) {
-			mutex_exit(&freemem_lock);
+		if (!page_reclaim_mem(adjusted_swap, segspt_minfree, 1)) {
 			mutex_exit(&anoninfo_lock);
 			return (ENOMEM);
 		}
-		availrmem -= adjusted_swap;
-		mutex_exit(&freemem_lock);
 
 		k_anoninfo.ani_mem_resv += adjusted_swap;
 		ASSERT(k_anoninfo.ani_phys_resv >= adjusted_swap);
--- a/usr/src/uts/common/vm/vm_page.c	Wed May 24 09:39:06 2006 -0700
+++ b/usr/src/uts/common/vm/vm_page.c	Wed May 24 10:08:05 2006 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -5789,6 +5788,50 @@
 	return (1);
 }
 
+#define	MAX_CNT	60	/* max num of iterations */
+/*
+ * Reclaim/reserve availrmem for npages.
+ * If there is not enough memory start reaping seg, kmem caches.
+ * Start pageout scanner (via page_needfree()).
+ * Exit after ~ MAX_CNT s regardless of how much memory has been released.
+ * Note: There is no guarantee that any availrmem will be freed as
+ * this memory typically is locked (kernel heap) or reserved for swap.
+ * Also due to memory fragmentation kmem allocator may not be able
+ * to free any memory (single user allocated buffer will prevent
+ * freeing slab or a page).
+ */
+int
+page_reclaim_mem(pgcnt_t npages, pgcnt_t epages, int adjust)
+{
+	int	i = 0;
+	int	ret = 0;
+	pgcnt_t	deficit;
+	pgcnt_t old_availrmem;
+
+	mutex_enter(&freemem_lock);
+	old_availrmem = availrmem - 1;
+	while ((availrmem < tune.t_minarmem + npages + epages) &&
+	    (old_availrmem < availrmem) && (i++ < MAX_CNT)) {
+		old_availrmem = availrmem;
+		deficit = tune.t_minarmem + npages + epages - availrmem;
+		mutex_exit(&freemem_lock);
+		page_needfree(deficit);
+		seg_preap();
+		kmem_reap();
+		delay(hz);
+		page_needfree(-(spgcnt_t)deficit);
+		mutex_enter(&freemem_lock);
+	}
+
+	if (adjust && (availrmem >= tune.t_minarmem + npages + epages)) {
+		availrmem -= npages;
+		ret = 1;
+	}
+
+	mutex_exit(&freemem_lock);
+
+	return (ret);
+}
 
 /*
  * Search the memory segments to locate the desired page.  Within a