svn commit: r305977 - in head/sys/ufs: ffs ufs

Konstantin Belousov kib at FreeBSD.org
Mon Sep 19 15:58:34 UTC 2016


Author: kib
Date: Mon Sep 19 15:58:33 2016
New Revision: 305977
URL: https://svnweb.freebsd.org/changeset/base/305977

Log:
  Be more strict when selecting between snapshot/regular mount.
  
  Reclaimed vnode type is VBAD, so succesful comparision like
  devvp->v_type != VREG does not imply that the devvp references
  snapshot, it might be due to a reclaimed vnode.  Explicitely check the
  vnode type.
  
  In the the most important case of ffs_blkfree(), the devfs vnode is
  locked and its type is stable.  In other cases, if the vnode is
  reclaimed right after the check, hopefully the buffer methods return
  right error codes.
  
  Reviewed by:	mckusick
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Modified:
  head/sys/ufs/ffs/ffs_alloc.c
  head/sys/ufs/ufs/ufs_gjournal.c

Modified: head/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- head/sys/ufs/ffs/ffs_alloc.c	Mon Sep 19 15:39:24 2016	(r305976)
+++ head/sys/ufs/ffs/ffs_alloc.c	Mon Sep 19 15:58:33 2016	(r305977)
@@ -2171,12 +2171,13 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size
 		MPASS(devvp->v_mount->mnt_data == ump);
 		dev = ump->um_devvp->v_rdev;
 		cgblkno = fragstoblks(fs, cgtod(fs, cg));
-	} else {
+	} else if (devvp->v_type == VCHR) {
 		/* devvp is a normal disk device */
 		dev = devvp->v_rdev;
 		cgblkno = fsbtodb(fs, cgtod(fs, cg));
 		ASSERT_VOP_LOCKED(devvp, "ffs_blkfree_cg");
-	}
+	} else
+		return;
 #ifdef INVARIANTS
 	if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 ||
 	    fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
@@ -2270,7 +2271,7 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size
 	ACTIVECLEAR(fs, cg);
 	UFS_UNLOCK(ump);
 	mp = UFSTOVFS(ump);
-	if (MOUNTEDSOFTDEP(mp) && devvp->v_type != VREG)
+	if (MOUNTEDSOFTDEP(mp) && devvp->v_type == VCHR)
 		softdep_setup_blkfree(UFSTOVFS(ump), bp, bno,
 		    numfrags(fs, size), dephd);
 	bdwrite(bp);
@@ -2335,7 +2336,7 @@ ffs_blkfree(ump, fs, devvp, bno, size, i
 	 * it has a snapshot(s) associated with it, and one of the
 	 * snapshots wants to claim the block.
 	 */
-	if (devvp->v_type != VREG &&
+	if (devvp->v_type == VCHR &&
 	    (devvp->v_vflag & VV_COPYONWRITE) &&
 	    ffs_snapblkfree(fs, devvp, bno, size, inum, vtype, dephd)) {
 		return;
@@ -2480,10 +2481,13 @@ ffs_freefile(ump, fs, devvp, ino, mode, 
 		MPASS(devvp->v_mount->mnt_data == ump);
 		dev = ump->um_devvp->v_rdev;
 		cgbno = fragstoblks(fs, cgtod(fs, cg));
-	} else {
+	} else if (devvp->v_type == VCHR) {
 		/* devvp is a normal disk device */
 		dev = devvp->v_rdev;
 		cgbno = fsbtodb(fs, cgtod(fs, cg));
+	} else {
+		bp = NULL;
+		return (0);
 	}
 	if (ino >= fs->fs_ipg * fs->fs_ncg)
 		panic("ffs_freefile: range: dev = %s, ino = %ju, fs = %s",
@@ -2522,7 +2526,7 @@ ffs_freefile(ump, fs, devvp, ino, mode, 
 	fs->fs_fmod = 1;
 	ACTIVECLEAR(fs, cg);
 	UFS_UNLOCK(ump);
-	if (MOUNTEDSOFTDEP(UFSTOVFS(ump)) && devvp->v_type != VREG)
+	if (MOUNTEDSOFTDEP(UFSTOVFS(ump)) && devvp->v_type == VCHR)
 		softdep_setup_inofree(UFSTOVFS(ump), bp,
 		    ino + cg * fs->fs_ipg, wkhd);
 	bdwrite(bp);
@@ -2549,9 +2553,11 @@ ffs_checkfreefile(fs, devvp, ino)
 	if (devvp->v_type == VREG) {
 		/* devvp is a snapshot */
 		cgbno = fragstoblks(fs, cgtod(fs, cg));
-	} else {
+	} else if (devvp->v_type == VCHR) {
 		/* devvp is a normal disk device */
 		cgbno = fsbtodb(fs, cgtod(fs, cg));
+	} else {
+		return (1);
 	}
 	if (ino >= fs->fs_ipg * fs->fs_ncg)
 		return (1);

Modified: head/sys/ufs/ufs/ufs_gjournal.c
==============================================================================
--- head/sys/ufs/ufs/ufs_gjournal.c	Mon Sep 19 15:39:24 2016	(r305976)
+++ head/sys/ufs/ufs/ufs_gjournal.c	Mon Sep 19 15:58:33 2016	(r305977)
@@ -71,14 +71,17 @@ ufs_gjournal_modref(struct vnode *vp, in
 	ino = ip->i_number;
 
 	cg = ino_to_cg(fs, ino);
-	if (devvp->v_type != VCHR) {
+	if (devvp->v_type == VREG) {
 		/* devvp is a snapshot */
 		dev = VFSTOUFS(devvp->v_mount)->um_devvp->v_rdev;
 		cgbno = fragstoblks(fs, cgtod(fs, cg));
-	} else {
+	} else if (devvp->v_type == VCHR) {
 		/* devvp is a normal disk device */
 		dev = devvp->v_rdev;
 		cgbno = fsbtodb(fs, cgtod(fs, cg));
+	} else {
+		bp = NULL;
+		return (EIO);
 	}
 	if ((u_int)ino >= fs->fs_ipg * fs->fs_ncg)
 		panic("ufs_gjournal_modref: range: dev = %s, ino = %lu, fs = %s",


More information about the svn-src-head mailing list