Date: Tue, 3 Dec 2019 23:07:09 +0000 (UTC) From: Kirk McKusick <mckusick@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r355371 - in head/sys: kern sys ufs/ffs Message-ID: <201912032307.xB3N79DG016921@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mckusick Date: Tue Dec 3 23:07:09 2019 New Revision: 355371 URL: https://svnweb.freebsd.org/changeset/base/355371 Log: Currently the breadn_flags() and getblkx() interfaces are passed the vnode, logical block number, and size of data block that is being requested. They then use the VOP_BMAP function to calculate the mapping from logical block number to physical block number from which to access the data. This change expands the interface to also pass the physical block number in cases where the VOP_MAP function may no longer work, for example when a file is being truncated. No functional change. Reviewed by: kib Tested by: Peter Holm Sponsored by: Netflix Modified: head/sys/kern/vfs_bio.c head/sys/kern/vfs_cluster.c head/sys/sys/buf.h head/sys/ufs/ffs/ffs_alloc.c head/sys/ufs/ffs/ffs_inode.c head/sys/ufs/ffs/ffs_softdep.c head/sys/ufs/ffs/ffs_vnops.c Modified: head/sys/kern/vfs_bio.c ============================================================================== --- head/sys/kern/vfs_bio.c Tue Dec 3 22:59:55 2019 (r355370) +++ head/sys/kern/vfs_bio.c Tue Dec 3 23:07:09 2019 (r355371) @@ -2126,10 +2126,17 @@ breada(struct vnode * vp, daddr_t * rablkno, int * rab * getblk(). Also starts asynchronous I/O on read-ahead blocks. * * Always return a NULL buffer pointer (in bpp) when returning an error. + * + * The blkno parameter is the logical block being requested. Normally + * the mapping of logical block number to disk block address is done + * by calling VOP_BMAP(). However, if the mapping is already known, the + * disk block address can be passed using the dblkno parameter. If the + * disk block address is not known, then the same value should be passed + * for blkno and dblkno. */ int -breadn_flags(struct vnode *vp, daddr_t blkno, int size, daddr_t *rablkno, - int *rabsize, int cnt, struct ucred *cred, int flags, +breadn_flags(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size, + daddr_t *rablkno, int *rabsize, int cnt, struct ucred *cred, int flags, void (*ckhashfunc)(struct buf *), struct buf **bpp) { struct buf *bp; @@ -2142,11 +2149,14 @@ breadn_flags(struct vnode *vp, daddr_t blkno, int size * Can only return NULL if GB_LOCK_NOWAIT or GB_SPARSE flags * are specified. */ - error = getblkx(vp, blkno, size, 0, 0, flags, &bp); + error = getblkx(vp, blkno, dblkno, size, 0, 0, flags, &bp); if (error != 0) { *bpp = NULL; return (error); } + KASSERT(blkno == bp->b_lblkno, + ("getblkx returned buffer for blkno %jd instead of blkno %jd", + (intmax_t)bp->b_lblkno, (intmax_t)blkno)); flags &= ~GB_NOSPARSE; *bpp = bp; @@ -3791,7 +3801,7 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int struct buf *bp; int error; - error = getblkx(vp, blkno, size, slpflag, slptimeo, flags, &bp); + error = getblkx(vp, blkno, blkno, size, slpflag, slptimeo, flags, &bp); if (error != 0) return (NULL); return (bp); @@ -3819,7 +3829,7 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int * case it is returned with B_INVAL clear and B_CACHE set based on the * backing VM. * - * getblk() also forces a bwrite() for any B_DELWRI buffer whos + * getblk() also forces a bwrite() for any B_DELWRI buffer whose * B_CACHE bit is clear. * * What this means, basically, is that the caller should use B_CACHE to @@ -3832,10 +3842,17 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int * a write attempt or if it was a successful read. If the caller * intends to issue a READ, the caller must clear B_INVAL and BIO_ERROR * prior to issuing the READ. biodone() will *not* clear B_INVAL. + * + * The blkno parameter is the logical block being requested. Normally + * the mapping of logical block number to disk block address is done + * by calling VOP_BMAP(). However, if the mapping is already known, the + * disk block address can be passed using the dblkno parameter. If the + * disk block address is not known, then the same value should be passed + * for blkno and dblkno. */ int -getblkx(struct vnode *vp, daddr_t blkno, int size, int slpflag, int slptimeo, - int flags, struct buf **bpp) +getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size, int slpflag, + int slptimeo, int flags, struct buf **bpp) { struct buf *bp; struct bufobj *bo; @@ -3854,7 +3871,7 @@ getblkx(struct vnode *vp, daddr_t blkno, int size, int flags &= ~(GB_UNMAPPED | GB_KVAALLOC); bo = &vp->v_bufobj; - d_blkno = blkno; + d_blkno = dblkno; loop: BO_RLOCK(bo); bp = gbincore(bo, blkno); Modified: head/sys/kern/vfs_cluster.c ============================================================================== --- head/sys/kern/vfs_cluster.c Tue Dec 3 22:59:55 2019 (r355370) +++ head/sys/kern/vfs_cluster.c Tue Dec 3 23:07:09 2019 (r355371) @@ -131,7 +131,7 @@ cluster_read(struct vnode *vp, u_quad_t filesize, dadd /* * get the requested block */ - error = getblkx(vp, lblkno, size, 0, 0, gbflags, &bp); + error = getblkx(vp, lblkno, lblkno, size, 0, 0, gbflags, &bp); if (error != 0) { *bpp = NULL; return (error); Modified: head/sys/sys/buf.h ============================================================================== --- head/sys/sys/buf.h Tue Dec 3 22:59:55 2019 (r355370) +++ head/sys/sys/buf.h Tue Dec 3 23:07:09 2019 (r355371) @@ -520,15 +520,16 @@ int buf_dirty_count_severe(void); void bremfree(struct buf *); void bremfreef(struct buf *); /* XXX Force bremfree, only for nfs. */ #define bread(vp, blkno, size, cred, bpp) \ - breadn_flags(vp, blkno, size, NULL, NULL, 0, cred, 0, NULL, bpp) + breadn_flags(vp, blkno, blkno, size, NULL, NULL, 0, cred, 0, \ + NULL, bpp) #define bread_gb(vp, blkno, size, cred, gbflags, bpp) \ - breadn_flags(vp, blkno, size, NULL, NULL, 0, cred, \ + 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, size, rablkno, rabsize, cnt, cred, \ + breadn_flags(vp, blkno, blkno, size, rablkno, rabsize, cnt, cred, \ 0, NULL, bpp) -int breadn_flags(struct vnode *, daddr_t, int, daddr_t *, int *, int, - struct ucred *, int, void (*)(struct buf *), struct buf **); +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 *); void bawrite(struct buf *); void babarrierwrite(struct buf *); @@ -544,8 +545,8 @@ void vfs_busy_pages_release(struct buf *bp); struct buf *incore(struct bufobj *, daddr_t); struct buf *gbincore(struct bufobj *, daddr_t); struct buf *getblk(struct vnode *, daddr_t, int, int, int, int); -int getblkx(struct vnode *vp, daddr_t blkno, int size, int slpflag, - int slptimeo, int flags, struct buf **bpp); +int getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size, + int slpflag, int slptimeo, int flags, struct buf **bpp); struct buf *geteblk(int, int); int bufwait(struct buf *); int bufwrite(struct buf *); Modified: head/sys/ufs/ffs/ffs_alloc.c ============================================================================== --- head/sys/ufs/ffs/ffs_alloc.c Tue Dec 3 22:59:55 2019 (r355370) +++ head/sys/ufs/ffs/ffs_alloc.c Tue Dec 3 23:07:09 2019 (r355371) @@ -2955,16 +2955,19 @@ ffs_getcg(fs, devvp, cg, flags, bpp, cgpp) struct buf *bp; struct cg *cgp; const struct statfs *sfs; + daddr_t blkno; int error; *bpp = NULL; *cgpp = NULL; if ((fs->fs_metackhash & CK_CYLGRP) != 0) flags |= GB_CKHASH; - error = breadn_flags(devvp, devvp->v_type == VREG ? - fragstoblks(fs, cgtod(fs, cg)) : fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NULL, NULL, 0, NOCRED, flags, - ffs_ckhash_cg, &bp); + if (devvp->v_type == VREG) + blkno = fragstoblks(fs, cgtod(fs, cg)); + else + blkno = fsbtodb(fs, cgtod(fs, cg)); + error = breadn_flags(devvp, blkno, blkno, (int)fs->fs_cgsize, NULL, + NULL, 0, NOCRED, flags, ffs_ckhash_cg, &bp); if (error != 0) return (error); cgp = (struct cg *)bp->b_data; Modified: head/sys/ufs/ffs/ffs_inode.c ============================================================================== --- head/sys/ufs/ffs/ffs_inode.c Tue Dec 3 22:59:55 2019 (r355370) +++ head/sys/ufs/ffs/ffs_inode.c Tue Dec 3 23:07:09 2019 (r355371) @@ -678,34 +678,14 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) * Get buffer of block pointers, zero those entries corresponding * to blocks to be free'd, and update on disk copy first. Since * double(triple) indirect before single(double) indirect, calls - * to bmap on these blocks will fail. However, we already have - * the on disk address, so we have to set the b_blkno field - * explicitly instead of letting bread do everything for us. + * to VOP_BMAP() on these blocks will fail. However, we already + * have the on-disk address, so we just pass it to bread() instead + * of having bread() attempt to calculate it using VOP_BMAP(). */ vp = ITOV(ip); - bp = getblk(vp, lbn, (int)fs->fs_bsize, 0, 0, 0); - if ((bp->b_flags & B_CACHE) == 0) { -#ifdef RACCT - if (racct_enable) { - PROC_LOCK(curproc); - racct_add_buf(curproc, bp, 0); - PROC_UNLOCK(curproc); - } -#endif /* RACCT */ - curthread->td_ru.ru_inblock++; /* pay for read */ - bp->b_iocmd = BIO_READ; - bp->b_flags &= ~B_INVAL; - bp->b_ioflags &= ~BIO_ERROR; - if (bp->b_bcount > bp->b_bufsize) - panic("ffs_indirtrunc: bad buffer size"); - bp->b_blkno = dbn; - vfs_busy_pages(bp, 0); - bp->b_iooffset = dbtob(bp->b_blkno); - bstrategy(bp); - error = bufwait(bp); - } + error = breadn_flags(vp, lbn, dbn, (int)fs->fs_bsize, NULL, NULL, 0, + NOCRED, 0, NULL, &bp); if (error) { - brelse(bp); *countp = 0; return (error); } Modified: head/sys/ufs/ffs/ffs_softdep.c ============================================================================== --- head/sys/ufs/ffs/ffs_softdep.c Tue Dec 3 22:59:55 2019 (r355370) +++ head/sys/ufs/ffs/ffs_softdep.c Tue Dec 3 23:07:09 2019 (r355371) @@ -6294,29 +6294,15 @@ setup_trunc_indir(freeblks, ip, lbn, lastlbn, blkno) return (0); mp = freeblks->fb_list.wk_mp; ump = VFSTOUFS(mp); - bp = getblk(ITOV(ip), lbn, mp->mnt_stat.f_iosize, 0, 0, 0); - if ((bp->b_flags & B_CACHE) == 0) { - bp->b_blkno = blkptrtodb(VFSTOUFS(mp), blkno); - bp->b_iocmd = BIO_READ; - bp->b_flags &= ~B_INVAL; - bp->b_ioflags &= ~BIO_ERROR; - vfs_busy_pages(bp, 0); - bp->b_iooffset = dbtob(bp->b_blkno); - bstrategy(bp); -#ifdef RACCT - if (racct_enable) { - PROC_LOCK(curproc); - racct_add_buf(curproc, bp, 0); - PROC_UNLOCK(curproc); - } -#endif /* RACCT */ - curthread->td_ru.ru_inblock++; - error = bufwait(bp); - if (error) { - brelse(bp); - return (error); - } - } + /* + * Here, calls to VOP_BMAP() will fail. However, we already have + * the on-disk address, so we just pass it to bread() instead of + * having bread() attempt to calculate it using VOP_BMAP(). + */ + error = breadn_flags(ITOV(ip), lbn, blkptrtodb(ump, blkno), + (int)mp->mnt_stat.f_iosize, NULL, NULL, 0, NOCRED, 0, NULL, &bp); + if (error) + return (error); level = lbn_level(lbn); lbnadd = lbn_offset(ump->um_fs, level); /* Modified: head/sys/ufs/ffs/ffs_vnops.c ============================================================================== --- head/sys/ufs/ffs/ffs_vnops.c Tue Dec 3 22:59:55 2019 (r355370) +++ head/sys/ufs/ffs/ffs_vnops.c Tue Dec 3 23:07:09 2019 (r355371) @@ -603,7 +603,7 @@ ffs_read(ap) * the 6th argument. */ u_int nextsize = blksize(fs, ip, nextlbn); - error = breadn_flags(vp, lbn, size, &nextlbn, + error = breadn_flags(vp, lbn, lbn, size, &nextlbn, &nextsize, 1, NOCRED, bflag, NULL, &bp); } else { /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912032307.xB3N79DG016921>