mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
Unify arc_prune_async() code
There is no sense to have separate implementations for FreeBSD and Linux. Make Linux code shared as more functional and just register FreeBSD-specific prune callback with arc_add_prune_callback() API. Aside of code cleanup this should fix excessive pruning on FreeBSD: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=274698 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Mark Johnston <markj@FreeBSD.org> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #15456
This commit is contained in:
committed by
Tony Hutter
parent
bd7a02c251
commit
3ec4ea68d4
@@ -886,6 +886,8 @@ static void l2arc_do_free_on_write(void);
|
||||
static void l2arc_hdr_arcstats_update(arc_buf_hdr_t *hdr, boolean_t incr,
|
||||
boolean_t state_only);
|
||||
|
||||
static void arc_prune_async(uint64_t adjust);
|
||||
|
||||
#define l2arc_hdr_arcstats_increment(hdr) \
|
||||
l2arc_hdr_arcstats_update((hdr), B_TRUE, B_FALSE)
|
||||
#define l2arc_hdr_arcstats_decrement(hdr) \
|
||||
@@ -6050,6 +6052,56 @@ arc_remove_prune_callback(arc_prune_t *p)
|
||||
kmem_free(p, sizeof (*p));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 *ptr)
|
||||
{
|
||||
arc_prune_t *ap = (arc_prune_t *)ptr;
|
||||
arc_prune_func_t *func = ap->p_pfunc;
|
||||
|
||||
if (func != NULL)
|
||||
func(ap->p_adjust, ap->p_private);
|
||||
|
||||
zfs_refcount_remove(&ap->p_refcnt, func);
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify registered consumers they must drop holds on a portion of the ARC
|
||||
* buffers they reference. This provides a mechanism to ensure the ARC can
|
||||
* honor the metadata limit and reclaim otherwise pinned ARC buffers.
|
||||
*
|
||||
* 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(uint64_t adjust)
|
||||
{
|
||||
arc_prune_t *ap;
|
||||
|
||||
mutex_enter(&arc_prune_mtx);
|
||||
for (ap = list_head(&arc_prune_list); ap != NULL;
|
||||
ap = list_next(&arc_prune_list, ap)) {
|
||||
|
||||
if (zfs_refcount_count(&ap->p_refcnt) >= 2)
|
||||
continue;
|
||||
|
||||
zfs_refcount_add(&ap->p_refcnt, ap->p_pfunc);
|
||||
ap->p_adjust = adjust;
|
||||
if (taskq_dispatch(arc_prune_taskq, arc_prune_task,
|
||||
ap, TQ_SLEEP) == TASKQID_INVALID) {
|
||||
zfs_refcount_remove(&ap->p_refcnt, ap->p_pfunc);
|
||||
continue;
|
||||
}
|
||||
ARCSTAT_BUMP(arcstat_prune);
|
||||
}
|
||||
mutex_exit(&arc_prune_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify the arc that a block was freed, and thus will never be used again.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user