char *ne_name;
uint64_t ne_guid;
uint64_t ne_order;
+ uint64_t ne_num_labels;
struct name_entry *ne_next;
} name_entry_t;
break;
}
- if (best == NULL || ne->ne_order < best->ne_order)
+ if (best == NULL) {
best = ne;
+ continue;
+ }
+
+ /* Prefer paths with move vdev labels. */
+ if (ne->ne_num_labels > best->ne_num_labels) {
+ best = ne;
+ continue;
+ }
+
+ /* Prefer paths earlier in the search order. */
+ if (best->ne_num_labels == best->ne_num_labels &&
+ ne->ne_order < best->ne_order) {
+ best = ne;
+ continue;
+ }
}
}
*/
static int
add_config(libzfs_handle_t *hdl, pool_list_t *pl, const char *path,
- int order, nvlist_t *config)
+ int order, int num_labels, nvlist_t *config)
{
uint64_t pool_guid, vdev_guid, top_guid, txg, state;
pool_entry_t *pe;
}
ne->ne_guid = vdev_guid;
ne->ne_order = order;
+ ne->ne_num_labels = num_labels;
ne->ne_next = pl->names;
pl->names = ne;
return (0);
ne->ne_guid = vdev_guid;
ne->ne_order = order;
+ ne->ne_num_labels = num_labels;
ne->ne_next = pl->names;
pl->names = ne;
/*
* Given a file descriptor, read the label information and return an nvlist
- * describing the configuration, if there is one.
+ * describing the configuration, if there is one. The number of valid
+ * labels found will be returned in num_labels when non-NULL.
*/
int
-zpool_read_label(int fd, nvlist_t **config)
+zpool_read_label(int fd, nvlist_t **config, int *num_labels)
{
struct stat64 statbuf;
- int l;
+ int l, count = 0;
vdev_label_t *label;
- uint64_t state, txg, size;
+ nvlist_t *expected_config = NULL;
+ uint64_t expected_guid = 0, size;
*config = NULL;
return (-1);
for (l = 0; l < VDEV_LABELS; l++) {
+ uint64_t state, guid, txg;
+
if (pread64(fd, label, sizeof (vdev_label_t),
label_offset(size, l)) != sizeof (vdev_label_t))
continue;
sizeof (label->vl_vdev_phys.vp_nvlist), config, 0) != 0)
continue;
+ if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_GUID,
+ &guid) != 0 || guid == 0) {
+ nvlist_free(*config);
+ continue;
+ }
+
if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_STATE,
&state) != 0 || state > POOL_STATE_L2CACHE) {
nvlist_free(*config);
continue;
}
- free(label);
- return (0);
+ if (expected_guid) {
+ if (expected_guid == guid)
+ count++;
+
+ nvlist_free(*config);
+ } else {
+ expected_config = *config;
+ expected_guid = guid;
+ count++;
+ }
}
+ if (num_labels != NULL)
+ *num_labels = count;
+
free(label);
- *config = NULL;
+ *config = expected_config;
+
return (0);
}
blkid_dev dev;
const char *devname;
nvlist_t *config;
- int fd, err;
+ int fd, err, num_labels;
err = blkid_get_cache(&cache, NULL);
if (err != 0) {
if ((fd = open64(devname, O_RDONLY)) < 0)
continue;
- err = zpool_read_label(fd, &config);
+ err = zpool_read_label(fd, &config, &num_labels);
(void) close(fd);
if (err != 0) {
}
if (config != NULL) {
- err = add_config(hdl, pools, devname, 0, config);
+ err = add_config(hdl, pools, devname, 0,
+ num_labels, config);
if (err != 0)
goto err_blkid3;
}
static nvlist_t *
zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg)
{
- int i, dirs = iarg->paths;
+ int i, num_labels, dirs = iarg->paths;
DIR *dirp = NULL;
struct dirent64 *dp;
char path[MAXPATHLEN];
if ((fd = openat64(dfd, name, O_RDONLY)) < 0)
continue;
- if ((zpool_read_label(fd, &config)) != 0) {
+ if ((zpool_read_label(fd, &config, &num_labels))) {
(void) close(fd);
(void) no_memory(hdl);
goto error;
}
/* use the non-raw path for the config */
(void) strlcpy(end, name, pathleft);
- if (add_config(hdl, &pools, path, i+1, config))
+ if (add_config(hdl, &pools, path, i+1,
+ num_labels, config))
goto error;
}
}
*inuse = B_FALSE;
- if (zpool_read_label(fd, &config) != 0) {
+ if (zpool_read_label(fd, &config, NULL) != 0) {
(void) no_memory(hdl);
return (-1);
}