View | Details | Raw Unified | Return to bug 187594 | Differences between
and this patch

Collapse All | Expand All

(-)cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c (-5 / +96 lines)
Lines 237-243 int zfs_arc_p_min_shift = 0; Link Here
237
int zfs_disable_dup_eviction = 0;
237
int zfs_disable_dup_eviction = 0;
238
uint64_t zfs_arc_average_blocksize = 8 * 1024; /* 8KB */
238
uint64_t zfs_arc_average_blocksize = 8 * 1024; /* 8KB */
239
u_int zfs_arc_free_target = 0;
239
u_int zfs_arc_free_target = 0;
240
u_int zfs_arc_wakeup_pager = 0;
241
u_int zfs_arc_wakeup_delay = 500;
242
int	zfs_arc_last_slab = 0;
240
243
244
#define	WAKE_PAGER
245
#ifdef	WAKE_PAGER
246
#define	WAKE_PAGER_CONSTANT	10 / 9	/* Pager wakeup threshold */
247
static	int	arc_init_done = 0;	/* After arc_warm is valid */
248
extern void pagedaemon_wakeup(void);
249
#endif
250
241
/* Absolute min for arc min / max is 16MB. */
251
/* Absolute min for arc min / max is 16MB. */
242
static uint64_t arc_abs_min = 16 << 20;
252
static uint64_t arc_abs_min = 16 << 20;
243
253
Lines 251-257 static void Link Here
251
arc_free_target_init(void *unused __unused)
261
arc_free_target_init(void *unused __unused)
252
{
262
{
253
263
254
	zfs_arc_free_target = vm_pageout_wakeup_thresh;
264
	zfs_arc_free_target = vm_pageout_wakeup_thresh + (vm_pageout_wakeup_thresh / 20);
265
	zfs_arc_wakeup_pager = vm_pageout_wakeup_thresh * WAKE_PAGER_CONSTANT;
255
}
266
}
256
SYSINIT(arc_free_target_init, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY,
267
SYSINIT(arc_free_target_init, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY,
257
    arc_free_target_init, NULL);
268
    arc_free_target_init, NULL);
Lines 3476-3481 int64_t arc_pages_pp_reserve = 64; Link Here
3476
int64_t arc_swapfs_reserve = 64;
3487
int64_t arc_swapfs_reserve = 64;
3477
3488
3478
/*
3489
/*
3490
 * Declare file-local static for event processor bypass
3491
 */
3492
static unsigned int arc_no_wake_event = 0;
3493
3494
/*
3479
 * Return the amount of memory that can be consumed before reclaim will be
3495
 * Return the amount of memory that can be consumed before reclaim will be
3480
 * needed.  Positive if there is sufficient free memory, negative indicates
3496
 * needed.  Positive if there is sufficient free memory, negative indicates
3481
 * the amount of memory that needs to be freed up.
3497
 * the amount of memory that needs to be freed up.
Lines 3488-3493 arc_available_memory(void) Link Here
3488
	free_memory_reason_t r = FMR_UNKNOWN;
3504
	free_memory_reason_t r = FMR_UNKNOWN;
3489
3505
3490
#ifdef _KERNEL
3506
#ifdef _KERNEL
3507
#ifdef WAKE_PAGER
3508
	sbintime_t now;
3509
	static sbintime_t last_pagedaemon_wake = 0;
3510
	void call_arc_kmem_reap(int);
3511
#endif	/* WAKE_PAGER */
3512
3491
	if (needfree > 0) {
3513
	if (needfree > 0) {
3492
		n = PAGESIZE * (-needfree);
3514
		n = PAGESIZE * (-needfree);
3493
		if (n < lowest) {
3515
		if (n < lowest) {
Lines 3495-3500 arc_available_memory(void) Link Here
3495
			r = FMR_NEEDFREE;
3517
			r = FMR_NEEDFREE;
3496
		}
3518
		}
3497
	}
3519
	}
