diff options
author | kmacy <kmacy@FreeBSD.org> | 2010-04-30 21:20:14 +0000 |
---|---|---|
committer | kmacy <kmacy@FreeBSD.org> | 2010-04-30 21:20:14 +0000 |
commit | bbf4b0c0bf425448cec9b0e1e4f1898f7f07fd38 (patch) | |
tree | d8a0cb7751e279e9bf6fac344dd2308f6091d8f8 /sys/vm | |
parent | 0637e80406802fa3e7dba2dd901b803b17051606 (diff) | |
download | FreeBSD-src-bbf4b0c0bf425448cec9b0e1e4f1898f7f07fd38.zip FreeBSD-src-bbf4b0c0bf425448cec9b0e1e4f1898f7f07fd38.tar.gz |
- acquire the page lock in vm_contig_launder_page before checking page fields
- release page queue lock before calling vm_pageout_flush
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/vm_contig.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c index 7220055..2c8b8b1 100644 --- a/sys/vm/vm_contig.c +++ b/sys/vm/vm_contig.c @@ -96,30 +96,33 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next) vm_page_t m_tmp; struct vnode *vp; struct mount *mp; - int vfslocked; + int vfslocked, dirty; - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock(m); + vm_page_lock_queues(); object = m->object; if (!VM_OBJECT_TRYLOCK(object) && !vm_pageout_fallback_object_lock(m, next)) { VM_OBJECT_UNLOCK(object); + vm_page_unlock_queues(); + vm_page_unlock(m); return (EAGAIN); } if (vm_page_sleep_if_busy(m, TRUE, "vpctw0")) { VM_OBJECT_UNLOCK(object); - vm_page_lock_queues(); return (EBUSY); } vm_page_test_dirty(m); if (m->dirty == 0 && m->hold_count == 0) pmap_remove_all(m); - if (m->dirty) { + if ((dirty = m->dirty) != 0) { + vm_page_unlock_queues(); + vm_page_unlock(m); if ((object->flags & OBJ_DEAD) != 0) { VM_OBJECT_UNLOCK(object); return (EAGAIN); } if (object->type == OBJT_VNODE) { - vm_page_unlock_queues(); vp = object->handle; vm_object_reference_locked(object); VM_OBJECT_UNLOCK(object); @@ -133,7 +136,6 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next) VFS_UNLOCK_GIANT(vfslocked); vm_object_deallocate(object); vn_finished_write(mp); - vm_page_lock_queues(); return (0); } else if (object->type == OBJT_SWAP || object->type == OBJT_DEFAULT) { @@ -144,6 +146,11 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next) } } else if (m->hold_count == 0) vm_page_cache(m); + + if (dirty == 0) { + vm_page_unlock_queues(); + vm_page_unlock(m); + } VM_OBJECT_UNLOCK(object); return (0); } @@ -162,7 +169,9 @@ vm_contig_launder(int queue) KASSERT(VM_PAGE_INQUEUE2(m, queue), ("vm_contig_launder: page %p's queue is not %d", m, queue)); + vm_page_unlock_queues(); error = vm_contig_launder_page(m, &next); + vm_page_lock_queues(); if (error == 0) return (TRUE); if (error == EBUSY) |