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",
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to