Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -555,8 +555,9 @@ */ int zfs_arc_meta_prune = 10000; unsigned long zfs_arc_dnode_limit_percent = 10; -int zfs_arc_meta_strategy = ARC_STRATEGY_META_ONLY; +int zfs_arc_meta_strategy = ARC_STRATEGY_META_BALANCED; int zfs_arc_meta_adjust_restarts = 4096; +#define ARC_BALANCED_MIN 8*1024UL*1024UL*1024UL SYSCTL_INT(_vfs_zfs, OID_AUTO, arc_meta_strategy, CTLFLAG_RWTUN, &zfs_arc_meta_strategy, 0, @@ -4117,6 +4118,46 @@ return (evicted); } +#if defined(__FreeBSD__) && defined(_KERNEL) +extern struct vfsops zfs_vfsops; +/* + * Helper function for arc_prune_async() it is responsible for safely + * handling the execution of a registered arc_prune_func_t. + */ +static void +arc_prune_task(void *arg) +{ + int64_t nr_scan = *(int64_t*)arg; + + free(arg, M_TEMP); + vnlru_free(nr_scan, &zfs_vfsops); +} + +/* + * Notify registered consumers they must drop holds on a portion of the ARC + * buffered they reference. This provides a mechanism to ensure the ARC can + * honor the arc_meta_limit and reclaim otherwise pinned ARC buffers. This + * is analogous to dnlc_reduce_cache() but more generic. + * + * This operation is performed asynchronously so it may be safely called + * in the context of the arc_reclaim_thread(). A reference is taken here + * for each registered arc_prune_t and the arc_prune_task() is responsible + * for releasing it once the registered arc_prune_func_t has completed. + */ +static void +arc_prune_async(int64_t adjust) +{ + + int64_t *adjustptr; + + if ((adjustptr = malloc(sizeof(int64_t), M_TEMP, M_NOWAIT)) == NULL) + return; + + *adjustptr = adjust; + taskq_dispatch(arc_prune_taskq, arc_prune_task, adjustptr, TQ_SLEEP); + ARCSTAT_BUMP(arcstat_prune); +} +#else /* * Helper function for arc_prune_async() it is responsible for safely * handling the execution of a registered arc_prune_func_t. @@ -4167,6 +4208,7 @@ } mutex_exit(&arc_prune_mtx); } +#endif /* * Evict the specified number of bytes from the state specified, @@ -4333,7 +4375,11 @@ static uint64_t arc_adjust_meta(uint64_t meta_used) { - if (zfs_arc_meta_strategy == ARC_STRATEGY_META_ONLY) + if (zfs_arc_meta_strategy == ARC_STRATEGY_META_ONLY +#ifdef __FreeBSD__ + || (zfs_arc_max && (zfs_arc_max < ARC_BALANCED_MIN)) +#endif + ) return (arc_adjust_meta_only(meta_used)); else return (arc_adjust_meta_balanced(meta_used));