Subject: Re: multiple mounts on same directory
To: None <tech-userlevel@NetBSD.org>
From: Alan Barrett <apb@cequrux.com>
List: tech-userlevel
Date: 07/18/2003 21:25:47
On Fri, 18 Jul 2003, Bill Studenmund wrote:
> > Is it OK to hard-code knowledge of these special cases in the duplicate
> > detection part of "mount -a"?
>
> I'd say a switch (fstype) would be best, and have it: 1) note if the
> fromname should be looked at (kern, proc, mfs would be no), and if the
> from name needs to be different than what's in the fstab.
OK. fstype is a string, so it's a chain of strcmp tests instead of a
switch. I append a patch for review.
I searched the kernel sources for anything that sets f_mntfromname or
calls set_statfs_info(), so I hope I found all file systems that do
something unusual.
--apb (Alan Barrett)
Index: sbin/mount/mount.c
--- mount.c 19 Jan 2003 10:49:12 -0000 1.65
+++ mount.c 18 Jul 2003 19:22:50 -0000
@@ -349,13 +349,77 @@
}
for(i = 0; i < numfs; i++) {
/*
- * XXX can't check f_mntfromname,
- * thanks to mfs, union, etc.
+ * If the mounted file system described by
+ * sfp[i] matches the file system to be mounted,
+ * then this would be a duplicate, so do not
+ * mount it.
+ *
+ * Note that a duplicate does not always have a
+ * matching f_mntfromname field. For example:
+ *
+ * fstype original name f_mntfromname
+ * ------ ------------- -------------
+ * mfs anything mfs:123
+ * kernfs anything kernfs
+ * procfs anything procfs
+ * union (with default UNMNT_ABOVE option)
+ * /some/dir <above>:/some/dir
+ * union (with "-b" UNMNT_BELOW option)
+ * /some/dir <below>:/some/dir
+ * union (with "-r" UNMNT_REPLACE option)
+ * /some/dir /some/dir
+ * smbfs ??? //user@host/service
+ * coda ??? CODA
+ *
+ * If f_mntonname and f_fstypename match, then
+ * we copy f_mntfromname into a local buffer
+ * (fromname) and possibly modify the copy
+ * before checking whether it equals the desired
+ * name.
*/
- if (strncmp(name, sfp[i].f_mntonname, MNAMELEN) == 0 &&
- strncmp(vfstype, sfp[i].f_fstypename,
- MFSNAMELEN) == 0) {
- if (verbose)
+ char fromname[MNAMELEN];
+ char *check_fromname = fromname;
+
+ if (strncmp(name, sfp[i].f_mntonname, MNAMELEN) != 0
+ || strncmp(vfstype, sfp[i].f_fstypename,
+ MFSNAMELEN) != 0)
+ continue; /* not a duplicate */
+ strlcpy(fromname, sfp[i].f_mntfromname, MNAMELEN);
+ if (strcmp(vfstype, "mfs") == 0
+ || strcmp(vfstype, "procfs") == 0
+ || strcmp(vfstype, "kernfs") == 0
+ || strcmp(vfstype, "coda") == 0
+ || strcmp(vfstype, "fdesc") == 0) {
+ /* Ignore fromname. */
+ check_fromname = NULL;
+ } else if (strcmp(vfstype, "union") == 0) {
+ /*
+ * Focus after the colon in
+ * "<above>:/some/dir" or
+ * "<below>:/some/dir". Note that
+ * there is no extra <foo> in the
+ * UNMNT_REPLACE case.
+ */
+ char *s;
+
+ if (fromname[0] == '<'
+ && (s = strchr(fromname, ':')) != NULL)
+ check_fromname = s + 1;
+ } else if (strcmp(vfstype, "smbfs") == 0) {
+ /*
+ * XXX: smbfs_mount() in
+ * sys/fs/smbfs/smbfs_vfsops.c
+ * creates f_mntfromname from
+ * several components, and I don't
+ * know where the components came
+ * from.
+ */
+ check_fromname = NULL;
+ }
+ if (check_fromname == NULL
+ || strncmp(spec, check_fromname, MNAMELEN) == 0) {
+ /* It's a duplicate. */
+ if (verbose) {
(void)printf("%s on %s type %.*s: "
"%s\n",
sfp[i].f_mntfromname,
@@ -363,6 +427,7 @@
MFSNAMELEN,
sfp[i].f_fstypename,
"already mounted");
+ }
return (0);
}
}