1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy 22eda14cbcSMatt Macy /* 23eda14cbcSMatt Macy * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24eda14cbcSMatt Macy * Copyright (c) 2012 by Delphix. All rights reserved. 25eda14cbcSMatt Macy * Copyright (c) 2013 Steven Hartland. All rights reserved. 26ee36e25aSMartin Matuska * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> 27eda14cbcSMatt Macy */ 28eda14cbcSMatt Macy 29eda14cbcSMatt Macy /* 30eda14cbcSMatt Macy * This file contains the functions which analyze the status of a pool. This 31eda14cbcSMatt Macy * include both the status of an active pool, as well as the status exported 32eda14cbcSMatt Macy * pools. Returns one of the ZPOOL_STATUS_* defines describing the status of 33eda14cbcSMatt Macy * the pool. This status is independent (to a certain degree) from the state of 34eda14cbcSMatt Macy * the pool. A pool's state describes only whether or not it is capable of 35eda14cbcSMatt Macy * providing the necessary fault tolerance for data. The status describes the 36eda14cbcSMatt Macy * overall status of devices. A pool that is online can still have a device 37eda14cbcSMatt Macy * that is experiencing errors. 38eda14cbcSMatt Macy * 39eda14cbcSMatt Macy * Only a subset of the possible faults can be detected using 'zpool status', 40eda14cbcSMatt Macy * and not all possible errors correspond to a FMA message ID. The explanation 41eda14cbcSMatt Macy * is left up to the caller, depending on whether it is a live pool or an 42eda14cbcSMatt Macy * import. 43eda14cbcSMatt Macy */ 44eda14cbcSMatt Macy 45eda14cbcSMatt Macy #include <libzfs.h> 46eda14cbcSMatt Macy #include <libzutil.h> 47eda14cbcSMatt Macy #include <stdlib.h> 48eda14cbcSMatt Macy #include <string.h> 49eda14cbcSMatt Macy #include <unistd.h> 50eda14cbcSMatt Macy #include <sys/systeminfo.h> 51eda14cbcSMatt Macy #include "libzfs_impl.h" 52eda14cbcSMatt Macy #include "zfeature_common.h" 53eda14cbcSMatt Macy 54eda14cbcSMatt Macy /* 55eda14cbcSMatt Macy * Message ID table. This must be kept in sync with the ZPOOL_STATUS_* defines 56eda14cbcSMatt Macy * in include/libzfs.h. Note that there are some status results which go past 57eda14cbcSMatt Macy * the end of this table, and hence have no associated message ID. 58eda14cbcSMatt Macy */ 59eda14cbcSMatt Macy static char *zfs_msgid_table[] = { 60eda14cbcSMatt Macy "ZFS-8000-14", /* ZPOOL_STATUS_CORRUPT_CACHE */ 61eda14cbcSMatt Macy "ZFS-8000-2Q", /* ZPOOL_STATUS_MISSING_DEV_R */ 62eda14cbcSMatt Macy "ZFS-8000-3C", /* ZPOOL_STATUS_MISSING_DEV_NR */ 63eda14cbcSMatt Macy "ZFS-8000-4J", /* ZPOOL_STATUS_CORRUPT_LABEL_R */ 64eda14cbcSMatt Macy "ZFS-8000-5E", /* ZPOOL_STATUS_CORRUPT_LABEL_NR */ 65eda14cbcSMatt Macy "ZFS-8000-6X", /* ZPOOL_STATUS_BAD_GUID_SUM */ 66eda14cbcSMatt Macy "ZFS-8000-72", /* ZPOOL_STATUS_CORRUPT_POOL */ 67eda14cbcSMatt Macy "ZFS-8000-8A", /* ZPOOL_STATUS_CORRUPT_DATA */ 68eda14cbcSMatt Macy "ZFS-8000-9P", /* ZPOOL_STATUS_FAILING_DEV */ 69eda14cbcSMatt Macy "ZFS-8000-A5", /* ZPOOL_STATUS_VERSION_NEWER */ 70eda14cbcSMatt Macy "ZFS-8000-EY", /* ZPOOL_STATUS_HOSTID_MISMATCH */ 71eda14cbcSMatt Macy "ZFS-8000-EY", /* ZPOOL_STATUS_HOSTID_ACTIVE */ 72eda14cbcSMatt Macy "ZFS-8000-EY", /* ZPOOL_STATUS_HOSTID_REQUIRED */ 73eda14cbcSMatt Macy "ZFS-8000-HC", /* ZPOOL_STATUS_IO_FAILURE_WAIT */ 74eda14cbcSMatt Macy "ZFS-8000-JQ", /* ZPOOL_STATUS_IO_FAILURE_CONTINUE */ 75eda14cbcSMatt Macy "ZFS-8000-MM", /* ZPOOL_STATUS_IO_FAILURE_MMP */ 76eda14cbcSMatt Macy "ZFS-8000-K4", /* ZPOOL_STATUS_BAD_LOG */ 77eda14cbcSMatt Macy "ZFS-8000-ER", /* ZPOOL_STATUS_ERRATA */ 78eda14cbcSMatt Macy /* 79eda14cbcSMatt Macy * The following results have no message ID. 80eda14cbcSMatt Macy * ZPOOL_STATUS_UNSUP_FEAT_READ 81eda14cbcSMatt Macy * ZPOOL_STATUS_UNSUP_FEAT_WRITE 82eda14cbcSMatt Macy * ZPOOL_STATUS_FAULTED_DEV_R 83eda14cbcSMatt Macy * ZPOOL_STATUS_FAULTED_DEV_NR 84eda14cbcSMatt Macy * ZPOOL_STATUS_VERSION_OLDER 85eda14cbcSMatt Macy * ZPOOL_STATUS_FEAT_DISABLED 86eda14cbcSMatt Macy * ZPOOL_STATUS_RESILVERING 87eda14cbcSMatt Macy * ZPOOL_STATUS_OFFLINE_DEV 88eda14cbcSMatt Macy * ZPOOL_STATUS_REMOVED_DEV 89eda14cbcSMatt Macy * ZPOOL_STATUS_REBUILDING 90eda14cbcSMatt Macy * ZPOOL_STATUS_REBUILD_SCRUB 91ee36e25aSMartin Matuska * ZPOOL_STATUS_COMPATIBILITY_ERR 9216038816SMartin Matuska * ZPOOL_STATUS_INCOMPATIBLE_FEAT 93eda14cbcSMatt Macy * ZPOOL_STATUS_OK 94eda14cbcSMatt Macy */ 95eda14cbcSMatt Macy }; 96eda14cbcSMatt Macy 97eda14cbcSMatt Macy #define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0])) 98eda14cbcSMatt Macy 99eda14cbcSMatt Macy static int 100eda14cbcSMatt Macy vdev_missing(vdev_stat_t *vs, uint_t vsc) 101eda14cbcSMatt Macy { 102*e92ffd9bSMartin Matuska (void) vsc; 103eda14cbcSMatt Macy return (vs->vs_state == VDEV_STATE_CANT_OPEN && 104eda14cbcSMatt Macy vs->vs_aux == VDEV_AUX_OPEN_FAILED); 105eda14cbcSMatt Macy } 106eda14cbcSMatt Macy 107eda14cbcSMatt Macy static int 108eda14cbcSMatt Macy vdev_faulted(vdev_stat_t *vs, uint_t vsc) 109eda14cbcSMatt Macy { 110*e92ffd9bSMartin Matuska (void) vsc; 111eda14cbcSMatt Macy return (vs->vs_state == VDEV_STATE_FAULTED); 112eda14cbcSMatt Macy } 113eda14cbcSMatt Macy 114eda14cbcSMatt Macy static int 115eda14cbcSMatt Macy vdev_errors(vdev_stat_t *vs, uint_t vsc) 116eda14cbcSMatt Macy { 117*e92ffd9bSMartin Matuska (void) vsc; 118eda14cbcSMatt Macy return (vs->vs_state == VDEV_STATE_DEGRADED || 119eda14cbcSMatt Macy vs->vs_read_errors != 0 || vs->vs_write_errors != 0 || 120eda14cbcSMatt Macy vs->vs_checksum_errors != 0); 121eda14cbcSMatt Macy } 122eda14cbcSMatt Macy 123eda14cbcSMatt Macy static int 124eda14cbcSMatt Macy vdev_broken(vdev_stat_t *vs, uint_t vsc) 125eda14cbcSMatt Macy { 126*e92ffd9bSMartin Matuska (void) vsc; 127eda14cbcSMatt Macy return (vs->vs_state == VDEV_STATE_CANT_OPEN); 128eda14cbcSMatt Macy } 129eda14cbcSMatt Macy 130eda14cbcSMatt Macy static int 131eda14cbcSMatt Macy vdev_offlined(vdev_stat_t *vs, uint_t vsc) 132eda14cbcSMatt Macy { 133*e92ffd9bSMartin Matuska (void) vsc; 134eda14cbcSMatt Macy return (vs->vs_state == VDEV_STATE_OFFLINE); 135eda14cbcSMatt Macy } 136eda14cbcSMatt Macy 137eda14cbcSMatt Macy static int 138eda14cbcSMatt Macy vdev_removed(vdev_stat_t *vs, uint_t vsc) 139eda14cbcSMatt Macy { 140*e92ffd9bSMartin Matuska (void) vsc; 141eda14cbcSMatt Macy return (vs->vs_state == VDEV_STATE_REMOVED); 142eda14cbcSMatt Macy } 143eda14cbcSMatt Macy 144eda14cbcSMatt Macy static int 145eda14cbcSMatt Macy vdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc) 146eda14cbcSMatt Macy { 147eda14cbcSMatt Macy if (getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") != NULL) 148eda14cbcSMatt Macy return (0); 149eda14cbcSMatt Macy 150eda14cbcSMatt Macy return (VDEV_STAT_VALID(vs_physical_ashift, vsc) && 151eda14cbcSMatt Macy vs->vs_configured_ashift < vs->vs_physical_ashift); 152eda14cbcSMatt Macy } 153eda14cbcSMatt Macy 154eda14cbcSMatt Macy /* 155eda14cbcSMatt Macy * Detect if any leaf devices that have seen errors or could not be opened. 156eda14cbcSMatt Macy */ 157eda14cbcSMatt Macy static boolean_t 158eda14cbcSMatt Macy find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t), 159eda14cbcSMatt Macy boolean_t ignore_replacing) 160eda14cbcSMatt Macy { 161eda14cbcSMatt Macy nvlist_t **child; 162eda14cbcSMatt Macy vdev_stat_t *vs; 163eda14cbcSMatt Macy uint_t c, vsc, children; 164eda14cbcSMatt Macy 165eda14cbcSMatt Macy /* 166eda14cbcSMatt Macy * Ignore problems within a 'replacing' vdev, since we're presumably in 167eda14cbcSMatt Macy * the process of repairing any such errors, and don't want to call them 168eda14cbcSMatt Macy * out again. We'll pick up the fact that a resilver is happening 169eda14cbcSMatt Macy * later. 170eda14cbcSMatt Macy */ 171eda14cbcSMatt Macy if (ignore_replacing == B_TRUE) { 172eda14cbcSMatt Macy char *type; 173eda14cbcSMatt Macy 174eda14cbcSMatt Macy verify(nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE, 175eda14cbcSMatt Macy &type) == 0); 176eda14cbcSMatt Macy if (strcmp(type, VDEV_TYPE_REPLACING) == 0) 177eda14cbcSMatt Macy return (B_FALSE); 178eda14cbcSMatt Macy } 179eda14cbcSMatt Macy 180eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_CHILDREN, &child, 181eda14cbcSMatt Macy &children) == 0) { 182eda14cbcSMatt Macy for (c = 0; c < children; c++) 183eda14cbcSMatt Macy if (find_vdev_problem(child[c], func, ignore_replacing)) 184eda14cbcSMatt Macy return (B_TRUE); 185eda14cbcSMatt Macy } else { 186eda14cbcSMatt Macy verify(nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS, 187eda14cbcSMatt Macy (uint64_t **)&vs, &vsc) == 0); 188eda14cbcSMatt Macy 189eda14cbcSMatt Macy if (func(vs, vsc) != 0) 190eda14cbcSMatt Macy return (B_TRUE); 191eda14cbcSMatt Macy } 192eda14cbcSMatt Macy 193eda14cbcSMatt Macy /* 194eda14cbcSMatt Macy * Check any L2 cache devs 195eda14cbcSMatt Macy */ 196eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_L2CACHE, &child, 197eda14cbcSMatt Macy &children) == 0) { 198eda14cbcSMatt Macy for (c = 0; c < children; c++) 199eda14cbcSMatt Macy if (find_vdev_problem(child[c], func, ignore_replacing)) 200eda14cbcSMatt Macy return (B_TRUE); 201eda14cbcSMatt Macy } 202eda14cbcSMatt Macy 203eda14cbcSMatt Macy return (B_FALSE); 204eda14cbcSMatt Macy } 205eda14cbcSMatt Macy 206eda14cbcSMatt Macy /* 207eda14cbcSMatt Macy * Active pool health status. 208eda14cbcSMatt Macy * 209eda14cbcSMatt Macy * To determine the status for a pool, we make several passes over the config, 210eda14cbcSMatt Macy * picking the most egregious error we find. In order of importance, we do the 211eda14cbcSMatt Macy * following: 212eda14cbcSMatt Macy * 213eda14cbcSMatt Macy * - Check for a complete and valid configuration 214eda14cbcSMatt Macy * - Look for any faulted or missing devices in a non-replicated config 215eda14cbcSMatt Macy * - Check for any data errors 216eda14cbcSMatt Macy * - Check for any faulted or missing devices in a replicated config 217eda14cbcSMatt Macy * - Look for any devices showing errors 218eda14cbcSMatt Macy * - Check for any resilvering or rebuilding devices 219eda14cbcSMatt Macy * 220eda14cbcSMatt Macy * There can obviously be multiple errors within a single pool, so this routine 221eda14cbcSMatt Macy * only picks the most damaging of all the current errors to report. 222eda14cbcSMatt Macy */ 223eda14cbcSMatt Macy static zpool_status_t 224ee36e25aSMartin Matuska check_status(nvlist_t *config, boolean_t isimport, 225ee36e25aSMartin Matuska zpool_errata_t *erratap, const char *compat) 226eda14cbcSMatt Macy { 227eda14cbcSMatt Macy nvlist_t *nvroot; 228eda14cbcSMatt Macy vdev_stat_t *vs; 229eda14cbcSMatt Macy pool_scan_stat_t *ps = NULL; 230eda14cbcSMatt Macy uint_t vsc, psc; 231eda14cbcSMatt Macy uint64_t nerr; 232eda14cbcSMatt Macy uint64_t version; 233eda14cbcSMatt Macy uint64_t stateval; 234eda14cbcSMatt Macy uint64_t suspended; 235eda14cbcSMatt Macy uint64_t hostid = 0; 236eda14cbcSMatt Macy uint64_t errata = 0; 237eda14cbcSMatt Macy unsigned long system_hostid = get_system_hostid(); 238eda14cbcSMatt Macy 239eda14cbcSMatt Macy verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 240eda14cbcSMatt Macy &version) == 0); 241eda14cbcSMatt Macy verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 242eda14cbcSMatt Macy &nvroot) == 0); 243eda14cbcSMatt Macy verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 244eda14cbcSMatt Macy (uint64_t **)&vs, &vsc) == 0); 245eda14cbcSMatt Macy verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 246eda14cbcSMatt Macy &stateval) == 0); 247eda14cbcSMatt Macy 248eda14cbcSMatt Macy /* 249eda14cbcSMatt Macy * Currently resilvering a vdev 250eda14cbcSMatt Macy */ 251eda14cbcSMatt Macy (void) nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS, 252eda14cbcSMatt Macy (uint64_t **)&ps, &psc); 253eda14cbcSMatt Macy if (ps != NULL && ps->pss_func == POOL_SCAN_RESILVER && 254eda14cbcSMatt Macy ps->pss_state == DSS_SCANNING) 255eda14cbcSMatt Macy return (ZPOOL_STATUS_RESILVERING); 256eda14cbcSMatt Macy 257eda14cbcSMatt Macy /* 258eda14cbcSMatt Macy * Currently rebuilding a vdev, check top-level vdevs. 259eda14cbcSMatt Macy */ 260eda14cbcSMatt Macy vdev_rebuild_stat_t *vrs = NULL; 261eda14cbcSMatt Macy nvlist_t **child; 262eda14cbcSMatt Macy uint_t c, i, children; 263eda14cbcSMatt Macy uint64_t rebuild_end_time = 0; 264eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 265eda14cbcSMatt Macy &child, &children) == 0) { 266eda14cbcSMatt Macy for (c = 0; c < children; c++) { 267eda14cbcSMatt Macy if ((nvlist_lookup_uint64_array(child[c], 268eda14cbcSMatt Macy ZPOOL_CONFIG_REBUILD_STATS, 269eda14cbcSMatt Macy (uint64_t **)&vrs, &i) == 0) && (vrs != NULL)) { 270eda14cbcSMatt Macy uint64_t state = vrs->vrs_state; 271eda14cbcSMatt Macy 272eda14cbcSMatt Macy if (state == VDEV_REBUILD_ACTIVE) { 273eda14cbcSMatt Macy return (ZPOOL_STATUS_REBUILDING); 274eda14cbcSMatt Macy } else if (state == VDEV_REBUILD_COMPLETE && 275eda14cbcSMatt Macy vrs->vrs_end_time > rebuild_end_time) { 276eda14cbcSMatt Macy rebuild_end_time = vrs->vrs_end_time; 277eda14cbcSMatt Macy } 278eda14cbcSMatt Macy } 279eda14cbcSMatt Macy } 280eda14cbcSMatt Macy 281eda14cbcSMatt Macy /* 282eda14cbcSMatt Macy * If we can determine when the last scrub was run, and it 283eda14cbcSMatt Macy * was before the last rebuild completed, then recommend 284eda14cbcSMatt Macy * that the pool be scrubbed to verify all checksums. When 285eda14cbcSMatt Macy * ps is NULL we can infer the pool has never been scrubbed. 286eda14cbcSMatt Macy */ 287eda14cbcSMatt Macy if (rebuild_end_time > 0) { 288eda14cbcSMatt Macy if (ps != NULL) { 289eda14cbcSMatt Macy if ((ps->pss_state == DSS_FINISHED && 290eda14cbcSMatt Macy ps->pss_func == POOL_SCAN_SCRUB && 291eda14cbcSMatt Macy rebuild_end_time > ps->pss_end_time) || 292eda14cbcSMatt Macy ps->pss_state == DSS_NONE) 293eda14cbcSMatt Macy return (ZPOOL_STATUS_REBUILD_SCRUB); 294eda14cbcSMatt Macy } else { 295eda14cbcSMatt Macy return (ZPOOL_STATUS_REBUILD_SCRUB); 296eda14cbcSMatt Macy } 297eda14cbcSMatt Macy } 298eda14cbcSMatt Macy } 299eda14cbcSMatt Macy 300eda14cbcSMatt Macy /* 301eda14cbcSMatt Macy * The multihost property is set and the pool may be active. 302eda14cbcSMatt Macy */ 303eda14cbcSMatt Macy if (vs->vs_state == VDEV_STATE_CANT_OPEN && 304eda14cbcSMatt Macy vs->vs_aux == VDEV_AUX_ACTIVE) { 305eda14cbcSMatt Macy mmp_state_t mmp_state; 306eda14cbcSMatt Macy nvlist_t *nvinfo; 307eda14cbcSMatt Macy 308eda14cbcSMatt Macy nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); 309eda14cbcSMatt Macy mmp_state = fnvlist_lookup_uint64(nvinfo, 310eda14cbcSMatt Macy ZPOOL_CONFIG_MMP_STATE); 311eda14cbcSMatt Macy 312eda14cbcSMatt Macy if (mmp_state == MMP_STATE_ACTIVE) 313eda14cbcSMatt Macy return (ZPOOL_STATUS_HOSTID_ACTIVE); 314eda14cbcSMatt Macy else if (mmp_state == MMP_STATE_NO_HOSTID) 315eda14cbcSMatt Macy return (ZPOOL_STATUS_HOSTID_REQUIRED); 316eda14cbcSMatt Macy else 317eda14cbcSMatt Macy return (ZPOOL_STATUS_HOSTID_MISMATCH); 318eda14cbcSMatt Macy } 319eda14cbcSMatt Macy 320eda14cbcSMatt Macy /* 321eda14cbcSMatt Macy * Pool last accessed by another system. 322eda14cbcSMatt Macy */ 323eda14cbcSMatt Macy (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid); 324eda14cbcSMatt Macy if (hostid != 0 && (unsigned long)hostid != system_hostid && 325eda14cbcSMatt Macy stateval == POOL_STATE_ACTIVE) 326eda14cbcSMatt Macy return (ZPOOL_STATUS_HOSTID_MISMATCH); 327eda14cbcSMatt Macy 328eda14cbcSMatt Macy /* 329eda14cbcSMatt Macy * Newer on-disk version. 330eda14cbcSMatt Macy */ 331eda14cbcSMatt Macy if (vs->vs_state == VDEV_STATE_CANT_OPEN && 332eda14cbcSMatt Macy vs->vs_aux == VDEV_AUX_VERSION_NEWER) 333eda14cbcSMatt Macy return (ZPOOL_STATUS_VERSION_NEWER); 334eda14cbcSMatt Macy 335eda14cbcSMatt Macy /* 336eda14cbcSMatt Macy * Unsupported feature(s). 337eda14cbcSMatt Macy */ 338eda14cbcSMatt Macy if (vs->vs_state == VDEV_STATE_CANT_OPEN && 339eda14cbcSMatt Macy vs->vs_aux == VDEV_AUX_UNSUP_FEAT) { 340eda14cbcSMatt Macy nvlist_t *nvinfo; 341eda14cbcSMatt Macy 342eda14cbcSMatt Macy verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, 343eda14cbcSMatt Macy &nvinfo) == 0); 344eda14cbcSMatt Macy if (nvlist_exists(nvinfo, ZPOOL_CONFIG_CAN_RDONLY)) 345eda14cbcSMatt Macy return (ZPOOL_STATUS_UNSUP_FEAT_WRITE); 346eda14cbcSMatt Macy return (ZPOOL_STATUS_UNSUP_FEAT_READ); 347eda14cbcSMatt Macy } 348eda14cbcSMatt Macy 349eda14cbcSMatt Macy /* 350eda14cbcSMatt Macy * Check that the config is complete. 351eda14cbcSMatt Macy */ 352eda14cbcSMatt Macy if (vs->vs_state == VDEV_STATE_CANT_OPEN && 353eda14cbcSMatt Macy vs->vs_aux == VDEV_AUX_BAD_GUID_SUM) 354eda14cbcSMatt Macy return (ZPOOL_STATUS_BAD_GUID_SUM); 355eda14cbcSMatt Macy 356eda14cbcSMatt Macy /* 357eda14cbcSMatt Macy * Check whether the pool has suspended. 358eda14cbcSMatt Macy */ 359eda14cbcSMatt Macy if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED, 360eda14cbcSMatt Macy &suspended) == 0) { 361eda14cbcSMatt Macy uint64_t reason; 362eda14cbcSMatt Macy 363eda14cbcSMatt Macy if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED_REASON, 364eda14cbcSMatt Macy &reason) == 0 && reason == ZIO_SUSPEND_MMP) 365eda14cbcSMatt Macy return (ZPOOL_STATUS_IO_FAILURE_MMP); 366eda14cbcSMatt Macy 367eda14cbcSMatt Macy if (suspended == ZIO_FAILURE_MODE_CONTINUE) 368eda14cbcSMatt Macy return (ZPOOL_STATUS_IO_FAILURE_CONTINUE); 369eda14cbcSMatt Macy return (ZPOOL_STATUS_IO_FAILURE_WAIT); 370eda14cbcSMatt Macy } 371eda14cbcSMatt Macy 372eda14cbcSMatt Macy /* 373eda14cbcSMatt Macy * Could not read a log. 374eda14cbcSMatt Macy */ 375eda14cbcSMatt Macy if (vs->vs_state == VDEV_STATE_CANT_OPEN && 376eda14cbcSMatt Macy vs->vs_aux == VDEV_AUX_BAD_LOG) { 377eda14cbcSMatt Macy return (ZPOOL_STATUS_BAD_LOG); 378eda14cbcSMatt Macy } 379eda14cbcSMatt Macy 380eda14cbcSMatt Macy /* 381eda14cbcSMatt Macy * Bad devices in non-replicated config. 382eda14cbcSMatt Macy */ 383eda14cbcSMatt Macy if (vs->vs_state == VDEV_STATE_CANT_OPEN && 384eda14cbcSMatt Macy find_vdev_problem(nvroot, vdev_faulted, B_TRUE)) 385eda14cbcSMatt Macy return (ZPOOL_STATUS_FAULTED_DEV_NR); 386eda14cbcSMatt Macy 387eda14cbcSMatt Macy if (vs->vs_state == VDEV_STATE_CANT_OPEN && 388eda14cbcSMatt Macy find_vdev_problem(nvroot, vdev_missing, B_TRUE)) 389eda14cbcSMatt Macy return (ZPOOL_STATUS_MISSING_DEV_NR); 390eda14cbcSMatt Macy 391eda14cbcSMatt Macy if (vs->vs_state == VDEV_STATE_CANT_OPEN && 392eda14cbcSMatt Macy find_vdev_problem(nvroot, vdev_broken, B_TRUE)) 393eda14cbcSMatt Macy return (ZPOOL_STATUS_CORRUPT_LABEL_NR); 394eda14cbcSMatt Macy 395eda14cbcSMatt Macy /* 396eda14cbcSMatt Macy * Corrupted pool metadata 397eda14cbcSMatt Macy */ 398eda14cbcSMatt Macy if (vs->vs_state == VDEV_STATE_CANT_OPEN && 399eda14cbcSMatt Macy vs->vs_aux == VDEV_AUX_CORRUPT_DATA) 400eda14cbcSMatt Macy return (ZPOOL_STATUS_CORRUPT_POOL); 401eda14cbcSMatt Macy 402eda14cbcSMatt Macy /* 403eda14cbcSMatt Macy * Persistent data errors. 404eda14cbcSMatt Macy */ 405eda14cbcSMatt Macy if (!isimport) { 406eda14cbcSMatt Macy if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 407eda14cbcSMatt Macy &nerr) == 0 && nerr != 0) 408eda14cbcSMatt Macy return (ZPOOL_STATUS_CORRUPT_DATA); 409eda14cbcSMatt Macy } 410eda14cbcSMatt Macy 411eda14cbcSMatt Macy /* 412eda14cbcSMatt Macy * Missing devices in a replicated config. 413eda14cbcSMatt Macy */ 414eda14cbcSMatt Macy if (find_vdev_problem(nvroot, vdev_faulted, B_TRUE)) 415eda14cbcSMatt Macy return (ZPOOL_STATUS_FAULTED_DEV_R); 416eda14cbcSMatt Macy if (find_vdev_problem(nvroot, vdev_missing, B_TRUE)) 417eda14cbcSMatt Macy return (ZPOOL_STATUS_MISSING_DEV_R); 418eda14cbcSMatt Macy if (find_vdev_problem(nvroot, vdev_broken, B_TRUE)) 419eda14cbcSMatt Macy return (ZPOOL_STATUS_CORRUPT_LABEL_R); 420eda14cbcSMatt Macy 421eda14cbcSMatt Macy /* 422eda14cbcSMatt Macy * Devices with errors 423eda14cbcSMatt Macy */ 424eda14cbcSMatt Macy if (!isimport && find_vdev_problem(nvroot, vdev_errors, B_TRUE)) 425eda14cbcSMatt Macy return (ZPOOL_STATUS_FAILING_DEV); 426eda14cbcSMatt Macy 427eda14cbcSMatt Macy /* 428eda14cbcSMatt Macy * Offlined devices 429eda14cbcSMatt Macy */ 430eda14cbcSMatt Macy if (find_vdev_problem(nvroot, vdev_offlined, B_TRUE)) 431eda14cbcSMatt Macy return (ZPOOL_STATUS_OFFLINE_DEV); 432eda14cbcSMatt Macy 433eda14cbcSMatt Macy /* 434eda14cbcSMatt Macy * Removed device 435eda14cbcSMatt Macy */ 436eda14cbcSMatt Macy if (find_vdev_problem(nvroot, vdev_removed, B_TRUE)) 437eda14cbcSMatt Macy return (ZPOOL_STATUS_REMOVED_DEV); 438eda14cbcSMatt Macy 439eda14cbcSMatt Macy /* 440eda14cbcSMatt Macy * Suboptimal, but usable, ashift configuration. 441eda14cbcSMatt Macy */ 442eda14cbcSMatt Macy if (find_vdev_problem(nvroot, vdev_non_native_ashift, B_FALSE)) 443eda14cbcSMatt Macy return (ZPOOL_STATUS_NON_NATIVE_ASHIFT); 444eda14cbcSMatt Macy 445eda14cbcSMatt Macy /* 446eda14cbcSMatt Macy * Informational errata available. 447eda14cbcSMatt Macy */ 448eda14cbcSMatt Macy (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRATA, &errata); 449eda14cbcSMatt Macy if (errata) { 450eda14cbcSMatt Macy *erratap = errata; 451eda14cbcSMatt Macy return (ZPOOL_STATUS_ERRATA); 452eda14cbcSMatt Macy } 453eda14cbcSMatt Macy 454eda14cbcSMatt Macy /* 455eda14cbcSMatt Macy * Outdated, but usable, version 456eda14cbcSMatt Macy */ 45716038816SMartin Matuska if (SPA_VERSION_IS_SUPPORTED(version) && version != SPA_VERSION) { 45816038816SMartin Matuska /* "legacy" compatibility disables old version reporting */ 45916038816SMartin Matuska if (compat != NULL && strcmp(compat, ZPOOL_COMPAT_LEGACY) == 0) 46016038816SMartin Matuska return (ZPOOL_STATUS_OK); 46116038816SMartin Matuska else 462eda14cbcSMatt Macy return (ZPOOL_STATUS_VERSION_OLDER); 46316038816SMartin Matuska } 464eda14cbcSMatt Macy 465eda14cbcSMatt Macy /* 46616038816SMartin Matuska * Usable pool with disabled or superfluous features 46716038816SMartin Matuska * (superfluous = beyond what's requested by 'compatibility') 468eda14cbcSMatt Macy */ 469eda14cbcSMatt Macy if (version >= SPA_VERSION_FEATURES) { 470eda14cbcSMatt Macy int i; 471eda14cbcSMatt Macy nvlist_t *feat; 472eda14cbcSMatt Macy 473eda14cbcSMatt Macy if (isimport) { 474eda14cbcSMatt Macy feat = fnvlist_lookup_nvlist(config, 475eda14cbcSMatt Macy ZPOOL_CONFIG_LOAD_INFO); 476eda14cbcSMatt Macy if (nvlist_exists(feat, ZPOOL_CONFIG_ENABLED_FEAT)) 477eda14cbcSMatt Macy feat = fnvlist_lookup_nvlist(feat, 478eda14cbcSMatt Macy ZPOOL_CONFIG_ENABLED_FEAT); 479eda14cbcSMatt Macy } else { 480eda14cbcSMatt Macy feat = fnvlist_lookup_nvlist(config, 481eda14cbcSMatt Macy ZPOOL_CONFIG_FEATURE_STATS); 482eda14cbcSMatt Macy } 483eda14cbcSMatt Macy 484ee36e25aSMartin Matuska /* check against all features, or limited set? */ 48516038816SMartin Matuska boolean_t c_features[SPA_FEATURES]; 486ee36e25aSMartin Matuska 48716038816SMartin Matuska switch (zpool_load_compat(compat, c_features, NULL, 0)) { 48816038816SMartin Matuska case ZPOOL_COMPATIBILITY_OK: 48916038816SMartin Matuska case ZPOOL_COMPATIBILITY_WARNTOKEN: 49016038816SMartin Matuska break; 49116038816SMartin Matuska default: 492ee36e25aSMartin Matuska return (ZPOOL_STATUS_COMPATIBILITY_ERR); 49316038816SMartin Matuska } 494eda14cbcSMatt Macy for (i = 0; i < SPA_FEATURES; i++) { 495eda14cbcSMatt Macy zfeature_info_t *fi = &spa_feature_table[i]; 496c170aa9fSMartin Matuska if (!fi->fi_zfs_mod_supported) 497c170aa9fSMartin Matuska continue; 49816038816SMartin Matuska if (c_features[i] && !nvlist_exists(feat, fi->fi_guid)) 499eda14cbcSMatt Macy return (ZPOOL_STATUS_FEAT_DISABLED); 50016038816SMartin Matuska if (!c_features[i] && nvlist_exists(feat, fi->fi_guid)) 50116038816SMartin Matuska return (ZPOOL_STATUS_INCOMPATIBLE_FEAT); 502eda14cbcSMatt Macy } 503eda14cbcSMatt Macy } 504eda14cbcSMatt Macy 505eda14cbcSMatt Macy return (ZPOOL_STATUS_OK); 506eda14cbcSMatt Macy } 507eda14cbcSMatt Macy 508eda14cbcSMatt Macy zpool_status_t 509eda14cbcSMatt Macy zpool_get_status(zpool_handle_t *zhp, char **msgid, zpool_errata_t *errata) 510eda14cbcSMatt Macy { 511ee36e25aSMartin Matuska /* 512ee36e25aSMartin Matuska * pass in the desired feature set, as 513ee36e25aSMartin Matuska * it affects check for disabled features 514ee36e25aSMartin Matuska */ 515ee36e25aSMartin Matuska char compatibility[ZFS_MAXPROPLEN]; 516ee36e25aSMartin Matuska if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compatibility, 517ee36e25aSMartin Matuska ZFS_MAXPROPLEN, NULL, B_FALSE) != 0) 518ee36e25aSMartin Matuska compatibility[0] = '\0'; 519ee36e25aSMartin Matuska 520ee36e25aSMartin Matuska zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE, errata, 521ee36e25aSMartin Matuska compatibility); 522ee36e25aSMartin Matuska 523eda14cbcSMatt Macy if (msgid != NULL) { 524eda14cbcSMatt Macy if (ret >= NMSGID) 525eda14cbcSMatt Macy *msgid = NULL; 526eda14cbcSMatt Macy else 527eda14cbcSMatt Macy *msgid = zfs_msgid_table[ret]; 528eda14cbcSMatt Macy } 529eda14cbcSMatt Macy return (ret); 530eda14cbcSMatt Macy } 531eda14cbcSMatt Macy 532eda14cbcSMatt Macy zpool_status_t 533eda14cbcSMatt Macy zpool_import_status(nvlist_t *config, char **msgid, zpool_errata_t *errata) 534eda14cbcSMatt Macy { 535ee36e25aSMartin Matuska zpool_status_t ret = check_status(config, B_TRUE, errata, NULL); 536eda14cbcSMatt Macy 537eda14cbcSMatt Macy if (ret >= NMSGID) 538eda14cbcSMatt Macy *msgid = NULL; 539eda14cbcSMatt Macy else 540eda14cbcSMatt Macy *msgid = zfs_msgid_table[ret]; 541eda14cbcSMatt Macy 542eda14cbcSMatt Macy return (ret); 543eda14cbcSMatt Macy } 544