3520
#ifdef WAKE_PAGER
3521
/*
3522
 * When arc is initialized, perform the following:
3523
 *
3524
 * 1. If we are in the "memory is low enough to wake the pager" zone,
3525
 *    reap the kernel UMA caches once per wakeup_delay period 500ms default)
3526
 *    AND wake the pager up (so it can demote pages from inactive to cache to
3527
 *    ultimately the free list.)
3528
 *
3529
 * 2. If we're below VM's free_target in free RAM reap *one* UMA zone per
3530
 *    time period (500ms).
3531
 * 
3532
 */
3533
	if (arc_init_done) {
3534
		now = getsbinuptime();
3535
		if ((now - last_pagedaemon_wake) / SBT_1MS > zfs_arc_wakeup_delay) {
3536
			last_pagedaemon_wake = now;
3537
			arc_no_wake_event++;    /* Set bypass flag for ARC */
3538
			if ( ( ((int64_t) freemem - zfs_arc_wakeup_pager) < 0) && (arc_warm == B_TRUE) ) {
3539
				call_arc_kmem_reap(0);	/* Reap caches if we're close */
3540
				DTRACE_PROBE(arc__wake_pagedaemon);
3541
				(void) pagedaemon_wakeup();    /* Wake the pager */
3542
			} else {
3543
				if ( ((int64_t) freemem - vm_cnt.v_free_target) < 0) {
3544
					call_arc_kmem_reap(1);	/* Reap one cache if lots of memory */
3545
					DTRACE_PROBE2(arc__reap_one, int, zfs_arc_last_slab, int, SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
3546
				}
3547
			}
3548
		}
3549
	} 
3550
#endif /* WAKE_PAGER */
3498
3551
3499
	/*
3552
	/*
3500
	 * Cooperate with pagedaemon when it's time for it to scan
3553
	 * Cooperate with pagedaemon when it's time for it to scan
Lines 3633-3644 extern kmem_cache_t *zio_buf_cache[]; Link Here
3633
extern kmem_cache_t	*zio_data_buf_cache[];
3686
extern kmem_cache_t	*zio_data_buf_cache[];
3634
extern kmem_cache_t	*range_seg_cache;
3687
extern kmem_cache_t	*range_seg_cache;
3635
3688
3689
/*
3690
 * Pass a flag to this routine; if zero, then reap all.  If not then reap
3691
 * one slab on a rotating basis.  This allows a low-rate call to be used
3692
 * on a routine, maintenance basis even when not low on RAM so we don't have
3693
 * huge amounts of RAM out in unused UMA allocations.
3694
 */
3636
static __noinline void
3695
static __noinline void
3637
arc_kmem_reap_now(void)
3696
arc_kmem_reap_now(flag)
3697
int	flag;
3638
{
3698
{
3639
	size_t			i;
3699
	size_t			i;
3640
	kmem_cache_t		*prev_cache = NULL;
3700
	kmem_cache_t		*prev_cache = NULL;
3641
	kmem_cache_t		*prev_data_cache = NULL;
3701
	kmem_cache_t		*prev_data_cache = NULL;
3702
	int			arc_cache_reaped = 0;
3703
	int			arc_data_cache_reaped = 0;
3704
	int			reset_last_slab = 0;
3642
3705
3643
	DTRACE_PROBE(arc__kmem_reap_start);
3706
	DTRACE_PROBE(arc__kmem_reap_start);
3644
#ifdef _KERNEL
3707
#ifdef _KERNEL
Lines 3660-3672 static __noinline void Link Here
3660
	for (i = 0; i < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT; i++) {
3723
	for (i = 0; i < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT; i++) {
3661
		if (zio_buf_cache[i] != prev_cache) {
3724
		if (zio_buf_cache[i] != prev_cache) {
3662
			prev_cache = zio_buf_cache[i];
3725
			prev_cache = zio_buf_cache[i];
3663
			kmem_cache_reap_now(zio_buf_cache[i]);
3726
			if ((!flag) || ((i > zfs_arc_last_slab) && (!arc_cache_reaped))) {
3727
				kmem_cache_reap_now(zio_buf_cache[i]);
3728
				arc_cache_reaped++;
3729
			}
3664
		}
3730
		}
3665
		if (zio_data_buf_cache[i] != prev_data_cache) {
3731
		if (zio_data_buf_cache[i] != prev_data_cache) {
3666
			prev_data_cache = zio_data_buf_cache[i];
3732
			prev_data_cache = zio_data_buf_cache[i];
3667
			kmem_cache_reap_now(zio_data_buf_cache[i]);
3733
			if ((!flag) || ((i > zfs_arc_last_slab) && (!arc_data_cache_reaped))) {
3734
				kmem_cache_reap_now(zio_data_buf_cache[i]);
3735
				arc_data_cache_reaped++;
3736
			}
3668
		}
3737
		}
3738
		if (flag && (!reset_last_slab) && (arc_cache_reaped || arc_data_cache_reaped)) {
3739
			reset_last_slab = i;
3740
		}
3669
	}
3741
	}
3742
	if (reset_last_slab) {
3743
		zfs_arc_last_slab = reset_last_slab;
3744
	}
3745
	if ((!arc_cache_reaped) && (!arc_data_cache_reaped) && (flag)) {	/* Found nothing to reap on one-pass */
3746
		zfs_arc_last_slab = 0;	/* Reset */
3747
	}
3670
	kmem_cache_reap_now(buf_cache);
3748
	kmem_cache_reap_now(buf_cache);
3671
	kmem_cache_reap_now(hdr_full_cache);
3749
	kmem_cache_reap_now(hdr_full_cache);
3672
	kmem_cache_reap_now(hdr_l2only_cache);
3750
	kmem_cache_reap_now(hdr_l2only_cache);
Lines 3684-3689 static __noinline void Link Here
3684
	DTRACE_PROBE(arc__kmem_reap_end);
3762
	DTRACE_PROBE(arc__kmem_reap_end);
3685
}
3763
}
3686
3764
3765
void	call_arc_kmem_reap(flag)
3766
int	flag;
3767
{
3768
	arc_kmem_reap_now(flag);
3769
}
3770
3687
/*
3771
/*
3688
 * Threads can block in arc_get_data_buf() waiting for this thread to evict
3772
 * Threads can block in arc_get_data_buf() waiting for this thread to evict
3689
 * enough data and signal them to proceed. When this happens, the threads in
3773
 * enough data and signal them to proceed. When this happens, the threads in
Lines 3726-3732 arc_reclaim_thread(void *dummy __unused) Link Here
3726
			 */
3810
			 */
3727
			growtime = gethrtime() + SEC2NSEC(arc_grow_retry);
3811
			growtime = gethrtime() + SEC2NSEC(arc_grow_retry);
3728
3812
3729
			arc_kmem_reap_now();
3813
			arc_kmem_reap_now(0);
3730
3814
3731
			/*
3815
			/*
3732
			 * If we are still low on memory, shrink the ARC
3816
			 * If we are still low on memory, shrink the ARC
Lines 5431-5436 static eventhandler_tag arc_event_lowmem = NULL; Link Here
5431
static void
5515
static void
5432
arc_lowmem(void *arg __unused, int howto __unused)
5516
arc_lowmem(void *arg __unused, int howto __unused)
5433
{
5517
{
5518
	if (arc_no_wake_event) {        /* Don't do it if we woke the pager */
5519
		arc_no_wake_event = 0;  /* Just clear the flag */
5520
		return;
5521
	}
5434
5522
5435
	mutex_enter(&arc_reclaim_lock);
5523
	mutex_enter(&arc_reclaim_lock);
5436
	/* XXX: Memory deficit should be passed as argument. */
5524
	/* XXX: Memory deficit should be passed as argument. */
Lines 5696-5701 arc_init(void) Link Here
5696
		printf("             in /boot/loader.conf.\n");
5784
		printf("             in /boot/loader.conf.\n");
5697
	}
5785
	}
5698
#endif
5786
#endif
5787
#ifdef	WAKE_PAGER
5788
	arc_init_done++;
5789
#endif	/* WAKE_PAGER */
5699
}
5790
}
5700
5791
5701
void
5792
void

Return to bug 187594