summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_cluster.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_cluster.c')
-rw-r--r--sys/kern/vfs_cluster.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c
index f2fae8e..71a123a 100644
--- a/sys/kern/vfs_cluster.c
+++ b/sys/kern/vfs_cluster.c
@@ -315,7 +315,7 @@ cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn,
daddr_t bn;
off_t off;
long tinc, tsize;
- int i, inc, j, toff;
+ int i, inc, j, k, toff;
KASSERT(size == vp->v_mount->mnt_stat.f_iosize,
("cluster_rbuild: size %ld != f_iosize %jd\n",
@@ -378,7 +378,15 @@ cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn,
inc = btodb(size);
bo = &vp->v_bufobj;
for (bn = blkno, i = 0; i < run; ++i, bn += inc) {
- if (i != 0) {
+ if (i == 0) {
+ VM_OBJECT_WLOCK(tbp->b_bufobj->bo_object);
+ vfs_drain_busy_pages(tbp);
+ vm_object_pip_add(tbp->b_bufobj->bo_object,
+ tbp->b_npages);
+ for (k = 0; k < tbp->b_npages; k++)
+ vm_page_sbusy(tbp->b_pages[k]);
+ VM_OBJECT_WUNLOCK(tbp->b_bufobj->bo_object);
+ } else {
if ((bp->b_npages * PAGE_SIZE) +
round_page(size) > vp->v_mount->mnt_iosize_max) {
break;
@@ -424,14 +432,23 @@ cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn,
if ((tbp->b_pages[j]->valid &
vm_page_bits(toff, tinc)) != 0)
break;
+ if (vm_page_xbusied(tbp->b_pages[j]))
+ break;
+ vm_object_pip_add(tbp->b_bufobj->bo_object, 1);
+ vm_page_sbusy(tbp->b_pages[j]);
off += tinc;
tsize -= tinc;
}
- VM_OBJECT_WUNLOCK(tbp->b_bufobj->bo_object);
if (tsize > 0) {
+clean_sbusy:
+ vm_object_pip_add(tbp->b_bufobj->bo_object, -j);
+ for (k = 0; k < j; k++)
+ vm_page_sunbusy(tbp->b_pages[k]);
+ VM_OBJECT_WUNLOCK(tbp->b_bufobj->bo_object);
bqrelse(tbp);
break;
}
+ VM_OBJECT_WUNLOCK(tbp->b_bufobj->bo_object);
/*
* Set a read-ahead mark as appropriate
@@ -451,8 +468,8 @@ cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn,
if (tbp->b_blkno == tbp->b_lblkno) {
tbp->b_blkno = bn;
} else if (tbp->b_blkno != bn) {
- brelse(tbp);
- break;
+ VM_OBJECT_WLOCK(tbp->b_bufobj->bo_object);
+ goto clean_sbusy;
}
}
/*
@@ -466,10 +483,8 @@ cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn,
for (j = 0; j < tbp->b_npages; j += 1) {
vm_page_t m;
m = tbp->b_pages[j];
- vm_page_sbusy(m);
- vm_object_pip_add(m->object, 1);
if ((bp->b_npages == 0) ||
- (bp->b_pages[bp->b_npages-1] != m)) {
+ (bp->b_pages[bp->b_npages-1] != m)) {
bp->b_pages[bp->b_npages] = m;
bp->b_npages++;
}
@@ -944,7 +959,9 @@ cluster_wbuild(struct vnode *vp, long size, daddr_t start_lbn, int len,
vm_page_t m;
VM_OBJECT_WLOCK(tbp->b_bufobj->bo_object);
- if (i != 0) { /* if not first buffer */
+ if (i == 0) {
+ vfs_drain_busy_pages(tbp);
+ } else { /* if not first buffer */
for (j = 0; j < tbp->b_npages; j += 1) {
m = tbp->b_pages[j];
if (vm_page_xbusied(m)) {
OpenPOWER on IntegriCloud