summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-09-05 12:56:08 +0000
committerkib <kib@FreeBSD.org>2013-09-05 12:56:08 +0000
commita08e5f97bc360935cbcff202e45eb4b92ececf39 (patch)
tree5595855b9e756985513ec6c0e3fe9a9b9f2c66f1
parent7ab18d4990d80767c250514df82b25bd076c5801 (diff)
downloadFreeBSD-src-a08e5f97bc360935cbcff202e45eb4b92ececf39.zip
FreeBSD-src-a08e5f97bc360935cbcff202e45eb4b92ececf39.tar.gz
The vm_pageout_flush() functions sbusies pages in the passed pages
run. After that, the pager put method is called, usually translated to VOP_WRITE(). For the filesystems which use buffer cache, bufwrite() sbusies the buffer pages again, waiting for the xbusy state to drain. The later is done in vfs_drain_busy_pages(), which is called with the buffer pages already sbusied (by vm_pageout_flush()). Since vfs_drain_busy_pages() can only wait for one page at the time, and during the wait, the object lock is dropped, previous pages in the buffer must be protected from other threads busying them. Up to the moment, it was done by xbusying the pages, that is incompatible with the sbusy state in the new implementation of busy. Switch to sbusy. Reported and tested by: pho Sponsored by: The FreeBSD Foundation
-rw-r--r--sys/kern/vfs_bio.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 04eab14..37ef663 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -3994,7 +3994,7 @@ vfs_drain_busy_pages(struct buf *bp)
m = bp->b_pages[i];
if (vm_page_xbusied(m)) {
for (; last_busied < i; last_busied++)
- vm_page_xbusy(bp->b_pages[last_busied]);
+ vm_page_sbusy(bp->b_pages[last_busied]);
while (vm_page_xbusied(m)) {
vm_page_lock(m);
VM_OBJECT_WUNLOCK(bp->b_bufobj->bo_object);
@@ -4004,7 +4004,7 @@ vfs_drain_busy_pages(struct buf *bp)
}
}
for (i = 0; i < last_busied; i++)
- vm_page_xunbusy(bp->b_pages[i]);
+ vm_page_sunbusy(bp->b_pages[i]);
}
/*
OpenPOWER on IntegriCloud