diff options
author | alc <alc@FreeBSD.org> | 2009-06-27 21:37:36 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2009-06-27 21:37:36 +0000 |
commit | 94560085671b8657f354518b2915e857b9c500f4 (patch) | |
tree | e9c5b8120c04ddc718420c6d8cd8c68d68befcf7 | |
parent | ff880be8b902c41ec399c05ac1f85bf74c0fa6ad (diff) | |
download | FreeBSD-src-94560085671b8657f354518b2915e857b9c500f4.zip FreeBSD-src-94560085671b8657f354518b2915e857b9c500f4.tar.gz |
Correct a long-standing performance bug in cluster_rbuild(). Specifically,
in the case of a file system with a block size that is less than the page
size, cluster_rbuild() looks at too many of the page's valid bits.
Consequently, it may terminate prematurely, resulting in poor performance.
Reported by: bde
Reviewed by: tegge
Approved by: re (kib)
-rw-r--r-- | sys/kern/vfs_cluster.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 34af452..5082f1f 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -310,7 +310,9 @@ cluster_rbuild(vp, filesize, lbn, blkno, size, run, fbp) struct bufobj *bo; struct buf *bp, *tbp; daddr_t bn; - int i, inc, j; + off_t off; + long tinc, tsize; + int i, inc, j, toff; KASSERT(size == vp->v_mount->mnt_stat.f_iosize, ("cluster_rbuild: size %ld != filesize %jd\n", @@ -402,15 +404,24 @@ cluster_rbuild(vp, filesize, lbn, blkno, size, run, fbp) * take part in the cluster. If it is partially valid * then we stop. */ + off = tbp->b_offset; + tsize = size; VM_OBJECT_LOCK(tbp->b_bufobj->bo_object); - for (j = 0;j < tbp->b_npages; j++) { + for (j = 0; tsize > 0; j++) { + toff = off & PAGE_MASK; + tinc = tsize; + if (toff + tinc > PAGE_SIZE) + tinc = PAGE_SIZE - toff; VM_OBJECT_LOCK_ASSERT(tbp->b_pages[j]->object, MA_OWNED); - if (tbp->b_pages[j]->valid) + if ((tbp->b_pages[j]->valid & + vm_page_bits(toff, tinc)) != 0) break; + off += tinc; + tsize -= tinc; } VM_OBJECT_UNLOCK(tbp->b_bufobj->bo_object); - if (j != tbp->b_npages) { + if (tsize > 0) { bqrelse(tbp); break; } |