diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2022-04-30 17:58:44 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2022-04-30 17:58:44 +0000 |
commit | 6448882f637819b06a27f7f4932fa15410711041 (patch) | |
tree | 0a4f126d39565504700166c0cca6ed3cf35e79d8 /sys/uvm | |
parent | 2f6b8ff237a0fbc1a850dbd2d37296bc78a04f78 (diff) |
Recheck PG_BUSY after locking the page.
Another thread can set the bit if we sleep during rw_enter(9) in which case
the page shouldn't be touched.
ok semarie@
Diffstat (limited to 'sys/uvm')
-rw-r--r-- | sys/uvm/uvm_pdaemon.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/sys/uvm/uvm_pdaemon.c b/sys/uvm/uvm_pdaemon.c index 59a5e28f350..e7eebee53c1 100644 --- a/sys/uvm/uvm_pdaemon.c +++ b/sys/uvm/uvm_pdaemon.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_pdaemon.c,v 1.96 2022/04/11 16:43:49 mpi Exp $ */ +/* $OpenBSD: uvm_pdaemon.c,v 1.97 2022/04/30 17:58:43 mpi Exp $ */ /* $NetBSD: uvm_pdaemon.c,v 1.23 2000/08/20 10:24:14 bjh21 Exp $ */ /* @@ -879,6 +879,8 @@ uvmpd_scan(void) int free, inactive_shortage, swap_shortage, pages_freed; struct vm_page *p, *nextpg; struct uvm_object *uobj; + struct vm_anon *anon; + struct rwlock *slock; boolean_t got_it; MUTEX_ASSERT_LOCKED(&uvm.pageqlock); @@ -947,20 +949,34 @@ uvmpd_scan(void) p != NULL && (inactive_shortage > 0 || swap_shortage > 0); p = nextpg) { nextpg = TAILQ_NEXT(p, pageq); - - /* skip this page if it's busy. */ - if (p->pg_flags & PG_BUSY) + if (p->pg_flags & PG_BUSY) { continue; + } - if (p->pg_flags & PQ_ANON) { - KASSERT(p->uanon != NULL); - if (rw_enter(p->uanon->an_lock, RW_WRITE|RW_NOSLEEP)) + /* + * lock the page's owner. + */ + if (p->uobject != NULL) { + uobj = p->uobject; + slock = uobj->vmobjlock; + if (rw_enter(slock, RW_WRITE|RW_NOSLEEP)) { continue; + } } else { - KASSERT(p->uobject != NULL); - if (rw_enter(p->uobject->vmobjlock, - RW_WRITE|RW_NOSLEEP)) + anon = p->uanon; + KASSERT(p->uanon != NULL); + slock = anon->an_lock; + if (rw_enter(slock, RW_WRITE|RW_NOSLEEP)) { continue; + } + } + + /* + * skip this page if it's busy. + */ + if ((p->pg_flags & PG_BUSY) != 0) { + rw_exit(slock); + continue; } /* @@ -997,10 +1013,11 @@ uvmpd_scan(void) uvmexp.pddeact++; inactive_shortage--; } - if (p->pg_flags & PQ_ANON) - rw_exit(p->uanon->an_lock); - else - rw_exit(p->uobject->vmobjlock); + + /* + * we're done with this page. + */ + rw_exit(slock); } } |