diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c --- a/sys/fs/msdosfs/msdosfs_denode.c +++ b/sys/fs/msdosfs/msdosfs_denode.c @@ -428,11 +428,12 @@ if ((boff = length & pmp->pm_crbomask) != 0) { if (isadir) { bn = cntobn(pmp, eofentry); - error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster, + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, pmp->pm_bpcluster, NOCRED, &bp); } else { - error = bread(DETOV(dep), de_cluster(pmp, length), - pmp->pm_bpcluster, cred, &bp); + bn = de_cluster(pmp, length); + error = breadb(DETOV(dep), bntocbn(pmp, bn), bn, pmp->pm_bpcluster, + cred, &bp); } if (error) { #ifdef MSDOSFS_DEBUG @@ -503,6 +504,7 @@ struct msdosfsmount *pmp = dep->de_pmp; struct vnode *vp = DETOV(dep); struct buf *bp; + daddr_t bn; off_t eof_clusteroff; u_long count; int error; @@ -547,7 +549,8 @@ * actual buffer content which might exist in the tail of the * already valid cluster. */ - error = bread(vp, de_cluster(pmp, dep->de_FileSize), pmp->pm_bpcluster, + bn = de_cluster(pmp, dep->de_FileSize); + error = breadb(vp, bntocbn(pmp, bn), bn, pmp->pm_bpcluster, NOCRED, &bp); if (error != 0) goto rewind; diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c --- a/sys/fs/msdosfs/msdosfs_fat.c +++ b/sys/fs/msdosfs/msdosfs_fat.c @@ -204,7 +204,8 @@ if (bn != bp_bn) { if (bp) brelse(bp); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, bsize, + NOCRED, &bp); if (error) { return (error); } @@ -509,7 +510,8 @@ byteoffset = FATOFS(pmp, cn); fatblock(pmp, byteoffset, &bn, &bsize, &bo); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, bsize, + NOCRED, &bp); if (error) { return (error); } @@ -591,7 +593,8 @@ while (count > 0) { byteoffset = FATOFS(pmp, start); fatblock(pmp, byteoffset, &bn, &bsize, &bo); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, bsize, + NOCRED, &bp); if (error) { return (error); } @@ -845,7 +848,8 @@ if (lbn != bn) { if (bp) updatefats(pmp, bp, lbn); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, bsize, + NOCRED, &bp); if (error) { MSDOSFS_UNLOCK_MP(pmp); return (error); @@ -927,7 +931,8 @@ if (bp != NULL) brelse(bp); fatblock(pmp, byteoffset, &bn, &bsize, NULL); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, bsize, + NOCRED, &bp); if (error != 0) return (error); } @@ -1160,7 +1165,8 @@ */ byteoffset = FATOFS(pmp, 1); fatblock(pmp, byteoffset, &bn, &bsize, &bo); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, bsize, + NOCRED, &bp); if (error) return (error); diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c --- a/sys/fs/msdosfs/msdosfs_lookup.c +++ b/sys/fs/msdosfs/msdosfs_lookup.c @@ -253,7 +253,8 @@ break; return (error); } - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, blsize, + NOCRED, &bp); if (error) { return (error); } @@ -678,7 +679,8 @@ diroffset = ddep->de_fndoffset; if (dirclust != MSDOSFSROOT) diroffset &= pmp->pm_crbomask; - if ((error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp)) != 0) { + if ((error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, blsize, + NOCRED, &bp)) != 0) { brelse(bp); return error; } @@ -711,8 +713,8 @@ if (error) return error; - error = bread(pmp->pm_devvp, bn, blsize, - NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), + bn, blsize, NOCRED, &bp); if (error) { return error; } @@ -778,7 +780,8 @@ return (1); /* it's empty */ return (0); } - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, blsize, + NOCRED, &bp); if (error) { return (0); } @@ -834,6 +837,7 @@ doscheckpath(struct denode *source, struct denode *target, daddr_t *wait_scn) { daddr_t scn; + daddr_t bn; struct msdosfsmount *pmp; struct direntry *ep; struct denode *dep; @@ -866,7 +870,8 @@ break; } scn = dep->de_StartCluster; - error = bread(pmp->pm_devvp, cntobn(pmp, scn), + bn = cntobn(pmp, scn); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, pmp->pm_bpcluster, NOCRED, &bp); if (error != 0) break; @@ -934,7 +939,8 @@ && de_blk(pmp, diroffset + blsize) > pmp->pm_rootdirsize) blsize = de_bn2off(pmp, pmp->pm_rootdirsize) & pmp->pm_crbomask; bn = detobn(pmp, dirclust, diroffset); - if ((error = bread(pmp->pm_devvp, bn, blsize, NOCRED, bpp)) != 0) { + if ((error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, blsize, + NOCRED, bpp)) != 0) { brelse(*bpp); *bpp = NULL; return (error); @@ -991,7 +997,8 @@ error = pcbmap(pdep, de_cluster(pmp, offset), &bn, 0, &blsize); if (error) return error; - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, blsize, + NOCRED, &bp); if (error) { return error; } @@ -1068,7 +1075,8 @@ return 0; return error; } - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, blsize, + NOCRED, &bp); if (error) { return error; } diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -457,7 +457,8 @@ printf("rootdir_free: dirclu=%d dirleft=%d readsize=%lu\n", dirclu, dirleft, readsize); #endif - if (bread(pmp->pm_devvp, dirclu, readsize, NOCRED, &bp) != 0) { + if (breadb(pmp->pm_devvp, bntocbn(pmp, dirclu), dirclu, readsize, + NOCRED, &bp) != 0) { printf("rootdir_free: read error\n"); if (bp != NULL) brelse(bp); @@ -757,6 +758,12 @@ goto error_exit; } + pmp->pm_cacheblockoffs = -pmp->pm_firstcluster % de_off2bn(pmp, PAGE_SIZE); +#ifdef MSDOSFS_DEBUG + printf("logblockoffs: firstcluster=%lu bpcluster=%lu bnshift=%lu blockoffs=%lu\n", + pmp->pm_firstcluster, pmp->pm_bpcluster, pmp->pm_bnshift, pmp->pm_cacheblockoffs); +#endif + /* * Release the bootsector buffer. */ @@ -771,8 +778,10 @@ */ if (pmp->pm_fsinfo) { struct fsinfo *fp; + daddr_t bn; - if ((error = bread(devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec, + bn = pmp->pm_fsinfo; + if ((error = breadb(devvp, bntocbn(pmp, bn), bn, pmp->pm_BytesPerSec, NOCRED, &bp)) != 0) goto error_exit; fp = (struct fsinfo *)bp->b_data; @@ -1073,6 +1082,7 @@ { struct fsinfo *fp; struct buf *bp; + daddr_t bn; int error; MSDOSFS_LOCK_MP(pmp); @@ -1080,7 +1090,8 @@ error = 0; goto unlock; } - error = bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec, + bn = pmp->pm_fsinfo; + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, pmp->pm_BytesPerSec, NOCRED, &bp); if (error != 0) { goto unlock; diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -573,18 +573,19 @@ break; } else if (error) break; - error = bread(pmp->pm_devvp, lbn, blsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, lbn), lbn, blsize, + NOCRED, &bp); } else if (de_cn2off(pmp, rablock) >= dep->de_FileSize) { - error = bread(vp, lbn, blsize, NOCRED, &bp); + error = breadb(vp, bntocbn(pmp, lbn), lbn, blsize, NOCRED, &bp); } else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { error = cluster_read(vp, dep->de_FileSize, lbn, blsize, NOCRED, on + uio->uio_resid, seqcount, 0, &bp); } else if (seqcount > 1) { rasize = blsize; - error = breadn(vp, lbn, + error = breadbn(vp, bntocbn(pmp, lbn), lbn, blsize, &rablock, &rasize, 1, NOCRED, &bp); } else { - error = bread(vp, lbn, blsize, NOCRED, &bp); + error = breadb(vp, bntocbn(pmp, lbn), lbn, blsize, NOCRED, &bp); } if (error) { brelse(bp); @@ -758,7 +759,8 @@ /* * The block we need to write into exists, so read it in. */ - error = bread(thisvp, bn, pmp->pm_bpcluster, cred, &bp); + error = breadb(thisvp, bntocbn(pmp, bn), bn, pmp->pm_bpcluster, + cred, &bp); if (error) { break; } @@ -1237,10 +1239,10 @@ if (cn == MSDOSFSROOT) { /* this should never happen */ panic("msdosfs_rename(): updating .. in root directory?"); - } else - bn = cntobn(pmp, cn); - error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster, - NOCRED, &bp); + } + bn = cntobn(pmp, cn); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, + pmp->pm_bpcluster, NOCRED, &bp); if (error != 0) { printf("%s: block read error %d while renaming dir\n", pmp->pm_mountp->mnt_stat.f_mntonname, @@ -1629,7 +1631,8 @@ error = pcbmap(dep, lbn, &bn, &cn, &blsize); if (error) break; - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); + error = breadb(pmp->pm_devvp, bntocbn(pmp, bn), bn, blsize, + NOCRED, &bp); if (error) { return (error); } diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h --- a/sys/fs/msdosfs/msdosfsmount.h +++ b/sys/fs/msdosfs/msdosfsmount.h @@ -91,6 +91,7 @@ u_long pm_rootdirblk; /* block # (cluster # for FAT32) of root directory number */ u_long pm_rootdirsize; /* size in blocks (not clusters) */ u_long pm_firstcluster; /* block number of first cluster */ + u_long pm_cacheblockoffs; /* offset from physical block to buffer cache block number */ u_long pm_maxcluster; /* maximum cluster number */ u_long pm_freeclustercount; /* number of free clusters */ u_long pm_cnshift; /* shift file offset right this amount to get a cluster number */ @@ -201,6 +202,13 @@ */ #define de_bn2off(pmp, bn) \ ((bn) << (pmp)->pm_bnshift) + +/* + * Convert offset to block number + */ +#define de_off2bn(pmp, off) \ + ((off) >> (pmp)->pm_bnshift) + /* * Map a cluster number into a filesystem relative block number. */ @@ -213,6 +221,12 @@ #define roottobn(pmp, dirofs) \ (de_blk((pmp), (dirofs)) + (pmp)->pm_rootdirblk) +/* + * Calculate buffer cache block number from disk block number + */ +#define bntocbn(pmp, bn) \ + ((pmp)->pm_cacheblockoffs + (bn)) + /* * Calculate block number for directory entry at cluster dirclu, offset * dirofs diff --git a/sys/sys/buf.h b/sys/sys/buf.h --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -542,12 +542,18 @@ #define bread(vp, blkno, size, cred, bpp) \ breadn_flags(vp, blkno, blkno, size, NULL, NULL, 0, cred, 0, \ NULL, bpp) +#define breadb(vp, blkno, dblkno, size, cred, bpp) \ + breadn_flags(vp, blkno, dblkno, size, NULL, NULL, 0, cred, 0, \ + NULL, bpp) #define bread_gb(vp, blkno, size, cred, gbflags, bpp) \ breadn_flags(vp, blkno, blkno, size, NULL, NULL, 0, cred, \ gbflags, NULL, bpp) #define breadn(vp, blkno, size, rablkno, rabsize, cnt, cred, bpp) \ breadn_flags(vp, blkno, blkno, size, rablkno, rabsize, cnt, cred, \ 0, NULL, bpp) +#define breadbn(vp, blkno, dblkno, size, rablkno, rabsize, cnt, cred, bpp) \ + breadn_flags(vp, blkno, dblkno, size, rablkno, rabsize, cnt, cred, \ + 0, NULL, bpp) int breadn_flags(struct vnode *, daddr_t, daddr_t, int, daddr_t *, int *, int, struct ucred *, int, void (*)(struct buf *), struct buf **); void bdwrite(struct buf *);