svn commit: r355371 - in head/sys: kern sys ufs/ffs

Kirk McKusick mckusick at FreeBSD.org
Tue Dec 3 23:07:11 UTC 2019


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 {
 			/*


More information about the svn-src-all mailing list