Skip site navigation (1)Skip section navigation (2)
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>