1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21236884Smm 22168404Spjd/* 23219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24236884Smm * Copyright (c) 2012 by Delphix. All rights reserved. 25252218Sdelphij * Copyright (c) 2013 Steven Hartland. All rights reserved. 26168404Spjd */ 27168404Spjd 28168404Spjd/* 29168404Spjd * This file contains the functions which analyze the status of a pool. This 30168404Spjd * include both the status of an active pool, as well as the status exported 31168404Spjd * pools. Returns one of the ZPOOL_STATUS_* defines describing the status of 32168404Spjd * the pool. This status is independent (to a certain degree) from the state of 33185029Spjd * the pool. A pool's state describes only whether or not it is capable of 34168404Spjd * providing the necessary fault tolerance for data. The status describes the 35168404Spjd * overall status of devices. A pool that is online can still have a device 36168404Spjd * that is experiencing errors. 37168404Spjd * 38168404Spjd * Only a subset of the possible faults can be detected using 'zpool status', 39168404Spjd * and not all possible errors correspond to a FMA message ID. The explanation 40168404Spjd * is left up to the caller, depending on whether it is a live pool or an 41168404Spjd * import. 42168404Spjd */ 43168404Spjd 44168404Spjd#include <libzfs.h> 45168404Spjd#include <string.h> 46168498Spjd#include <unistd.h> 47168404Spjd#include "libzfs_impl.h" 48238926Smm#include "zfeature_common.h" 49168404Spjd 50168404Spjd/* 51185029Spjd * Message ID table. This must be kept in sync with the ZPOOL_STATUS_* defines 52168404Spjd * in libzfs.h. Note that there are some status results which go past the end 53168404Spjd * of this table, and hence have no associated message ID. 54168404Spjd */ 55168498Spjdstatic char *zfs_msgid_table[] = { 56168404Spjd "ZFS-8000-14", 57168404Spjd "ZFS-8000-2Q", 58168404Spjd "ZFS-8000-3C", 59168404Spjd "ZFS-8000-4J", 60168404Spjd "ZFS-8000-5E", 61168404Spjd "ZFS-8000-6X", 62168404Spjd "ZFS-8000-72", 63168404Spjd "ZFS-8000-8A", 64168404Spjd "ZFS-8000-9P", 65168498Spjd "ZFS-8000-A5", 66185029Spjd "ZFS-8000-EY", 67185029Spjd "ZFS-8000-HC", 68185029Spjd "ZFS-8000-JQ", 69185029Spjd "ZFS-8000-K4", 70168404Spjd}; 71168404Spjd 72168498Spjd#define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0])) 73168404Spjd 74168404Spjd/* ARGSUSED */ 75168404Spjdstatic int 76254591Sgibbsvdev_missing(vdev_stat_t *vs, uint_t vsc) 77168404Spjd{ 78254591Sgibbs return (vs->vs_state == VDEV_STATE_CANT_OPEN && 79254591Sgibbs vs->vs_aux == VDEV_AUX_OPEN_FAILED); 80168404Spjd} 81168404Spjd 82168404Spjd/* ARGSUSED */ 83168404Spjdstatic int 84254591Sgibbsvdev_faulted(vdev_stat_t *vs, uint_t vsc) 85185029Spjd{ 86254591Sgibbs return (vs->vs_state == VDEV_STATE_FAULTED); 87185029Spjd} 88185029Spjd 89185029Spjd/* ARGSUSED */ 90185029Spjdstatic int 91254591Sgibbsvdev_errors(vdev_stat_t *vs, uint_t vsc) 92168404Spjd{ 93254591Sgibbs return (vs->vs_state == VDEV_STATE_DEGRADED || 94254591Sgibbs vs->vs_read_errors != 0 || vs->vs_write_errors != 0 || 95254591Sgibbs vs->vs_checksum_errors != 0); 96168404Spjd} 97168404Spjd 98168404Spjd/* ARGSUSED */ 99168404Spjdstatic int 100254591Sgibbsvdev_broken(vdev_stat_t *vs, uint_t vsc) 101168404Spjd{ 102254591Sgibbs return (vs->vs_state == VDEV_STATE_CANT_OPEN); 103168404Spjd} 104168404Spjd 105168404Spjd/* ARGSUSED */ 106168404Spjdstatic int 107254591Sgibbsvdev_offlined(vdev_stat_t *vs, uint_t vsc) 108168404Spjd{ 109254591Sgibbs return (vs->vs_state == VDEV_STATE_OFFLINE); 110168404Spjd} 111168404Spjd 112219089Spjd/* ARGSUSED */ 113219089Spjdstatic int 114254591Sgibbsvdev_removed(vdev_stat_t *vs, uint_t vsc) 115219089Spjd{ 116254591Sgibbs return (vs->vs_state == VDEV_STATE_REMOVED); 117219089Spjd} 118219089Spjd 119254591Sgibbsstatic int 120254591Sgibbsvdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc) 121254591Sgibbs{ 122254591Sgibbs return (VDEV_STAT_VALID(vs_physical_ashift, vsc) && 123254591Sgibbs vs->vs_configured_ashift < vs->vs_physical_ashift); 124254591Sgibbs} 125254591Sgibbs 126168404Spjd/* 127168404Spjd * Detect if any leaf devices that have seen errors or could not be opened. 128168404Spjd */ 129168404Spjdstatic boolean_t 130254591Sgibbsfind_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t), 131254591Sgibbs boolean_t ignore_replacing) 132168404Spjd{ 133168404Spjd nvlist_t **child; 134168404Spjd vdev_stat_t *vs; 135254591Sgibbs uint_t c, vsc, children; 136168404Spjd 137168404Spjd /* 138168404Spjd * Ignore problems within a 'replacing' vdev, since we're presumably in 139168404Spjd * the process of repairing any such errors, and don't want to call them 140168404Spjd * out again. We'll pick up the fact that a resilver is happening 141168404Spjd * later. 142168404Spjd */ 143254591Sgibbs if (ignore_replacing == B_TRUE) { 144254591Sgibbs char *type; 145168404Spjd 146254591Sgibbs verify(nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE, 147254591Sgibbs &type) == 0); 148254591Sgibbs if (strcmp(type, VDEV_TYPE_REPLACING) == 0) 149254591Sgibbs return (B_FALSE); 150254591Sgibbs } 151254591Sgibbs 152168404Spjd if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_CHILDREN, &child, 153168404Spjd &children) == 0) { 154168404Spjd for (c = 0; c < children; c++) 155254591Sgibbs if (find_vdev_problem(child[c], func, ignore_replacing)) 156168404Spjd return (B_TRUE); 157168404Spjd } else { 158219089Spjd verify(nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS, 159254591Sgibbs (uint64_t **)&vs, &vsc) == 0); 160168404Spjd 161254591Sgibbs if (func(vs, vsc) != 0) 162168404Spjd return (B_TRUE); 163168404Spjd } 164168404Spjd 165245479Ssmh /* 166245479Ssmh * Check any L2 cache devs 167245479Ssmh */ 168245479Ssmh if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_L2CACHE, &child, 169245479Ssmh &children) == 0) { 170245479Ssmh for (c = 0; c < children; c++) 171254591Sgibbs if (find_vdev_problem(child[c], func, ignore_replacing)) 172245479Ssmh return (B_TRUE); 173245479Ssmh } 174245479Ssmh 175168404Spjd return (B_FALSE); 176168404Spjd} 177168404Spjd 178168404Spjd/* 179168404Spjd * Active pool health status. 180168404Spjd * 181168404Spjd * To determine the status for a pool, we make several passes over the config, 182168404Spjd * picking the most egregious error we find. In order of importance, we do the 183168404Spjd * following: 184168404Spjd * 185168404Spjd * - Check for a complete and valid configuration 186185029Spjd * - Look for any faulted or missing devices in a non-replicated config 187168404Spjd * - Check for any data errors 188185029Spjd * - Check for any faulted or missing devices in a replicated config 189168404Spjd * - Look for any devices showing errors 190168404Spjd * - Check for any resilvering devices 191168404Spjd * 192168404Spjd * There can obviously be multiple errors within a single pool, so this routine 193168404Spjd * only picks the most damaging of all the current errors to report. 194168404Spjd */ 195168404Spjdstatic zpool_status_t 196168404Spjdcheck_status(nvlist_t *config, boolean_t isimport) 197168404Spjd{ 198168404Spjd nvlist_t *nvroot; 199168404Spjd vdev_stat_t *vs; 200219089Spjd pool_scan_stat_t *ps = NULL; 201219089Spjd uint_t vsc, psc; 202168404Spjd uint64_t nerr; 203168404Spjd uint64_t version; 204168498Spjd uint64_t stateval; 205185029Spjd uint64_t suspended; 206168498Spjd uint64_t hostid = 0; 207168404Spjd 208168404Spjd verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 209168404Spjd &version) == 0); 210168404Spjd verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 211168404Spjd &nvroot) == 0); 212219089Spjd verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 213168404Spjd (uint64_t **)&vs, &vsc) == 0); 214168498Spjd verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 215168498Spjd &stateval) == 0); 216168404Spjd 217168404Spjd /* 218219089Spjd * Currently resilvering a vdev 219219089Spjd */ 220219089Spjd (void) nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS, 221219089Spjd (uint64_t **)&ps, &psc); 222219089Spjd if (ps && ps->pss_func == POOL_SCAN_RESILVER && 223219089Spjd ps->pss_state == DSS_SCANNING) 224219089Spjd return (ZPOOL_STATUS_RESILVERING); 225219089Spjd 226219089Spjd /* 227168498Spjd * Pool last accessed by another system. 228168498Spjd */ 229219089Spjd (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid); 230168498Spjd if (hostid != 0 && (unsigned long)hostid != gethostid() && 231168498Spjd stateval == POOL_STATE_ACTIVE) 232168498Spjd return (ZPOOL_STATUS_HOSTID_MISMATCH); 233168498Spjd 234168498Spjd /* 235168404Spjd * Newer on-disk version. 236168404Spjd */ 237168404Spjd if (vs->vs_state == VDEV_STATE_CANT_OPEN && 238168404Spjd vs->vs_aux == VDEV_AUX_VERSION_NEWER) 239168404Spjd return (ZPOOL_STATUS_VERSION_NEWER); 240168404Spjd 241168404Spjd /* 242236884Smm * Unsupported feature(s). 243236884Smm */ 244236884Smm if (vs->vs_state == VDEV_STATE_CANT_OPEN && 245236884Smm vs->vs_aux == VDEV_AUX_UNSUP_FEAT) { 246236884Smm nvlist_t *nvinfo; 247236884Smm 248236884Smm verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, 249236884Smm &nvinfo) == 0); 250236884Smm if (nvlist_exists(nvinfo, ZPOOL_CONFIG_CAN_RDONLY)) 251236884Smm return (ZPOOL_STATUS_UNSUP_FEAT_WRITE); 252236884Smm return (ZPOOL_STATUS_UNSUP_FEAT_READ); 253236884Smm } 254236884Smm 255236884Smm /* 256168404Spjd * Check that the config is complete. 257168404Spjd */ 258168404Spjd if (vs->vs_state == VDEV_STATE_CANT_OPEN && 259168404Spjd vs->vs_aux == VDEV_AUX_BAD_GUID_SUM) 260168404Spjd return (ZPOOL_STATUS_BAD_GUID_SUM); 261168404Spjd 262168404Spjd /* 263185029Spjd * Check whether the pool has suspended due to failed I/O. 264168404Spjd */ 265185029Spjd if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED, 266185029Spjd &suspended) == 0) { 267185029Spjd if (suspended == ZIO_FAILURE_MODE_CONTINUE) 268185029Spjd return (ZPOOL_STATUS_IO_FAILURE_CONTINUE); 269185029Spjd return (ZPOOL_STATUS_IO_FAILURE_WAIT); 270185029Spjd } 271185029Spjd 272185029Spjd /* 273185029Spjd * Could not read a log. 274185029Spjd */ 275168404Spjd if (vs->vs_state == VDEV_STATE_CANT_OPEN && 276185029Spjd vs->vs_aux == VDEV_AUX_BAD_LOG) { 277185029Spjd return (ZPOOL_STATUS_BAD_LOG); 278185029Spjd } 279185029Spjd 280185029Spjd /* 281185029Spjd * Bad devices in non-replicated config. 282185029Spjd */ 283185029Spjd if (vs->vs_state == VDEV_STATE_CANT_OPEN && 284254591Sgibbs find_vdev_problem(nvroot, vdev_faulted, B_TRUE)) 285185029Spjd return (ZPOOL_STATUS_FAULTED_DEV_NR); 286185029Spjd 287185029Spjd if (vs->vs_state == VDEV_STATE_CANT_OPEN && 288254591Sgibbs find_vdev_problem(nvroot, vdev_missing, B_TRUE)) 289168404Spjd return (ZPOOL_STATUS_MISSING_DEV_NR); 290168404Spjd 291168404Spjd if (vs->vs_state == VDEV_STATE_CANT_OPEN && 292254591Sgibbs find_vdev_problem(nvroot, vdev_broken, B_TRUE)) 293168404Spjd return (ZPOOL_STATUS_CORRUPT_LABEL_NR); 294168404Spjd 295168404Spjd /* 296168404Spjd * Corrupted pool metadata 297168404Spjd */ 298168404Spjd if (vs->vs_state == VDEV_STATE_CANT_OPEN && 299168404Spjd vs->vs_aux == VDEV_AUX_CORRUPT_DATA) 300168404Spjd return (ZPOOL_STATUS_CORRUPT_POOL); 301168404Spjd 302168404Spjd /* 303168404Spjd * Persistent data errors. 304168404Spjd */ 305168404Spjd if (!isimport) { 306168404Spjd if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 307168404Spjd &nerr) == 0 && nerr != 0) 308168404Spjd return (ZPOOL_STATUS_CORRUPT_DATA); 309168404Spjd } 310168404Spjd 311168404Spjd /* 312168404Spjd * Missing devices in a replicated config. 313168404Spjd */ 314254591Sgibbs if (find_vdev_problem(nvroot, vdev_faulted, B_TRUE)) 315185029Spjd return (ZPOOL_STATUS_FAULTED_DEV_R); 316254591Sgibbs if (find_vdev_problem(nvroot, vdev_missing, B_TRUE)) 317168404Spjd return (ZPOOL_STATUS_MISSING_DEV_R); 318254591Sgibbs if (find_vdev_problem(nvroot, vdev_broken, B_TRUE)) 319168404Spjd return (ZPOOL_STATUS_CORRUPT_LABEL_R); 320168404Spjd 321168404Spjd /* 322168404Spjd * Devices with errors 323168404Spjd */ 324254591Sgibbs if (!isimport && find_vdev_problem(nvroot, vdev_errors, B_TRUE)) 325168404Spjd return (ZPOOL_STATUS_FAILING_DEV); 326168404Spjd 327168404Spjd /* 328168404Spjd * Offlined devices 329168404Spjd */ 330254591Sgibbs if (find_vdev_problem(nvroot, vdev_offlined, B_TRUE)) 331168404Spjd return (ZPOOL_STATUS_OFFLINE_DEV); 332168404Spjd 333168404Spjd /* 334219089Spjd * Removed device 335168404Spjd */ 336254591Sgibbs if (find_vdev_problem(nvroot, vdev_removed, B_TRUE)) 337219089Spjd return (ZPOOL_STATUS_REMOVED_DEV); 338168404Spjd 339168404Spjd /* 340254591Sgibbs * Suboptimal, but usable, ashift configuration. 341254591Sgibbs */ 342254591Sgibbs if (find_vdev_problem(nvroot, vdev_non_native_ashift, B_FALSE)) 343254591Sgibbs return (ZPOOL_STATUS_NON_NATIVE_ASHIFT); 344254591Sgibbs 345254591Sgibbs /* 346168404Spjd * Outdated, but usable, version 347168404Spjd */ 348236884Smm if (SPA_VERSION_IS_SUPPORTED(version) && version != SPA_VERSION) 349168404Spjd return (ZPOOL_STATUS_VERSION_OLDER); 350168404Spjd 351238926Smm /* 352238926Smm * Usable pool with disabled features 353238926Smm */ 354238926Smm if (version >= SPA_VERSION_FEATURES) { 355238926Smm int i; 356238926Smm nvlist_t *feat; 357238926Smm 358238926Smm if (isimport) { 359238926Smm feat = fnvlist_lookup_nvlist(config, 360238926Smm ZPOOL_CONFIG_LOAD_INFO); 361238926Smm feat = fnvlist_lookup_nvlist(feat, 362238926Smm ZPOOL_CONFIG_ENABLED_FEAT); 363238926Smm } else { 364238926Smm feat = fnvlist_lookup_nvlist(config, 365238926Smm ZPOOL_CONFIG_FEATURE_STATS); 366238926Smm } 367238926Smm 368238926Smm for (i = 0; i < SPA_FEATURES; i++) { 369238926Smm zfeature_info_t *fi = &spa_feature_table[i]; 370238926Smm if (!nvlist_exists(feat, fi->fi_guid)) 371238926Smm return (ZPOOL_STATUS_FEAT_DISABLED); 372238926Smm } 373238926Smm } 374238926Smm 375168404Spjd return (ZPOOL_STATUS_OK); 376168404Spjd} 377168404Spjd 378168404Spjdzpool_status_t 379168404Spjdzpool_get_status(zpool_handle_t *zhp, char **msgid) 380168404Spjd{ 381168404Spjd zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE); 382168404Spjd 383168404Spjd if (ret >= NMSGID) 384168404Spjd *msgid = NULL; 385168404Spjd else 386185029Spjd *msgid = zfs_msgid_table[ret]; 387168404Spjd 388168404Spjd return (ret); 389168404Spjd} 390168404Spjd 391168404Spjdzpool_status_t 392168404Spjdzpool_import_status(nvlist_t *config, char **msgid) 393168404Spjd{ 394168404Spjd zpool_status_t ret = check_status(config, B_TRUE); 395168404Spjd 396168404Spjd if (ret >= NMSGID) 397168404Spjd *msgid = NULL; 398168404Spjd else 399168498Spjd *msgid = zfs_msgid_table[ret]; 400168404Spjd 401168404Spjd return (ret); 402168404Spjd} 403219089Spjd 404219089Spjdstatic void 405219089Spjddump_ddt_stat(const ddt_stat_t *dds, int h) 406219089Spjd{ 407219089Spjd char refcnt[6]; 408219089Spjd char blocks[6], lsize[6], psize[6], dsize[6]; 409219089Spjd char ref_blocks[6], ref_lsize[6], ref_psize[6], ref_dsize[6]; 410219089Spjd 411219089Spjd if (dds == NULL || dds->dds_blocks == 0) 412219089Spjd return; 413219089Spjd 414219089Spjd if (h == -1) 415219089Spjd (void) strcpy(refcnt, "Total"); 416219089Spjd else 417219089Spjd zfs_nicenum(1ULL << h, refcnt, sizeof (refcnt)); 418219089Spjd 419219089Spjd zfs_nicenum(dds->dds_blocks, blocks, sizeof (blocks)); 420219089Spjd zfs_nicenum(dds->dds_lsize, lsize, sizeof (lsize)); 421219089Spjd zfs_nicenum(dds->dds_psize, psize, sizeof (psize)); 422219089Spjd zfs_nicenum(dds->dds_dsize, dsize, sizeof (dsize)); 423219089Spjd zfs_nicenum(dds->dds_ref_blocks, ref_blocks, sizeof (ref_blocks)); 424219089Spjd zfs_nicenum(dds->dds_ref_lsize, ref_lsize, sizeof (ref_lsize)); 425219089Spjd zfs_nicenum(dds->dds_ref_psize, ref_psize, sizeof (ref_psize)); 426219089Spjd zfs_nicenum(dds->dds_ref_dsize, ref_dsize, sizeof (ref_dsize)); 427219089Spjd 428219089Spjd (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 429219089Spjd refcnt, 430219089Spjd blocks, lsize, psize, dsize, 431219089Spjd ref_blocks, ref_lsize, ref_psize, ref_dsize); 432219089Spjd} 433219089Spjd 434219089Spjd/* 435219089Spjd * Print the DDT histogram and the column totals. 436219089Spjd */ 437219089Spjdvoid 438219089Spjdzpool_dump_ddt(const ddt_stat_t *dds_total, const ddt_histogram_t *ddh) 439219089Spjd{ 440219089Spjd int h; 441219089Spjd 442219089Spjd (void) printf("\n"); 443219089Spjd 444219089Spjd (void) printf("bucket " 445219089Spjd " allocated " 446219089Spjd " referenced \n"); 447219089Spjd (void) printf("______ " 448219089Spjd "______________________________ " 449219089Spjd "______________________________\n"); 450219089Spjd 451219089Spjd (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 452219089Spjd "refcnt", 453219089Spjd "blocks", "LSIZE", "PSIZE", "DSIZE", 454219089Spjd "blocks", "LSIZE", "PSIZE", "DSIZE"); 455219089Spjd 456219089Spjd (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 457219089Spjd "------", 458219089Spjd "------", "-----", "-----", "-----", 459219089Spjd "------", "-----", "-----", "-----"); 460219089Spjd 461219089Spjd for (h = 0; h < 64; h++) 462219089Spjd dump_ddt_stat(&ddh->ddh_stat[h], h); 463219089Spjd 464219089Spjd dump_ddt_stat(dds_total, -1); 465219089Spjd 466219089Spjd (void) printf("\n"); 467219089Spjd} 468