diff options
author | dillon <dillon@FreeBSD.org> | 2001-01-19 05:31:07 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2001-01-19 05:31:07 +0000 |
commit | 9b157601a0098d78f887142a8cca3f3cf17d5839 (patch) | |
tree | 88791e800b2f41b16cf38c45bfeab418abffe80d /sys/kern/vfs_cluster.c | |
parent | 37decc93f5a2dfb49438d1e77245218780583ef6 (diff) | |
download | FreeBSD-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.c | 24 |
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); |