Subject: bin/749: mount -a mounts things that are already mounted
To: None <gnats-admin@NetBSD.ORG>
From: der Mouse <mouse@Collatz.McRCIM.McGill.EDU>
List: netbsd-bugs
Date: 01/22/1995 17:50:03
>Number:         749
>Category:       bin
>Synopsis:       mount -a mounts things that are already mounted
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Jan 22 17:50:01 1995
>Originator:     der Mouse
>Organization:
	As little as I can get away with
>Release:        NetBSD/sparc 1.0, present in -current as well
>Environment:
	SPARC IPC, not that it matters
>Description:
	mount -a will happily try to mount things that are already
	mounted.  This patch makes the -a flag check and not attempt to
	mount things that appear to be already mounted.  It also adds
	-A, which behaves the way -a does now, not checking existing
	mounts.  It also adds -x and -X, which permit explicit
	exclusions for -a to be provided.

	These patches are for 1.0, but mount has changed little between
	1.0 and -current (only the addition of the MNT_USER flag,
	according to diffs I just did).
>How-To-Repeat:
	Run mount -a and notice that it happily remounts things that
	are already mounted, in cases (like NFS mounts) where this is
	possible.
>Fix:
	--- /sources/1.0-usr-src/./sbin/mount/mount.8	Wed Jun  8 15:02:42 1994
	+++ /usr/src/./sbin/mount/mount.8	Wed Dec 14 17:45:28 1994
	@@ -75,6 +75,23 @@
	 .Pp
	 The options are as follows:
	 .Bl -tag -width indent
	+.It Fl a
	+Causes
	+.Nm mount
	+to mount all filesystems listed in
	+.Pa /etc/fstab ,
	+except those which appear to be already mounted.  This option is conservative;
	+it is possible for it to fail to notice that a filesystem is already mounted.
	+.Fl x
	+or
	+.Fl X
	+can be used to deal with these cases.
	+.It Fl A
	+Like
	+.Fl a
	+except that
	+.Nm mount
	+makes no attempt to check whether filesystems are already mounted or not.
	 .It Fl d
	 Causes everything to be done except for the actual system call.
	 This option is useful in conjunction with the
	@@ -235,6 +252,34 @@
	 The options specific to NFS filesystems are described in the
	 .Xr mount_nfs 8
	 manual page.
	+.It Fl x Ar "mount-points"
	+Exclude any filesystems mounted on the listed mount points from a
	+.Fl a
	+or
	+.Fl A
	+operation.  (The argument is a comma-separated list; additionally, whitespace
	+at the beginning of a pathname is ignored.)  All remarks listed for
	+.Fl X
	+apply to each element of the list;
	+.Nm mount
	+behaves exactly as if multiple
	+.Fl X
	+options had been given, one for each element of the list.
	+.It Fl X Ar "mount-point"
	+Exclude any filesystems mounted on the given mount point from a
	+.Fl a
	+or
	+.Fl A
	+operation.  Unlike
	+.Fl x ,
	+the argument is taken verbatim as a mount point; whitespace and commas have
	+no special meaning.  This option can be given multiple times and/or combined
	+with
	+.Fl x ;
	+all such options accumulate a single list of excluded mount points.  Note that
	+the argument string must match the attempted mount point; symbolic links are
	+expanded before mounting, but after checking the mount point against the
	+exclusion list.
	 .Sh FILES
	 .Bl -tag -width /etc/fstab -compact
	 .It Pa /etc/fstab
	
	--- /sources/1.0-usr-src/./sbin/mount/mount.c	Sun Aug 28 22:38:00 1994
	+++ /usr/src/./sbin/mount/mount.c	Wed Dec 14 17:45:30 1994
	@@ -59,6 +59,9 @@
	 
	 int debug, verbose, skipvfs;
	 
	+static char **exclusions = 0;
	+static int nexcl = 0;
	+
	 int	badvfsname __P((const char *, const char **));
	 char   *catopt __P((char *, const char *));
	 struct statfs
	@@ -71,6 +74,11 @@
	 			int, const char *, const char *));
	 void	prmount __P((struct statfs *));
	 void	usage __P((void));
	+int     alreadymounted __P((struct fstab *));
	+void    set_exclude_list __P((const char *));
	+void    set_exclude __P((const char *));
	+void    set_exclude_ __P((const char *, int));
	+int     excluded __P((const char *));
	 
	 /* From mount_ufs.c. */
	 int	mount_ufs __P((int, char * const *));
	@@ -104,17 +112,22 @@
	 	struct statfs *mntbuf;
	 	FILE *mountdfp;
	 	pid_t pid;
	-	int all, ch, i, init_flags, mntsize, rval;
	+	int all, All, ch, i, init_flags, mntsize, rval;
	 	char *options;
	 
	 	all = init_flags = 0;
	 	options = NULL;
	 	vfslist = NULL;
	 	vfstype = "ufs";
	-	while ((ch = getopt(argc, argv, "adfo:rwt:uv")) != EOF)
	+	while ((ch = getopt(argc, argv, "Aadfo:rwt:uvx:X:")) != EOF)
	 		switch (ch) {
	 		case 'a':
	 			all = 1;
	+			All = 0;
	+			break;
	+		case 'A':
	+			all = 1;
	+			All = 1;
	 			break;
	 		case 'd':
	 			debug = 1;
	@@ -144,6 +157,12 @@
	 		case 'w':
	 			init_flags &= ~MNT_RDONLY;
	 			break;
	+		case 'x':
	+			set_exclude_list(optarg);
	+			break;
	+		case 'X':
	+			set_exclude(optarg);
	+			break;
	 		case '?':
	 		default:
	 			usage();
	@@ -167,6 +186,10 @@
	 					continue;
	 				if (hasopt(fs->fs_mntops, "noauto"))
	 					continue;
	+				if (!All && alreadymounted(fs))
	+					continue;
	+				if (excluded(fs->fs_file))
	+					continue;
	 				if (mountfs(fs->fs_vfstype, fs->fs_spec,
	 				    fs->fs_file, init_flags, options,
	 				    fs->fs_mntops))
	@@ -240,6 +263,79 @@
	 	}
	 
	 	exit(rval);
	+}
	+
	+int
	+excluded(s)
	+	const char *s;
	+{
	+ int i;
	+
	+ for (i=0;i<nexcl;i++) if (!strcmp(exclusions[i],s)) return(1);
	+ return(0);
	+}
	+
	+void
	+set_exclude_(s,len)
	+	const char *s;
	+	int len;
	+{
	+ char *t;
	+
	+ t = malloc(len+1);
	+ strncpy(t,s,len);
	+ t[len] = '\0';
	+ exclusions = realloc(exclusions,(nexcl+1)*sizeof(char *));
	+ exclusions[nexcl++] = t;
	+}
	+
	+void
	+set_exclude_list(s)
	+	const char *s;
	+{
	+ const char *t;
	+ const char *t0;
	+
	+ t = s;
	+ while (*t)
	+  { while (*t && ((*t == ',') || (*t == ' '))) t ++;
	+    t0 = t;
	+    while (*t && (*t != ',')) t ++;
	+    if (t > t0) set_exclude_(t0,t-t0);
	+  }
	+}
	+
	+void
	+set_exclude(s)
	+	const char *s;
	+{
	+ set_exclude_(s,strlen(s));
	+}
	+
	+int
	+alreadymounted(fs)
	+	struct fstab *fs;
	+{
	+ int siz;
	+ struct statfs *buf;
	+ int i;
	+
	+ /* don't cache the result of getmntinfo because it can change from one call
	+    to the next.  This won't affect our results in most cases (unless a
	+    filesystem is listed twice in fstab), but so what?  It's cheap, and
	+    mount -a isn't run often. */
	+ siz = getmntinfo(&buf,MNT_NOWAIT);
	+ if (siz == 0) err(1,"getmntinfo");
	+ for (i=0;i<siz;i++)
	+  { /* this check isn't perfect; for example, unionfs below mounts have
	+       a mntfromname that doesn't match what was passed in.  But it'll catch
	+       the commonest cases - eg, NFS mounts - and the rest can be dealt with
	+       by exclusions. */
	+    if ( !strcmp(buf[i].f_mntfromname,fs->fs_spec) &&
	+	 !strcmp(buf[i].f_mntonname,fs->fs_file) &&
	+	 !strcmp(buf[i].f_fstypename,fs->fs_vfstype) ) return(1);
	+  }
	+ return(0);
	 }
	 
	 int
	
					der Mouse

			    mouse@collatz.mcrcim.mcgill.edu
>Audit-Trail:
>Unformatted: