summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Harris <Robert.Harris@Sun.COM>2010-07-23 04:16:05 -0700
committerRobert Harris <Robert.Harris@Sun.COM>2010-07-23 04:16:05 -0700
commitd7de0cea9111a93d26efcfa259585dabbde02eea (patch)
treecaa047d7621ae20b9a1b2351545cbea6f23c6108
parent04fdf45595eefac2f4793a31f7be253c3ddd3368 (diff)
downloadillumos-joyent-d7de0cea9111a93d26efcfa259585dabbde02eea.tar.gz
6950914 remount can change mount point to "unspecified_mountpoint", causing panics
-rw-r--r--usr/src/uts/common/fs/fd/fdops.c2
-rw-r--r--usr/src/uts/common/fs/mntfs/mntvfsops.c2
-rw-r--r--usr/src/uts/common/fs/namefs/namevfs.c2
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_vfsops.c5
-rw-r--r--usr/src/uts/common/fs/proc/prvfsops.c2
-rw-r--r--usr/src/uts/common/fs/tmpfs/tmp_vfsops.c2
-rw-r--r--usr/src/uts/common/fs/vfs.c86
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ctldir.c4
-rw-r--r--usr/src/uts/common/sys/vfs.h9
9 files changed, 48 insertions, 66 deletions
diff --git a/usr/src/uts/common/fs/fd/fdops.c b/usr/src/uts/common/fs/fd/fdops.c
index 8c398be2ee..a8c03455f3 100644
--- a/usr/src/uts/common/fs/fd/fdops.c
+++ b/usr/src/uts/common/fs/fd/fdops.c
@@ -383,7 +383,7 @@ fdmount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
/*
* 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;
diff --git a/usr/src/uts/common/fs/mntfs/mntvfsops.c b/usr/src/uts/common/fs/mntfs/mntvfsops.c
index 102e681e8e..8f7f7c9f75 100644
--- a/usr/src/uts/common/fs/mntfs/mntvfsops.c
+++ b/usr/src/uts/common/fs/mntfs/mntvfsops.c
@@ -201,7 +201,7 @@ mntmount(struct vfs *vfsp, struct vnode *mvp,
/*
* 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);
diff --git a/usr/src/uts/common/fs/namefs/namevfs.c b/usr/src/uts/common/fs/namefs/namevfs.c
index 0725504842..13e620d410 100644
--- a/usr/src/uts/common/fs/namefs/namevfs.c
+++ b/usr/src/uts/common/fs/namefs/namevfs.c
@@ -522,7 +522,7 @@ nm_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *crp)
"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);
diff --git a/usr/src/uts/common/fs/nfs/nfs4_vfsops.c b/usr/src/uts/common/fs/nfs/nfs4_vfsops.c
index 040fbed7bd..35152c3a39 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_vfsops.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_vfsops.c
@@ -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 @@ nfs4rootvp(vnode_t **rtvpp, vfs_t *vfsp, struct servinfo4 *svp_head,
(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);
}
diff --git a/usr/src/uts/common/fs/proc/prvfsops.c b/usr/src/uts/common/fs/proc/prvfsops.c
index d0bebc7163..efc3c37ce7 100644
--- a/usr/src/uts/common/fs/proc/prvfsops.c
+++ b/usr/src/uts/common/fs/proc/prvfsops.c
@@ -211,7 +211,7 @@ prmount(struct vfs *vfsp, struct vnode *mvp,
/*
* 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);
diff --git a/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c b/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c
index 9bb96e4165..f8a36a528f 100644
--- a/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c
+++ b/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c
@@ -259,7 +259,7 @@ tmp_mount(
/*
* 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...
diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c
index 2bfe3908f0..9a106fd3d0 100644
--- a/usr/src/uts/common/fs/vfs.c
+++ b/usr/src/uts/common/fs/vfs.c
@@ -670,8 +670,8 @@ vfs_mountdevices(void)
/*
* 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 @@ vfs_mountdev1(void)
/*
* 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 @@ vfs_mountroot(void)
* 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 @@ vfs_mountroot(void)
/*
* 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 @@ vfs_mountroot(void)
* 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 @@ vfs_mountroot(void)
}
/*
- * 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 @@ domount(char *fsname, struct mounta *uap, vnode_t *vp, struct cred *credp,
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 @@ domount(char *fsname, struct mounta *uap, vnode_t *vp, struct cred *credp,
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 @@ errout:
}
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 @@ vfs_setpath(struct vfs *vfsp, refstr_t **refp, const char *newpath)
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 @@ out:
* 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 @@ vfs_setresource(struct vfs *vfsp, const char *resource)
* 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. */
diff --git a/usr/src/uts/common/fs/zfs/zfs_ctldir.c b/usr/src/uts/common/fs/zfs/zfs_ctldir.c
index 362de4dd15..07f18f29f0 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ctldir.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ctldir.c
@@ -590,7 +590,7 @@ zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm)
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 @@ zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm)
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);
}
diff --git a/usr/src/uts/common/sys/vfs.h b/usr/src/uts/common/sys/vfs.h
index 97e176fc1a..5fca4584eb 100644
--- a/usr/src/uts/common/sys/vfs.h
+++ b/usr/src/uts/common/sys/vfs.h
@@ -442,6 +442,11 @@ enum {
#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_mnttab_modtimeupd(void);
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 **);