Changeset View
Changeset View
Standalone View
Standalone View
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
Show First 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | vdev_geom_set_rotation_rate(vdev_t *vd, struct g_consumer *cp) | ||||
error = g_getattr("GEOM::rotation_rate", cp, &rate); | error = g_getattr("GEOM::rotation_rate", cp, &rate); | ||||
if (error == 0) | if (error == 0) | ||||
vd->vdev_rotation_rate = rate; | vd->vdev_rotation_rate = rate; | ||||
else | else | ||||
vd->vdev_rotation_rate = VDEV_RATE_UNKNOWN; | vd->vdev_rotation_rate = VDEV_RATE_UNKNOWN; | ||||
} | } | ||||
static void | 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; | vdev_t *vd; | ||||
spa_t *spa; | |||||
char *physpath; | char *physpath; | ||||
int error, physpath_len; | 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) | if (g_access(cp, 1, 0, 0) != 0) | ||||
return; | return; | ||||
/* | vd = cp->private; | ||||
* Record/Update physical path information for this device. | |||||
*/ | |||||
spa = vd->vdev_spa; | |||||
physpath_len = MAXPATHLEN; | physpath_len = MAXPATHLEN; | ||||
physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO); | physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO); | ||||
error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath); | error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath); | ||||
g_access(cp, -1, 0, 0); | g_access(cp, -1, 0, 0); | ||||
if (error == 0) { | if (error == 0) { | ||||
char *old_physpath; | char *old_physpath; | ||||
/* g_topology lock ensures that vdev has not been closed */ | /* g_topology lock ensures that vdev has not been closed */ | ||||
g_topology_assert(); | g_topology_assert(); | ||||
old_physpath = vd->vdev_physpath; | old_physpath = vd->vdev_physpath; | ||||
vd->vdev_physpath = spa_strdup(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); | spa_strfree(old_physpath); | ||||
} else | |||||
needs_update = do_null_update; | |||||
} | } | ||||
g_free(physpath); | 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 | 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 | |||||
vdev_geom_orphan(struct g_consumer *cp) | vdev_geom_orphan(struct g_consumer *cp) | ||||
{ | { | ||||
vdev_t *vd; | vdev_t *vd; | ||||
g_topology_assert(); | g_topology_assert(); | ||||
vd = cp->private; | vd = cp->private; | ||||
if (vd == NULL) { | if (vd == NULL) { | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | vdev_geom_attach(struct g_provider *pp, vdev_t *vd) | ||||
* 2) We are trying to reopen a missing vdev and we are scanning by | * 2) We are trying to reopen a missing vdev and we are scanning by | ||||
* guid. In that case, we'll ultimately fail to open this consumer, | * guid. In that case, we'll ultimately fail to open this consumer, | ||||
* but not until after setting the private field. | * but not until after setting the private field. | ||||
* The solution is to: | * The solution is to: | ||||
* 1) Don't set the private field until after the open succeeds, and | * 1) Don't set the private field until after the open succeeds, and | ||||
* 2) Set it to a linked list of vdevs, not just a single vdev | * 2) Set it to a linked list of vdevs, not just a single vdev | ||||
*/ | */ | ||||
cp->private = vd; | cp->private = vd; | ||||
if (vd != NULL) | if (vd != NULL) { | ||||
vd->vdev_tsd = cp; | vd->vdev_tsd = cp; | ||||
vdev_geom_set_physpath(cp, /*do_null_update*/B_FALSE); | |||||
} | |||||
cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; | cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; | ||||
return (cp); | return (cp); | ||||
} | } | ||||
static void | static void | ||||
vdev_geom_detach(struct g_consumer *cp, boolean_t open_for_read) | vdev_geom_detach(struct g_consumer *cp, boolean_t open_for_read) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 768 Lines • Show Last 20 Lines |