Subject: Re: bin/4030: Unable to unmount filesystem mounted on ../blah
To: Michael Graff <explorer@flame.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: netbsd-bugs
Date: 08/23/1997 18:48:14
> A user, in a directory of /u1/home/gregp/mnt, ran this command:
> 	mount_procfs /proc ../blah
> [...] and this cannot be unmounted.  [...]
> When I wrote a small C program to issue
> 	unmount("/home/gregp/blah", 0);
> it was unmounted.

I thought I had submitted a PR with these changes to umount, but I
can't find any evidence of it.

The following patches add a -R option that is what you want in this
case; they also document the -F option, which I wasn't aware of until I
discovered it when I went into the source to add -R.

	--- OLD/sbin/umount/umount.8	Thu Jan  1 00:00:00 1970
	+++ NEW/sbin/umount/umount.8	Thu Jan  1 00:00:00 1970
	@@ -41,11 +41,11 @@
	 .Nd unmount file systems
	 .Sh SYNOPSIS
	 .Nm umount
	-.Op Fl fv
	+.Op Fl fvFR
	 .Ar special | node
	 .Nm umount
	 .Fl a
	-.Op Fl fv
	+.Op Fl fvF
	 .Op Fl h Ar host
	 .Op Fl t Ar ufs | lfs | external_type
	 .Sh DESCRIPTION
	@@ -77,6 +77,29 @@
	 Active special devices continue to work,
	 but all other files return errors if further accesses are attempted.
	 The root file system cannot be forcibly unmounted.
	+.It Fl F
	+Fake the unmount: perform all other processing but do not actually
	+attempt the unmount.  (This is most useful in conjunction with
	+.Fl v ,
	+to see what
	+.Nm
	+would attempt to do.)
	+.It Fl R
	+Take the
	+.Ar special | node
	+argument as a path to be passed directly to
	+.Xr unmount 2 ,
	+bypassing all attempts to be smart about mechanically determining the
	+correct path from the argument.  This option is incompatible with any
	+option that potentially umounts more than one filesystem, such as
	+.Fl a ,
	+but it can be used with
	+.Fl f
	+and/or
	+.Fl v .
	+This is the only way to unmount something that does not appear as a
	+directory (such as a nullfs mount of a plain file); there are probably
	+other cases where it is necessary.
	 .It Fl h Ar host
	 Only filesystems mounted from the specified host will be
	 unmounted.
	--- OLD/sbin/umount/umount.c	Thu Jan  1 00:00:00 1970
	+++ NEW/sbin/umount/umount.c	Thu Jan  1 00:00:00 1970
	@@ -69,7 +69,7 @@
	 
	 typedef enum { MNTANY, MNTON, MNTFROM } mntwhat;
	 
	-int	fake, fflag, verbose;
	+int	fake, fflag, verbose, raw;
	 char	**typelist = NULL;
	 char	*nfshost;
	 
	@@ -93,7 +93,7 @@
	 	sync();
	 
	 	all = 0;
	-	while ((ch = getopt(argc, argv, "aFfh:t:v")) != EOF)
	+	while ((ch = getopt(argc, argv, "aFfh:Rt:v")) != EOF)
	 		switch (ch) {
	 		case 'a':
	 			all = 1;
	@@ -108,6 +108,9 @@
	 			all = 1;
	 			nfshost = optarg;
	 			break;
	+		case 'R':
	+			raw = 1;
	+			break;
	 		case 't':
	 			if (typelist != NULL)
	 				errx(1, "only one -t option may be specified.");
	@@ -123,7 +126,7 @@
	 	argc -= optind;
	 	argv += optind;
	 
	-	if (argc == 0 && !all || argc != 0 && all)
	+	if (argc == 0 && !all || argc != 0 && all || all && raw)
	 		usage();
	 
	 	/* -h implies "-t nfs" if no -t flag. */
	@@ -179,63 +182,68 @@
	 	char *delimp, *hostp, *mntpt, rname[MAXPATHLEN], type[MFSNAMELEN];
	 	mntwhat what;
	 
	-	if (realpath(name, rname) == NULL) {
	-		warn("%s", rname);
	-		return (1);
	-	}
	-
	-	what = MNTANY;
	-	mntpt = name = rname;
	-
	-	if (stat(name, &sb) == 0) {
	-		if (S_ISBLK(sb.st_mode))
	-			what = MNTON;
	-		else if (S_ISDIR(sb.st_mode))
	-			what = MNTFROM;
	-	}
	-
	-	switch (what) {
	-	case MNTON:
	-		if ((mntpt = getmntname(name, MNTON, type)) == NULL) {
	-			warnx("%s: not currently mounted", name);
	+	hp = 0;
	+	if (raw) {
	+		mntpt = name;
	+	} else {
	+		if (realpath(name, rname) == NULL) {
	+			warn("%s", rname);
	 			return (1);
	 		}
	-		break;
	-	case MNTFROM:
	-		if ((name = getmntname(mntpt, MNTFROM, type)) == NULL) {
	-			warnx("%s: not currently mounted", mntpt);
	-			return (1);
	+
	+		what = MNTANY;
	+		mntpt = name = rname;
	+
	+		if (stat(name, &sb) == 0) {
	+			if (S_ISBLK(sb.st_mode))
	+				what = MNTON;
	+			else if (S_ISDIR(sb.st_mode))
	+				what = MNTFROM;
	 		}
	-		break;
	-	default:
	-		if ((name = getmntname(mntpt, MNTFROM, type)) == NULL) {
	-			name = rname;
	+
	+		switch (what) {
	+		case MNTON:
	 			if ((mntpt = getmntname(name, MNTON, type)) == NULL) {
	 				warnx("%s: not currently mounted", name);
	 				return (1);
	 			}
	+			break;
	+		case MNTFROM:
	+			if ((name = getmntname(mntpt, MNTFROM, type)) == NULL) {
	+				warnx("%s: not currently mounted", mntpt);
	+				return (1);
	+			}
	+			break;
	+		default:
	+			if ((name = getmntname(mntpt, MNTFROM, type)) == NULL) {
	+				name = rname;
	+				if ((mntpt = getmntname(name, MNTON, type)) == NULL) {
	+					warnx("%s: not currently mounted", name);
	+					return (1);
	+				}
	+			}
	 		}
	-	}
	 
	-	if (!selected(type))
	-		return (1);
	-
	-	if (!strncmp(type, MOUNT_NFS, MFSNAMELEN)) {
	-		if ((delimp = strchr(name, '@')) != NULL) {
	-			hostp = delimp + 1;
	-			*delimp = '\0';
	-			hp = gethostbyname(hostp);
	-			*delimp = '@';
	-		} else if ((delimp = strchr(name, ':')) != NULL) {
	-			*delimp = '\0';
	-			hostp = name;
	-			hp = gethostbyname(hostp);
	-			name = delimp + 1;
	-			*delimp = ':';
	-		} else
	-			hp = NULL;
	-		if (!namematch(hp))
	+		if (!selected(type))
	 			return (1);
	+
	+		if (!strncmp(type, MOUNT_NFS, MFSNAMELEN)) {
	+			if ((delimp = strchr(name, '@')) != NULL) {
	+				hostp = delimp + 1;
	+				*delimp = '\0';
	+				hp = gethostbyname(hostp);
	+				*delimp = '@';
	+			} else if ((delimp = strchr(name, ':')) != NULL) {
	+				*delimp = '\0';
	+				hostp = name;
	+				hp = gethostbyname(hostp);
	+				name = delimp + 1;
	+				*delimp = ':';
	+			} else
	+				hp = NULL;
	+			if (!namematch(hp))
	+				return (1);
	+		}
	 	}
	 
	 	if (verbose)
	@@ -407,7 +415,7 @@
	 {
	 	(void)fprintf(stderr,
	 	    "usage: %s\n       %s\n",
	-	    "umount [-fv] [-t fstypelist] special | node",
	-	    "umount -a[fv] [-h host] [-t fstypelist]");
	+	    "umount [-fvFR] [-t fstypelist] special | node",
	+	    "umount -a[fvF] [-h host] [-t fstypelist]");
	 	exit(1);
	 }
	

					der Mouse

			       mouse@rodents.montreal.qc.ca
		     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B