changeset 12906:3ca11e9f39b7

6950914 remount can change mount point to "unspecified_mountpoint", causing panics
author Robert Harris <Robert.Harris@Sun.COM>
date Fri, 23 Jul 2010 04:16:05 -0700
parents f5b5eba6d470
children 805f5f4df09e
files usr/src/uts/common/fs/fd/fdops.c usr/src/uts/common/fs/mntfs/mntvfsops.c usr/src/uts/common/fs/namefs/namevfs.c usr/src/uts/common/fs/nfs/nfs4_vfsops.c usr/src/uts/common/fs/proc/prvfsops.c usr/src/uts/common/fs/tmpfs/tmp_vfsops.c usr/src/uts/common/fs/vfs.c usr/src/uts/common/fs/zfs/zfs_ctldir.c usr/src/uts/common/sys/vfs.h
diffstat 9 files changed, 48 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/fd/fdops.c	Fri Jul 23 08:57:27 2010 +0100
+++ b/usr/src/uts/common/fs/fd/fdops.c	Fri Jul 23 04:16:05 2010 -0700
@@ -383,7 +383,7 @@
 	/*
 	 * Having the resource be anything but "fd" doesn't make sense
 	 */
-	vfs_setresource(vfsp, "fd");
+	vfs_setresource(vfsp, "fd", 0);
 
 	vp = vn_alloc(KM_SLEEP);
 	vp->v_vfsp = vfsp;
--- a/usr/src/uts/common/fs/mntfs/mntvfsops.c	Fri Jul 23 08:57:27 2010 +0100
+++ b/usr/src/uts/common/fs/mntfs/mntvfsops.c	Fri Jul 23 04:16:05 2010 -0700
@@ -201,7 +201,7 @@
 	/*
 	 * Having the resource be anything but "mnttab" doesn't make sense
 	 */
-	vfs_setresource(vfsp, "mnttab");
+	vfs_setresource(vfsp, "mnttab", 0);
 
 	mnt = kmem_zalloc(sizeof (*mnt), KM_SLEEP);
 	mutex_enter(&mvp->v_lock);
--- a/usr/src/uts/common/fs/namefs/namevfs.c	Fri Jul 23 08:57:27 2010 +0100
+++ b/usr/src/uts/common/fs/namefs/namevfs.c	Fri Jul 23 04:16:05 2010 -0700
@@ -522,7 +522,7 @@
 		    "unspecified_%s", resource_nodetype);
 	}
 
-	vfs_setresource(vfsp, resource_name);
+	vfs_setresource(vfsp, resource_name, 0);
 
 	kmem_free(svfsp, sizeof (statvfs64_t));
 	kmem_free(resource_name, RESOURCE_NAME_SZ);
--- a/usr/src/uts/common/fs/nfs/nfs4_vfsops.c	Fri Jul 23 08:57:27 2010 +0100
+++ b/usr/src/uts/common/fs/nfs/nfs4_vfsops.c	Fri Jul 23 04:16:05 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -2616,7 +2615,7 @@
 		(void) strcat(resource, svp->sv_hostname);
 		(void) strcat(resource, ":");
 		(void) strcat(resource, svp->sv_path);
-		vfs_setresource(vfsp, resource);
+		vfs_setresource(vfsp, resource, 0);
 		kmem_free(resource, len);
 	}
 
--- a/usr/src/uts/common/fs/proc/prvfsops.c	Fri Jul 23 08:57:27 2010 +0100
+++ b/usr/src/uts/common/fs/proc/prvfsops.c	Fri Jul 23 04:16:05 2010 -0700
@@ -211,7 +211,7 @@
 	/*
 	 * Having the resource be anything but "proc" doesn't make sense
 	 */
-	vfs_setresource(vfsp, "proc");
+	vfs_setresource(vfsp, "proc", 0);
 
 	pnp = kmem_alloc(sizeof (*pnp), KM_SLEEP);
 	mutex_enter(&pr_mount_lock);
--- a/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c	Fri Jul 23 08:57:27 2010 +0100
+++ b/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c	Fri Jul 23 04:16:05 2010 -0700
@@ -259,7 +259,7 @@
 	/*
 	 * Having the resource be anything but "swap" doesn't make sense.
 	 */
-	vfs_setresource(vfsp, "swap");
+	vfs_setresource(vfsp, "swap", 0);
 
 	/*
 	 * now look for options we understand...
--- a/usr/src/uts/common/fs/vfs.c	Fri Jul 23 08:57:27 2010 +0100
+++ b/usr/src/uts/common/fs/vfs.c	Fri Jul 23 04:16:05 2010 -0700
@@ -670,8 +670,8 @@
 	/*
 	 * Set appropriate members and add to vfs list for mnttab display
 	 */
