Date: Sat, 12 Jan 2008 13:02:15 +0100 From: Kris Kennaway <kris@FreeBSD.org> To: Darren Pilgrim <freebsd@bitfreak.org> Cc: freebsd-questions@freebsd.org Subject: Re: Unable to unmount idle filesystem on 6.2 Message-ID: <4788AC47.5060404@FreeBSD.org> In-Reply-To: <47882812.1010403@bitfreak.org> References: <47871856.2070505@bitfreak.org> <47874B18.5020408@FreeBSD.org> <47882812.1010403@bitfreak.org>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------080708010808070208070809 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Darren Pilgrim wrote: > Kris Kennaway wrote: >> Darren Pilgrim wrote: >>> I'm unable to unmount an idle filesystem (or even drop it to >>> read-only): >>> >>> # mount >>> /dev/da0s1a on / (ufs, local, noatime) >>> devfs on /dev (devfs, local) >>> /dev/da0s1d on /var (ufs, local, noatime, soft-updates) >>> /dev/da0s1e on /usr (ufs, local, noatime, soft-updates) >>> /dev/da0s1fp1 on /usr/obj (ufs, asynchronous, local, noatime) >>> /dev/da0s1fp2 on /usr/ports (ufs, local, soft-updates) >>> /dev/da0s1fp3 on /usr/src (ufs, local, soft-updates) >>> /dev/da0s2d on /data (ufs, local, noatime, soft-updates) >>> >>> # fstat -f /usr/ports >>> USER CMD PID FD MOUNT INUM MODE SZ|DV R/W >>> >>> # umount /usr/ports >>> umount: unmount of /usr/ports failed: Device busy >>> >>> # umount -f /usr/ports >>> umount: unmount of /usr/ports failed: Device busy >>> >>> # mount -o ro /usr/ports >>> mount: /dev/da0s1fp2: Operation not permitted >>> >>> # uname -r >>> 6.2-RELEASE-p8 >>> _______________________________________________ >>> freebsd-questions@freebsd.org mailing list >>> http://lists.freebsd.org/mailman/listinfo/freebsd-questions >>> To unsubscribe, send any mail to >>> "freebsd-questions-unsubscribe@freebsd.org" >>> >>> >> >> Strange, can you break to DDB and do 'show lockedvnods'? > > I haven't done that yet; however, I did find 12 instances of the > following in the log: > > softdep_waitidle: Failed to flush worklist for 0xc66e5298 > > A quick check and that message gets spit out whenever I issue any of the > following commands: > > # mount -uo ro /usr/ports > # umount /usr/ports > # umount -f /usr/ports > > A bit of searching on that error message tells me I've hit some kind of > a corner case with soft-updates. The filesystem was mounted read-only, > then upgraded to rw so I could update the ports tree. After cvsup was > done, I tried to take the filesystem back down to read-only. The common > case seems to be that the mount change is followed too quickly after the > large number of writes and it somehow wedges soft-updates. > > Unfortunately, I haven't been able to find a fix other than rebooting > the machine. The problem is that the search results[1] also tell me the > filesystem may well be hosed and the reboot won't be clean. Luckily for > me, I can just drop the FS from /etc/fstab and newfs the partition after > the box comes back up. As luck would have it I ran into this in my own testing yesterday, and Kostik Belousov has a proposed fix (apply it with patch -p2). This is against 8.0 but should also appy to 7.0. Don't know about 6.x. Kris --------------080708010808070208070809 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="mntq.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="mntq.diff" diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index c4d2346..ba99e8a 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1020,9 +1020,15 @@ insmntque1(struct vnode *vp, struct mount *mp, KASSERT(vp->v_mount == NULL, ("insmntque: vnode already on per mount vnode list")); VNASSERT(mp != NULL, vp, ("Don't call insmntque(foo, NULL)")); +#ifdef DEBUG_VFS_LOCKS + if (!VFS_NEEDSGIANT(mp)) + ASSERT_VOP_ELOCKED(vp, + "insmntque: mp-safe fs and non-locked vp"); +#endif MNT_ILOCK(mp); if ((mp->mnt_kern_flag & MNTK_NOINSMNTQ) != 0 && - mp->mnt_nvnodelistsize == 0) { + mp->mnt_nvnodelistsize == 0 && + VOP_ISLOCKED(vp, curthread) && !(vp->v_vflag & VV_FORCEINSMQ)) { MNT_IUNLOCK(mp); if (dtr != NULL) dtr(vp, dtr_arg); @@ -3133,9 +3139,13 @@ vfs_allocate_syncvnode(struct mount *mp) return (error); } vp->v_type = VNON; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vp->v_vflag |= VV_FORCEINSMQ; error = insmntque(vp, mp); if (error != 0) panic("vfs_allocate_syncvnode: insmntque failed"); + vp->v_vflag &= ~VV_FORCEINSMQ; + VOP_UNLOCK(vp, 0, curthread); /* * Place the vnode onto the syncer worklist. We attempt to * scatter them about on the list so that they will go off diff --git a/sys/sys/lockmgr.h b/sys/sys/lockmgr.h index fcbb187..d4e0c9b 100644 --- a/sys/sys/lockmgr.h +++ b/sys/sys/lockmgr.h @@ -125,6 +125,10 @@ struct lock { * unlock passed mutex after getting * lk_interlock */ +#define LK_FORCE 0x00004000 /* + * fsops_vget: try hard to success; + * in particular, force insmntque + */ /* * Internal lock flags. * diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 0525a43..4b95233 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -255,6 +255,7 @@ struct xvnode { #define VV_NOKNOTE 0x0200 /* don't activate knotes on this vnode */ #define VV_DELETED 0x0400 /* should be removed */ #define VV_MD 0x0800 /* vnode backs the md device */ +#define VV_FORCEINSMQ 0x1000 /* force the insmntque to succeed */ /* * Vnode attributes. A field value of VNOVAL represents a field whose value diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index a221b66..da91f8b 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -920,7 +920,7 @@ process_worklist_item(mp, flags) ump->softdep_on_worklist_inprogress++; FREE_LOCK(&lk); ffs_vget(mp, WK_DIRREM(wk)->dm_oldinum, - LK_NOWAIT | LK_EXCLUSIVE, &vp); + LK_NOWAIT | LK_EXCLUSIVE | LK_FORCE, &vp); ACQUIRE_LOCK(&lk); wk->wk_state &= ~INPROGRESS; ump->softdep_on_worklist_inprogress--; @@ -2771,7 +2771,7 @@ handle_workitem_freeblocks(freeblks, flags) if (freeblks->fb_chkcnt != blocksreleased && (fs->fs_flags & FS_UNCLEAN) != 0 && ffs_vget(freeblks->fb_list.wk_mp, freeblks->fb_previousinum, - (flags & LK_NOWAIT) | LK_EXCLUSIVE, &vp) == 0) { + (flags & LK_NOWAIT) | LK_EXCLUSIVE | LK_FORCE, &vp) == 0) { ip = VTOI(vp); DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + \ freeblks->fb_chkcnt - blocksreleased); @@ -3559,7 +3559,7 @@ handle_workitem_remove(dirrem, xp) if ((vp = xp) == NULL && (error = ffs_vget(dirrem->dm_list.wk_mp, - dirrem->dm_oldinum, LK_EXCLUSIVE, &vp)) != 0) { + dirrem->dm_oldinum, LK_EXCLUSIVE | LK_FORCE, &vp)) != 0) { softdep_error("handle_workitem_remove: vget", error); return; } @@ -5074,9 +5074,11 @@ softdep_fsync(vp) * for details on possible races. */ FREE_LOCK(&lk); - if (ffs_vget(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp)) { + if (ffs_vget(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE | LK_FORCE, + &pvp)) { VOP_UNLOCK(vp, 0, td); - error = ffs_vget(mp, parentino, LK_EXCLUSIVE, &pvp); + error = ffs_vget(mp, parentino, LK_EXCLUSIVE | LK_FORCE, + &pvp); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (error != 0) return (error); @@ -5576,7 +5578,8 @@ flush_pagedep_deps(pvp, mp, diraddhdp) inum = dap->da_newinum; if (dap->da_state & MKDIR_BODY) { FREE_LOCK(&lk); - if ((error = ffs_vget(mp, inum, LK_EXCLUSIVE, &vp))) + if ((error = ffs_vget(mp, inum, LK_EXCLUSIVE | LK_FORCE, + &vp))) break; if ((error=ffs_syncvnode(vp, MNT_NOWAIT)) || (error=ffs_syncvnode(vp, MNT_NOWAIT))) { @@ -5911,7 +5914,8 @@ clear_remove(td) if (vn_start_write(NULL, &mp, V_NOWAIT) != 0) continue; FREE_LOCK(&lk); - if ((error = ffs_vget(mp, ino, LK_EXCLUSIVE, &vp))) { + if ((error = ffs_vget(mp, ino, LK_EXCLUSIVE | LK_FORCE, + &vp))) { softdep_error("clear_remove: vget", error); vn_finished_write(mp); ACQUIRE_LOCK(&lk); @@ -5982,7 +5986,8 @@ clear_inodedeps(td) if (vn_start_write(NULL, &mp, V_NOWAIT) != 0) continue; FREE_LOCK(&lk); - if ((error = ffs_vget(mp, ino, LK_EXCLUSIVE, &vp)) != 0) { + if ((error = ffs_vget(mp, ino, LK_EXCLUSIVE | LK_FORCE, + &vp)) != 0) { softdep_error("clear_inodedeps: vget", error); vn_finished_write(mp); ACQUIRE_LOCK(&lk); diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 14ffd0b..95fe60b 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1382,12 +1382,15 @@ ffs_vget(mp, ino, flags, vpp) td = curthread; lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL, td); + if (flags & LK_FORCE) + vp->v_vflag |= VV_FORCEINSMQ; error = insmntque(vp, mp); if (error != 0) { uma_zfree(uma_inode, ip); *vpp = NULL; return (error); } + vp->v_vflag &= ~VV_FORCEINSMQ; error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL); if (error || *vpp != NULL) return (error); --------------080708010808070208070809--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4788AC47.5060404>