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