Hi, When I force to unmount a filesystem where another mountpoint is located, an unlinked mountpoint will remain. I have not found a way to restore the kernel to a sane state.
# mount /dev/vnd0a /mnt # mkdir /mnt/mnt # mount /dev/vnd1a /mnt/mnt # mount /dev/sd0a on / type ffs (local) /dev/vnd0a on /mnt type ffs (local) /dev/vnd1a on /mnt/mnt type ffs (local) # umount /mnt umount: /mnt: Device busy # umount -f /mnt # mount /dev/sd0a on / type ffs (local) /dev/vnd1a on /mnt/mnt type ffs (local) # umount /mnt/mnt umount: /mnt/mnt: No such file or directory # mkdir /mnt/mnt # umount /mnt/mnt umount: /mnt/mnt: Invalid argument # vnconfig -u vnd1 vnconfig: VNDIOCCLR: Device busy The fix could be to unmount recursively. ok? bluhm Index: kern/vfs_syscalls.c =================================================================== RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.267 diff -u -p -r1.267 vfs_syscalls.c --- kern/vfs_syscalls.c 10 Jan 2017 20:13:17 -0000 1.267 +++ kern/vfs_syscalls.c 10 Jan 2017 20:36:05 -0000 @@ -88,6 +88,7 @@ int domkdirat(struct proc *, int, const int doutimensat(struct proc *, int, const char *, struct timespec [2], int); int dovutimens(struct proc *, struct vnode *, struct timespec [2]); int dofutimens(struct proc *, int, struct timespec [2]); +int unmount_vnode(struct vnode *, void *); /* * Virtual File System System Calls @@ -368,15 +369,56 @@ sys_unmount(struct proc *p, void *v, reg return (dounmount(mp, SCARG(uap, flags) & MNT_FORCE, p)); } +struct unmount_args { + struct proc *ua_proc; + int ua_flags; + int ua_error; +}; + +int +unmount_vnode(struct vnode *vp, void *args) +{ + struct unmount_args *ua = args; + struct mount *mp; + int error; + + if (vp->v_type != VDIR) + return (0); + if ((mp = vp->v_mountedhere) == NULL) + return (0); + if (!(ua->ua_flags & MNT_FORCE)) { + ua->ua_error = EBUSY; + return (EBUSY); + } + if (vfs_busy(mp, VB_WRITE|VB_WAIT)) { + ua->ua_error = EBUSY; + return (0); + } + error = dounmount(mp, ua->ua_flags, ua->ua_proc); + if (error) + ua->ua_error = error; + return (0); +} + /* * Do the actual file system unmount. */ int dounmount(struct mount *mp, int flags, struct proc *p) { + struct unmount_args ua; struct vnode *coveredvp; int error; int hadsyncer = 0; + + ua.ua_proc = p; + ua.ua_flags = flags; + ua.ua_error = 0; + vfs_mount_foreach_vnode(mp, unmount_vnode, &ua); + if (ua.ua_error && !(flags & MNT_DOOMED)) { + vfs_unbusy(mp); + return (ua.ua_error); + } mp->mnt_flag &=~ MNT_ASYNC; cache_purgevfs(mp); /* remove cache entries for this file sys */