-	vfs_setresource(&devices, "/devices");
-	vfs_setmntpoint(&devices, "/devices");
+	vfs_setresource(&devices, "/devices", 0);
+	vfs_setmntpoint(&devices, "/devices", 0);
 
 	/*
 	 * Hold the root of /devices so it won't go away
@@ -748,8 +748,8 @@
 	/*
 	 * Set appropriate members and add to vfs list for mnttab display
 	 */
-	vfs_setresource(&dev, "/dev");
-	vfs_setmntpoint(&dev, "/dev");
+	vfs_setresource(&dev, "/dev", 0);
+	vfs_setmntpoint(&dev, "/dev", 0);
 
 	/*
 	 * Hold the root of /dev so it won't go away
@@ -832,7 +832,7 @@
 	 * to point to it.  These are used by lookuppn() so that it
 	 * knows where to start from ('/' or '.').
 	 */
-	vfs_setmntpoint(rootvfs, "/");
+	vfs_setmntpoint(rootvfs, "/", 0);
 	if (VFS_ROOT(rootvfs, &rootdir))
 		panic("vfs_mountroot: no root vnode");
 
@@ -872,7 +872,7 @@
 	/*
 	 * Set up mnttab information for root
 	 */
-	vfs_setresource(rootvfs, rootfs.bo_name);
+	vfs_setresource(rootvfs, rootfs.bo_name, 0);
 
 	/*
 	 * Notify cluster software that the root filesystem is available.
@@ -930,7 +930,7 @@
 		 * mnttab should reflect the new root device
 		 */
 		vfs_lock_wait(rootvfs);
-		vfs_setresource(rootvfs, rootfs.bo_name);
+		vfs_setresource(rootvfs, rootfs.bo_name, 0);
 		vfs_unlock(rootvfs);
 	}
 #endif /* __sparc */
@@ -962,39 +962,6 @@
 }
 
 /*
- * If remount failed and we're in a zone we need to check for the zone
- * root path and strip it before the call to vfs_setpath().
- *
- * If strpath doesn't begin with the zone_rootpath the original
- * strpath is returned unchanged.
- */
-static const char *
-stripzonepath(const char *strpath)
-{
-	char *str1, *str2;
-	int i;
-	zone_t *zonep = curproc->p_zone;
-
-	if (zonep->zone_rootpath == NULL || strpath == NULL) {
-		return (NULL);
-	}
-
-	/*
-	 * we check for the end of the string at one past the
-	 * current position because the zone_rootpath always
-	 * ends with "/" but we don't want to strip that off.
-	 */
-	str1 = zonep->zone_rootpath;
-	str2 = (char *)strpath;
-	ASSERT(str1[0] != '\0');
-	for (i = 0; str1[i + 1] != '\0'; i++) {
-		if (str1[i] != str2[i])
-			return ((char *)strpath);
-	}
-	return (&str2[i]);
-}
-
-/*
  * Check to see if our "block device" is actually a file.  If so,
  * automatically add a lofi device, and keep track of this fact.
  */
@@ -1645,8 +1612,8 @@
 		if ((oldmntpt = vfsp->vfs_mntpt) != NULL)
 			refstr_hold(oldmntpt);
 	}
-	vfs_setresource(vfsp, resource);
-	vfs_setmntpoint(vfsp, mountpt);
+	vfs_setresource(vfsp, resource, 0);
+	vfs_setmntpoint(vfsp, mountpt, 0);
 
 	/*
 	 * going to mount on this vnode, so notify.
@@ -1667,12 +1634,12 @@
 		if (remount) {
 			/* put back pre-remount options */
 			vfs_swapopttbl(&mnt_mntopts, &vfsp->vfs_mntopts);
-			vfs_setmntpoint(vfsp, (stripzonepath(
-			    refstr_value(oldmntpt))));
+			vfs_setmntpoint(vfsp, refstr_value(oldmntpt),
+			    VFSSP_VERBATIM);
 			if (oldmntpt)
 				refstr_rele(oldmntpt);
-			vfs_setresource(vfsp, (stripzonepath(
-			    refstr_value(oldresource))));
+			vfs_setresource(vfsp, refstr_value(oldresource),
+			    VFSSP_VERBATIM);
 			if (oldresource)
 				refstr_rele(oldresource);
 			vfsp->vfs_flag = ovflags;
@@ -1842,7 +1809,11 @@
 }
 
 static void
