When the Dynamic Buffer Cache has been introduced bread_cluster()
became the replacement of cluster_read(). However this function,
currently used by ffs_read() only, does not consider the B_CACHE
flag of the first buffer of a cluster like its predecessor did.
This basically mean that the kernel might ends up fetching the
same block(s) multiple times if bread_cluster() is used to read
sequential blocks.
The simplest change to improve this situation is to not perform
any read-ahead when the first block has been found in the cache.
This change allows me to read files on cheap USB sticks with a
MSDOSFS using bread_cluster() (see next diff) as fast as doing
physio(9).
Index: kern/vfs_bio.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_bio.c,v
retrieving revision 1.171
diff -u -p -r1.171 vfs_bio.c
--- kern/vfs_bio.c 28 Nov 2015 21:52:02 -0000 1.171
+++ kern/vfs_bio.c 3 Jan 2016 19:07:26 -0000
@@ -461,13 +461,19 @@ bread_cluster(struct vnode *vp, daddr_t
*rbpp = bio_doread(vp, blkno, size, 0);
+ /*
+ * If the buffer is in the cache skip any I/O operation.
+ */
+ if (ISSET((*rbpp)->b_flags, B_CACHE))
+ goto out;
+
if (size != round_page(size))
goto out;
if (VOP_BMAP(vp, blkno + 1, NULL, &sblkno, &maxra))
goto out;
- maxra++;
+ maxra++;
if (sblkno == -1 || maxra < 2)
goto out;