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 Submitted by: will, asomers MFC after: 4 weeks Sponsored by: Spectra Logic Corp Differential Revision: https://reviews.freebsd.org/D6428
This commit is contained in:
parent
583febf416
commit
151746b244
@ -85,32 +85,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;
|
||||
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);
|
||||
@ -122,12 +107,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
|
||||
@ -257,8 +276,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);
|
||||
|
@ -222,55 +222,68 @@ g_dev_print(void)
|
||||
}
|
||||
|
||||
static void
|
||||
g_dev_attrchanged(struct g_consumer *cp, const char *attr)
|
||||
g_dev_set_physpath(struct g_consumer *cp)
|
||||
{
|
||||
struct g_dev_softc *sc;
|
||||
char *physpath;
|
||||
int error, physpath_len;
|
||||
|
||||
if (g_access(cp, 1, 0, 0) != 0)
|
||||
return;
|
||||
|
||||
sc = cp->private;
|
||||
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 && strlen(physpath) != 0) {
|
||||
struct cdev *dev, *old_alias_dev;
|
||||
struct cdev **alias_devp;
|
||||
|
||||
dev = sc->sc_dev;
|
||||
old_alias_dev = sc->sc_alias;
|
||||
alias_devp = (struct cdev **)&sc->sc_alias;
|
||||
make_dev_physpath_alias(MAKEDEV_WAITOK, alias_devp, dev,
|
||||
old_alias_dev, physpath);
|
||||
} else if (sc->sc_alias) {
|
||||
destroy_dev((struct cdev *)sc->sc_alias);
|
||||
sc->sc_alias = NULL;
|
||||
}
|
||||
g_free(physpath);
|
||||
}
|
||||
|
||||
static void
|
||||
g_dev_set_media(struct g_consumer *cp)
|
||||
{
|
||||
struct g_dev_softc *sc;
|
||||
struct cdev *dev;
|
||||
char buf[SPECNAMELEN + 6];
|
||||
|
||||
sc = cp->private;
|
||||
if (strcmp(attr, "GEOM::media") == 0) {
|
||||
dev = sc->sc_dev;
|
||||
dev = sc->sc_dev;
|
||||
snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name);
|
||||
devctl_notify_f("DEVFS", "CDEV", "MEDIACHANGE", buf, M_WAITOK);
|
||||
devctl_notify_f("GEOM", "DEV", "MEDIACHANGE", buf, M_WAITOK);
|
||||
dev = sc->sc_alias;
|
||||
if (dev != NULL) {
|
||||
snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name);
|
||||
devctl_notify_f("DEVFS", "CDEV", "MEDIACHANGE", buf, M_WAITOK);
|
||||
devctl_notify_f("GEOM", "DEV", "MEDIACHANGE", buf, M_WAITOK);
|
||||
dev = sc->sc_alias;
|
||||
if (dev != NULL) {
|
||||
snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name);
|
||||
devctl_notify_f("DEVFS", "CDEV", "MEDIACHANGE", buf,
|
||||
M_WAITOK);
|
||||
devctl_notify_f("GEOM", "DEV", "MEDIACHANGE", buf,
|
||||
M_WAITOK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
g_dev_attrchanged(struct g_consumer *cp, const char *attr)
|
||||
{
|
||||
|
||||
if (strcmp(attr, "GEOM::media") == 0) {
|
||||
g_dev_set_media(cp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(attr, "GEOM::physpath") != 0)
|
||||
if (strcmp(attr, "GEOM::physpath") == 0) {
|
||||
g_dev_set_physpath(cp);
|
||||
return;
|
||||
|
||||
if (g_access(cp, 1, 0, 0) == 0) {
|
||||
char *physpath;
|
||||
int error, physpath_len;
|
||||
|
||||
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 && strlen(physpath) != 0) {
|
||||
struct cdev *old_alias_dev;
|
||||
struct cdev **alias_devp;
|
||||
|
||||
dev = sc->sc_dev;
|
||||
old_alias_dev = sc->sc_alias;
|
||||
alias_devp = (struct cdev **)&sc->sc_alias;
|
||||
make_dev_physpath_alias(MAKEDEV_WAITOK, alias_devp,
|
||||
dev, old_alias_dev, physpath);
|
||||
} else if (sc->sc_alias) {
|
||||
destroy_dev((struct cdev *)sc->sc_alias);
|
||||
sc->sc_alias = NULL;
|
||||
}
|
||||
g_free(physpath);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user