Date: Mon, 19 Sep 2016 15:58:33 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r305977 - in head/sys/ufs: ffs ufs Message-ID: <201609191558.u8JFwXW7029334@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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",
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609191558.u8JFwXW7029334>