FreeBSD/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c
/*
 * Active pool health status.
 *
 * To determine the status for a pool, we make several passes over the config,
 * picking the most egregious error we find.  In order of importance, we do the
 * following:
 *
 *	- Check for a complete and valid configuration
 *	- Look for any faulted or missing devices in a non-replicated config
 *	- Check for any data errors
 *	- Check for any faulted or missing devices in a replicated config
 *	- Look for any devices showing errors
 *	- Check for any resilvering devices
 *
 * There can obviously be multiple errors within a single pool, so this routine
 * only picks the most damaging of all the current errors to report.
 */
Active pool health status.
To determine the status for a pool, we make several passes over the config,
picking the most egregious error we find.  In order of importance, we do the
following.



There can obviously be multiple errors within a single pool, so this routine
only picks the most damaging of all the current errors to report.
Active pool health status . To determine the status for a pool we make several passes over the config picking the most egregious error we find . In order of importance we do the following . There can obviously be multiple errors within a single pool so this routine only picks the most damaging of all the current errors to report .
static zpool_status_t
check_status(nvlist_t *config, boolean_t isimport)
{
	nvlist_t *nvroot;
	vdev_stat_t *vs;
	pool_scan_stat_t *ps = NULL;
	uint_t vsc, psc;
	uint64_t nerr;
	uint64_t version;
	uint64_t stateval;
	uint64_t suspended;
	uint64_t hostid = 0;
	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
	    &version) == 0);
	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
	    &nvroot) == 0);
	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
	    (uint64_t **)&vs, &vsc) == 0);
	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
	    &stateval) == 0);
	(void) nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS,
	    (uint64_t **)&ps, &psc);
	if (ps && ps->pss_func == POOL_SCAN_RESILVER &&
	    ps->pss_state == DSS_SCANNING)
		return (ZPOOL_STATUS_RESILVERING);
	(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
	if (hostid != 0 && (unsigned long)hostid != gethostid() &&
	    stateval == POOL_STATE_ACTIVE)
		return (ZPOOL_STATUS_HOSTID_MISMATCH);
	if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
	    vs->vs_aux == VDEV_AUX_VERSION_NEWER)
		return (ZPOOL_STATUS_VERSION_NEWER);
	if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
	    vs->vs_aux == VDEV_AUX_UNSUP_FEAT) {
		nvlist_t *nvinfo;
		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO,
		    &nvinfo) == 0);
		if (nvlist_exists(nvinfo, ZPOOL_CONFIG_CAN_RDONLY))
			return (ZPOOL_STATUS_UNSUP_FEAT_WRITE);
		return (ZPOOL_STATUS_UNSUP_FEAT_READ);
	}
	if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
	    vs->vs_aux == VDEV_AUX_BAD_GUID_SUM)
		return (ZPOOL_STATUS_BAD_GUID_SUM);
	if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED,
	    &suspended) == 0) {
		if (suspended == ZIO_FAILURE_MODE_CONTINUE)
			return (ZPOOL_STATUS_IO_FAILURE_CONTINUE);
		return (ZPOOL_STATUS_IO_FAILURE_WAIT);
	}
	if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
	    vs->vs_aux == VDEV_AUX_BAD_LOG) {
		return (ZPOOL_STATUS_BAD_LOG);
	}
	if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
	    find_vdev_problem(nvroot, vdev_faulted, B_TRUE))
		return (ZPOOL_STATUS_FAULTED_DEV_NR);
	if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
	    find_vdev_problem(nvroot, vdev_missing, B_TRUE))
		return (ZPOOL_STATUS_MISSING_DEV_NR);
	if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
	    find_vdev_problem(nvroot, vdev_broken, B_TRUE))
		return (ZPOOL_STATUS_CORRUPT_LABEL_NR);
	if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
	    vs->vs_aux == VDEV_AUX_CORRUPT_DATA)
		return (ZPOOL_STATUS_CORRUPT_POOL);
	if (!isimport) {
		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
		    &nerr) == 0 && nerr != 0)
			return (ZPOOL_STATUS_CORRUPT_DATA);
	}
	if (find_vdev_problem(nvroot, vdev_faulted, B_TRUE))
		return (ZPOOL_STATUS_FAULTED_DEV_R);
	if (find_vdev_problem(nvroot, vdev_missing, B_TRUE))
		return (ZPOOL_STATUS_MISSING_DEV_R);
	if (find_vdev_problem(nvroot, vdev_broken, B_TRUE))
		return (ZPOOL_STATUS_CORRUPT_LABEL_R);
	if (!isimport && find_vdev_problem(nvroot, vdev_errors, B_TRUE))
		return (ZPOOL_STATUS_FAILING_DEV);
	if (find_vdev_problem(nvroot, vdev_offlined, B_TRUE))
		return (ZPOOL_STATUS_OFFLINE_DEV);
	if (find_vdev_problem(nvroot, vdev_removed, B_TRUE))
		return (ZPOOL_STATUS_REMOVED_DEV);
	if (find_vdev_problem(nvroot, vdev_non_native_ashift, B_FALSE))
		return (ZPOOL_STATUS_NON_NATIVE_ASHIFT);
	if (SPA_VERSION_IS_SUPPORTED(version) && version != SPA_VERSION)
		return (ZPOOL_STATUS_VERSION_OLDER);
	if (version >= SPA_VERSION_FEATURES) {
		int i;
		nvlist_t *feat;
		if (isimport) {
			feat = fnvlist_lookup_nvlist(config,
			    ZPOOL_CONFIG_LOAD_INFO);
			feat = fnvlist_lookup_nvlist(feat,
			    ZPOOL_CONFIG_ENABLED_FEAT);
		} else {
			feat = fnvlist_lookup_nvlist(config,
			    ZPOOL_CONFIG_FEATURE_STATS);
		}
		for (i = 0; i < SPA_FEATURES; i++) {
			zfeature_info_t *fi = &spa_feature_table[i];
			if (!nvlist_exists(feat, fi->fi_guid))
				return (ZPOOL_STATUS_FEAT_DISABLED);
		}
	}
	return (ZPOOL_STATUS_OK);
}
static zpool_status_t check_status ( nvlist_t * config , boolean_t isimport ) { nvlist_t * nvroot ; vdev_stat_t * vs ; pool_scan_stat_t * ps = NULL ; uint_t vsc , psc ; uint64_t nerr ; uint64_t version ; uint64_t stateval ; uint64_t suspended ; uint64_t hostid = 0 ; verify ( nvlist_lookup_uint64 ( config , ZPOOL_CONFIG_VERSION , & version ) == 0 ) ; verify ( nvlist_lookup_nvlist ( config , ZPOOL_CONFIG_VDEV_TREE , & nvroot ) == 0 ) ; verify ( nvlist_lookup_uint64_array ( nvroot , ZPOOL_CONFIG_VDEV_STATS , ( uint64_t * * ) & vs , & vsc ) == 0 ) ; verify ( nvlist_lookup_uint64 ( config , ZPOOL_CONFIG_POOL_STATE , & stateval ) == 0 ) ; ( void ) nvlist_lookup_uint64_array ( nvroot , ZPOOL_CONFIG_SCAN_STATS , ( uint64_t * * ) & ps , & psc ) ; if ( ps && ps -> pss_func == POOL_SCAN_RESILVER && ps -> pss_state == DSS_SCANNING ) return ( ZPOOL_STATUS_RESILVERING ) ; ( void ) nvlist_lookup_uint64 ( config , ZPOOL_CONFIG_HOSTID , & hostid ) ; if ( hostid != 0 && ( unsigned long ) hostid != gethostid ( ) && stateval == POOL_STATE_ACTIVE ) return ( ZPOOL_STATUS_HOSTID_MISMATCH ) ; if ( vs -> vs_state == VDEV_STATE_CANT_OPEN && vs -> vs_aux == VDEV_AUX_VERSION_NEWER ) return ( ZPOOL_STATUS_VERSION_NEWER ) ; if ( vs -> vs_state == VDEV_STATE_CANT_OPEN && vs -> vs_aux == VDEV_AUX_UNSUP_FEAT ) { nvlist_t * nvinfo ; verify ( nvlist_lookup_nvlist ( config , ZPOOL_CONFIG_LOAD_INFO , & nvinfo ) == 0 ) ; if ( nvlist_exists ( nvinfo , ZPOOL_CONFIG_CAN_RDONLY ) ) return ( ZPOOL_STATUS_UNSUP_FEAT_WRITE ) ; return ( ZPOOL_STATUS_UNSUP_FEAT_READ ) ; } if ( vs -> vs_state == VDEV_STATE_CANT_OPEN && vs -> vs_aux == VDEV_AUX_BAD_GUID_SUM ) return ( ZPOOL_STATUS_BAD_GUID_SUM ) ; if ( nvlist_lookup_uint64 ( config , ZPOOL_CONFIG_SUSPENDED , & suspended ) == 0 ) { if ( suspended == ZIO_FAILURE_MODE_CONTINUE ) return ( ZPOOL_STATUS_IO_FAILURE_CONTINUE ) ; return ( ZPOOL_STATUS_IO_FAILURE_WAIT ) ; } if ( vs -> vs_state == VDEV_STATE_CANT_OPEN && vs -> vs_aux == VDEV_AUX_BAD_LOG ) { return ( ZPOOL_STATUS_BAD_LOG ) ; } if ( vs -> vs_state == VDEV_STATE_CANT_OPEN && find_vdev_problem ( nvroot , vdev_faulted , B_TRUE ) ) return ( ZPOOL_STATUS_FAULTED_DEV_NR ) ; if ( vs -> vs_state == VDEV_STATE_CANT_OPEN && find_vdev_problem ( nvroot , vdev_missing , B_TRUE ) ) return ( ZPOOL_STATUS_MISSING_DEV_NR ) ; if ( vs -> vs_state == VDEV_STATE_CANT_OPEN && find_vdev_problem ( nvroot , vdev_broken , B_TRUE ) ) return ( ZPOOL_STATUS_CORRUPT_LABEL_NR ) ; if ( vs -> vs_state == VDEV_STATE_CANT_OPEN && vs -> vs_aux == VDEV_AUX_CORRUPT_DATA ) return ( ZPOOL_STATUS_CORRUPT_POOL ) ; if ( ! isimport ) { if ( nvlist_lookup_uint64 ( config , ZPOOL_CONFIG_ERRCOUNT , & nerr ) == 0 && nerr != 0 ) return ( ZPOOL_STATUS_CORRUPT_DATA ) ; } if ( find_vdev_problem ( nvroot , vdev_faulted , B_TRUE ) ) return ( ZPOOL_STATUS_FAULTED_DEV_R ) ; if ( find_vdev_problem ( nvroot , vdev_missing , B_TRUE ) ) return ( ZPOOL_STATUS_MISSING_DEV_R ) ; if ( find_vdev_problem ( nvroot , vdev_broken , B_TRUE ) ) return ( ZPOOL_STATUS_CORRUPT_LABEL_R ) ; if ( ! isimport && find_vdev_problem ( nvroot , vdev_errors , B_TRUE ) ) return ( ZPOOL_STATUS_FAILING_DEV ) ; if ( find_vdev_problem ( nvroot , vdev_offlined , B_TRUE ) ) return ( ZPOOL_STATUS_OFFLINE_DEV ) ; if ( find_vdev_problem ( nvroot , vdev_removed , B_TRUE ) ) return ( ZPOOL_STATUS_REMOVED_DEV ) ; if ( find_vdev_problem ( nvroot , vdev_non_native_ashift , B_FALSE ) ) return ( ZPOOL_STATUS_NON_NATIVE_ASHIFT ) ; if ( SPA_VERSION_IS_SUPPORTED ( version ) && version != SPA_VERSION ) return ( ZPOOL_STATUS_VERSION_OLDER ) ; if ( version >= SPA_VERSION_FEATURES ) { int i ; nvlist_t * feat ; if ( isimport ) { feat = fnvlist_lookup_nvlist ( config , ZPOOL_CONFIG_LOAD_INFO ) ; feat = fnvlist_lookup_nvlist ( feat , ZPOOL_CONFIG_ENABLED_FEAT ) ; } else { feat = fnvlist_lookup_nvlist ( config , ZPOOL_CONFIG_FEATURE_STATS ) ; } for ( i = 0 ; i < SPA_FEATURES ; i ++ ) { zfeature_info_t * fi = & spa_feature_table [ i ] ; if ( ! nvlist_exists ( feat , fi -> fi_guid ) ) return ( ZPOOL_STATUS_FEAT_DISABLED ) ; } } return ( ZPOOL_STATUS_OK ) ; }
Active pool health status.
Active pool health status .
/*
	 * Currently resilvering a vdev
	 */ /*
	 * Pool last accessed by another system.
	 */ /*
	 * Newer on-disk version.
	 */ /*
	 * Unsupported feature(s).
	 */ /*
	 * Check that the config is complete.
	 */ /*
	 * Check whether the pool has suspended due to failed I/O.
	 */ /*
	 * Could not read a log.
	 */ /*
	 * Bad devices in non-replicated config.
	 */ /*
	 * Corrupted pool metadata
	 */ /*
	 * Persistent data errors.
	 */ /*
	 * Missing devices in a replicated config.
	 */ /*
	 * Devices with errors
	 */ /*
	 * Offlined devices
	 */ /*
	 * Removed device
	 */ /*
	 * Suboptimal, but usable, ashift configuration.
	 */ /*
	 * Outdated, but usable, version
	 */ /*
	 * Usable pool with disabled features
	 */