summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2010-05-02 19:10:27 +0000
committeralc <alc@FreeBSD.org>2010-05-02 19:10:27 +0000
commit299c89c6fb0cdd9e93b22b9aed707322f2846c8a (patch)
tree171ac765879e73e42a59cce9c20b2fbe1d951eb1 /sys/kern/vfs_bio.c
parent6637c2369d116e42113a80f7912a0b5a2d9e7fbf (diff)
downloadFreeBSD-src-299c89c6fb0cdd9e93b22b9aed707322f2846c8a.zip
FreeBSD-src-299c89c6fb0cdd9e93b22b9aed707322f2846c8a.tar.gz
Properly synchronize access to the page's hold_count in vfs_vmio_release().
Reviewed by: kib
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index dbcd6e8..1048998 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -1563,7 +1563,6 @@ vfs_vmio_release(struct buf *bp)
vm_page_t m;
VM_OBJECT_LOCK(bp->b_bufobj->bo_object);
- vm_page_lock_queues();
for (i = 0; i < bp->b_npages; i++) {
m = bp->b_pages[i];
bp->b_pages[i] = NULL;
@@ -1571,16 +1570,16 @@ vfs_vmio_release(struct buf *bp)
* In order to keep page LRU ordering consistent, put
* everything on the inactive queue.
*/
+ vm_page_lock(m);
+ vm_page_lock_queues();
vm_page_unwire(m, 0);
/*
* We don't mess with busy pages, it is
* the responsibility of the process that
* busied the pages to deal with them.
*/
- if ((m->oflags & VPO_BUSY) || (m->busy != 0))
- continue;
-
- if (m->wire_count == 0) {
+ if ((m->oflags & VPO_BUSY) == 0 && m->busy == 0 &&
+ m->wire_count == 0) {
/*
* Might as well free the page if we can and it has
* no valid data. We also free the page if the
@@ -1595,8 +1594,9 @@ vfs_vmio_release(struct buf *bp)
vm_page_try_to_cache(m);
}
}
+ vm_page_unlock_queues();
+ vm_page_unlock(m);
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(bp->b_bufobj->bo_object);
pmap_qremove(trunc_page((vm_offset_t) bp->b_data), bp->b_npages);
OpenPOWER on IntegriCloud