summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_cluster.c
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1997-02-01 00:09:32 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1997-02-01 00:09:32 +0000
commit3762bf8489078680d13997a124227bdaf33bbe8a (patch)
tree7edc795b8b2d8eb3475ae7e625013b40aa1a704c /sys/kern/vfs_cluster.c
parent16da1118ce7326422ef560e4289a2f37d5f87dd0 (diff)
Correct early termination case of read clustering which could cause
buffer cache poisoning when bufpages/nbuf is larger than 1. Also correct readahead amount calculation. Optimize page moving when buffers have excess pages.
Diffstat (limited to 'sys/kern/vfs_cluster.c')
-rw-r--r--sys/kern/vfs_cluster.c41
1 files changed, 17 insertions, 24 deletions
diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c
index f54dc1836f5..7a3b320f09d 100644
--- a/sys/kern/vfs_cluster.c
+++ b/sys/kern/vfs_cluster.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_cluster.c,v 1.6 1997/01/10 23:18:40 niklas Exp $ */
+/* $OpenBSD: vfs_cluster.c,v 1.7 1997/02/01 00:09:31 niklas Exp $ */
/* $NetBSD: vfs_cluster.c,v 1.12 1996/04/22 01:39:05 christos Exp $ */
/*-
@@ -267,7 +267,7 @@ skip_readahead:
if (rbp == NULL)
rbp = bp;
if (rbp)
- vp->v_maxra = rbp->b_lblkno + (rbp->b_bufsize / size) - 1;
+ vp->v_maxra = rbp->b_lblkno + (rbp->b_bcount / size) - 1;
if (bp)
return(biowait(bp));
@@ -315,8 +315,8 @@ cluster_rbuild(vp, filesize, bp, lbn, blkno, size, run, flags)
if (bp->b_flags & (B_DONE | B_DELWRI))
return (bp);
- b_save = malloc(sizeof(struct buf *) * run + sizeof(struct cluster_save),
- M_SEGMENT, M_WAITOK);
+ b_save = malloc(sizeof(struct buf *) * run +
+ sizeof(struct cluster_save), M_SEGMENT, M_WAITOK);
b_save->bs_bufsize = b_save->bs_bcount = size;
b_save->bs_nchildren = 0;
b_save->bs_children = (struct buf **)(b_save + 1);
@@ -352,29 +352,16 @@ cluster_rbuild(vp, filesize, bp, lbn, blkno, size, run, flags)
if (tbp->b_bufsize > MAXBSIZE)
panic("cluster_rbuild: too much memory");
#endif
+ /* This buffer is *not* valid. */
+ tbp->b_flags |= B_INVAL;
brelse(tbp);
break;
}
- if (tbp->b_bufsize > size) {
- /*
- * XXX if the source and destination regions
- * overlap we have to copy backward to avoid
- * clobbering any valid pages (i.e. pagemove
- * implementations typically can't handle
- * overlap).
- */
- bdata += tbp->b_bufsize;
- while (bdata > (char *)tbp->b_data) {
- bdata -= CLBYTES;
- pagemove(bdata, bdata + size, CLBYTES);
- }
- } else
- pagemove(bdata, bdata + size, tbp->b_bufsize);
+ pagemove(bdata, bdata + tbp->b_bufsize, size);
}
tbp->b_blkno = bn;
tbp->b_flags |= flags | B_READ | B_ASYNC;
- ++b_save->bs_nchildren;
- b_save->bs_children[i - 1] = tbp;
+ b_save->bs_children[b_save->bs_nchildren++] = tbp;
}
/*
* The cluster may have been terminated early, adjust the cluster
@@ -471,7 +458,13 @@ cluster_callback(bp)
if (bp->b_bufsize != bsize) {
if (bp->b_bufsize < bsize)
panic("cluster_callback: too little memory");
- pagemove(cp, (char *)bp->b_data + bsize, bp->b_bufsize - bsize);
+ if (bp->b_bufsize < cp - (char *)bp->b_data)
+ pagemove(cp, (char *)bp->b_data + bsize,
+ bp->b_bufsize - bsize);
+ else
+ pagemove((char *)bp->b_data + bp->b_bufsize,
+ (char *)bp->b_data + bsize,
+ cp - ((char *)bp->b_data + bsize));
}
bp->b_bcount = bsize;
bp->b_iodone = NULL;
@@ -667,8 +660,8 @@ redo:
}
--len;
- b_save = malloc(sizeof(struct buf *) * len + sizeof(struct cluster_save),
- M_SEGMENT, M_WAITOK);
+ b_save = malloc(sizeof(struct buf *) * len +
+ sizeof(struct cluster_save), M_SEGMENT, M_WAITOK);
b_save->bs_bcount = bp->b_bcount;
b_save->bs_bufsize = bp->b_bufsize;
b_save->bs_nchildren = 0;