1fa9e4066Sahrens /*
2fa9e4066Sahrens * CDDL HEADER START
3fa9e4066Sahrens *
4fa9e4066Sahrens * The contents of this file are subject to the terms of the
5ea8dc4b6Seschrock * Common Development and Distribution License (the "License").
6ea8dc4b6Seschrock * You may not use this file except in compliance with the License.
7fa9e4066Sahrens *
8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens * See the License for the specific language governing permissions
11fa9e4066Sahrens * and limitations under the License.
12fa9e4066Sahrens *
13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens *
19fa9e4066Sahrens * CDDL HEADER END
20fa9e4066Sahrens */
21ad135b5dSChristopher Siden
22fa9e4066Sahrens /*
233f9d6ad7SLin Ling * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24ad135b5dSChristopher Siden * Copyright (c) 2012 by Delphix. All rights reserved.
257f2416efSSteven Hartland * Copyright (c) 2013 Steven Hartland. All rights reserved.
26fa9e4066Sahrens */
27fa9e4066Sahrens
28fa9e4066Sahrens /*
29fa9e4066Sahrens * This file contains the functions which analyze the status of a pool. This
30fa9e4066Sahrens * include both the status of an active pool, as well as the status exported
31fa9e4066Sahrens * pools. Returns one of the ZPOOL_STATUS_* defines describing the status of
32fa9e4066Sahrens * the pool. This status is independent (to a certain degree) from the state of
333d7072f8Seschrock * the pool. A pool's state describes only whether or not it is capable of
34fa9e4066Sahrens * providing the necessary fault tolerance for data. The status describes the
35fa9e4066Sahrens * overall status of devices. A pool that is online can still have a device
36fa9e4066Sahrens * that is experiencing errors.
37fa9e4066Sahrens *
38fa9e4066Sahrens * Only a subset of the possible faults can be detected using 'zpool status',
39fa9e4066Sahrens * and not all possible errors correspond to a FMA message ID. The explanation
40fa9e4066Sahrens * is left up to the caller, depending on whether it is a live pool or an
41fa9e4066Sahrens * import.
42fa9e4066Sahrens */
43fa9e4066Sahrens
44fa9e4066Sahrens #include <libzfs.h>
45*d8ab6e12SDon Brady #include <libzutil.h>
46fa9e4066Sahrens #include <string.h>
4795173954Sek #include <unistd.h>
48fa9e4066Sahrens #include "libzfs_impl.h"
4957221772SChristopher Siden #include "zfeature_common.h"
50fa9e4066Sahrens
51fa9e4066Sahrens /*
523d7072f8Seschrock * Message ID table. This must be kept in sync with the ZPOOL_STATUS_* defines
53fa9e4066Sahrens * in libzfs.h. Note that there are some status results which go past the end
54fa9e4066Sahrens * of this table, and hence have no associated message ID.
55fa9e4066Sahrens */
5695173954Sek static char *zfs_msgid_table[] = {
57e0f1c0afSOlaf Faaland "ZFS-8000-14", /* ZPOOL_STATUS_CORRUPT_CACHE */
58e0f1c0afSOlaf Faaland "ZFS-8000-2Q", /* ZPOOL_STATUS_MISSING_DEV_R */
59e0f1c0afSOlaf Faaland "ZFS-8000-3C", /* ZPOOL_STATUS_MISSING_DEV_NR */
60e0f1c0afSOlaf Faaland "ZFS-8000-4J", /* ZPOOL_STATUS_CORRUPT_LABEL_R */
61e0f1c0afSOlaf Faaland "ZFS-8000-5E", /* ZPOOL_STATUS_CORRUPT_LABEL_NR */
62e0f1c0afSOlaf Faaland "ZFS-8000-6X", /* ZPOOL_STATUS_BAD_GUID_SUM */
63e0f1c0afSOlaf Faaland "ZFS-8000-72", /* ZPOOL_STATUS_CORRUPT_POOL */
64e0f1c0afSOlaf Faaland "ZFS-8000-8A", /* ZPOOL_STATUS_CORRUPT_DATA */
65e0f1c0afSOlaf Faaland "ZFS-8000-9P", /* ZPOOL_STATUS_FAILING_DEV */
66e0f1c0afSOlaf Faaland "ZFS-8000-A5", /* ZPOOL_STATUS_VERSION_NEWER */
67e0f1c0afSOlaf Faaland "ZFS-8000-EY", /* ZPOOL_STATUS_HOSTID_MISMATCH */
68e0f1c0afSOlaf Faaland "ZFS-8000-EY", /* ZPOOL_STATUS_HOSTID_ACTIVE */
69e0f1c0afSOlaf Faaland "ZFS-8000-EY", /* ZPOOL_STATUS_HOSTID_REQUIRED */
70e0f1c0afSOlaf Faaland "ZFS-8000-HC", /* ZPOOL_STATUS_IO_FAILURE_WAIT */
71e0f1c0afSOlaf Faaland "ZFS-8000-JQ", /* ZPOOL_STATUS_IO_FAILURE_CONTINUE */
72e0f1c0afSOlaf Faaland "ZFS-8000-MM", /* ZPOOL_STATUS_IO_FAILURE_MMP */
73e0f1c0afSOlaf Faaland "ZFS-8000-K4", /* ZPOOL_STATUS_BAD_LOG */
74e0f1c0afSOlaf Faaland /*
75e0f1c0afSOlaf Faaland * The following results have no message ID.
76e0f1c0afSOlaf Faaland * ZPOOL_STATUS_UNSUP_FEAT_READ
77e0f1c0afSOlaf Faaland * ZPOOL_STATUS_UNSUP_FEAT_WRITE
78e0f1c0afSOlaf Faaland * ZPOOL_STATUS_FAULTED_DEV_R
79e0f1c0afSOlaf Faaland * ZPOOL_STATUS_FAULTED_DEV_NR
80e0f1c0afSOlaf Faaland * ZPOOL_STATUS_VERSION_OLDER
81e0f1c0afSOlaf Faaland * ZPOOL_STATUS_FEAT_DISABLED
82e0f1c0afSOlaf Faaland * ZPOOL_STATUS_RESILVERING
83e0f1c0afSOlaf Faaland * ZPOOL_STATUS_OFFLINE_DEV
84e0f1c0afSOlaf Faaland * ZPOOL_STATUS_REMOVED_DEV
85e0f1c0afSOlaf Faaland * ZPOOL_STATUS_OK
86e0f1c0afSOlaf Faaland */
87fa9e4066Sahrens };
88fa9e4066Sahrens
8995173954Sek #define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0]))
90fa9e4066Sahrens
91fa9e4066Sahrens /* ARGSUSED */
92fa9e4066Sahrens static int
vdev_missing(uint64_t state,uint64_t aux,uint64_t errs)93fa9e4066Sahrens vdev_missing(uint64_t state, uint64_t aux, uint64_t errs)
94fa9e4066Sahrens {
95fa9e4066Sahrens return (state == VDEV_STATE_CANT_OPEN &&
96fa9e4066Sahrens aux == VDEV_AUX_OPEN_FAILED);
97fa9e4066Sahrens }
98fa9e4066Sahrens
993d7072f8Seschrock /* ARGSUSED */
1003d7072f8Seschrock static int
vdev_faulted(uint64_t state,uint64_t aux,uint64_t errs)1013d7072f8Seschrock vdev_faulted(uint64_t state, uint64_t aux, uint64_t errs)
1023d7072f8Seschrock {
1033d7072f8Seschrock return (state == VDEV_STATE_FAULTED);
1043d7072f8Seschrock }
1053d7072f8Seschrock
106fa9e4066Sahrens /* ARGSUSED */
107fa9e4066Sahrens static int
vdev_errors(uint64_t state,uint64_t aux,uint64_t errs)108fa9e4066Sahrens vdev_errors(uint64_t state, uint64_t aux, uint64_t errs)
109fa9e4066Sahrens {
1103d7072f8Seschrock return (state == VDEV_STATE_DEGRADED || errs != 0);
111fa9e4066Sahrens }
112fa9e4066Sahrens
113fa9e4066Sahrens /* ARGSUSED */
114fa9e4066Sahrens static int
vdev_broken(uint64_t state,uint64_t aux,uint64_t errs)115fa9e4066Sahrens vdev_broken(uint64_t state, uint64_t aux, uint64_t errs)
116fa9e4066Sahrens {
117fa9e4066Sahrens return (state == VDEV_STATE_CANT_OPEN);
118fa9e4066Sahrens }
119fa9e4066Sahrens
120fa9e4066Sahrens /* ARGSUSED */
121fa9e4066Sahrens static int
vdev_offlined(uint64_t state,uint64_t aux,uint64_t errs)122fa9e4066Sahrens vdev_offlined(uint64_t state, uint64_t aux, uint64_t errs)
123fa9e4066Sahrens {
124fa9e4066Sahrens return (state == VDEV_STATE_OFFLINE);
125fa9e4066Sahrens }
126fa9e4066Sahrens
127c25309d4SGeorge Wilson /* ARGSUSED */
128c25309d4SGeorge Wilson static int
vdev_removed(uint64_t state,uint64_t aux,uint64_t errs)129c25309d4SGeorge Wilson vdev_removed(uint64_t state, uint64_t aux, uint64_t errs)
130c25309d4SGeorge Wilson {
131c25309d4SGeorge Wilson return (state == VDEV_STATE_REMOVED);
132c25309d4SGeorge Wilson }
133c25309d4SGeorge Wilson
134fa9e4066Sahrens /*
135fa9e4066Sahrens * Detect if any leaf devices that have seen errors or could not be opened.
136fa9e4066Sahrens */
13799653d4eSeschrock static boolean_t
find_vdev_problem(nvlist_t * vdev,int (* func)(uint64_t,uint64_t,uint64_t))138fa9e4066Sahrens find_vdev_problem(nvlist_t *vdev, int (*func)(uint64_t, uint64_t, uint64_t))
139fa9e4066Sahrens {
140fa9e4066Sahrens nvlist_t **child;
141fa9e4066Sahrens vdev_stat_t *vs;
142fa9e4066Sahrens uint_t c, children;
143fa9e4066Sahrens char *type;
144fa9e4066Sahrens
145fa9e4066Sahrens /*
146fa9e4066Sahrens * Ignore problems within a 'replacing' vdev, since we're presumably in
147fa9e4066Sahrens * the process of repairing any such errors, and don't want to call them
148fa9e4066Sahrens * out again. We'll pick up the fact that a resilver is happening
149fa9e4066Sahrens * later.
150fa9e4066Sahrens */
151fa9e4066Sahrens verify(nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE, &type) == 0);
152fa9e4066Sahrens if (strcmp(type, VDEV_TYPE_REPLACING) == 0)
15399653d4eSeschrock return (B_FALSE);
154fa9e4066Sahrens
155fa9e4066Sahrens if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_CHILDREN, &child,
156fa9e4066Sahrens &children) == 0) {
157fa9e4066Sahrens for (c = 0; c < children; c++)
158fa9e4066Sahrens if (find_vdev_problem(child[c], func))
15999653d4eSeschrock return (B_TRUE);
160fa9e4066Sahrens } else {
1613f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS,
162fa9e4066Sahrens (uint64_t **)&vs, &c) == 0);
163fa9e4066Sahrens
164fa9e4066Sahrens if (func(vs->vs_state, vs->vs_aux,
165fa9e4066Sahrens vs->vs_read_errors +
166fa9e4066Sahrens vs->vs_write_errors +
167fa9e4066Sahrens vs->vs_checksum_errors))
16899653d4eSeschrock return (B_TRUE);
169fa9e4066Sahrens }
170fa9e4066Sahrens
1717f2416efSSteven Hartland /*
1727f2416efSSteven Hartland * Check any L2 cache devs
1737f2416efSSteven Hartland */
1747f2416efSSteven Hartland if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_L2CACHE, &child,
1757f2416efSSteven Hartland &children) == 0) {
1767f2416efSSteven Hartland for (c = 0; c < children; c++)
1777f2416efSSteven Hartland if (find_vdev_problem(child[c], func))
1787f2416efSSteven Hartland return (B_TRUE);
1797f2416efSSteven Hartland }
1807f2416efSSteven Hartland
18199653d4eSeschrock return (B_FALSE);
182fa9e4066Sahrens }
183fa9e4066Sahrens
184fa9e4066Sahrens /*
185fa9e4066Sahrens * Active pool health status.
186fa9e4066Sahrens *
187fa9e4066Sahrens * To determine the status for a pool, we make several passes over the config,
188fa9e4066Sahrens * picking the most egregious error we find. In order of importance, we do the
189fa9e4066Sahrens * following:
190fa9e4066Sahrens *
191fa9e4066Sahrens * - Check for a complete and valid configuration
1923d7072f8Seschrock * - Look for any faulted or missing devices in a non-replicated config
193fa9e4066Sahrens * - Check for any data errors
1943d7072f8Seschrock * - Check for any faulted or missing devices in a replicated config
195ea8dc4b6Seschrock * - Look for any devices showing errors
196fa9e4066Sahrens * - Check for any resilvering devices
197fa9e4066Sahrens *
198fa9e4066Sahrens * There can obviously be multiple errors within a single pool, so this routine
199fa9e4066Sahrens * only picks the most damaging of all the current errors to report.
200fa9e4066Sahrens */
201fa9e4066Sahrens static zpool_status_t
check_status(nvlist_t * config,boolean_t isimport,zpool_errata_t * erratap)202eb633035STom Caputi check_status(nvlist_t *config, boolean_t isimport, zpool_errata_t *erratap)
203fa9e4066Sahrens {
204fa9e4066Sahrens nvlist_t *nvroot;
205fa9e4066Sahrens vdev_stat_t *vs;
2063f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL;
2073f9d6ad7SLin Ling uint_t vsc, psc;
208ea8dc4b6Seschrock uint64_t nerr;
209eaca9bbdSeschrock uint64_t version;
21095173954Sek uint64_t stateval;
211e14bb325SJeff Bonwick uint64_t suspended;
21295173954Sek uint64_t hostid = 0;
213eb633035STom Caputi uint64_t errata = 0;
214e0f1c0afSOlaf Faaland unsigned long system_hostid = get_system_hostid();
215fa9e4066Sahrens
216eaca9bbdSeschrock verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
217eaca9bbdSeschrock &version) == 0);
218fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
219fa9e4066Sahrens &nvroot) == 0);
2203f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
221fa9e4066Sahrens (uint64_t **)&vs, &vsc) == 0);
22295173954Sek verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
22395173954Sek &stateval) == 0);
2243f9d6ad7SLin Ling
2253f9d6ad7SLin Ling /*
2263f9d6ad7SLin Ling * Currently resilvering a vdev
2273f9d6ad7SLin Ling */
2283f9d6ad7SLin Ling (void) nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS,
2293f9d6ad7SLin Ling (uint64_t **)&ps, &psc);
230a3874b8bSToomas Soome if (ps != NULL && ps->pss_func == POOL_SCAN_RESILVER &&
2313f9d6ad7SLin Ling ps->pss_state == DSS_SCANNING)
2323f9d6ad7SLin Ling return (ZPOOL_STATUS_RESILVERING);
23395173954Sek
234e0f1c0afSOlaf Faaland /*
235e0f1c0afSOlaf Faaland * The multihost property is set and the pool may be active.
236e0f1c0afSOlaf Faaland */
237e0f1c0afSOlaf Faaland if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
238e0f1c0afSOlaf Faaland vs->vs_aux == VDEV_AUX_ACTIVE) {
239e0f1c0afSOlaf Faaland mmp_state_t mmp_state;
240e0f1c0afSOlaf Faaland nvlist_t *nvinfo;
241e0f1c0afSOlaf Faaland
242e0f1c0afSOlaf Faaland nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
243e0f1c0afSOlaf Faaland mmp_state = fnvlist_lookup_uint64(nvinfo,
244e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_STATE);
245e0f1c0afSOlaf Faaland
246e0f1c0afSOlaf Faaland if (mmp_state == MMP_STATE_ACTIVE)
247e0f1c0afSOlaf Faaland return (ZPOOL_STATUS_HOSTID_ACTIVE);
248e0f1c0afSOlaf Faaland else if (mmp_state == MMP_STATE_NO_HOSTID)
249e0f1c0afSOlaf Faaland return (ZPOOL_STATUS_HOSTID_REQUIRED);
250e0f1c0afSOlaf Faaland else
251e0f1c0afSOlaf Faaland return (ZPOOL_STATUS_HOSTID_MISMATCH);
252e0f1c0afSOlaf Faaland }
253e0f1c0afSOlaf Faaland
25495173954Sek /*
25595173954Sek * Pool last accessed by another system.
25695173954Sek */
2573f9d6ad7SLin Ling (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
258e0f1c0afSOlaf Faaland if (hostid != 0 && (unsigned long)hostid != system_hostid &&
25995173954Sek stateval == POOL_STATE_ACTIVE)
26095173954Sek return (ZPOOL_STATUS_HOSTID_MISMATCH);
261fa9e4066Sahrens
262eaca9bbdSeschrock /*
263eaca9bbdSeschrock * Newer on-disk version.
264eaca9bbdSeschrock */
265eaca9bbdSeschrock if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
266eaca9bbdSeschrock vs->vs_aux == VDEV_AUX_VERSION_NEWER)
267eaca9bbdSeschrock return (ZPOOL_STATUS_VERSION_NEWER);
268eaca9bbdSeschrock
269ad135b5dSChristopher Siden /*
270ad135b5dSChristopher Siden * Unsupported feature(s).
271ad135b5dSChristopher Siden */
272ad135b5dSChristopher Siden if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
273ad135b5dSChristopher Siden vs->vs_aux == VDEV_AUX_UNSUP_FEAT) {
274ad135b5dSChristopher Siden nvlist_t *nvinfo;
275ad135b5dSChristopher Siden
276ad135b5dSChristopher Siden verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO,
277ad135b5dSChristopher Siden &nvinfo) == 0);
278ad135b5dSChristopher Siden if (nvlist_exists(nvinfo, ZPOOL_CONFIG_CAN_RDONLY))
279ad135b5dSChristopher Siden return (ZPOOL_STATUS_UNSUP_FEAT_WRITE);
280ad135b5dSChristopher Siden return (ZPOOL_STATUS_UNSUP_FEAT_READ);
281ad135b5dSChristopher Siden }
282ad135b5dSChristopher Siden
283fa9e4066Sahrens /*
284fa9e4066Sahrens * Check that the config is complete.
285fa9e4066Sahrens */
286fa9e4066Sahrens if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
287ea8dc4b6Seschrock vs->vs_aux == VDEV_AUX_BAD_GUID_SUM)
288fa9e4066Sahrens return (ZPOOL_STATUS_BAD_GUID_SUM);
289fa9e4066Sahrens
29032b87932Sek /*
291e0f1c0afSOlaf Faaland * Check whether the pool has suspended.
29232b87932Sek */
293e14bb325SJeff Bonwick if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED,
294e14bb325SJeff Bonwick &suspended) == 0) {
295e0f1c0afSOlaf Faaland uint64_t reason;
296e0f1c0afSOlaf Faaland
297e0f1c0afSOlaf Faaland if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED_REASON,
298e0f1c0afSOlaf Faaland &reason) == 0 && reason == ZIO_SUSPEND_MMP)
299e0f1c0afSOlaf Faaland return (ZPOOL_STATUS_IO_FAILURE_MMP);
300e0f1c0afSOlaf Faaland
301e14bb325SJeff Bonwick if (suspended == ZIO_FAILURE_MODE_CONTINUE)
30232b87932Sek return (ZPOOL_STATUS_IO_FAILURE_CONTINUE);
303e14bb325SJeff Bonwick return (ZPOOL_STATUS_IO_FAILURE_WAIT);
30432b87932Sek }
30532b87932Sek
306b87f3af3Sperrin /*
307b87f3af3Sperrin * Could not read a log.
308b87f3af3Sperrin */
309b87f3af3Sperrin if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
310b87f3af3Sperrin vs->vs_aux == VDEV_AUX_BAD_LOG) {
311b87f3af3Sperrin return (ZPOOL_STATUS_BAD_LOG);
312b87f3af3Sperrin }
313b87f3af3Sperrin
314fa9e4066Sahrens /*
3153d7072f8Seschrock * Bad devices in non-replicated config.
316fa9e4066Sahrens */
3173d7072f8Seschrock if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
3183d7072f8Seschrock find_vdev_problem(nvroot, vdev_faulted))
3193d7072f8Seschrock return (ZPOOL_STATUS_FAULTED_DEV_NR);
3203d7072f8Seschrock
321ea8dc4b6Seschrock if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
322ea8dc4b6Seschrock find_vdev_problem(nvroot, vdev_missing))
323ea8dc4b6Seschrock return (ZPOOL_STATUS_MISSING_DEV_NR);
324ea8dc4b6Seschrock
325ea8dc4b6Seschrock if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
326ea8dc4b6Seschrock find_vdev_problem(nvroot, vdev_broken))
327ea8dc4b6Seschrock return (ZPOOL_STATUS_CORRUPT_LABEL_NR);
328ea8dc4b6Seschrock
329ea8dc4b6Seschrock /*
330ea8dc4b6Seschrock * Corrupted pool metadata
331ea8dc4b6Seschrock */
332ea8dc4b6Seschrock if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
333ea8dc4b6Seschrock vs->vs_aux == VDEV_AUX_CORRUPT_DATA)
334ea8dc4b6Seschrock return (ZPOOL_STATUS_CORRUPT_POOL);
335fa9e4066Sahrens
336fa9e4066Sahrens /*
337ea8dc4b6Seschrock * Persistent data errors.
338fa9e4066Sahrens */
339ea8dc4b6Seschrock if (!isimport) {
340ea8dc4b6Seschrock if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
341ea8dc4b6Seschrock &nerr) == 0 && nerr != 0)
342ea8dc4b6Seschrock return (ZPOOL_STATUS_CORRUPT_DATA);
343fa9e4066Sahrens }
344fa9e4066Sahrens
345ea8dc4b6Seschrock /*
346ea8dc4b6Seschrock * Missing devices in a replicated config.
347ea8dc4b6Seschrock */
3483d7072f8Seschrock if (find_vdev_problem(nvroot, vdev_faulted))
3493d7072f8Seschrock return (ZPOOL_STATUS_FAULTED_DEV_R);
350ea8dc4b6Seschrock if (find_vdev_problem(nvroot, vdev_missing))
351ea8dc4b6Seschrock return (ZPOOL_STATUS_MISSING_DEV_R);
352ea8dc4b6Seschrock if (find_vdev_problem(nvroot, vdev_broken))
353ea8dc4b6Seschrock return (ZPOOL_STATUS_CORRUPT_LABEL_R);
354ea8dc4b6Seschrock
355fa9e4066Sahrens /*
356fa9e4066Sahrens * Devices with errors
357fa9e4066Sahrens */
358fa9e4066Sahrens if (!isimport && find_vdev_problem(nvroot, vdev_errors))
359fa9e4066Sahrens return (ZPOOL_STATUS_FAILING_DEV);
360fa9e4066Sahrens
361fa9e4066Sahrens /*
362fa9e4066Sahrens * Offlined devices
363fa9e4066Sahrens */
364fa9e4066Sahrens if (find_vdev_problem(nvroot, vdev_offlined))
365fa9e4066Sahrens return (ZPOOL_STATUS_OFFLINE_DEV);
366fa9e4066Sahrens
367c25309d4SGeorge Wilson /*
368c25309d4SGeorge Wilson * Removed device
369c25309d4SGeorge Wilson */
370c25309d4SGeorge Wilson if (find_vdev_problem(nvroot, vdev_removed))
371c25309d4SGeorge Wilson return (ZPOOL_STATUS_REMOVED_DEV);
372c25309d4SGeorge Wilson
373eb633035STom Caputi /*
374eb633035STom Caputi * Informational errata available.
375eb633035STom Caputi */
376eb633035STom Caputi (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRATA, &errata);
377eb633035STom Caputi if (errata) {
378eb633035STom Caputi *erratap = errata;
379eb633035STom Caputi return (ZPOOL_STATUS_ERRATA);
380eb633035STom Caputi }
381eb633035STom Caputi
382fa9e4066Sahrens /*
383eaca9bbdSeschrock * Outdated, but usable, version
384fa9e4066Sahrens */
385ad135b5dSChristopher Siden if (SPA_VERSION_IS_SUPPORTED(version) && version != SPA_VERSION)
386eaca9bbdSeschrock return (ZPOOL_STATUS_VERSION_OLDER);
387fa9e4066Sahrens
38857221772SChristopher Siden /*
38957221772SChristopher Siden * Usable pool with disabled features
39057221772SChristopher Siden */
39157221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) {
39257221772SChristopher Siden int i;
39357221772SChristopher Siden nvlist_t *feat;
39457221772SChristopher Siden
39557221772SChristopher Siden if (isimport) {
39657221772SChristopher Siden feat = fnvlist_lookup_nvlist(config,
39757221772SChristopher Siden ZPOOL_CONFIG_LOAD_INFO);
398e0f1c0afSOlaf Faaland if (nvlist_exists(feat, ZPOOL_CONFIG_ENABLED_FEAT))
399e0f1c0afSOlaf Faaland feat = fnvlist_lookup_nvlist(feat,
400e0f1c0afSOlaf Faaland ZPOOL_CONFIG_ENABLED_FEAT);
40157221772SChristopher Siden } else {
40257221772SChristopher Siden feat = fnvlist_lookup_nvlist(config,
40357221772SChristopher Siden ZPOOL_CONFIG_FEATURE_STATS);
40457221772SChristopher Siden }
40557221772SChristopher Siden
40657221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) {
40757221772SChristopher Siden zfeature_info_t *fi = &spa_feature_table[i];
40857221772SChristopher Siden if (!nvlist_exists(feat, fi->fi_guid))
40957221772SChristopher Siden return (ZPOOL_STATUS_FEAT_DISABLED);
41057221772SChristopher Siden }
41157221772SChristopher Siden }
41257221772SChristopher Siden
413fa9e4066Sahrens return (ZPOOL_STATUS_OK);
414fa9e4066Sahrens }
415fa9e4066Sahrens
416fa9e4066Sahrens zpool_status_t
zpool_get_status(zpool_handle_t * zhp,char ** msgid,zpool_errata_t * errata)417eb633035STom Caputi zpool_get_status(zpool_handle_t *zhp, char **msgid, zpool_errata_t *errata)
418fa9e4066Sahrens {
419eb633035STom Caputi zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE, errata);
420fa9e4066Sahrens
421fa9e4066Sahrens if (ret >= NMSGID)
422fa9e4066Sahrens *msgid = NULL;
423fa9e4066Sahrens else
4243d7072f8Seschrock *msgid = zfs_msgid_table[ret];
425fa9e4066Sahrens
426fa9e4066Sahrens return (ret);
427fa9e4066Sahrens }
428fa9e4066Sahrens
429fa9e4066Sahrens zpool_status_t
zpool_import_status(nvlist_t * config,char ** msgid,zpool_errata_t * errata)430eb633035STom Caputi zpool_import_status(nvlist_t *config, char **msgid, zpool_errata_t *errata)
431fa9e4066Sahrens {
432eb633035STom Caputi zpool_status_t ret = check_status(config, B_TRUE, errata);
433fa9e4066Sahrens
434fa9e4066Sahrens if (ret >= NMSGID)
435fa9e4066Sahrens *msgid = NULL;
436fa9e4066Sahrens else
43795173954Sek *msgid = zfs_msgid_table[ret];
438fa9e4066Sahrens
439fa9e4066Sahrens return (ret);
440fa9e4066Sahrens }
441