diff options
Diffstat (limited to 'usr')
-rw-r--r-- | usr/src/uts/common/vm/page.h | 7 | ||||
-rw-r--r-- | usr/src/uts/common/vm/page_retire.c | 23 | ||||
-rw-r--r-- | usr/src/uts/common/vm/vm_page.c | 39 |
3 files changed, 43 insertions, 26 deletions
diff --git a/usr/src/uts/common/vm/page.h b/usr/src/uts/common/vm/page.h index fe975a0900..da2879b687 100644 --- a/usr/src/uts/common/vm/page.h +++ b/usr/src/uts/common/vm/page.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -770,8 +770,9 @@ int page_unretire_pp(page_t *, int); void page_tryretire(page_t *); void page_retire_mdboot(); uint64_t page_retire_pend_count(void); -void page_retire_incr_pend_count(void); -void page_retire_decr_pend_count(void); +uint64_t page_retire_pend_kas_count(void); +void page_retire_incr_pend_count(void *); +void page_retire_decr_pend_count(void *); void page_clrtoxic(page_t *, uchar_t); void page_settoxic(page_t *, uchar_t); diff --git a/usr/src/uts/common/vm/page_retire.c b/usr/src/uts/common/vm/page_retire.c index 0dbcd41245..fa454101f8 100644 --- a/usr/src/uts/common/vm/page_retire.c +++ b/usr/src/uts/common/vm/page_retire.c @@ -178,6 +178,7 @@ struct page_retire_kstat { kstat_named_t pr_enqueue_fail; kstat_named_t pr_dequeue_fail; kstat_named_t pr_pending; + kstat_named_t pr_pending_kas; kstat_named_t pr_failed; kstat_named_t pr_failed_kernel; kstat_named_t pr_limit; @@ -198,6 +199,7 @@ static struct page_retire_kstat page_retire_kstat = { { "pages_notenqueued", KSTAT_DATA_UINT64}, { "pages_notdequeued", KSTAT_DATA_UINT64}, { "pages_pending", KSTAT_DATA_UINT64}, + { "pages_pending_kas", KSTAT_DATA_UINT64}, { "pages_deferred", KSTAT_DATA_UINT64}, { "pages_deferred_kernel", KSTAT_DATA_UINT64}, { "pages_limit", KSTAT_DATA_UINT64}, @@ -222,6 +224,7 @@ static kstat_t *page_retire_ksp = NULL; #define PR_KSTAT_RETIRED_FMA (page_retire_kstat.pr_fma.value.ui64) #define PR_KSTAT_RETIRED_NOTUE (PR_KSTAT_RETIRED_CE + PR_KSTAT_RETIRED_FMA) #define PR_KSTAT_PENDING (page_retire_kstat.pr_pending.value.ui64) +#define PR_KSTAT_PENDING_KAS (page_retire_kstat.pr_pending_kas.value.ui64) #define PR_KSTAT_EQFAIL (page_retire_kstat.pr_enqueue_fail.value.ui64) #define PR_KSTAT_DQFAIL (page_retire_kstat.pr_dequeue_fail.value.ui64) @@ -834,16 +837,30 @@ page_retire_pend_count(void) return (PR_KSTAT_PENDING); } +uint64_t +page_retire_pend_kas_count(void) +{ + return (PR_KSTAT_PENDING_KAS); +} + void -page_retire_incr_pend_count(void) +page_retire_incr_pend_count(void *datap) { PR_INCR_KSTAT(pr_pending); + + if ((datap == &kvp) || (datap == &zvp)) { + PR_INCR_KSTAT(pr_pending_kas); + } } void -page_retire_decr_pend_count(void) +page_retire_decr_pend_count(void *datap) { PR_DECR_KSTAT(pr_pending); + + if ((datap == &kvp) || (datap == &zvp)) { + PR_DECR_KSTAT(pr_pending_kas); + } } /* @@ -1042,7 +1059,7 @@ page_retire(uint64_t pa, uchar_t reason) if (MTBF(pr_calls, pr_mtbf)) { page_settoxic(pp, reason); - if (page_trycapture(pp, 0, CAPTURE_RETIRE, NULL) == 0) { + if (page_trycapture(pp, 0, CAPTURE_RETIRE, pp->p_vnode) == 0) { PR_DEBUG(prd_prlocked); } else { PR_DEBUG(prd_prnotlocked); diff --git a/usr/src/uts/common/vm/vm_page.c b/usr/src/uts/common/vm/vm_page.c index 836881f6d2..f5a36ae2cf 100644 --- a/usr/src/uts/common/vm/vm_page.c +++ b/usr/src/uts/common/vm/vm_page.c @@ -6451,7 +6451,7 @@ page_capture_add_hash(page_t *pp, uint_t szc, uint_t flags, void *datap) page_capture_hash[index].lists[0].next = bp1; page_capture_hash[index].num_pages++; if (flags & CAPTURE_RETIRE) { - page_retire_incr_pend_count(); + page_retire_incr_pend_count(datap); } mutex_exit(&page_capture_hash[index].pchh_mutex); rw_exit(&pc_cb[cb_index].cb_rwlock); @@ -6477,7 +6477,8 @@ page_capture_add_hash(page_t *pp, uint_t szc, uint_t flags, void *datap) if (bp2->pp == pp) { if (flags & CAPTURE_RETIRE) { if (!(bp2->flags & CAPTURE_RETIRE)) { - page_retire_incr_pend_count(); + page_retire_incr_pend_count( + datap); bp2->flags = flags; bp2->expires = bp1->expires; bp2->datap = datap; @@ -6829,7 +6830,7 @@ page_capture_take_action(page_t *pp, uint_t flags, void *datap) if (ret >= 0) { if (found) { if (bp1->flags & CAPTURE_RETIRE) { - page_retire_decr_pend_count(); + page_retire_decr_pend_count(datap); } kmem_free(bp1, sizeof (*bp1)); } @@ -7278,28 +7279,16 @@ page_capture_handle_outstanding(void) { int ntry; - if (!page_retire_pend_count()) { - /* - * Do we really want to be this aggressive - * for things other than page_retire? - * Maybe have a counter for each callback - * type to guide how aggressive we should - * be here. Thus if there's at least one - * page for page_retire we go ahead and reap - * like this. - */ - kmem_reap(); - seg_preap(); - page_capture_async(); - } else if (hat_supported(HAT_DYNAMIC_ISM_UNMAP, (void *)0)) { + /* Reap pages before attempting capture pages */ + kmem_reap(); + + if ((page_retire_pend_count() > page_retire_pend_kas_count()) && + hat_supported(HAT_DYNAMIC_ISM_UNMAP, (void *)0)) { /* * Note: Purging only for platforms that support * ISM hat_pageunload() - mainly SPARC. On x86/x64 * platforms ISM pages SE_SHARED locked until destroyed. - * There are pages pending retirement, so - * we reap prior to attempting to capture. */ - kmem_reap(); /* disable and purge seg_pcache */ (void) seg_p_disable(); @@ -7317,7 +7306,17 @@ page_capture_handle_outstanding(void) } /* reenable seg_pcache */ seg_p_enable(); + + /* completed what can be done. break out */ + return; } + + /* + * For kernel pages and/or unsupported HAT_DYNAMIC_ISM_UNMAP, reap + * and then attempt to capture. + */ + seg_preap(); + page_capture_async(); } /* |