xref: /freebsd-src/sys/contrib/openzfs/lib/libzfs/libzfs_status.c (revision eda14cbc264d6969b02f2b1994cef11148e914f1)
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