diff options
author | eschrock <none@none> | 2006-01-30 21:34:28 -0800 |
---|---|---|
committer | eschrock <none@none> | 2006-01-30 21:34:28 -0800 |
commit | c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07 (patch) | |
tree | c677def7879e53aed9cc2dd748194594ce86aaea /usr/src/lib/libzfs/common/libzfs_import.c | |
parent | 6a0b2badb8e0f78966c154a45bd14bf3069c1486 (diff) | |
download | illumos-joyent-c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07.tar.gz |
6362672 import gets confused about overlapping slices
6364582 need to fixup paths if they've changed
Diffstat (limited to 'usr/src/lib/libzfs/common/libzfs_import.c')
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_import.c | 54 |
1 files changed, 46 insertions, 8 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_import.c b/usr/src/lib/libzfs/common/libzfs_import.c index 6c56a1a2da..cc86292a50 100644 --- a/usr/src/lib/libzfs/common/libzfs_import.c +++ b/usr/src/lib/libzfs/common/libzfs_import.c @@ -108,6 +108,7 @@ get_devid(const char *path) devid_str_free(minor); devid_free(devid); } + (void) close(fd); return (ret); } @@ -123,8 +124,9 @@ fix_paths(nvlist_t *nv, name_entry_t *names) nvlist_t **child; uint_t c, children; uint64_t guid; - name_entry_t *ne; - char *devid; + name_entry_t *ne, *best; + char *path, *devid; + int matched; if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, &children) == 0) { @@ -137,19 +139,55 @@ fix_paths(nvlist_t *nv, name_entry_t *names) * This is a leaf (file or disk) vdev. In either case, go through * the name list and see if we find a matching guid. If so, replace * the path and see if we can calculate a new devid. + * + * There may be multiple names associated with a particular guid, in + * which case we have overlapping slices or multiple paths to the same + * disk. If this is the case, then we want to pick the path that is + * the most similar to the original, where "most similar" is the number + * of matching characters starting from the end of the path. This will + * preserve slice numbers even if the disks have been reorganized, and + * will also catch preferred disk names if multiple paths exist. */ verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0); + if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0) + path = NULL; + + matched = 0; + best = NULL; + for (ne = names; ne != NULL; ne = ne->ne_next) { + if (ne->ne_guid == guid) { + const char *src, *dst; + int count; + + if (path == NULL) { + best = ne; + break; + } - for (ne = names; ne != NULL; ne = ne->ne_next) - if (ne->ne_guid == guid) - break; + src = ne->ne_name + strlen(ne->ne_name) - 1; + dst = path + strlen(path) - 1; + for (count = 0; src >= ne->ne_name && dst >= path; + src--, dst--, count++) + if (*src != *dst) + break; + + /* + * At this point, 'count' is the number of characters + * matched from the end. + */ + if (count > matched || best == NULL) { + best = ne; + matched = count; + } + } + } - if (ne == NULL) + if (best == NULL) return; - verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, ne->ne_name) == 0); + verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, best->ne_name) == 0); - if ((devid = get_devid(ne->ne_name)) == NULL) { + if ((devid = get_devid(best->ne_name)) == NULL) { (void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID); } else { verify(nvlist_add_string(nv, ZPOOL_CONFIG_DEVID, devid) == 0); |