aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Roberson <jeff@FreeBSD.org>2018-01-02 04:35:56 +0000
committerJeff Roberson <jeff@FreeBSD.org>2018-01-02 04:35:56 +0000
commitad5b0f5b51eb2c0da2d2f835a54e6909320a03f4 (patch)
tree24dd492792c92e7b73ed9f0703b3afdd2899b849
parent67530f82dd5e50b0666ded863e33d0aeda8cacee (diff)
downloadsrc-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.h3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c28
-rw-r--r--sys/vm/uma.h8
-rw-r--r--sys/vm/uma_core.c12
-rw-r--r--sys/vm/uma_int.h4
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 */