-vfs_setpath(struct vfs *vfsp, refstr_t **refp, const char *newpath)
+vfs_setpath(
+    struct vfs *vfsp,		/* vfs being updated */
+    refstr_t **refp,		/* Ref-count string to contain the new path */
+    const char *newpath,	/* Path to add to refp (above) */
+    uint32_t flag)		/* flag */
 {
 	size_t len;
 	refstr_t *ref;
@@ -1871,9 +1842,16 @@
 	if (*refp != NULL)
 		refstr_rele(*refp);
 
-	/* Do we need to modify the path? */
-
-	if (zone == global_zone || *newpath != '/') {
+	/*
+	 * If we are in a non-global zone then we prefix the supplied path,
+	 * newpath, with the zone's root path, with two exceptions. The first
+	 * is where we have been explicitly directed to avoid doing so; this
+	 * will be the case following a failed remount, where the path supplied
+	 * will be a saved version which must now be restored. The second
+	 * exception is where newpath is not a pathname but a descriptive name,
+	 * e.g. "procfs".
+	 */
+	if (zone == global_zone || (flag & VFSSP_VERBATIM) || *newpath != '/') {
 		ref = refstr_alloc(newpath);
 		goto out;
 	}
@@ -1925,11 +1903,11 @@
  * If vfsp is already mounted, caller must hold the vfs lock.
  */
 void
-vfs_setresource(struct vfs *vfsp, const char *resource)
+vfs_setresource(struct vfs *vfsp, const char *resource, uint32_t flag)
 {
 	if (resource == NULL || resource[0] == '\0')
 		resource = VFS_NORESOURCE;
-	vfs_setpath(vfsp, &vfsp->vfs_resource, resource);
+	vfs_setpath(vfsp, &vfsp->vfs_resource, resource, flag);
 }
 
 /*
@@ -1937,11 +1915,11 @@
  * If vfsp is already mounted, caller must hold the vfs lock.
  */
 void
-vfs_setmntpoint(struct vfs *vfsp, const char *mntpt)
+vfs_setmntpoint(struct vfs *vfsp, const char *mntpt, uint32_t flag)
 {
 	if (mntpt == NULL || mntpt[0] == '\0')
 		mntpt = VFS_NOMNTPT;
-	vfs_setpath(vfsp, &vfsp->vfs_mntpt, mntpt);
+	vfs_setpath(vfsp, &vfsp->vfs_mntpt, mntpt, flag);
 }
 
 /* Returns the vfs_resource. Caller must call refstr_rele() when finished. */
--- a/usr/src/uts/common/fs/zfs/zfs_ctldir.c	Fri Jul 23 08:57:27 2010 +0100
+++ b/usr/src/uts/common/fs/zfs/zfs_ctldir.c	Fri Jul 23 04:16:05 2010 -0700
@@ -590,7 +590,7 @@
 	ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath));
 	(void) strcat(newpath, nm);
 	refstr_rele(pathref);
-	vfs_setmntpoint(vfsp, newpath);
+	vfs_setmntpoint(vfsp, newpath, 0);
 
 	pathref = vfs_getresource(vfsp);
 	(void) strncpy(newpath, refstr_value(pathref), sizeof (newpath));
@@ -599,7 +599,7 @@
 	ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath));
 	(void) strcat(newpath, nm);
 	refstr_rele(pathref);
-	vfs_setresource(vfsp, newpath);
+	vfs_setresource(vfsp, newpath, 0);
 
 	vfs_unlock(vfsp);
 }
--- a/usr/src/uts/common/sys/vfs.h	Fri Jul 23 08:57:27 2010 +0100
+++ b/usr/src/uts/common/sys/vfs.h	Fri Jul 23 04:16:05 2010 -0700
@@ -442,6 +442,11 @@
 
 #define	VSW_INSTALLED	0x8000	/* this vsw is associated with a file system */
 
+/*
+ * A flag for vfs_setpath().
+ */
+#define	VFSSP_VERBATIM	0x1	/* do not prefix the supplied path */
+
 #if defined(_KERNEL)
 /*
  * Public operations.
@@ -502,8 +507,8 @@
 
 void	vfs_clearmntopt(struct vfs *, const char *);
 void	vfs_setmntopt(struct vfs *, const char *, const char *, int);
-void	vfs_setresource(struct vfs *, const char *);
-void	vfs_setmntpoint(struct vfs *, const char *);
+void	vfs_setresource(struct vfs *, const char *, uint32_t);
+void	vfs_setmntpoint(struct vfs *, const char *, uint32_t);
 refstr_t *vfs_getresource(const struct vfs *);
 refstr_t *vfs_getmntpoint(const struct vfs *);
 int	vfs_optionisset(const struct vfs *, const char *, char **);