diff options
author | Jeff Roberson <jeff@FreeBSD.org> | 2018-01-02 04:35:56 +0000 |
---|---|---|
committer | Jeff Roberson <jeff@FreeBSD.org> | 2018-01-02 04:35:56 +0000 |
commit | ad5b0f5b51eb2c0da2d2f835a54e6909320a03f4 (patch) | |
tree | 24dd492792c92e7b73ed9f0703b3afdd2899b849 | |
parent | 67530f82dd5e50b0666ded863e33d0aeda8cacee (diff) | |
download | src-ad5b0f5b51eb2c0da2d2f835a54e6909320a03f4.tar.gz src-ad5b0f5b51eb2c0da2d2f835a54e6909320a03f4.zip |
Fix arc after r326347 broke various memory limit queries. Use UMA features
rather than kmem arena size to determine available memory.
Initialize the UMA limit to LONG_MAX to avoid spurious wakeups on boot before
the real limit is set.
PR: 224330 (partial), 224080
Reviewed by: markj, avg
Sponsored by: Netflix / Dell EMC Isilon
Differential Revision: https://reviews.freebsd.org/D13494
Notes
Notes:
svn path=/head/; revision=327485
-rw-r--r-- | sys/cddl/compat/opensolaris/sys/kmem.h | 3 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c | 28 | ||||
-rw-r--r-- | sys/vm/uma.h | 8 | ||||
-rw-r--r-- | sys/vm/uma_core.c | 12 | ||||
-rw-r--r-- | sys/vm/uma_int.h | 4 |
5 files changed, 26 insertions, 29 deletions
diff --git a/sys/cddl/compat/opensolaris/sys/kmem.h b/sys/cddl/compat/opensolaris/sys/kmem.h index 75837d29e20a..7b5c4f9956b3 100644 --- a/sys/cddl/compat/opensolaris/sys/kmem.h +++ b/sys/cddl/compat/opensolaris/sys/kmem.h @@ -80,7 +80,8 @@ void *calloc(size_t n, size_t s); #define freemem vm_cnt.v_free_count #define minfree vm_cnt.v_free_min -#define heap_arena kmem_arena +#define heap_arena kernel_arena +#define zio_arena NULL #define kmem_alloc(size, kmflags) zfs_kmem_alloc((size), (kmflags)) #define kmem_zalloc(size, kmflags) zfs_kmem_alloc((size), (kmflags) | M_ZERO) #define kmem_free(buf, size) zfs_kmem_free((buf), (size)) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c index 0cff5a70a55e..facd1d227bc6 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -4207,7 +4207,6 @@ typedef enum free_memory_reason_t { FMR_PAGES_PP_MAXIMUM, FMR_HEAP_ARENA, FMR_ZIO_ARENA, - FMR_ZIO_FRAG, } free_memory_reason_t; int64_t last_free_memory; @@ -4302,15 +4301,11 @@ arc_available_memory(void) * heap is allocated. (Or, in the calculation, if less than 1/4th is * free) */ - n = (int64_t)vmem_size(heap_arena, VMEM_FREE) - - (vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC) >> 2); + n = uma_avail() - (long)(uma_limit() / 4); if (n < lowest) { lowest = n; r = FMR_HEAP_ARENA; } -#define zio_arena NULL -#else -#define zio_arena heap_arena #endif /* @@ -4331,20 +4326,6 @@ arc_available_memory(void) } } - /* - * Above limits know nothing about real level of KVA fragmentation. - * Start aggressive reclamation if too little sequential KVA left. - */ - if (lowest > 0) { - n = (vmem_size(heap_arena, VMEM_MAXFREE) < SPA_MAXBLOCKSIZE) ? - -((int64_t)vmem_size(heap_arena, VMEM_ALLOC) >> 4) : - INT64_MAX; - if (n < lowest) { - lowest = n; - r = FMR_ZIO_FRAG; - } - } - #else /* _KERNEL */ /* Every 100 calls, free a small amount */ if (spa_get_random(100) == 0) @@ -6110,8 +6091,7 @@ arc_memory_throttle(uint64_t reserve, uint64_t txg) static uint64_t last_txg = 0; #if defined(__i386) || !defined(UMA_MD_SMALL_ALLOC) - available_memory = - MIN(available_memory, ptob(vmem_size(heap_arena, VMEM_FREE))); + available_memory = MIN(available_memory, uma_avail()); #endif if (freemem > (uint64_t)physmem * arc_lotsfree_percent / 100) @@ -6492,9 +6472,13 @@ arc_init(void) * Metadata is stored in the kernel's heap. Don't let us * use more than half the heap for the ARC. */ +#ifdef __FreeBSD__ + arc_meta_limit = MIN(arc_meta_limit, uma_limit() / 2); +#else arc_meta_limit = MIN(arc_meta_limit, vmem_size(heap_arena, VMEM_ALLOC | VMEM_FREE) / 2); #endif +#endif /* Allow the tunable to override if it is reasonable */ if (zfs_arc_meta_limit > 0 && zfs_arc_meta_limit <= arc_c_max) diff --git a/sys/vm/uma.h b/sys/vm/uma.h index 1ea8ee06245b..1bd366416cbc 100644 --- a/sys/vm/uma.h +++ b/sys/vm/uma.h @@ -698,4 +698,12 @@ struct uma_percpu_stat { void uma_reclaim_wakeup(void); void uma_reclaim_worker(void *); +unsigned long uma_limit(void); + +/* Return the amount of memory managed by UMA. */ +unsigned long uma_size(void); + +/* Return the amount of memory remaining. May be negative. */ +long uma_avail(void); + #endif /* _VM_UMA_H_ */ diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 81c953a48383..0dd16dd9c325 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include <sys/eventhandler.h> #include <sys/kernel.h> #include <sys/types.h> +#include <sys/limits.h> #include <sys/queue.h> #include <sys/malloc.h> #include <sys/ktr.h> @@ -148,7 +149,7 @@ static struct mtx uma_boot_pages_mtx; static struct sx uma_drain_lock; /* kmem soft limit. */ -static unsigned long uma_kmem_limit; +static unsigned long uma_kmem_limit = LONG_MAX; static volatile unsigned long uma_kmem_total; /* Is the VM done starting up? */ @@ -3265,7 +3266,14 @@ unsigned long uma_size(void) { - return uma_kmem_total; + return (uma_kmem_total); +} + +long +uma_avail(void) +{ + + return (uma_kmem_limit - uma_kmem_total); } void diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h index 158c2383c885..a8aca454f066 100644 --- a/sys/vm/uma_int.h +++ b/sys/vm/uma_int.h @@ -428,10 +428,6 @@ void uma_small_free(void *mem, vm_size_t size, uint8_t flags); /* Set a global soft limit on UMA managed memory. */ void uma_set_limit(unsigned long limit); -unsigned long uma_limit(void); - -/* Return the amount of memory managed by UMA. */ -unsigned long uma_size(void); #endif /* _KERNEL */ #endif /* VM_UMA_INT_H */ |