Date: Mon, 16 Apr 2001 13:07:52 -0400 From: Matthew Fredette <fredette@MIT.EDU> To: gnats-admin@FreeBSD.org, freebsd-bugs@FreeBSD.org Subject: Re: kern/26618: unmount(2) can't unmount a filesystem whose device has been lost Message-ID: <200104161707.NAA26501@ten-thousand-dollar-bill.mit.edu> In-Reply-To: Your message of "Mon, 16 Apr 2001 10:00:01 PDT." <200104161700.f3GH01u25681@freefall.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Here's a patch against sys/kern/vfs_syscalls.c revision 1.187:
[snip]
--- vfs_syscalls.c.orig Mon Apr 16 12:32:59 2001
+++ vfs_syscalls.c Mon Apr 16 12:36:37 2001
@@ -468,11 +468,71 @@
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
SCARG(uap, path), p);
- if ((error = namei(&nd)) != 0)
+ if ((error = namei(&nd)) == ENXIO && suser(p) == 0) {
+ /*
+ * When root is trying to unmount a filesystem on a
+ * device that has disappeared, try to find the
+ * mountpoint by looking through the mountlist.
+ * Otherwise, such a filesystem can never get unmounted.
+ */
+ char *path;
+ register struct mount *nmp;
+ register struct statfs *sp;
+
+ mp = NULL;
+ simple_lock(&mountlist_slock);
+ path = zalloc(namei_zone);
+ for (;;) {
+
+ /* Copy in the mount point. */
+ if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
+ break;
+
+ /* Don't allow empty pathnames. */
+ if (*path == '\0') {
+ error = ENOENT;
+ break;
+ }
+
+ /* Walk the mount list. */
+ for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ continue;
+ }
+ sp = &mp->mnt_stat;
+ if (!strcmp(sp->f_mntonname, path)) {
+ vfs_unbusy(mp, p);
+ break;
+ }
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ vfs_unbusy(mp, p);
+ }
+
+ error = (mp == NULL ? ENOENT : 0);
+ break;
+ }
+
+ zfree(namei_zone, path);
+ simple_unlock(&mountlist_slock);
+ if (error)
+ return (error);
+ } else if (error != 0)
return (error);
- vp = nd.ni_vp;
- NDFREE(&nd, NDF_ONLY_PNBUF);
- mp = vp->v_mount;
+ else {
+ vp = nd.ni_vp;
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ mp = vp->v_mount;
+
+ /*
+ * Must be the root of the filesystem
+ */
+ if ((vp->v_flag & VROOT) == 0) {
+ vput(vp);
+ return (EINVAL);
+ }
+ vput(vp);
+ }
/*
* Only root, or the user that did the original mount is
@@ -480,7 +540,6 @@
*/
if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
(error = suser(p))) {
- vput(vp);
return (error);
}
@@ -488,18 +547,9 @@
* Don't allow unmounting the root file system.
*/
if (mp->mnt_flag & MNT_ROOTFS) {
- vput(vp);
return (EINVAL);
}
- /*
- * Must be the root of the filesystem
- */
- if ((vp->v_flag & VROOT) == 0) {
- vput(vp);
- return (EINVAL);
- }
- vput(vp);
return (dounmount(mp, SCARG(uap, flags), p));
}
[snip]
Matt
--
Matt Fredette
http://mit.edu/fredette/www
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200104161707.NAA26501>
