On 29/05/17(Mon) 14:15, Stefan Fritsch wrote:
> 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.

A complete diff would be easier to review.

> 
> 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)
> 

Reply via email to