summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_cluster.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2001-01-19 05:31:07 +0000
committerdillon <dillon@FreeBSD.org>2001-01-19 05:31:07 +0000
commit9b157601a0098d78f887142a8cca3f3cf17d5839 (patch)
tree88791e800b2f41b16cf38c45bfeab418abffe80d /sys/kern/vfs_cluster.c
parent37decc93f5a2dfb49438d1e77245218780583ef6 (diff)
downloadFreeBSD-src-9b157601a0098d78f887142a8cca3f3cf17d5839.zip
FreeBSD-src-9b157601a0098d78f887142a8cca3f3cf17d5839.tar.gz
Do not cluster with B_LOCKED buffers.
This is an odd one. This patch appears to fix a panic related to background bitmap writes (for FFS), though neither Kirk, Ian, or I can figure out how B_CLUSTEROK could possibly be set on a bitmap block to cause the clustering code to improperly cluster with a buffer undergoing a background write. In anycase, the clustering code is very fragile and this patch helps with that, as well as possibly fixing a bug Andre was having. Suggested by: Ian Dowse <iedowse@maths.tcd.ie> Testing by: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
Diffstat (limited to 'sys/kern/vfs_cluster.c')
-rw-r--r--sys/kern/vfs_cluster.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c
index 088dc40..8836236 100644
--- a/sys/kern/vfs_cluster.c
+++ b/sys/kern/vfs_cluster.c
@@ -399,15 +399,22 @@ cluster_rbuild(vp, filesize, lbn, blkno, size, run, fbp)
tbp = getblk(vp, lbn + i, size, 0, 0);
- if ((tbp->b_flags & B_CACHE) ||
+ /*
+ * If the buffer is already fully valid or locked
+ * (which could also mean that a background write is
+ * in progress), or the buffer is not backed by VMIO,
+ * stop.
+ */
+ if ((tbp->b_flags & (B_CACHE|B_LOCKED)) ||
(tbp->b_flags & B_VMIO) == 0) {
bqrelse(tbp);
break;
}
- for (j = 0;j < tbp->b_npages; j++)
+ for (j = 0;j < tbp->b_npages; j++) {
if (tbp->b_pages[j]->valid)
break;
+ }
if (j != tbp->b_npages) {
bqrelse(tbp);
@@ -710,8 +717,13 @@ cluster_wbuild(vp, size, start_lbn, len)
while (len > 0) {
s = splbio();
+ /*
+ * If the buffer is not delayed-write (i.e. dirty), or it
+ * is delayed-write but either locked or inval, it cannot
+ * partake in teh clustered write.
+ */
if (((tbp = gbincore(vp, start_lbn)) == NULL) ||
- ((tbp->b_flags & (B_INVAL | B_DELWRI)) != B_DELWRI) ||
+ ((tbp->b_flags & (B_LOCKED | B_INVAL | B_DELWRI)) != B_DELWRI) ||
BUF_LOCK(tbp, LK_EXCLUSIVE | LK_NOWAIT)) {
++start_lbn;
--len;
@@ -784,12 +796,16 @@ cluster_wbuild(vp, size, start_lbn, len)
/*
* If it IS in core, but has different
- * characteristics, don't cluster with it.
+ * characteristics, or is locked (which
+ * means it could be undergoing a background
+ * I/O or be in a weird state), then don't
+ * cluster with it.
*/
if ((tbp->b_flags & (B_VMIO | B_CLUSTEROK |
B_INVAL | B_DELWRI | B_NEEDCOMMIT))
!= (B_DELWRI | B_CLUSTEROK |
(bp->b_flags & (B_VMIO | B_NEEDCOMMIT))) ||
+ (tbp->b_flags & B_LOCKED) ||
tbp->b_wcred != bp->b_wcred ||
BUF_LOCK(tbp, LK_EXCLUSIVE | LK_NOWAIT)) {
splx(s);
OpenPOWER on IntegriCloud