diff options
author | mav <mav@FreeBSD.org> | 2016-10-28 18:25:32 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2016-10-28 18:25:32 +0000 |
commit | c12394dc80b2b30e2c76deb5e0559fff9d3c57ac (patch) | |
tree | 5f44797268aed769b43b3764a0c95f7c55e4332b /sys/cddl/contrib/opensolaris/uts/common | |
parent | 748b013188753a4b409720c333b6786231ac801f (diff) | |
download | FreeBSD-src-c12394dc80b2b30e2c76deb5e0559fff9d3c57ac.zip FreeBSD-src-c12394dc80b2b30e2c76deb5e0559fff9d3c57ac.tar.gz |
MFC r300881, r302058 (by asomers):
Avoid issuing spa config updates for physical path when not necessary
ZFS's configuration needs to be updated whenever the physical path for a
device changes, but not when a new device is introduced. This is because new
devices necessarily cause config updates, but only if they are actually
accepted into the pool.
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
Split vdev_geom_set_physpath out of vdev_geom_attrchanged. When
setting the vdev's physical path, only request a config update if
the physical path has changed. Don't request it when opening a
device for the first time, because the config sync will happen
anyway upstack.
sys/geom/geom_dev.c
Split g_dev_set_physpath and g_dev_set_media out of
g_dev_attrchanged
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common')
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c index 9ae07d1..fa38d08 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c @@ -87,32 +87,17 @@ vdev_geom_set_rotation_rate(vdev_t *vd, struct g_consumer *cp) } static void -vdev_geom_attrchanged(struct g_consumer *cp, const char *attr) +vdev_geom_set_physpath(struct g_consumer *cp, boolean_t do_null_update) { + boolean_t needs_update = B_FALSE; vdev_t *vd; - spa_t *spa; char *physpath; int error, physpath_len; - vd = cp->private; - if (vd == NULL) - return; - - if (strcmp(attr, "GEOM::rotation_rate") == 0) { - vdev_geom_set_rotation_rate(vd, cp); - return; - } - - if (strcmp(attr, "GEOM::physpath") != 0) - return; - if (g_access(cp, 1, 0, 0) != 0) return; - /* - * Record/Update physical path information for this device. - */ - spa = vd->vdev_spa; + vd = cp->private; physpath_len = MAXPATHLEN; physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO); error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath); @@ -124,12 +109,46 @@ vdev_geom_attrchanged(struct g_consumer *cp, const char *attr) g_topology_assert(); old_physpath = vd->vdev_physpath; vd->vdev_physpath = spa_strdup(physpath); - spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE); - if (old_physpath != NULL) + if (old_physpath != NULL) { + needs_update = (strcmp(old_physpath, + vd->vdev_physpath) != 0); spa_strfree(old_physpath); + } else + needs_update = do_null_update; } g_free(physpath); + + /* + * If the physical path changed, update the config. + * Only request an update for previously unset physpaths if + * requested by the caller. + */ + if (needs_update) + spa_async_request(vd->vdev_spa, SPA_ASYNC_CONFIG_UPDATE); + +} + +static void +vdev_geom_attrchanged(struct g_consumer *cp, const char *attr) +{ + vdev_t *vd; + char *old_physpath; + int error; + + vd = cp->private; + if (vd == NULL) + return; + + if (strcmp(attr, "GEOM::rotation_rate") == 0) { + vdev_geom_set_rotation_rate(vd, cp); + return; + } + + if (strcmp(attr, "GEOM::physpath") == 0) { + vdev_geom_set_physpath(cp, /*do_null_update*/B_TRUE); + return; + } } static void @@ -259,8 +278,10 @@ vdev_geom_attach(struct g_provider *pp, vdev_t *vd) * 2) Set it to a linked list of vdevs, not just a single vdev */ cp->private = vd; - if (vd != NULL) + if (vd != NULL) { vd->vdev_tsd = cp; + vdev_geom_set_physpath(cp, /*do_null_update*/B_FALSE); + } cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; return (cp); |