Permalink
Browse files

OS-4005 lx brand: madvise(MADV_DONTNEED) needs to unreserve swap

  • Loading branch information...
bcantrill committed Mar 25, 2015
1 parent 36e818b commit a9a452609b1832657d68c06f674196b4db54a5d6
@@ -391,7 +391,8 @@ extern int anon_fill_cow_holes(struct seg *, caddr_t, struct anon_hdr *,
uint_t, struct vpage [], struct cred *);
extern void anon_free(struct anon_hdr *, ulong_t, size_t);
extern void anon_free_pages(struct anon_hdr *, ulong_t, size_t, uint_t);
extern int anon_disclaim(struct anon_map *, ulong_t, size_t, uint_t);
extern int anon_disclaim(struct anon_map *,
ulong_t, size_t, uint_t, pgcnt_t *);
extern int anon_getpage(struct anon **, uint_t *, struct page **,
size_t, struct seg *, caddr_t, enum seg_rw, struct cred *);
extern int swap_getconpage(struct vnode *, u_offset_t, size_t,
@@ -2892,7 +2892,7 @@ segspt_shmadvise(struct seg *seg, caddr_t addr, size_t len, uint_t behav)
if ((ppa = sptd->spt_ppa) == NULL) {
mutex_exit(&sptd->spt_lock);
ANON_LOCK_ENTER(&amp->a_rwlock, RW_READER);
(void) anon_disclaim(amp, pg_idx, len, behav);
(void) anon_disclaim(amp, pg_idx, len, behav, NULL);
ANON_LOCK_EXIT(&amp->a_rwlock);
return (0);
}
@@ -2951,7 +2951,7 @@ segspt_shmadvise(struct seg *seg, caddr_t addr, size_t len, uint_t behav)
}
ANON_LOCK_ENTER(&amp->a_rwlock, RW_READER);
(void) anon_disclaim(amp, pg_idx, len, behav);
(void) anon_disclaim(amp, pg_idx, len, behav, NULL);
ANON_LOCK_EXIT(&amp->a_rwlock);
} else if (lgrp_optimizations() && (behav == MADV_ACCESS_LWP ||
behav == MADV_ACCESS_MANY || behav == MADV_ACCESS_DEFAULT)) {
@@ -8178,6 +8178,8 @@ segvn_advise(struct seg *seg, caddr_t addr, size_t len, uint_t behav)
amp = svd->amp;
vp = svd->vp;
if (behav == MADV_FREE || behav == MADV_PURGE) {
pgcnt_t purged;
if (behav == MADV_FREE && (vp != NULL || amp == NULL)) {
/*
* MADV_FREE is not supported for segments with an
@@ -8205,7 +8207,25 @@ segvn_advise(struct seg *seg, caddr_t addr, size_t len, uint_t behav)
page = seg_page(seg, addr);
ANON_LOCK_ENTER(&amp->a_rwlock, RW_READER);
err = anon_disclaim(amp, svd->anon_index + page, len, behav);
err = anon_disclaim(amp,
svd->anon_index + page, len, behav, &purged);
if (purged != 0 && (svd->flags & MAP_NORESERVE)) {
/*
* If we purged pages on a MAP_NORESERVE mapping, we
* need to be sure to now unreserve our reserved swap.
* (We use the atomic operations to manipulate our
* segment and address space counters because we only
* have the corresponding locks held as reader, not
* writer.)
*/
ssize_t bytes = ptob(purged);
anon_unresv_zone(bytes, seg->s_as->a_proc->p_zone);
atomic_add_long(&svd->swresv, -bytes);
atomic_add_long(&seg->s_as->a_resvsize, -bytes);
}
ANON_LOCK_EXIT(&amp->a_rwlock);
SEGVN_LOCK_EXIT(seg->s_as, &svd->lock);
@@ -1670,15 +1670,16 @@ anon_free_pages(
* Make anonymous pages discardable
*/
int
anon_disclaim(struct anon_map *amp, ulong_t index, size_t size, uint_t behav)
anon_disclaim(struct anon_map *amp, ulong_t index, size_t size,
uint_t behav, pgcnt_t *purged)
{
spgcnt_t npages = btopr(size);
struct anon *ap;
struct vnode *vp;
anoff_t off;
page_t *pp, *root_pp;
kmutex_t *ahm;
pgcnt_t pgcnt;
pgcnt_t pgcnt, npurged = 0;
ulong_t old_idx, idx, i;
struct anon_hdr *ahp = amp->ahp;
anon_sync_obj_t cookie;
@@ -1785,7 +1786,7 @@ anon_disclaim(struct anon_map *amp, ulong_t index, size_t size, uint_t behav)
mutex_exit(ahm);
(void) anon_set_ptr(ahp, index,
NULL, ANON_SLEEP);
npurged++;
ANI_ADD(1);
kmem_cache_free(anon_cache, ap);
} else {
@@ -1887,6 +1888,9 @@ anon_disclaim(struct anon_map *amp, ulong_t index, size_t size, uint_t behav)
anon_array_exit(&cookie);
}
if (purged != NULL)
*purged = npurged;
return (err);
}

0 comments on commit a9a4526

Please sign in to comment.