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