svn commit: r224921 -
projects/zfsd/head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Justin T. Gibbs
gibbs at FreeBSD.org
Tue Aug 16 22:33:06 UTC 2011
Author: gibbs
Date: Tue Aug 16 22:33:05 2011
New Revision: 224921
URL: http://svn.freebsd.org/changeset/base/224921
Log:
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c:
Subscribe to attribute change notifications and update
vdev physical path information (in core and on disk) when
a GEOM::physpath event indicates they have changed.
Sponsored by: Spectra Logic Corporation
Modified:
projects/zfsd/head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
Modified: projects/zfsd/head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
==============================================================================
--- projects/zfsd/head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c Tue Aug 16 22:20:45 2011 (r224920)
+++ projects/zfsd/head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c Tue Aug 16 22:33:05 2011 (r224921)
@@ -88,6 +88,59 @@ vdev_geom_orphan(struct g_consumer *cp)
spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
}
+static void
+vdev_geom_attrchanged(struct g_consumer *cp, const char *attr)
+{
+ vdev_t *vd;
+ spa_t *spa;
+ char *physpath;
+ int error, physpath_len;
+
+ g_topology_assert();
+
+ if (strcmp(attr, "GEOM::physpath") != 0)
+ return;
+
+ if (g_access(cp, 1, 0, 0) != 0)
+ return;
+
+ /*
+ * Record/Update physical path information for this device.
+ */
+ vd = cp->private;
+ spa = vd->vdev_spa;
+ physpath_len = MAXPATHLEN;
+ physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO);
+ error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath);
+ g_access(cp, -1, 0, 0);
+ if (error == 0) {
+ char *old_physpath;
+
+ old_physpath = vd->vdev_physpath;
+ vd->vdev_physpath = spa_strdup(physpath);
+ spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
+
+ if (old_physpath != NULL) {
+ int held_lock;
+
+ held_lock = spa_config_held(spa, SCL_STATE, RW_WRITER);
+ if (held_lock == 0) {
+ g_topology_unlock();
+ spa_config_enter(spa, SCL_STATE, FTAG,
+ RW_WRITER);
+ }
+
+ spa_strfree(old_physpath);
+
+ if (held_lock == 0) {
+ spa_config_exit(spa, SCL_STATE, FTAG);
+ g_topology_lock();
+ }
+ }
+ }
+ g_free(physpath);
+}
+
static struct g_consumer *
vdev_geom_attach(struct g_provider *pp, vdev_t *vd)
{
@@ -108,6 +161,7 @@ vdev_geom_attach(struct g_provider *pp,
if (gp == NULL) {
gp = g_new_geomf(&zfs_vdev_class, "zfs::vdev");
gp->orphan = vdev_geom_orphan;
+ gp->attrchanged = vdev_geom_attrchanged;
cp = g_new_consumer(gp);
if (g_attach(cp, pp) != 0) {
g_wither_geom(gp, ENXIO);
@@ -144,7 +198,12 @@ vdev_geom_attach(struct g_provider *pp,
ZFS_LOG(1, "Used existing consumer for %s.", pp->name);
}
}
+
cp->private = vd;
+
+ /* Fetch initial physical path information for this device. */
+ vdev_geom_attrchanged(cp, "GEOM::physpath");
+
return (cp);
}
@@ -521,9 +580,8 @@ vdev_geom_open(vdev_t *vd, uint64_t *psi
vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
return (error);
}
-
- vd->vdev_tsd = cp;
pp = cp->provider;
+ vd->vdev_tsd = cp;
/*
* Determine the actual size of the device.
@@ -541,12 +599,6 @@ vdev_geom_open(vdev_t *vd, uint64_t *psi
*/
vd->vdev_nowritecache = B_FALSE;
- if (vd->vdev_physpath != NULL)
- spa_strfree(vd->vdev_physpath);
- bufsize = sizeof("/dev/") + strlen(pp->name);
- vd->vdev_physpath = kmem_alloc(bufsize, KM_SLEEP);
- snprintf(vd->vdev_physpath, bufsize, "/dev/%s", pp->name);
-
return (0);
}
More information about the svn-src-projects
mailing list