Index: cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c =================================================================== --- cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -4290,6 +4290,7 @@ } #endif /* illumos */ +#ifdef __FreeBSD__ #if defined(__i386) || !defined(UMA_MD_SMALL_ALLOC) /* * If we're on an i386 platform, it's possible that we'll exhaust the @@ -4302,16 +4303,14 @@ * 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; } +#endif #define zio_arena NULL -#else -#define zio_arena heap_arena -#endif +#endif /* __FreeBSD__ */ /* * If zio data pages are being allocated out of a separate heap segment, @@ -4335,6 +4334,8 @@ * Above limits know nothing about real level of KVA fragmentation. * Start aggressive reclamation if too little sequential KVA left. */ +#ifndef __FreeBSD__ + /* FreeBSD will reclaim via a uma or vmem lowmem callback. */ if (lowest > 0) { n = (vmem_size(heap_arena, VMEM_MAXFREE) < SPA_MAXBLOCKSIZE) ? -((int64_t)vmem_size(heap_arena, VMEM_ALLOC) >> 4) : @@ -4344,6 +4345,7 @@ r = FMR_ZIO_FRAG; } } +#endif #else /* _KERNEL */ /* Every 100 calls, free a small amount */ @@ -6110,8 +6112,7 @@ 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 +6493,13 @@ * 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) Index: vm/uma.h =================================================================== --- vm/uma.h +++ vm/uma.h @@ -698,4 +698,12 @@ 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_ */ Index: vm/uma_core.c =================================================================== --- vm/uma_core.c +++ vm/uma_core.c @@ -3265,9 +3265,16 @@ uma_size(void) { - return uma_kmem_total; + return (uma_kmem_total); } +long +uma_avail(void) +{ + + return (uma_kmem_limit - uma_kmem_total); +} + void uma_print_stats(void) { Index: vm/uma_int.h =================================================================== --- vm/uma_int.h +++ vm/uma_int.h @@ -428,10 +428,6 @@ /* 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 */