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>