summaryrefslogtreecommitdiffstats
path: root/sys/cddl
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cddl')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c288
1 files changed, 69 insertions, 219 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 f151f83..54ba8bd 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
@@ -229,22 +229,6 @@ vdev_geom_worker(void *arg)
}
}
-static char *
-vdev_geom_get_id(struct g_consumer *cp)
-{
- char *id;
- int len;
-
- g_topology_assert_not();
- len = DISK_IDENT_SIZE;
- id = kmem_zalloc(len, KM_SLEEP);
- if (g_io_getattr("GEOM::ident", cp, &len, id) != 0) {
- kmem_free(id, DISK_IDENT_SIZE);
- return (NULL);
- }
- return (id);
-}
-
static uint64_t
nvlist_get_guid(nvlist_t *list)
{
@@ -261,79 +245,6 @@ nvlist_get_guid(nvlist_t *list)
return (0);
}
-static char *
-nvlist_get_devid(nvlist_t *list, uint64_t guid)
-{
- nvpair_t *elem = NULL;
- int progress;
- char *id;
-
- progress = 0;
- id = NULL;
-
- while ((elem = nvlist_next_nvpair(list, elem)) != NULL) {
- switch (nvpair_type(elem)) {
- case DATA_TYPE_STRING:
- {
- char *value;
-
- VERIFY(nvpair_value_string(elem, &value) == 0);
- if (strcmp(nvpair_name(elem), "type") == 0 &&
- strcmp(value, "disk") == 0) {
- progress |= 0x01;
- } else if (strcmp(nvpair_name(elem), "devid") == 0) {
- progress |= 0x02;
- id = value;
- }
- break;
- }
- case DATA_TYPE_UINT64:
- {
- uint64_t value;
-
- VERIFY(nvpair_value_uint64(elem, &value) == 0);
- if (strcmp(nvpair_name(elem), "guid") == 0 &&
- value == guid) {
- progress |= 0x04;
- }
- break;
- }
- case DATA_TYPE_NVLIST:
- {
- nvlist_t *value;
- char *lid;
-
- VERIFY(nvpair_value_nvlist(elem, &value) == 0);
- lid = nvlist_get_devid(value, guid);
- if (lid != NULL)
- return (lid);
- break;
- }
- case DATA_TYPE_NVLIST_ARRAY:
- {
- nvlist_t **value;
- u_int c, count;
- char *lid;
-
- VERIFY(nvpair_value_nvlist_array(elem, &value,
- &count) == 0);
-
- for (c = 0; c < count; c++) {
- lid = nvlist_get_devid(value[c], guid);
- if (lid != NULL)
- return (lid);
- }
- break;
- }
- }
- if (progress == 0x07)
- break;
- }
- if (progress != 0x07)
- id = NULL;
- return (id);
-}
-
static int
vdev_geom_io(struct g_consumer *cp, int cmd, void *data, off_t offset, off_t size)
{
@@ -368,8 +279,8 @@ vdev_geom_io(struct g_consumer *cp, int cmd, void *data, off_t offset, off_t siz
return (error);
}
-static char *
-vdev_geom_read_id(struct g_consumer *cp)
+static uint64_t
+vdev_geom_read_guid(struct g_consumer *cp)
{
struct g_provider *pp;
vdev_label_t *label;
@@ -377,7 +288,7 @@ vdev_geom_read_id(struct g_consumer *cp)
size_t buflen;
uint64_t psize;
off_t offset, size;
- char *id;
+ uint64_t guid;
int error, l, len;
g_topology_assert_not();
@@ -390,13 +301,12 @@ vdev_geom_read_id(struct g_consumer *cp)
size = sizeof(*label) + pp->sectorsize -
((sizeof(*label) - 1) % pp->sectorsize) - 1;
- id = NULL;
+ guid = 0;
label = kmem_alloc(size, KM_SLEEP);
buflen = sizeof(label->vl_vdev_phys.vp_nvlist);
- for (l = 0; l < VDEV_LABELS && id == NULL; l++) {
+ for (l = 0; l < VDEV_LABELS; l++) {
nvlist_t *config = NULL;
- uint64_t guid;
offset = vdev_label_offset(psize, l, 0);
if ((offset % pp->sectorsize) != 0)
@@ -411,38 +321,19 @@ vdev_geom_read_id(struct g_consumer *cp)
continue;
guid = nvlist_get_guid(config);
- if (guid == 0) {
- nvlist_free(config);
- continue;
- }
- id = nvlist_get_devid(config, guid);
- if (id != NULL) {
- char *tmp;
-
- tmp = kmem_zalloc(DISK_IDENT_SIZE, KM_SLEEP);
- strlcpy(tmp, id, DISK_IDENT_SIZE);
- id = tmp;
- }
-
nvlist_free(config);
+ if (guid != 0)
+ break;
}
kmem_free(label, size);
- if (id != NULL)
- ZFS_LOG(1, "ID of %s: %s", pp->name, id);
- return (id);
-}
-
-static void
-vdev_geom_free_id(char *id)
-{
-
- if (id != NULL)
- kmem_free(id, DISK_IDENT_SIZE);
+ if (guid != 0)
+ ZFS_LOG(1, "guid for %s is %ju", pp->name, (uintmax_t)guid);
+ return (guid);
}
struct vdev_geom_find {
- const char *id;
+ uint64_t guid;
int write;
struct g_consumer *cp;
};
@@ -456,14 +347,14 @@ vdev_geom_taste_orphan(struct g_consumer *cp)
}
static void
-vdev_geom_attach_by_id_event(void *arg, int flags __unused)
+vdev_geom_attach_by_guid_event(void *arg, int flags __unused)
{
struct vdev_geom_find *ap;
struct g_class *mp;
struct g_geom *gp, *zgp;
struct g_provider *pp;
struct g_consumer *zcp;
- char *id;
+ uint64_t guid;
g_topology_assert();
@@ -474,42 +365,6 @@ vdev_geom_attach_by_id_event(void *arg, int flags __unused)
zgp->orphan = vdev_geom_taste_orphan;
zcp = g_new_consumer(zgp);
- /* First round tries to get provider's ID without reading metadata. */
- LIST_FOREACH(mp, &g_classes, class) {
- if (mp == &zfs_vdev_class)
- continue;
- LIST_FOREACH(gp, &mp->geom, geom) {
- if (gp->flags & G_GEOM_WITHER)
- continue;
- LIST_FOREACH(pp, &gp->provider, provider) {
- if (pp->flags & G_PF_WITHER)
- continue;
- g_attach(zcp, pp);
- if (g_access(zcp, 1, 0, 0) != 0) {
- g_detach(zcp);
- continue;
- }
- g_topology_unlock();
- id = vdev_geom_get_id(zcp);
- g_topology_lock();
- g_access(zcp, -1, 0, 0);
- g_detach(zcp);
- if (id == NULL || strcmp(id, ap->id) != 0) {
- vdev_geom_free_id(id);
- continue;
- }
- vdev_geom_free_id(id);
- ap->cp = vdev_geom_attach(pp, ap->write);
- if (ap->cp == NULL) {
- printf("ZFS WARNING: Cannot open %s "
- "for writting.\n", pp->name);
- continue;
- }
- goto end;
- }
- }
- }
- /* Second round looks for ID by reading ZFS metadata. */
LIST_FOREACH(mp, &g_classes, class) {
if (mp == &zfs_vdev_class)
continue;
@@ -525,15 +380,12 @@ vdev_geom_attach_by_id_event(void *arg, int flags __unused)
continue;
}
g_topology_unlock();
- id = vdev_geom_read_id(zcp);
+ guid = vdev_geom_read_guid(zcp);
g_topology_lock();
g_access(zcp, -1, 0, 0);
g_detach(zcp);
- if (id == NULL || strcmp(id, ap->id) != 0) {
- vdev_geom_free_id(id);
+ if (guid != ap->guid)
continue;
- }
- vdev_geom_free_id(id);
ap->cp = vdev_geom_attach(pp, ap->write);
if (ap->cp == NULL) {
printf("ZFS WARNING: Cannot open %s "
@@ -551,26 +403,53 @@ end:
}
static struct g_consumer *
-vdev_geom_attach_by_id(const char *id, int write)
+vdev_geom_attach_by_guid(uint64_t guid, int write)
{
struct vdev_geom_find *ap;
struct g_consumer *cp;
ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
- ap->id = id;
+ ap->guid = guid;
ap->write = write;
- g_waitfor_event(vdev_geom_attach_by_id_event, ap, M_WAITOK, NULL);
+ g_waitfor_event(vdev_geom_attach_by_guid_event, ap, M_WAITOK, NULL);
cp = ap->cp;
kmem_free(ap, sizeof(*ap));
return (cp);
}
static struct g_consumer *
-vdev_geom_open_by_path_and_devid(vdev_t *vd)
+vdev_geom_open_by_guid(vdev_t *vd)
+{
+ struct g_consumer *cp;
+ char *buf;
+ size_t len;
+
+ ZFS_LOG(1, "Searching by guid [%ju].", (uintmax_t)vd->vdev_guid);
+ cp = vdev_geom_attach_by_guid(vd->vdev_guid, !!(spa_mode & FWRITE));
+ if (cp != NULL) {
+ len = strlen(cp->provider->name) + strlen("/dev/") + 1;
+ buf = kmem_alloc(len, KM_SLEEP);
+
+ snprintf(buf, len, "/dev/%s", cp->provider->name);
+ spa_strfree(vd->vdev_path);
+ vd->vdev_path = buf;
+
+ ZFS_LOG(1, "Attach by guid [%ju] succeeded, provider %s.",
+ (uintmax_t)vd->vdev_guid, vd->vdev_path);
+ } else {
+ ZFS_LOG(1, "Search by guid [%ju] failed.",
+ (uintmax_t)vd->vdev_guid);
+ }
+
+ return (cp);
+}
+
+static struct g_consumer *
+vdev_geom_open_by_path(vdev_t *vd, int check_guid)
{
struct g_provider *pp;
struct g_consumer *cp;
- char *id;
+ uint64_t guid;
cp = NULL;
g_topology_lock();
@@ -578,20 +457,20 @@ vdev_geom_open_by_path_and_devid(vdev_t *vd)
if (pp != NULL) {
ZFS_LOG(1, "Found provider by name %s.", vd->vdev_path);
cp = vdev_geom_attach(pp, !!(spa_mode & FWRITE));
- if (cp != NULL && vd->vdev_devid != NULL) {
+ if (cp != NULL && check_guid) {
g_topology_unlock();
- id = vdev_geom_get_id(cp);
+ guid = vdev_geom_read_guid(cp);
g_topology_lock();
- if (id == NULL || strcmp(id, vd->vdev_devid) != 0) {
+ if (guid != vd->vdev_guid) {
vdev_geom_detach(cp, 0);
cp = NULL;
- ZFS_LOG(1, "ID mismatch for provider %s: "
- "[%s]!=[%s].", vd->vdev_path,
- vd->vdev_devid, id);
- } else
- ZFS_LOG(1, "ID match for provider %s.",
+ ZFS_LOG(1, "guid mismatch for provider %s: "
+ "%ju != %ju.", vd->vdev_path,
+ (uintmax_t)vd->vdev_guid, (uintmax_t)guid);
+ } else {
+ ZFS_LOG(1, "guid match for provider %s.",
vd->vdev_path);
- vdev_geom_free_id(id);
+ }
}
}
g_topology_unlock();
@@ -599,37 +478,6 @@ vdev_geom_open_by_path_and_devid(vdev_t *vd)
return (cp);
}
-static struct g_consumer *
-vdev_geom_open_by_devid(vdev_t *vd)
-{
- struct g_consumer *cp;
- char *buf;
- size_t len;
-
- /*
- * We can't search by devid if it's missing.
- */
- if (vd->vdev_devid == NULL)
- return (NULL);
-
- ZFS_LOG(1, "Searching by ID [%s].", vd->vdev_devid);
- cp = vdev_geom_attach_by_id(vd->vdev_devid, !!(spa_mode & FWRITE));
- if (cp != NULL) {
- len = strlen(cp->provider->name) + strlen("/dev/") + 1;
- buf = kmem_alloc(len, KM_SLEEP);
-
- snprintf(buf, len, "/dev/%s", cp->provider->name);
- spa_strfree(vd->vdev_path);
- vd->vdev_path = buf;
-
- ZFS_LOG(1, "Attach by ID [%s] succeeded, provider %s.",
- vd->vdev_devid, vd->vdev_path);
- } else
- ZFS_LOG(1, "Search by ID [%s] failed.", vd->vdev_devid);
-
- return (cp);
-}
-
static int
vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
{
@@ -650,21 +498,23 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
if ((owned = mtx_owned(&Giant)))
mtx_unlock(&Giant);
- cp = vdev_geom_open_by_path_and_devid(vd);
+ cp = vdev_geom_open_by_path(vd, 0);
if (cp == NULL) {
/*
- * The device at vd->vdev_path doesn't have the right devid.
+ * The device at vd->vdev_path doesn't have the expected guid.
* The disks might have merely moved around so try all other
- * geom providers to find one with the right devid.
+ * geom providers to find one with the right guid.
*/
- cp = vdev_geom_open_by_devid(vd);
- if (cp == NULL) {
- ZFS_LOG(1, "Provider %s not found.", vd->vdev_path);
- vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
- if (owned)
- mtx_lock(&Giant);
- return (EACCES);
- }
+ cp = vdev_geom_open_by_guid(vd);
+ }
+ if (cp == NULL)
+ cp = vdev_geom_open_by_path(vd, 1);
+ if (cp == NULL) {
+ ZFS_LOG(1, "Provider %s not found.", vd->vdev_path);
+ vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+ if (owned)
+ mtx_lock(&Giant);
+ return (EACCES);
}
if (owned)
mtx_lock(&Giant);
OpenPOWER on IntegriCloud