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
This commit is contained in:
parent
67530f82dd
commit
ad5b0f5b51
@ -80,7 +80,8 @@ void *calloc(size_t n, size_t s);
|
|||||||
|
|
||||||
#define freemem vm_cnt.v_free_count
|
#define freemem vm_cnt.v_free_count
|
||||||
#define minfree vm_cnt.v_free_min
|
#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_alloc(size, kmflags) zfs_kmem_alloc((size), (kmflags))
|
||||||
#define kmem_zalloc(size, kmflags) zfs_kmem_alloc((size), (kmflags) | M_ZERO)
|
#define kmem_zalloc(size, kmflags) zfs_kmem_alloc((size), (kmflags) | M_ZERO)
|
||||||
#define kmem_free(buf, size) zfs_kmem_free((buf), (size))
|
#define kmem_free(buf, size) zfs_kmem_free((buf), (size))
|
||||||
|
@ -4207,7 +4207,6 @@ typedef enum free_memory_reason_t {
|
|||||||
FMR_PAGES_PP_MAXIMUM,
|
FMR_PAGES_PP_MAXIMUM,
|
||||||
FMR_HEAP_ARENA,
|
FMR_HEAP_ARENA,
|
||||||
FMR_ZIO_ARENA,
|
FMR_ZIO_ARENA,
|
||||||
FMR_ZIO_FRAG,
|
|
||||||
} free_memory_reason_t;
|
} free_memory_reason_t;
|
||||||
|
|
||||||
int64_t last_free_memory;
|
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
|
* heap is allocated. (Or, in the calculation, if less than 1/4th is
|
||||||
* free)
|
* free)
|
||||||
*/
|
*/
|
||||||
n = (int64_t)vmem_size(heap_arena, VMEM_FREE) -
|
n = uma_avail() - (long)(uma_limit() / 4);
|
||||||
(vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC) >> 2);
|
|
||||||
if (n < lowest) {
|
if (n < lowest) {
|
||||||
lowest = n;
|
lowest = n;
|
||||||
r = FMR_HEAP_ARENA;
|
r = FMR_HEAP_ARENA;
|
||||||
}
|
}
|
||||||
#define zio_arena NULL
|
|
||||||
#else
|
|
||||||
#define zio_arena heap_arena
|
|
||||||
#endif
|
#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 */
|
#else /* _KERNEL */
|
||||||
/* Every 100 calls, free a small amount */
|
/* Every 100 calls, free a small amount */
|
||||||
if (spa_get_random(100) == 0)
|
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;
|
static uint64_t last_txg = 0;
|
||||||
|
|
||||||
#if defined(__i386) || !defined(UMA_MD_SMALL_ALLOC)
|
#if defined(__i386) || !defined(UMA_MD_SMALL_ALLOC)
|
||||||
available_memory =
|
available_memory = MIN(available_memory, uma_avail());
|
||||||
MIN(available_memory, ptob(vmem_size(heap_arena, VMEM_FREE)));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (freemem > (uint64_t)physmem * arc_lotsfree_percent / 100)
|
if (freemem > (uint64_t)physmem * arc_lotsfree_percent / 100)
|
||||||
@ -6492,8 +6472,12 @@ arc_init(void)
|
|||||||
* Metadata is stored in the kernel's heap. Don't let us
|
* Metadata is stored in the kernel's heap. Don't let us
|
||||||
* use more than half the heap for the ARC.
|
* 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,
|
arc_meta_limit = MIN(arc_meta_limit,
|
||||||
vmem_size(heap_arena, VMEM_ALLOC | VMEM_FREE) / 2);
|
vmem_size(heap_arena, VMEM_ALLOC | VMEM_FREE) / 2);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Allow the tunable to override if it is reasonable */
|
/* Allow the tunable to override if it is reasonable */
|
||||||
|
@ -698,4 +698,12 @@ struct uma_percpu_stat {
|
|||||||
void uma_reclaim_wakeup(void);
|
void uma_reclaim_wakeup(void);
|
||||||
void uma_reclaim_worker(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_ */
|
#endif /* _VM_UMA_H_ */
|
||||||
|
@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/eventhandler.h>
|
#include <sys/eventhandler.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/limits.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
#include <sys/ktr.h>
|
#include <sys/ktr.h>
|
||||||
@ -148,7 +149,7 @@ static struct mtx uma_boot_pages_mtx;
|
|||||||
static struct sx uma_drain_lock;
|
static struct sx uma_drain_lock;
|
||||||
|
|
||||||
/* kmem soft limit. */
|
/* kmem soft limit. */
|
||||||
static unsigned long uma_kmem_limit;
|
static unsigned long uma_kmem_limit = LONG_MAX;
|
||||||
static volatile unsigned long uma_kmem_total;
|
static volatile unsigned long uma_kmem_total;
|
||||||
|
|
||||||
/* Is the VM done starting up? */
|
/* Is the VM done starting up? */
|
||||||
@ -3265,7 +3266,14 @@ unsigned long
|
|||||||
uma_size(void)
|
uma_size(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
return uma_kmem_total;
|
return (uma_kmem_total);
|
||||||
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
uma_avail(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (uma_kmem_limit - uma_kmem_total);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -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. */
|
/* Set a global soft limit on UMA managed memory. */
|
||||||
void uma_set_limit(unsigned long limit);
|
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 /* _KERNEL */
|
||||||
|
|
||||||
#endif /* VM_UMA_INT_H */
|
#endif /* VM_UMA_INT_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user