diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2015-05-09 20:08:36 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2015-05-09 20:08:36 +0000 |
commit | 44ec2b63c50ae6d0b2765d5cbdbffb0beb276ad4 (patch) | |
tree | 076f93ba33455e8fa9706dc599764746cfac5937 /sys/vm | |
parent | 4bc8ff08029571c916ed5e025717b05dcf9c82f4 (diff) | |
download | src-44ec2b63c50ae6d0b2765d5cbdbffb0beb276ad4.tar.gz src-44ec2b63c50ae6d0b2765d5cbdbffb0beb276ad4.zip |
The vmem callback to reclaim kmem arena address space on low or
fragmented conditions currently just wakes up the pagedaemon. The
kmem arena is significantly smaller then the total available physical
memory, which means that there are loads where kmem arena space could
be exhausted, while there is a lot of pages available still. The
woken up pagedaemon sees vm_pages_needed != 0, verifies the condition
vm_paging_needed() which is false, clears the pass and returns back to
sleep, not calling neither uma_reclaim() nor lowmem handler.
To handle low kmem arena conditions, create additional pagedaemon
thread which calls uma_reclaim() directly. The thread sleeps on the
dedicated channel and kmem_reclaim() wakes the thread in addition to
the pagedaemon.
Reported and tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Notes
Notes:
svn path=/head/; revision=282690
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/uma.h | 3 | ||||
-rw-r--r-- | sys/vm/uma_core.c | 42 | ||||
-rw-r--r-- | sys/vm/vm_pageout.c | 7 |
3 files changed, 47 insertions, 5 deletions
diff --git a/sys/vm/uma.h b/sys/vm/uma.h index df6cc5c7a118..d3e0658aef15 100644 --- a/sys/vm/uma.h +++ b/sys/vm/uma.h @@ -690,4 +690,7 @@ struct uma_percpu_stat { uint64_t _ups_reserved[5]; /* Reserved. */ }; +void uma_reclaim_wakeup(void); +void uma_reclaim_worker(void *); + #endif /* _VM_UMA_H_ */ diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 4ff177f8129f..d1573e68beb6 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -3222,16 +3222,17 @@ uma_find_refcnt(uma_zone_t zone, void *item) } /* See uma.h */ -void -uma_reclaim(void) +static void +uma_reclaim_locked(bool kmem_danger) { + #ifdef UMA_DEBUG printf("UMA: vm asked us to release pages!\n"); #endif - sx_xlock(&uma_drain_lock); + sx_assert(&uma_drain_lock, SA_XLOCKED); bucket_enable(); zone_foreach(zone_drain); - if (vm_page_count_min()) { + if (vm_page_count_min() || kmem_danger) { cache_drain_safe(NULL); zone_foreach(zone_drain); } @@ -3243,9 +3244,42 @@ uma_reclaim(void) zone_drain(slabzone); zone_drain(slabrefzone); bucket_zone_drain(); +} + +void +uma_reclaim(void) +{ + + sx_xlock(&uma_drain_lock); + uma_reclaim_locked(false); sx_xunlock(&uma_drain_lock); } +static int uma_reclaim_needed; + +void +uma_reclaim_wakeup(void) +{ + + uma_reclaim_needed = 1; + wakeup(&uma_reclaim_needed); +} + +void +uma_reclaim_worker(void *arg __unused) +{ + + sx_xlock(&uma_drain_lock); + for (;;) { + sx_sleep(&uma_reclaim_needed, &uma_drain_lock, PVM, + "umarcl", 0); + if (uma_reclaim_needed) { + uma_reclaim_needed = 0; + uma_reclaim_locked(true); + } + } +} + /* See uma.h */ int uma_zone_exhausted(uma_zone_t zone) diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 872ffd8f6a07..2f57579da353 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -1724,8 +1724,9 @@ vm_pageout_init(void) static void vm_pageout(void) { + int error; #if MAXMEMDOM > 1 - int error, i; + int i; #endif swap_pager_swap_init(); @@ -1739,6 +1740,10 @@ vm_pageout(void) } } #endif + error = kthread_add(uma_reclaim_worker, NULL, curproc, NULL, + 0, 0, "uma"); + if (error != 0) + panic("starting uma_reclaim helper, error %d\n", error); vm_pageout_worker((void *)(uintptr_t)0); } |