diff --git a/sys/fs/mntfs/mntfs_vnops.c b/sys/fs/mntfs/mntfs_vnops.c --- a/sys/fs/mntfs/mntfs_vnops.c +++ b/sys/fs/mntfs/mntfs_vnops.c @@ -89,7 +89,7 @@ void mntfs_freevp(struct vnode *vp) { - + ASSERT_VOP_ELOCKED(vp, "mntfs_freevp"); vgone(vp); - vrele(vp); + vput(vp); } diff --git a/sys/geom/geom_vfs.c b/sys/geom/geom_vfs.c --- a/sys/geom/geom_vfs.c +++ b/sys/geom/geom_vfs.c @@ -302,12 +302,16 @@ { struct g_geom *gp; struct g_vfs_softc *sc; + struct vnode *vp; g_topology_assert(); gp = cp->geom; sc = gp->softc; + vp = cp->private; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); bufobj_invalbuf(sc->sc_bo, V_SAVE, 0, 0); + VOP_UNLOCK(vp); sc->sc_bo->bo_private = cp->private; gp->softc = NULL; mtx_destroy(&sc->sc_mtx); diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -3911,7 +3911,8 @@ CTR3(KTR_BUF, "getblk(%p, %ld, %d)", vp, (long)blkno, size); KASSERT((flags & (GB_UNMAPPED | GB_KVAALLOC)) != GB_KVAALLOC, ("GB_KVAALLOC only makes sense with GB_UNMAPPED")); - ASSERT_VOP_LOCKED(vp, "getblk"); + if (vp->v_type != VCHR) + ASSERT_VOP_LOCKED(vp, "getblk"); if (size > maxbcachebuf) panic("getblk: size(%d) > maxbcachebuf(%d)\n", size, maxbcachebuf); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1896,7 +1896,9 @@ mac_vnode_destroy(vp); #endif if (vp->v_pollinfo != NULL) { + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); destroy_vpollinfo(vp->v_pollinfo); + VOP_UNLOCK(vp); vp->v_pollinfo = NULL; } vp->v_mountedhere = NULL; @@ -5363,13 +5365,6 @@ } #ifdef DEBUG_VFS_LOCKS -/* - * This only exists to suppress warnings from unlocked specfs accesses. It is - * no longer ok to have an unlocked VFS. - */ -#define IGNORE_LOCK(vp) (KERNEL_PANICKED() || (vp) == NULL || \ - (vp)->v_type == VCHR || (vp)->v_type == VBAD) - int vfs_badlock_ddb = 1; /* Drop into debugger on violation. */ SYSCTL_INT(_debug, OID_AUTO, vfs_badlock_ddb, CTLFLAG_RW, &vfs_badlock_ddb, 0, "Drop into debugger on lock violation"); @@ -5429,26 +5424,31 @@ { int locked; - if (!IGNORE_LOCK(vp)) { - locked = VOP_ISLOCKED(vp); - if (locked == 0 || locked == LK_EXCLOTHER) - vfs_badlock("is not locked but should be", str, vp); - } + if (KERNEL_PANICKED() || vp == NULL) + return; + + locked = VOP_ISLOCKED(vp); + if (locked == 0 || locked == LK_EXCLOTHER) + vfs_badlock("is not locked but should be", str, vp); } void assert_vop_unlocked(struct vnode *vp, const char *str) { + if (KERNEL_PANICKED() || vp == NULL) + return; - if (!IGNORE_LOCK(vp) && VOP_ISLOCKED(vp) == LK_EXCLUSIVE) + if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) vfs_badlock("is locked but should not be", str, vp); } void assert_vop_elocked(struct vnode *vp, const char *str) { + if (KERNEL_PANICKED() || vp == NULL) + return; - if (!IGNORE_LOCK(vp) && VOP_ISLOCKED(vp) != LK_EXCLUSIVE) + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) vfs_badlock("is not exclusive locked but should be", str, vp); } #endif /* DEBUG_VFS_LOCKS */ @@ -5536,6 +5536,54 @@ VFS_SMR_ASSERT_ENTERED(); } + +static void +vop_fsync_debugprepost(struct vnode *vp, const char *name) +{ + if (vp->v_type == VCHR) + ; + else if (MNT_EXTENDED_SHARED(vp->v_mount)) + ASSERT_VOP_LOCKED(vp, name); + else + ASSERT_VOP_ELOCKED(vp, name); +} + +void +vop_fsync_debugpre(void *a) +{ + struct vop_fsync_args *ap; + + ap = a; + vop_fsync_debugprepost(ap->a_vp, "fsync"); +} + +void +vop_fsync_debugpost(void *a, int rc __unused) +{ + struct vop_fsync_args *ap; + + ap = a; + vop_fsync_debugprepost(ap-a_vp, "fsync"); +} + +void +vop_fdatasync_debugpre(void *a) +{ + struct vop_fdatasync_args *ap; + + ap = a; + vop_fsync_debugprepost(ap->a_vp, "fsync"); +} + +void +vop_fdatasync_debugpost(void *a, int rc __unused) +{ + struct vop_fdatasync_args *ap; + + ap = a; + vop_fsync_debugprepost(ap-a_vp, "fsync"); +} + void vop_strategy_debugpre(void *ap) { diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -295,7 +295,9 @@ }; -%% fsync vp L L L +%% fsync vp - - - +%! fsync pre vop_fsync_debugpre +%! fsync post vop_fsync_debugpost vop_fsync { IN struct vnode *vp; @@ -769,7 +771,9 @@ }; -%% fdatasync vp L L L +%% fdatasync vp - - - +%! fdatasync pre vop_fdatasync_debugpre +%! fdatasync post vop_fdatasync_debugpost vop_fdatasync { IN struct vnode *vp; diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -927,10 +927,14 @@ int vop_sigdefer(struct vop_vector *vop, struct vop_generic_args *a); #ifdef DEBUG_VFS_LOCKS +void vop_fdatasync_debugpre(void *a); +void vop_fdatasync_debugpost(void *a, int rc); void vop_fplookup_vexec_debugpre(void *a); void vop_fplookup_vexec_debugpost(void *a, int rc); void vop_fplookup_symlink_debugpre(void *a); void vop_fplookup_symlink_debugpost(void *a, int rc); +void vop_fsync_debugpre(void *a); +void vop_fsync_debugpost(void *a, int rc); void vop_strategy_debugpre(void *a); void vop_lock_debugpre(void *a); void vop_lock_debugpost(void *a, int rc); @@ -939,10 +943,14 @@ void vop_need_inactive_debugpost(void *a, int rc); void vop_mkdir_debugpost(void *a, int rc); #else +#define vop_fdatasync_debugpre(x) do { } while (0) +#define vop_fdatasync_debugpost(x, y) do { } while (0) #define vop_fplookup_vexec_debugpre(x) do { } while (0) #define vop_fplookup_vexec_debugpost(x, y) do { } while (0) #define vop_fplookup_symlink_debugpre(x) do { } while (0) #define vop_fplookup_symlink_debugpost(x, y) do { } while (0) +#define vop_fsync_debugpre(x) do { } while (0) +#define vop_fsync_debugpost(x, y) do { } while (0) #define vop_strategy_debugpre(x) do { } while (0) #define vop_lock_debugpre(x) do { } while (0) #define vop_lock_debugpost(x, y) do { } while (0) diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -2251,9 +2251,12 @@ MPASS(devvp->v_mount->mnt_data == ump); dev = ump->um_devvp->v_rdev; } else if (devvp->v_type == VCHR) { - /* devvp is a normal disk device */ + /* + * devvp is a normal disk device + * XXXKIB: devvp is not locked there, v_rdev access depends on + * busy mount, which prevents mntfs devvp from reclamation. + */ dev = devvp->v_rdev; - ASSERT_VOP_LOCKED(devvp, "ffs_blkfree_cg"); } else return; #ifdef INVARIANTS diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -2124,7 +2124,6 @@ } VOP_UNLOCK(vp); VI_LOCK(devvp); - ASSERT_VOP_LOCKED(devvp, "ffs_snapshot_mount"); sn->sn_listsize = snaplistsize; sn->sn_blklist = (daddr_t *)snapblklist; devvp->v_vflag |= VV_COPYONWRITE; @@ -2172,7 +2171,6 @@ sn = devvp->v_rdev->si_snapdata; } try_free_snapdata(devvp); - ASSERT_VOP_LOCKED(devvp, "ffs_snapshot_unmount"); } /* diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -928,6 +928,7 @@ devvp = mntfs_allocvp(mp, odevvp); VOP_UNLOCK(odevvp); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); KASSERT(devvp->v_type == VCHR, ("reclaimed devvp")); dev = devvp->v_rdev; KASSERT(dev->si_snapdata == NULL, ("non-NULL snapshot data")); @@ -949,6 +950,7 @@ BO_LOCK(&odevvp->v_bufobj); odevvp->v_bufobj.bo_flag |= BO_NOBUFS; BO_UNLOCK(&odevvp->v_bufobj); + VOP_UNLOCK(devvp); if (dev->si_iosize_max != 0) mp->mnt_iosize_max = dev->si_iosize_max; if (mp->mnt_iosize_max > maxphys) @@ -1233,6 +1235,7 @@ odevvp->v_bufobj.bo_flag &= ~BO_NOBUFS; BO_UNLOCK(&odevvp->v_bufobj); atomic_store_rel_ptr((uintptr_t *)&dev->si_mountpt, 0); + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); mntfs_freevp(devvp); dev_rel(dev); return (error); @@ -1435,6 +1438,7 @@ ump->um_odevvp->v_bufobj.bo_flag &= ~BO_NOBUFS; BO_UNLOCK(&ump->um_odevvp->v_bufobj); atomic_store_rel_ptr((uintptr_t *)&ump->um_dev->si_mountpt, 0); + vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); mntfs_freevp(ump->um_devvp); vrele(ump->um_odevvp); dev_rel(ump->um_dev); @@ -1511,7 +1515,7 @@ */ } #endif - ASSERT_VOP_LOCKED(ump->um_devvp, "ffs_flushfiles"); + /* devvp is not locked there */ if (ump->um_devvp->v_vflag & VV_COPYONWRITE) { if ((error = vflush(mp, 0, SKIPSYSTEM | flags, td)) != 0) return (error);