diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libzfs/libzfs_import.c | 74 | ||||
-rw-r--r-- | lib/libzfs/libzfs_pool.c | 55 | ||||
-rw-r--r-- | lib/libzfs/libzfs_status.c | 27 | ||||
-rw-r--r-- | lib/libzfs/libzfs_util.c | 9 | ||||
-rw-r--r-- | lib/libzpool/Makefile.am | 1 |
5 files changed, 161 insertions, 5 deletions
diff --git a/lib/libzfs/libzfs_import.c b/lib/libzfs/libzfs_import.c index 02264433e..f371d925b 100644 --- a/lib/libzfs/libzfs_import.c +++ b/lib/libzfs/libzfs_import.c @@ -2166,6 +2166,80 @@ zpool_search_import(libzfs_handle_t *hdl, importargs_t *import) return (zpool_find_import_impl(hdl, import)); } +static boolean_t +pool_match(nvlist_t *cfg, char *tgt) +{ + uint64_t v, guid = strtoull(tgt, NULL, 0); + char *s; + + if (guid != 0) { + if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_GUID, &v) == 0) + return (v == guid); + } else { + if (nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &s) == 0) + return (strcmp(s, tgt) == 0); + } + return (B_FALSE); +} + +int +zpool_tryimport(libzfs_handle_t *hdl, char *target, nvlist_t **configp, + importargs_t *args) +{ + nvlist_t *pools; + nvlist_t *match = NULL; + nvlist_t *config = NULL; + char *name = NULL, *sepp = NULL; + char sep = '\0'; + int count = 0; + char *targetdup = strdup(target); + + *configp = NULL; + + if ((sepp = strpbrk(targetdup, "/@")) != NULL) { + sep = *sepp; + *sepp = '\0'; + } + + pools = zpool_search_import(hdl, args); + + if (pools != NULL) { + nvpair_t *elem = NULL; + while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { + VERIFY0(nvpair_value_nvlist(elem, &config)); + if (pool_match(config, targetdup)) { + count++; + if (match != NULL) { + /* multiple matches found */ + continue; + } else { + match = config; + name = nvpair_name(elem); + } + } + } + } + + if (count == 0) { + (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "no pools found")); + free(targetdup); + return (ENOENT); + } + + if (count > 1) { + (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "%d pools found, use pool GUID\n"), count); + free(targetdup); + return (EINVAL); + } + + *configp = match; + free(targetdup); + + return (0); +} + boolean_t find_guid(nvlist_t *nv, uint64_t guid) { diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 746e6a8cc..58d91c8f4 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -676,7 +676,14 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname, goto error; } break; - + case ZPOOL_PROP_MULTIHOST: + if (get_system_hostid() == 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "requires a non-zero system hostid")); + (void) zfs_error(hdl, EZFS_BADPROP, errbuf); + goto error; + } + break; default: zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "property '%s'(%d) not defined"), propname, prop); @@ -1779,6 +1786,7 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, if (error) { char desc[1024]; + char aux[256]; /* * Dry-run failed, but we print out what success @@ -1824,6 +1832,47 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, (void) zfs_error(hdl, EZFS_BADVERSION, desc); break; + case EREMOTEIO: + if (nv != NULL && nvlist_lookup_nvlist(nv, + ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0) { + char *hostname = "<unknown>"; + uint64_t hostid = 0; + mmp_state_t mmp_state; + + mmp_state = fnvlist_lookup_uint64(nvinfo, + ZPOOL_CONFIG_MMP_STATE); + + if (nvlist_exists(nvinfo, + ZPOOL_CONFIG_MMP_HOSTNAME)) + hostname = fnvlist_lookup_string(nvinfo, + ZPOOL_CONFIG_MMP_HOSTNAME); + + if (nvlist_exists(nvinfo, + ZPOOL_CONFIG_MMP_HOSTID)) + hostid = fnvlist_lookup_uint64(nvinfo, + ZPOOL_CONFIG_MMP_HOSTID); + + if (mmp_state == MMP_STATE_ACTIVE) { + (void) snprintf(aux, sizeof (aux), + dgettext(TEXT_DOMAIN, "pool is imp" + "orted on host '%s' (hostid=%lx).\n" + "Export the pool on the other " + "system, then run 'zpool import'."), + hostname, (unsigned long) hostid); + } else if (mmp_state == MMP_STATE_NO_HOSTID) { + (void) snprintf(aux, sizeof (aux), + dgettext(TEXT_DOMAIN, "pool has " + "the multihost property on and " + "the\nsystem's hostid is not set. " + "Set a unique system hostid with " + "the genhostid(1) command.\n")); + } + + (void) zfs_error_aux(hdl, aux); + } + (void) zfs_error(hdl, EZFS_ACTIVE_POOL, desc); + break; + case EINVAL: (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); break; @@ -2206,7 +2255,7 @@ zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare, } static int -vdev_online(nvlist_t *nv) +vdev_is_online(nvlist_t *nv) { uint64_t ival; @@ -2274,7 +2323,7 @@ vdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size, return (EZFS_INVALCONFIG); } - if (vdev_online(nv)) { + if (vdev_is_online(nv)) { if ((ret = vdev_get_one_physpath(nv, physpath, phypath_size, rsz)) != 0) return (ret); diff --git a/lib/libzfs/libzfs_status.c b/lib/libzfs/libzfs_status.c index d5470f412..05a9afce8 100644 --- a/lib/libzfs/libzfs_status.c +++ b/lib/libzfs/libzfs_status.c @@ -64,6 +64,8 @@ static char *zfs_msgid_table[] = { "ZFS-8000-9P", "ZFS-8000-A5", "ZFS-8000-EY", + "ZFS-8000-EY", + "ZFS-8000-EY", "ZFS-8000-HC", "ZFS-8000-JQ", "ZFS-8000-K4", @@ -216,6 +218,26 @@ check_status(nvlist_t *config, boolean_t isimport, zpool_errata_t *erratap) return (ZPOOL_STATUS_RESILVERING); /* + * The multihost property is set and the pool may be active. + */ + if (vs->vs_state == VDEV_STATE_CANT_OPEN && + vs->vs_aux == VDEV_AUX_ACTIVE) { + mmp_state_t mmp_state; + nvlist_t *nvinfo; + + nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); + mmp_state = fnvlist_lookup_uint64(nvinfo, + ZPOOL_CONFIG_MMP_STATE); + + if (mmp_state == MMP_STATE_ACTIVE) + return (ZPOOL_STATUS_HOSTID_ACTIVE); + else if (mmp_state == MMP_STATE_NO_HOSTID) + return (ZPOOL_STATUS_HOSTID_REQUIRED); + else + return (ZPOOL_STATUS_HOSTID_MISMATCH); + } + + /* * Pool last accessed by another system. */ (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid); @@ -344,8 +366,9 @@ check_status(nvlist_t *config, boolean_t isimport, zpool_errata_t *erratap) if (isimport) { feat = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); - feat = fnvlist_lookup_nvlist(feat, - ZPOOL_CONFIG_ENABLED_FEAT); + if (nvlist_exists(feat, ZPOOL_CONFIG_ENABLED_FEAT)) + feat = fnvlist_lookup_nvlist(feat, + ZPOOL_CONFIG_ENABLED_FEAT); } else { feat = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS); diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index 30255d643..bc51a76a8 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -261,6 +261,9 @@ libzfs_error_description(libzfs_handle_t *hdl) return (dgettext(TEXT_DOMAIN, "invalid diff data")); case EZFS_POOLREADONLY: return (dgettext(TEXT_DOMAIN, "pool is read-only")); + case EZFS_ACTIVE_POOL: + return (dgettext(TEXT_DOMAIN, "pool is imported on a " + "different host")); case EZFS_UNKNOWN: return (dgettext(TEXT_DOMAIN, "unknown error")); default: @@ -423,6 +426,9 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) "pool I/O is currently suspended")); zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); break; + case EREMOTEIO: + zfs_verror(hdl, EZFS_ACTIVE_POOL, fmt, ap); + break; default: zfs_error_aux(hdl, strerror(error)); zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); @@ -511,6 +517,9 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) "block size out of range or does not match")); zfs_verror(hdl, EZFS_BADPROP, fmt, ap); break; + case EREMOTEIO: + zfs_verror(hdl, EZFS_ACTIVE_POOL, fmt, ap); + break; default: zfs_error_aux(hdl, strerror(error)); diff --git a/lib/libzpool/Makefile.am b/lib/libzpool/Makefile.am index 1e95f8064..a8c72c98d 100644 --- a/lib/libzpool/Makefile.am +++ b/lib/libzpool/Makefile.am @@ -71,6 +71,7 @@ KERNEL_C = \ lzjb.c \ lz4.c \ metaslab.c \ + mmp.c \ multilist.c \ pathname.c \ range_tree.c \ |