summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2004-10-27 18:29:17 +0000
committeralc <alc@FreeBSD.org>2004-10-27 18:29:17 +0000
commitce02afb50053c051ed2f43b7135a4d361d01c2d5 (patch)
tree92090b368a1fe724a8eb98fe87f45e389f54b0c3 /sys/vm
parent7f88af1f93599792d9c99ff21dcb247e6c3c729d (diff)
downloadFreeBSD-src-ce02afb50053c051ed2f43b7135a4d361d01c2d5.zip
FreeBSD-src-ce02afb50053c051ed2f43b7135a4d361d01c2d5.tar.gz
During traversal of the active queue, try locking the page's containing
object before accessing the page's flags or the object's reference count. If the trylock fails, handle the page as though it is busy.
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_pageout.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 412c430..0e52be2 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -1018,12 +1018,19 @@ unlock_and_continue:
("vm_pageout_scan: page %p isn't active", m));
next = TAILQ_NEXT(m, pageq);
+ object = m->object;
+ if (!VM_OBJECT_TRYLOCK(object)) {
+ vm_pageq_requeue(m);
+ continue;
+ }
+
/*
* Don't deactivate pages that are busy.
*/
if ((m->busy != 0) ||
(m->flags & PG_BUSY) ||
(m->hold_count != 0)) {
+ VM_OBJECT_UNLOCK(object);
vm_pageq_requeue(m);
m = next;
continue;
@@ -1039,7 +1046,7 @@ unlock_and_continue:
* Check to see "how much" the page has been used.
*/
actcount = 0;
- if (m->object->ref_count != 0) {
+ if (object->ref_count != 0) {
if (m->flags & PG_REFERENCED) {
actcount += 1;
}
@@ -1060,15 +1067,15 @@ unlock_and_continue:
* Only if an object is currently being used, do we use the
* page activation count stats.
*/
- if (actcount && (m->object->ref_count != 0)) {
+ if (actcount && (object->ref_count != 0)) {
vm_pageq_requeue(m);
} else {
m->act_count -= min(m->act_count, ACT_DECLINE);
if (vm_pageout_algorithm ||
- m->object->ref_count == 0 ||
+ object->ref_count == 0 ||
m->act_count == 0) {
page_shortage--;
- if (m->object->ref_count == 0) {
+ if (object->ref_count == 0) {
pmap_remove_all(m);
if (m->dirty == 0)
vm_page_cache(m);
@@ -1081,6 +1088,7 @@ unlock_and_continue:
vm_pageq_requeue(m);
}
}
+ VM_OBJECT_UNLOCK(object);
m = next;
}
OpenPOWER on IntegriCloud