4034947 anon_swap_adjust() should call kmem_reap() if availrmem is low.
--- 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