Mercurial > illumos > illumos-gate
changeset 12975:6bd5885dca7c
1225025 mlock:ed anonymous memory remains backed by swap
author | Stan Studzinski <Stan.Studzinski@Sun.COM> |
---|---|
date | Thu, 29 Jul 2010 18:49:19 -0700 |
parents | 468ace4afeec |
children | d106a535d961 |
files | usr/src/uts/common/vm/anon.h usr/src/uts/common/vm/page.h usr/src/uts/common/vm/seg_spt.c usr/src/uts/common/vm/vm_anon.c usr/src/uts/common/vm/vm_page.c |
diffstat | 5 files changed, 61 insertions(+), 44 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/vm/anon.h Thu Jul 29 16:10:08 2010 -0600 +++ b/usr/src/uts/common/vm/anon.h Thu Jul 29 18:49:19 2010 -0700 @@ -426,7 +426,7 @@ extern void anon_decref(struct anon *); extern int non_anon(struct anon_hdr *, ulong_t, u_offset_t *, size_t *); extern pgcnt_t anon_pages(struct anon_hdr *, ulong_t, pgcnt_t); -extern int anon_swap_adjust(pgcnt_t); +extern int anon_swap_adjust(pgcnt_t, pgcnt_t, int); extern void anon_swap_restore(pgcnt_t); extern struct anon_hdr *anon_create(pgcnt_t, int); extern void anon_release(struct anon_hdr *, pgcnt_t);
--- a/usr/src/uts/common/vm/page.h Thu Jul 29 16:10:08 2010 -0600 +++ b/usr/src/uts/common/vm/page.h Thu Jul 29 18:49:19 2010 -0700 @@ -823,7 +823,7 @@ void page_settoxic(page_t *, uchar_t); int page_mem_avail(pgcnt_t); -int page_reclaim_mem(pgcnt_t, pgcnt_t, int); +int page_reclaim_mem(pgcnt_t, pgcnt_t, int, int); void page_set_props(page_t *, uint_t); void page_clr_all_props(page_t *);
--- a/usr/src/uts/common/vm/seg_spt.c Thu Jul 29 16:10:08 2010 -0600 +++ b/usr/src/uts/common/vm/seg_spt.c Thu Jul 29 18:49:19 2010 -0700 @@ -399,7 +399,7 @@ tnf_opaque, addr, addr, tnf_ulong, len, seg->s_size); #endif if ((sptcargs->flags & SHM_PAGEABLE) == 0) { - if (err = anon_swap_adjust(npages)) + if (err = anon_swap_adjust(npages, segspt_minfree, 60)) return (err); } err = ENOMEM;
--- a/usr/src/uts/common/vm/vm_anon.c Thu Jul 29 16:10:08 2010 -0600 +++ b/usr/src/uts/common/vm/vm_anon.c Thu Jul 29 18:49:19 2010 -0700 @@ -863,7 +863,7 @@ } mutex_exit(&anoninfo_lock); - (void) page_reclaim_mem(mswap_pages, floor_pages, 0); + (void) page_reclaim_mem(mswap_pages, floor_pages, 0, 60); mutex_enter(&anoninfo_lock); } @@ -3450,12 +3450,20 @@ } /* - * Move reserved phys swap into memory swap (unreserve phys swap - * and reserve mem swap by the same amount). - * Used by segspt when it needs to lock reserved swap npages in memory + * When memory is locked the corresponding swap is unreserved. + * Swap for locked memory is "locked" which means that it can + * not be unreserved until its memory is unlocked. + * If there is enough of mem swap reserved, nothing is done + * because availrmem was already decremented (when mem swap + * was reserved). + * If there is not enough of mem swap reserved, move reserved disk + * swap into memory swap (unreserve phys swap and reserve mem swap + * by the same amount) and decrement availrmem. The availrmem needs + * to be decremented because pages are locked!. + * Used by segspt and mlock when memory is locked. */ int -anon_swap_adjust(pgcnt_t npages) +anon_swap_adjust(pgcnt_t npages, pgcnt_t limit, int cnt) { pgcnt_t unlocked_mem_swap; @@ -3473,7 +3481,7 @@ * if there is not enough unlocked mem swap we take missing * amount from phys swap and give it to mem swap */ - if (!page_reclaim_mem(adjusted_swap, segspt_minfree, 1)) { + if (!page_reclaim_mem(adjusted_swap, limit, 1, cnt)) { mutex_exit(&anoninfo_lock); return (ENOMEM); } @@ -3495,8 +3503,9 @@ } /* - * 'unlocked' reserved mem swap so when it is unreserved it - * can be moved back phys (disk) swap + * When memory is unlocked make its "locked" swap freeable. + * The unlocked mem swap is unreserved (and availrmem is decremented) + * in anon_unresvmem(). */ void anon_swap_restore(pgcnt_t npages)
--- a/usr/src/uts/common/vm/vm_page.c Thu Jul 29 16:10:08 2010 -0600 +++ b/usr/src/uts/common/vm/vm_page.c Thu Jul 29 18:49:19 2010 -0700 @@ -109,12 +109,13 @@ * pages_useclaim,pages_claimed : These two variables track the * claim adjustments because of the protection changes on a segvn segment. * - * All these globals are protected by the same lock which protects availrmem. + * The pages_locked is protected by pages_locked_lock lock. + * All other globals are protected by the same lock which protects availrmem. */ pgcnt_t pages_locked = 0; pgcnt_t pages_useclaim = 0; pgcnt_t pages_claimed = 0; - +kmutex_t pages_locked_lock; /* * new_freemem_lock protects freemem, freemem_wait & freemem_cv. @@ -3097,18 +3098,27 @@ * We are doing a modified version of page_pp_unlock here. */ if ((pp->p_lckcnt != 0) || (pp->p_cowcnt != 0)) { - mutex_enter(&freemem_lock); if (pp->p_lckcnt != 0) { - availrmem++; + /* + * Page has not been unlocked via + * page_pp_unlock(). Therefore + * anon_swap_restore() is called to unlock + * swap for this page so its swap can be + * unreserved. + */ + anon_swap_restore(1); + mutex_enter(&pages_locked_lock); pages_locked--; + mutex_exit(&pages_locked_lock); pp->p_lckcnt = 0; } if (pp->p_cowcnt != 0) { - availrmem += pp->p_cowcnt; + anon_swap_restore(pp->p_cowcnt); + mutex_enter(&pages_locked_lock); pages_locked -= pp->p_cowcnt; + mutex_exit(&pages_locked_lock); pp->p_cowcnt = 0; } - mutex_exit(&freemem_lock); } /* * Put the page on the "free" list. @@ -3826,20 +3836,20 @@ * Acquire the "freemem_lock" for availrmem. */ if (cow) { - mutex_enter(&freemem_lock); - if ((availrmem > pages_pp_maximum) && - (pp->p_cowcnt < (ushort_t)PAGE_LOCK_MAXIMUM)) { - availrmem--; - pages_locked++; - mutex_exit(&freemem_lock); - r = 1; - if (++pp->p_cowcnt == (ushort_t)PAGE_LOCK_MAXIMUM) { - cmn_err(CE_WARN, - "COW lock limit reached on pfn 0x%lx", - page_pptonum(pp)); + if (pp->p_cowcnt < (ushort_t)PAGE_LOCK_MAXIMUM) { + if (!anon_swap_adjust(1, pages_pp_maximum, 0)) { + mutex_enter(&pages_locked_lock); + pages_locked++; + mutex_exit(&pages_locked_lock); + r = 1; + if (++pp->p_cowcnt == + (ushort_t)PAGE_LOCK_MAXIMUM) { + cmn_err(CE_WARN, + "COW lock limit on pfn 0x%lx", + page_pptonum(pp)); + } } - } else - mutex_exit(&freemem_lock); + } } else { if (pp->p_lckcnt) { if (pp->p_lckcnt < (ushort_t)PAGE_LOCK_MAXIMUM) { @@ -3857,14 +3867,13 @@ ++pp->p_lckcnt; r = 1; } else { - mutex_enter(&freemem_lock); - if (availrmem > pages_pp_maximum) { - availrmem--; + if (!anon_swap_adjust(1, pages_pp_maximum, 0)) { + mutex_enter(&pages_locked_lock); pages_locked++; + mutex_exit(&pages_locked_lock); ++pp->p_lckcnt; r = 1; } - mutex_exit(&freemem_lock); } } } @@ -3895,19 +3904,19 @@ */ if (cow) { if (pp->p_cowcnt) { - mutex_enter(&freemem_lock); + anon_swap_restore(1); pp->p_cowcnt--; - availrmem++; + mutex_enter(&pages_locked_lock); pages_locked--; - mutex_exit(&freemem_lock); + mutex_exit(&pages_locked_lock); } } else { if (pp->p_lckcnt && --pp->p_lckcnt == 0) { if (!kernel) { - mutex_enter(&freemem_lock); - availrmem++; + anon_swap_restore(1); + mutex_enter(&pages_locked_lock); pages_locked--; - mutex_exit(&freemem_lock); + mutex_exit(&pages_locked_lock); } } } @@ -5768,12 +5777,11 @@ return (1); } -#define MAX_CNT 60 /* max num of iterations */ /* * Reclaim/reserve availrmem for npages. * If there is not enough memory start reaping seg, kmem caches. * Start pageout scanner (via page_needfree()). - * Exit after ~ MAX_CNT s regardless of how much memory has been released. + * Exit after max_cnt tries regardless of how much memory has been released. * Note: There is no guarantee that any availrmem will be freed as * this memory typically is locked (kernel heap) or reserved for swap. * Also due to memory fragmentation kmem allocator may not be able @@ -5781,7 +5789,7 @@ * freeing slab or a page). */ int -page_reclaim_mem(pgcnt_t npages, pgcnt_t epages, int adjust) +page_reclaim_mem(pgcnt_t npages, pgcnt_t epages, int adjust, int max_cnt) { int i = 0; int ret = 0; @@ -5791,7 +5799,7 @@ mutex_enter(&freemem_lock); old_availrmem = availrmem - 1; while ((availrmem < tune.t_minarmem + npages + epages) && - (old_availrmem < availrmem) && (i++ < MAX_CNT)) { + (old_availrmem < availrmem) && (i++ < max_cnt)) { old_availrmem = availrmem; deficit = tune.t_minarmem + npages + epages - availrmem; mutex_exit(&freemem_lock);