Index: sys/ufs/ffs/ffs_snapshot.c =================================================================== --- sys/ufs/ffs/ffs_snapshot.c +++ sys/ufs/ffs/ffs_snapshot.c @@ -368,8 +368,12 @@ if (error) goto out; bawrite(nbp); - if (cg % 10 == 0) - ffs_syncvnode(vp, MNT_WAIT, 0); + if (cg % 10 == 0) { + error = ffs_syncvnode(vp, MNT_WAIT, 0); + /* vp possibly reclaimed if unlocked */ + if (error != 0) + goto out; + } } /* * Copy all the cylinder group maps. Although the @@ -391,8 +395,8 @@ goto out; error = cgaccount(cg, vp, nbp, 1); bawrite(nbp); - if (cg % 10 == 0) - ffs_syncvnode(vp, MNT_WAIT, 0); + if (cg % 10 == 0 && error == 0) + error = ffs_syncvnode(vp, MNT_WAIT, 0); if (error) goto out; } Index: sys/ufs/ffs/ffs_softdep.c =================================================================== --- sys/ufs/ffs/ffs_softdep.c +++ sys/ufs/ffs/ffs_softdep.c @@ -1389,6 +1389,46 @@ /* List of all filesystems mounted with soft updates */ static TAILQ_HEAD(, mount_softdeps) softdepmounts; +static int +get_parent_vp(struct vnode *vp, struct mount *mp, ino_t inum, + struct vnode **rvp) +{ + struct vnode *pvp; + int error; + + ASSERT_VOP_ELOCKED(vp, "child vnode must be locked"); + for (;;) { + error = ffs_vgetf(mp, inum, LK_NOWAIT | LK_EXCLUSIVE, &pvp, + FFSV_FORCEINSMQ); + if (error == 0) { + *rvp = pvp; + return (0); + } + VOP_UNLOCK(vp); + error = ffs_vgetf(mp, inum, LK_EXCLUSIVE, &pvp, FFSV_FORCEINSMQ); + if (error != 0) { + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + return (error); + } + MPASS(VTOI(pvp)->i_mode != 0); + error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOWAIT); + if (error == 0) + break; + vput(pvp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (VN_IS_DOOMED(vp)) + return (ENOENT); + } + if (VN_IS_DOOMED(vp)) { + if (error == 0) + vput(*rvp); + error = ENOENT; + } + if (error == 0) + *rvp = pvp; + return (error); +} + /* * This function cleans the worklist for a filesystem. * Each filesystem running with soft dependencies gets its own @@ -12629,25 +12669,9 @@ * for details on possible races. */ FREE_LOCK(ump); - if (ffs_vgetf(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp, - FFSV_FORCEINSMQ)) { - /* - * Unmount cannot proceed after unlock because - * caller must have called vn_start_write(). - */ - VOP_UNLOCK(vp); - error = ffs_vgetf(mp, parentino, LK_EXCLUSIVE, - &pvp, FFSV_FORCEINSMQ); - MPASS(VTOI(pvp)->i_mode != 0); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - if (VN_IS_DOOMED(vp)) { - if (error == 0) - vput(pvp); - error = ENOENT; - } - if (error != 0) - return (error); - } + error = get_parent_vp(vp, mp, parentino, &pvp); + if (error != 0) + return (error); /* * All MKDIR_PARENT dependencies and all the NEWBLOCK pagedeps * that are contained in direct blocks will be resolved by @@ -13278,10 +13302,9 @@ } if (dap->da_state & MKDIR_BODY) { FREE_LOCK(ump); - if ((error = ffs_vgetf(mp, inum, LK_EXCLUSIVE, &vp, - FFSV_FORCEINSMQ))) + error = get_parent_vp(pvp, mp, inum, &vp); + if (error != 0) break; - MPASS(VTOI(vp)->i_mode != 0); error = flush_newblk_dep(vp, mp, 0); /* * If we still have the dependency we might need to @@ -13343,10 +13366,9 @@ */ if (dap == LIST_FIRST(diraddhdp)) { FREE_LOCK(ump); - if ((error = ffs_vgetf(mp, inum, LK_EXCLUSIVE, &vp, - FFSV_FORCEINSMQ))) + error = get_parent_vp(pvp, mp, inum, &vp); + if (error) break; - MPASS(VTOI(vp)->i_mode != 0); error = ffs_update(vp, 1); vput(vp); if (error)