Last year, mpi@ implemented VFS read clustering for MSDOSFS in sys/msdosfs/denode.h 1.28 sys/msdosfs/msdosfs_vnops.c 1.105
This caused regressions when doing seeks past the end of the file and had to be reverted. I have now written a test that catches the bug (committed in regress/sys/fileops) and got a fix that does not break the test: There was some confusion as to what block sizes are used in file operations. Openbsd seems to be more like netbsd than like freebsd. See msdosfs_vnops.c 1.62 in freebsd: Author: msmith <msm...@freebsd.org> Date: Sun Mar 1 21:26:09 1998 +0000 Fix mmap() on msdosfs. In the words of the submitter: |In the process of evaluating the getpages/putpages issues I discovered |that mmap on MSDOSFS does not work. This is because I blindly merged |NetBSD changes in msdosfs_bmap and msdosfs_strategy. Apparently, their |blocksize is always DEV_BSIZE (even in files), while in FreeBSD |blocksize in files is v_mount->mnt_stat.f_iosize (i.e. clustersize in |MSDOSFS case). The patch is below. Submitted by: Dmitrij Tejblum <d...@tejblum.dnttm.rssi.ru> The diff is meant to be on top of mpi's diff (or on top of a revert of the revert 1.113). I can send the complete diff if that's preferred. diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c index 45a479fb646..46ff2736ca4 100644 --- sys/msdosfs/msdosfs_vnops.c +++ sys/msdosfs/msdosfs_vnops.c @@ -516,7 +516,7 @@ msdosfs_read(void *v) int isadir, error = 0; uint32_t n, diff, size, on; struct buf *bp; - daddr_t cn; + daddr_t cn, bn; /* * If they didn't ask for any data, then we are done. @@ -556,10 +556,11 @@ msdosfs_read(void *v) return (error); error = bread(pmp->pm_devvp, cn, size, &bp); } else { + bn = de_cn2bn(pmp, cn); if (de_cn2off(pmp, cn + 1) >= dep->de_FileSize) - error = bread(vp, cn, size, &bp); + error = bread(vp, bn, size, &bp); else - error = bread_cluster(vp, cn, size, &bp); + error = bread_cluster(vp, bn, size, &bp); } n = min(n, pmp->pm_bpcluster - bp->b_resid); if (error) { @@ -588,7 +589,7 @@ msdosfs_write(void *v) uint32_t osize; int error = 0; uint32_t count, lastcn; - daddr_t cn; + daddr_t cn, bn; struct buf *bp; int ioflag = ap->a_ioflag; struct uio *uio = ap->a_uio; @@ -681,18 +682,19 @@ msdosfs_write(void *v) * or we write the cluster from its start beyond EOF, * then no need to read data from disk. */ - bp = getblk(thisvp, cn, pmp->pm_bpcluster, 0, 0); + bn = de_cn2bn(pmp, cn); + bp = getblk(thisvp, bn, pmp->pm_bpcluster, 0, 0); clrbuf(bp); /* * Do the bmap now, since pcbmap needs buffers * for the fat table. (see msdosfs_strategy) */ if (bp->b_blkno == bp->b_lblkno) { - error = pcbmap(dep, bp->b_lblkno, &cn, 0, 0); + error = pcbmap(dep, + de_bn2cn(pmp, bp->b_lblkno), + &bp->b_blkno, 0, 0); if (error) bp->b_blkno = -1; - else - bp->b_blkno = cn; } if (bp->b_blkno == -1) { brelse(bp); @@ -705,7 +707,8 @@ msdosfs_write(void *v) * The block we need to write into exists, so * read it in. */ - error = bread(thisvp, cn, pmp->pm_bpcluster, &bp); + bn = de_cn2bn(pmp, cn); + error = bread(thisvp, bn, pmp->pm_bpcluster, &bp); if (error) { brelse(bp); break; @@ -1820,7 +1823,8 @@ msdosfs_strategy(void *v) * don't allow files with holes, so we shouldn't ever see this. */ if (bp->b_blkno == bp->b_lblkno) { - error = pcbmap(dep, bp->b_lblkno, &bp->b_blkno, 0, 0); + error = pcbmap(dep, de_bn2cn(dep->de_pmp, bp->b_lblkno), + &bp->b_blkno, 0, 0); if (error) bp->b_blkno = -1; if (bp->b_blkno == -1)