X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=lib%2Flibzfs%2Flibzfs_import.c;h=ad343e896ea32842fbf8b65546a6cfd030c32105;hb=0e20a31b4bb7f9745fe6d5cafe513c9c1df3e933;hp=7048a52c9ced6f4bc80652f26297245364fe685f;hpb=f03e41e8da6d184039ea3b03ba4937f4786a3f22;p=zfs.git diff --git a/lib/libzfs/libzfs_import.c b/lib/libzfs/libzfs_import.c index 7048a52..ad343e8 100644 --- a/lib/libzfs/libzfs_import.c +++ b/lib/libzfs/libzfs_import.c @@ -20,6 +20,8 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ /* @@ -85,6 +87,7 @@ typedef struct pool_entry { typedef struct name_entry { char *ne_name; uint64_t ne_guid; + uint64_t ne_order; struct name_entry *ne_next; } name_entry_t; @@ -130,7 +133,6 @@ fix_paths(nvlist_t *nv, name_entry_t *names) uint64_t guid; name_entry_t *ne, *best; char *path, *devid; - int matched; if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, &children) == 0) { @@ -146,44 +148,33 @@ fix_paths(nvlist_t *nv, name_entry_t *names) * 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. + * which case we have overlapping partitions or multiple paths to the + * same disk. In this case we prefer to use the path name which + * matches the ZPOOL_CONFIG_PATH. If no matching entry is found we + * use the lowest order device which corresponds to the first match + * while traversing the ZPOOL_IMPORT_PATH search path. */ 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; } - 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) { + if ((strlen(path) == strlen(ne->ne_name)) && + !strncmp(path, ne->ne_name, strlen(path))) { best = ne; - matched = count; + break; } + + if (best == NULL || ne->ne_order < best->ne_order) + best = ne; } } @@ -209,7 +200,7 @@ fix_paths(nvlist_t *nv, name_entry_t *names) */ static int add_config(libzfs_handle_t *hdl, pool_list_t *pl, const char *path, - nvlist_t *config) + int order, nvlist_t *config) { uint64_t pool_guid, vdev_guid, top_guid, txg, state; pool_entry_t *pe; @@ -234,6 +225,7 @@ add_config(libzfs_handle_t *hdl, pool_list_t *pl, const char *path, return (-1); } ne->ne_guid = vdev_guid; + ne->ne_order = order; ne->ne_next = pl->names; pl->names = ne; return (0); @@ -335,6 +327,7 @@ add_config(libzfs_handle_t *hdl, pool_list_t *pl, const char *path, } ne->ne_guid = vdev_guid; + ne->ne_order = order; ne->ne_next = pl->names; pl->names = ne; @@ -441,7 +434,7 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok) uint_t i, nspares, nl2cache; boolean_t config_seen; uint64_t best_txg; - char *name, *hostname; + char *name, *hostname, *comment; uint64_t version, guid; uint_t children = 0; nvlist_t **child = NULL; @@ -530,6 +523,7 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok) * version * pool guid * name + * comment (if available) * pool state * hostid (if available) * hostname (if available) @@ -551,11 +545,24 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok) if (nvlist_add_string(config, ZPOOL_CONFIG_POOL_NAME, name) != 0) goto nomem; + + /* + * COMMENT is optional, don't bail if it's not + * there, instead, set it to NULL. + */ + if (nvlist_lookup_string(tmp, + ZPOOL_CONFIG_COMMENT, &comment) != 0) + comment = NULL; + else if (nvlist_add_string(config, + ZPOOL_CONFIG_COMMENT, comment) != 0) + goto nomem; + verify(nvlist_lookup_uint64(tmp, ZPOOL_CONFIG_POOL_STATE, &state) == 0); if (nvlist_add_uint64(config, ZPOOL_CONFIG_POOL_STATE, state) != 0) goto nomem; + hostid = 0; if (nvlist_lookup_uint64(tmp, ZPOOL_CONFIG_HOSTID, &hostid) == 0) { @@ -962,7 +969,7 @@ zpool_find_import_blkid(libzfs_handle_t *hdl, pool_list_t *pools) } if (config != NULL) { - err = add_config(hdl, pools, devname, config); + err = add_config(hdl, pools, devname, 0, config); if (err != 0) goto err_blkid3; } @@ -977,6 +984,18 @@ err_blkid1: } #endif /* HAVE_LIBBLKID */ +char * +zpool_default_import_path[DEFAULT_IMPORT_PATH_SIZE] = { + "/dev/disk/by-vdev", /* Custom rules, use first if they exist */ + "/dev/disk/zpool", /* Custom rules, use first if they exist */ + "/dev/mapper", /* Use multipath devices before components */ + "/dev/disk/by-uuid", /* Single unique entry and persistent */ + "/dev/disk/by-id", /* May be multiple entries and persistent */ + "/dev/disk/by-path", /* Encodes physical location and persistent */ + "/dev/disk/by-label", /* Custom persistent labels */ + "/dev" /* UNSAFE device names will change */ +}; + /* * Given a list of directories to search, find all pools stored on disk. This * includes partial pools which are not available to import. If no args are @@ -995,7 +1014,6 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg) size_t pathleft; struct stat64 statbuf; nvlist_t *ret = NULL, *config; - static char *default_dir = DISK_ROOT; int fd; pool_list_t pools = { 0 }; pool_entry_t *pe, *penext; @@ -1015,8 +1033,9 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg) dgettext(TEXT_DOMAIN, "blkid failure falling back " "to manual probing")); #endif /* HAVE_LIBBLKID */ - dirs = 1; - dir = &default_dir; + + dir = zpool_default_import_path; + dirs = DEFAULT_IMPORT_PATH_SIZE; } /* @@ -1030,6 +1049,12 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg) /* use realpath to normalize the path */ if (realpath(dir[i], path) == 0) { + + /* it is safe to skip missing search paths */ + if (errno == ENOENT) + continue; + + zfs_error_aux(hdl, strerror(errno)); (void) zfs_error_fmt(hdl, EZFS_BADPATH, dgettext(TEXT_DOMAIN, "cannot open '%s'"), dir[i]); goto error; @@ -1117,14 +1142,15 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg) if (config != NULL) { boolean_t matched = B_TRUE; + char *pname; + + if ((iarg->poolname != NULL) && + (nvlist_lookup_string(config, + ZPOOL_CONFIG_POOL_NAME, &pname) == 0)) { - if (iarg->poolname != NULL) { - char *pname; + if (strcmp(iarg->poolname, pname)) + matched = B_FALSE; - matched = nvlist_lookup_string(config, - ZPOOL_CONFIG_POOL_NAME, - &pname) == 0 && - strcmp(iarg->poolname, pname) == 0; } else if (iarg->guid != 0) { uint64_t this_guid; @@ -1140,7 +1166,7 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg) } /* use the non-raw path for the config */ (void) strlcpy(end, name, pathleft); - if (add_config(hdl, &pools, path, config) != 0) + if (add_config(hdl, &pools, path, i+1, config)) goto error; } }