Subject: bin/4261: mount -a fails to skip existing mounts in some cases
To: None <gnats-bugs@gnats.netbsd.org>
From: Matthias Drochner <drochner@zelz26.zel.kfa-juelich.de>
List: netbsd-bugs
Date: 10/11/1997 16:25:06
>Number:         4261
>Category:       bin
>Synopsis:       mount -a fails to skip existing mounts in some cases
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Oct 11 07:35:04 1997
>Last-Modified:
>Originator:     Matthias Drochner
>Organization:
	KFA Juelich
>Release:        NetBSD/current, Oct 10 1997
>Environment:
	NetBSD/current, Oct 10 1997
System: NetBSD zelz26 1.2G NetBSD 1.2G (GENERIC.KGDB) #132: Fri Oct 10 18:31:12 MEST 1997 drochner@zelz26:/mnt/sys/arch/i386/compile/GENERIC.KGDB i386


>Description:
	In setups with union mounts, the code which determines if a given mount
lready exists may fail.
The code uses a statfs() on the mountpoint, for which of the 2 mounts
the information is returned is undefined.
In my setup it looks as follows:

/etc/fstab:
[...]
zelnfs:/netbsd/src       /usr/src        nfs     ro      0 0
[...]
/altroot/src             /usr/src 	 union  rw
[...]

mount -av recognizes all but these 2 filesystems as mounted
It shows up that fsstat() returned information for the union mount when
the nfs mount was checked and vice-versa.
fsstat() returns the information for the last mounted filesystem, thus
it cannot be used at this place.
>How-To-Repeat:
	See above.
>Fix:
	One possibility (using getmntinfo() instead):

*** mount.c.orig	Sat Oct 11 15:58:49 1997
--- mount.c	Sat Oct 11 15:58:25 1997
***************
*** 300,306 ****
  	};
  	const char *argv[100], **edir;
! 	struct statfs sf;
  	pid_t pid;
! 	int argc, i, status;
  	char *optbuf, execname[MAXPATHLEN + 1], mntpath[MAXPATHLEN];
  #ifdef __GNUC__
--- 300,306 ----
  	};
  	const char *argv[100], **edir;
! 	struct statfs *sfp, sf;
  	pid_t pid;
! 	int argc, numfs, i, status;
  	char *optbuf, execname[MAXPATHLEN + 1], mntpath[MAXPATHLEN];
  #ifdef __GNUC__
***************
*** 332,348 ****
  		flags |= MNT_UPDATE;
  	else if (skipmounted) {
! 		if (statfs(name, &sf) < 0) {
! 			warn("statfs %s", name);
  			return (1);
  		}
! 		/* XXX can't check f_mntfromname, thanks to mfs, union, etc. */
! 		if (strncmp(name, sf.f_mntonname, MNAMELEN) == 0 &&
! 		    strncmp(vfstype, sf.f_fstypename, MFSNAMELEN) == 0) {
! 			if (verbose)
! 				(void)printf("%s on %s type %.*s: %s\n",
! 				    sf.f_mntfromname, sf.f_mntonname,
! 			            MFSNAMELEN, sf.f_fstypename,
! 				    "already mounted");
! 			return (0);
  		}
  	}
--- 332,350 ----
  		flags |= MNT_UPDATE;
  	else if (skipmounted) {
! 		if ((numfs = getmntinfo(&sfp, MNT_WAIT)) == 0) {
! 			warn("getmntinfo");
  			return (1);
  		}
! 		for(i = 0; i < numfs; i++) {
! 			/* XXX can't check f_mntfromname, thanks to mfs, union, etc. */
! 			if (strncmp(name, sfp[i].f_mntonname, MNAMELEN) == 0 &&
! 			    strncmp(vfstype, sfp[i].f_fstypename, MFSNAMELEN) == 0) {
! 				if (verbose)
! 					(void)printf("%s on %s type %.*s: %s\n",
! 						     sfp[i].f_mntfromname, sfp[i].f_mntonname,
! 						     MFSNAMELEN, sfp[i].f_fstypename,
! 						     "already mounted");
! 				return (0);
! 			}
  		}
  	}
>Audit-Trail:
>Unformatted: