1fa9e406ahrens/*
2fa9e406ahrens * CDDL HEADER START
3fa9e406ahrens *
4fa9e406ahrens * The contents of this file are subject to the terms of the
5441d80alling * Common Development and Distribution License (the "License").
6441d80alling * You may not use this file except in compliance with the License.
7fa9e406ahrens *
8fa9e406ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e406ahrens * or http://www.opensolaris.org/os/licensing.
10fa9e406ahrens * See the License for the specific language governing permissions
11fa9e406ahrens * and limitations under the License.
12fa9e406ahrens *
13fa9e406ahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e406ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e406ahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e406ahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e406ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e406ahrens *
19fa9e406ahrens * CDDL HEADER END
20fa9e406ahrens */
21ad135b5Christopher Siden
22fa9e406ahrens/*
233f9d6adLin Ling * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
248671400Serapheim Dimitropoulos * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
25663207aDon Brady * Copyright (c) 2017, Intel Corporation.
26dd50e0cTony Hutter * Copyright 2020 Joyent, Inc.
27fa9e406ahrens */
28fa9e406ahrens
29fa9e406ahrens/*
30fa9e406ahrens * Virtual Device Labels
31fa9e406ahrens * ---------------------
32fa9e406ahrens *
33fa9e406ahrens * The vdev label serves several distinct purposes:
34fa9e406ahrens *
35fa9e406ahrens *	1. Uniquely identify this device as part of a ZFS pool and confirm its
36fa9e406ahrens *	   identity within the pool.
37fa9e406ahrens *
38cfd63e1Matthew Ahrens *	2. Verify that all the devices given in a configuration are present
39fa9e406ahrens *         within the pool.
40fa9e406ahrens *
41cfd63e1Matthew Ahrens *	3. Determine the uberblock for the pool.
42fa9e406ahrens *
43cfd63e1Matthew Ahrens *	4. In case of an import operation, determine the configuration of the
44fa9e406ahrens *         toplevel vdev of which it is a part.
45fa9e406ahrens *
46cfd63e1Matthew Ahrens *	5. If an import operation cannot find all the devices in the pool,
47fa9e406ahrens *         provide enough information to the administrator to determine which
48fa9e406ahrens *         devices are missing.
49fa9e406ahrens *
50fa9e406ahrens * It is important to note that while the kernel is responsible for writing the
51fa9e406ahrens * label, it only consumes the information in the first three cases.  The
52fa9e406ahrens * latter information is only consumed in userland when determining the
53fa9e406ahrens * configuration to import a pool.
54fa9e406ahrens *
55fa9e406ahrens *
56fa9e406ahrens * Label Organization
57fa9e406ahrens * ------------------
58fa9e406ahrens *
59fa9e406ahrens * Before describing the contents of the label, it's important to understand how
60fa9e406ahrens * the labels are written and updated with respect to the uberblock.
61fa9e406ahrens *
62fa9e406ahrens * When the pool configuration is altered, either because it was newly created
63fa9e406ahrens * or a device was added, we want to update all the labels such that we can deal
64fa9e406ahrens * with fatal failure at any point.  To this end, each disk has two labels which
65fa9e406ahrens * are updated before and after the uberblock is synced.  Assuming we have
663d7072feschrock * labels and an uberblock with the following transaction groups:
67fa9e406ahrens *
68fa9e406ahrens *              L1          UB          L2
69fa9e406ahrens *           +------+    +------+    +------+
70fa9e406ahrens *           |      |    |      |    |      |
71fa9e406ahrens *           | t10  |    | t10  |    | t10  |
72fa9e406ahrens *           |      |    |      |    |      |
73fa9e406ahrens *           +------+    +------+    +------+
74fa9e406ahrens *
75fa9e406ahrens * In this stable state, the labels and the uberblock were all updated within
76fa9e406ahrens * the same transaction group (10).  Each label is mirrored and checksummed, so
77fa9e406ahrens * that we can detect when we fail partway through writing the label.
78fa9e406ahrens *
79fa9e406ahrens * In order to identify which labels are valid, the labels are written in the
80fa9e406ahrens * following manner:
81fa9e406ahrens *
82cfd63e1Matthew Ahrens *	1. For each vdev, update 'L1' to the new label
83cfd63e1Matthew Ahrens *	2. Update the uberblock
84cfd63e1Matthew Ahrens *	3. For each vdev, update 'L2' to the new label
85fa9e406ahrens *
86fa9e406ahrens * Given arbitrary failure, we can determine the correct label to use based on
87fa9e406ahrens * the transaction group.  If we fail after updating L1 but before updating the
88fa9e406ahrens * UB, we will notice that L1's transaction group is greater than the uberblock,
89fa9e406ahrens * so L2 must be valid.  If we fail after writing the uberblock but before
90fa9e406ahrens * writing L2, we will notice that L2's transaction group is less than L1, and
91fa9e406ahrens * therefore L1 is valid.
92fa9e406ahrens *
93fa9e406ahrens * Another added complexity is that not every label is updated when the config
94fa9e406ahrens * is synced.  If we add a single device, we do not want to have to re-write
95fa9e406ahrens * every label for every device in the pool.  This means that both L1 and L2 may
96fa9e406ahrens * be older than the pool uberblock, because the necessary information is stored
97fa9e406ahrens * on another vdev.
98fa9e406ahrens *
99fa9e406ahrens *
100fa9e406ahrens * On-disk Format
101fa9e406ahrens * --------------
102fa9e406ahrens *
103fa9e406ahrens * The vdev label consists of two distinct parts, and is wrapped within the
104fa9e406ahrens * vdev_label_t structure.  The label includes 8k of padding to permit legacy
105fa9e406ahrens * VTOC disk labels, but is otherwise ignored.
106fa9e406ahrens *
107fa9e406ahrens * The first half of the label is a packed nvlist which contains pool wide
108fa9e406ahrens * properties, per-vdev properties, and configuration information.  It is
109fa9e406ahrens * described in more detail below.
110fa9e406ahrens *
111fa9e406ahrens * The latter half of the label consists of a redundant array of uberblocks.
112fa9e406ahrens * These uberblocks are updated whenever a transaction group is committed,
113fa9e406ahrens * or when the configuration is updated.  When a pool is loaded, we scan each
114fa9e406ahrens * vdev for the 'best' uberblock.
115fa9e406ahrens *
116fa9e406ahrens *
117fa9e406ahrens * Configuration Information
118fa9e406ahrens * -------------------------
119fa9e406ahrens *
120fa9e406ahrens * The nvlist describing the pool and vdev contains the following elements:
121fa9e406ahrens *
122cfd63e1Matthew Ahrens *	version		ZFS on-disk version
123cfd63e1Matthew Ahrens *	name		Pool name
124cfd63e1Matthew Ahrens *	state		Pool state
125cfd63e1Matthew Ahrens *	txg		Transaction group in which this label was written
126cfd63e1Matthew Ahrens *	pool_guid	Unique identifier for this pool
127cfd63e1Matthew Ahrens *	vdev_tree	An nvlist describing vdev tree.
128ad135b5Christopher Siden *	features_for_read
129ad135b5Christopher Siden *			An nvlist of the features necessary for reading the MOS.
130fa9e406ahrens *
131fa9e406ahrens * Each leaf device label also contains the following:
132fa9e406ahrens *
133cfd63e1Matthew Ahrens *	top_guid	Unique ID for top-level vdev in which this is contained
134cfd63e1Matthew Ahrens *	guid		Unique ID for the leaf vdev
135fa9e406ahrens *
136fa9e406ahrens * The 'vs' configuration follows the format described in 'spa_config.c'.
137fa9e406ahrens */
138fa9e406ahrens
139fa9e406ahrens#include <sys/zfs_context.h>
140fa9e406ahrens#include <sys/spa.h>
141fa9e406ahrens#include <sys/spa_impl.h>
142fa9e406ahrens#include <sys/dmu.h>
143fa9e406ahrens#include <sys/zap.h>
144fa9e406ahrens#include <sys/vdev.h>
145fa9e406ahrens#include <sys/vdev_impl.h>
146fa9e406ahrens#include <sys/uberblock_impl.h>
147fa9e406ahrens#include <sys/metaslab.h>
1485cabbc6Prashanth Sreenivasa#include <sys/metaslab_impl.h>
149fa9e406ahrens#include <sys/zio.h>
1503f9d6adLin Ling#include <sys/dsl_scan.h>
151770499eDan Kimmel#include <sys/abd.h>
152fa9e406ahrens#include <sys/fs/zfs.h>
153fa9e406ahrens
154fa9e406ahrens/*
155fa9e406ahrens * Basic routines to read and write from a vdev label.
156fa9e406ahrens * Used throughout the rest of this file.
157fa9e406ahrens */
158fa9e406ahrensuint64_t
159fa9e406ahrensvdev_label_offset(uint64_t psize, int l, uint64_t offset)
160fa9e406ahrens{
161ecc2d60bonwick	ASSERT(offset < sizeof (vdev_label_t));
162e743726ahrens	ASSERT(P2PHASE_TYPED(psize, sizeof (vdev_label_t), uint64_t) == 0);
163ecc2d60bonwick
164fa9e406ahrens	return (offset + l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
165fa9e406ahrens	    0 : psize - VDEV_LABELS * sizeof (vdev_label_t)));
166fa9e406ahrens}
167fa9e406ahrens
16821bf64agw/*
16921bf64agw * Returns back the vdev label associated with the passed in offset.
17021bf64agw */
17121bf64agwint
17221bf64agwvdev_label_number(uint64_t psize, uint64_t offset)
17321bf64agw{
17421bf64agw	int l;
17521bf64agw
17621bf64agw	if (offset >= psize - VDEV_LABEL_END_SIZE) {
17721bf64agw		offset -= psize - VDEV_LABEL_END_SIZE;
17821bf64agw		offset += (VDEV_LABELS / 2) * sizeof (vdev_label_t);
17921bf64agw	}
18021bf64agw	l = offset / sizeof (vdev_label_t);
18121bf64agw	return (l < VDEV_LABELS ? l : -1);
18221bf64agw}
18321bf64agw
184fa9e406ahrensstatic void
185770499eDan Kimmelvdev_label_read(zio_t *zio, vdev_t *vd, int l, abd_t *buf, uint64_t offset,
1869a686fbPaul Dagnelie    uint64_t size, zio_done_func_t *done, void *private, int flags)
187fa9e406ahrens{
18858447f6Olaf Faaland	ASSERT(
18958447f6Olaf Faaland	    spa_config_held(zio->io_spa, SCL_STATE, RW_READER) == SCL_STATE ||
19058447f6Olaf Faaland	    spa_config_held(zio->io_spa, SCL_STATE, RW_WRITER) == SCL_STATE);
191e14bb32Jeff Bonwick	ASSERT(flags & ZIO_FLAG_CONFIG_WRITER);
192fa9e406ahrens
193fa9e406ahrens	zio_nowait(zio_read_phys(zio, vd,
194fa9e406ahrens	    vdev_label_offset(vd->vdev_psize, l, offset),
195fa9e406ahrens	    size, buf, ZIO_CHECKSUM_LABEL, done, private,
196e14bb32Jeff Bonwick	    ZIO_PRIORITY_SYNC_READ, flags, B_TRUE));
197fa9e406ahrens}
198fa9e406ahrens
199e0f1c0aOlaf Faalandvoid
200770499eDan Kimmelvdev_label_write(zio_t *zio, vdev_t *vd, int l, abd_t *buf, uint64_t offset,
2019a686fbPaul Dagnelie    uint64_t size, zio_done_func_t *done, void *private, int flags)
202fa9e406ahrens{
20358447f6Olaf Faaland	ASSERT(
20458447f6Olaf Faaland	    spa_config_held(zio->io_spa, SCL_STATE, RW_READER) == SCL_STATE ||
20558447f6Olaf Faaland	    spa_config_held(zio->io_spa, SCL_STATE, RW_WRITER) == SCL_STATE);
206e14bb32Jeff Bonwick	ASSERT(flags & ZIO_FLAG_CONFIG_WRITER);
207fa9e406ahrens
208fa9e406ahrens	zio_nowait(zio_write_phys(zio, vd,
209fa9e406ahrens	    vdev_label_offset(vd->vdev_psize, l, offset),
210fa9e406ahrens	    size, buf, ZIO_CHECKSUM_LABEL, done, private,
21117f17c2bonwick	    ZIO_PRIORITY_SYNC_WRITE, flags, B_TRUE));
212fa9e406ahrens}
213fa9e406ahrens
214dd50e0cTony Hutter/*
215dd50e0cTony Hutter * Generate the nvlist representing this vdev's stats
216dd50e0cTony Hutter */
217dd50e0cTony Huttervoid
218dd50e0cTony Huttervdev_config_generate_stats(vdev_t *vd, nvlist_t *nv)
219dd50e0cTony Hutter{
220dd50e0cTony Hutter	nvlist_t *nvx;
221dd50e0cTony Hutter	vdev_stat_t *vs;
222dd50e0cTony Hutter	vdev_stat_ex_t *vsx;
223dd50e0cTony Hutter
224dd50e0cTony Hutter	vs = kmem_alloc(sizeof (*vs), KM_SLEEP);
225dd50e0cTony Hutter	vsx = kmem_alloc(sizeof (*vsx), KM_SLEEP);
226dd50e0cTony Hutter
227dd50e0cTony Hutter	vdev_get_stats_ex(vd, vs, vsx);
228dd50e0cTony Hutter	fnvlist_add_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
229dd50e0cTony Hutter	    (uint64_t *)vs, sizeof (*vs) / sizeof (uint64_t));
230dd50e0cTony Hutter
231dd50e0cTony Hutter	/*
232dd50e0cTony Hutter	 * Add extended stats into a special extended stats nvlist.  This keeps
233dd50e0cTony Hutter	 * all the extended stats nicely grouped together.  The extended stats
234dd50e0cTony Hutter	 * nvlist is then added to the main nvlist.
235dd50e0cTony Hutter	 */
236dd50e0cTony Hutter	nvx = fnvlist_alloc();
237dd50e0cTony Hutter
238dd50e0cTony Hutter	/* ZIOs in flight to disk */
239dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
240dd50e0cTony Hutter	    vsx->vsx_active_queue[ZIO_PRIORITY_SYNC_READ]);
241dd50e0cTony Hutter
242dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
243dd50e0cTony Hutter	    vsx->vsx_active_queue[ZIO_PRIORITY_SYNC_WRITE]);
244dd50e0cTony Hutter
245dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
246dd50e0cTony Hutter	    vsx->vsx_active_queue[ZIO_PRIORITY_ASYNC_READ]);
247dd50e0cTony Hutter
248dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
249dd50e0cTony Hutter	    vsx->vsx_active_queue[ZIO_PRIORITY_ASYNC_WRITE]);
250dd50e0cTony Hutter
251dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
252dd50e0cTony Hutter	    vsx->vsx_active_queue[ZIO_PRIORITY_SCRUB]);
253dd50e0cTony Hutter
254dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
255dd50e0cTony Hutter	    vsx->vsx_active_queue[ZIO_PRIORITY_TRIM]);
256dd50e0cTony Hutter
257dd50e0cTony Hutter	/* ZIOs pending */
258dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE,
259dd50e0cTony Hutter	    vsx->vsx_pend_queue[ZIO_PRIORITY_SYNC_READ]);
260dd50e0cTony Hutter
261dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE,
262dd50e0cTony Hutter	    vsx->vsx_pend_queue[ZIO_PRIORITY_SYNC_WRITE]);
263dd50e0cTony Hutter
264dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE,
265dd50e0cTony Hutter	    vsx->vsx_pend_queue[ZIO_PRIORITY_ASYNC_READ]);
266dd50e0cTony Hutter
267dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE,
268dd50e0cTony Hutter	    vsx->vsx_pend_queue[ZIO_PRIORITY_ASYNC_WRITE]);
269dd50e0cTony Hutter
270dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE,
271dd50e0cTony Hutter	    vsx->vsx_pend_queue[ZIO_PRIORITY_SCRUB]);
272dd50e0cTony Hutter
273dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_TRIM_PEND_QUEUE,
274dd50e0cTony Hutter	    vsx->vsx_pend_queue[ZIO_PRIORITY_TRIM]);
275dd50e0cTony Hutter
276dd50e0cTony Hutter	/* Histograms */
277dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
278dd50e0cTony Hutter	    vsx->vsx_total_histo[ZIO_TYPE_READ],
279dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_total_histo[ZIO_TYPE_READ]));
280dd50e0cTony Hutter
281dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
282dd50e0cTony Hutter	    vsx->vsx_total_histo[ZIO_TYPE_WRITE],
283dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_total_histo[ZIO_TYPE_WRITE]));
284dd50e0cTony Hutter
285dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
286dd50e0cTony Hutter	    vsx->vsx_disk_histo[ZIO_TYPE_READ],
287dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_disk_histo[ZIO_TYPE_READ]));
288dd50e0cTony Hutter
289dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
290dd50e0cTony Hutter	    vsx->vsx_disk_histo[ZIO_TYPE_WRITE],
291dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_disk_histo[ZIO_TYPE_WRITE]));
292dd50e0cTony Hutter
293dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
294dd50e0cTony Hutter	    vsx->vsx_queue_histo[ZIO_PRIORITY_SYNC_READ],
295dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_queue_histo[ZIO_PRIORITY_SYNC_READ]));
296dd50e0cTony Hutter
297dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
298dd50e0cTony Hutter	    vsx->vsx_queue_histo[ZIO_PRIORITY_SYNC_WRITE],
299dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_queue_histo[ZIO_PRIORITY_SYNC_WRITE]));
300dd50e0cTony Hutter
301dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
302dd50e0cTony Hutter	    vsx->vsx_queue_histo[ZIO_PRIORITY_ASYNC_READ],
303dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_queue_histo[ZIO_PRIORITY_ASYNC_READ]));
304dd50e0cTony Hutter
305dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
306dd50e0cTony Hutter	    vsx->vsx_queue_histo[ZIO_PRIORITY_ASYNC_WRITE],
307dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_queue_histo[ZIO_PRIORITY_ASYNC_WRITE]));
308dd50e0cTony Hutter
309dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
310dd50e0cTony Hutter	    vsx->vsx_queue_histo[ZIO_PRIORITY_SCRUB],
311dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_queue_histo[ZIO_PRIORITY_SCRUB]));
312dd50e0cTony Hutter
313dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
314dd50e0cTony Hutter	    vsx->vsx_queue_histo[ZIO_PRIORITY_TRIM],
315dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_queue_histo[ZIO_PRIORITY_TRIM]));
316dd50e0cTony Hutter
317dd50e0cTony Hutter	/* Request sizes */
318dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO,
319dd50e0cTony Hutter	    vsx->vsx_ind_histo[ZIO_PRIORITY_SYNC_READ],
320dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_ind_histo[ZIO_PRIORITY_SYNC_READ]));
321dd50e0cTony Hutter
322dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO,
323dd50e0cTony Hutter	    vsx->vsx_ind_histo[ZIO_PRIORITY_SYNC_WRITE],
324dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_ind_histo[ZIO_PRIORITY_SYNC_WRITE]));
325dd50e0cTony Hutter
326dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO,
327dd50e0cTony Hutter	    vsx->vsx_ind_histo[ZIO_PRIORITY_ASYNC_READ],
328dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_ind_histo[ZIO_PRIORITY_ASYNC_READ]));
329dd50e0cTony Hutter
330dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO,
331dd50e0cTony Hutter	    vsx->vsx_ind_histo[ZIO_PRIORITY_ASYNC_WRITE],
332dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_ind_histo[ZIO_PRIORITY_ASYNC_WRITE]));
333dd50e0cTony Hutter
334dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO,
335dd50e0cTony Hutter	    vsx->vsx_ind_histo[ZIO_PRIORITY_SCRUB],
336dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_ind_histo[ZIO_PRIORITY_SCRUB]));
337dd50e0cTony Hutter
338dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO,
339dd50e0cTony Hutter	    vsx->vsx_ind_histo[ZIO_PRIORITY_TRIM],
340dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_ind_histo[ZIO_PRIORITY_TRIM]));
341dd50e0cTony Hutter
342dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO,
343dd50e0cTony Hutter	    vsx->vsx_agg_histo[ZIO_PRIORITY_SYNC_READ],
344dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_agg_histo[ZIO_PRIORITY_SYNC_READ]));
345dd50e0cTony Hutter
346dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO,
347dd50e0cTony Hutter	    vsx->vsx_agg_histo[ZIO_PRIORITY_SYNC_WRITE],
348dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_agg_histo[ZIO_PRIORITY_SYNC_WRITE]));
349dd50e0cTony Hutter
350dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO,
351dd50e0cTony Hutter	    vsx->vsx_agg_histo[ZIO_PRIORITY_ASYNC_READ],
352dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_agg_histo[ZIO_PRIORITY_ASYNC_READ]));
353dd50e0cTony Hutter
354dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO,
355dd50e0cTony Hutter	    vsx->vsx_agg_histo[ZIO_PRIORITY_ASYNC_WRITE],
356dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_agg_histo[ZIO_PRIORITY_ASYNC_WRITE]));
357dd50e0cTony Hutter
358dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO,
359dd50e0cTony Hutter	    vsx->vsx_agg_histo[ZIO_PRIORITY_SCRUB],
360dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_agg_histo[ZIO_PRIORITY_SCRUB]));
361dd50e0cTony Hutter
362dd50e0cTony Hutter	fnvlist_add_uint64_array(nvx, ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO,
363dd50e0cTony Hutter	    vsx->vsx_agg_histo[ZIO_PRIORITY_TRIM],
364dd50e0cTony Hutter	    ARRAY_SIZE(vsx->vsx_agg_histo[ZIO_PRIORITY_TRIM]));
365dd50e0cTony Hutter
366dd50e0cTony Hutter	/* IO delays */
367dd50e0cTony Hutter	fnvlist_add_uint64(nvx, ZPOOL_CONFIG_VDEV_SLOW_IOS, vs->vs_slow_ios);
368dd50e0cTony Hutter
369dd50e0cTony Hutter	/* Add extended stats nvlist to main nvlist */
370dd50e0cTony Hutter	fnvlist_add_nvlist(nv, ZPOOL_CONFIG_VDEV_STATS_EX, nvx);
371dd50e0cTony Hutter
372dd50e0cTony Hutter	nvlist_free(nvx);
373dd50e0cTony Hutter	kmem_free(vs, sizeof (*vs));
374dd50e0cTony Hutter	kmem_free(vsx, sizeof (*vsx));
375dd50e0cTony Hutter}
376dd50e0cTony Hutter
3778671400Serapheim Dimitropoulosstatic void
3788671400Serapheim Dimitropoulosroot_vdev_actions_getprogress(vdev_t *vd, nvlist_t *nvl)
3798671400Serapheim Dimitropoulos{
3808671400Serapheim Dimitropoulos	spa_t *spa = vd->vdev_spa;
3818671400Serapheim Dimitropoulos
3828671400Serapheim Dimitropoulos	if (vd != spa->spa_root_vdev)
3838671400Serapheim Dimitropoulos		return;
3848671400Serapheim Dimitropoulos
3858671400Serapheim Dimitropoulos	/* provide either current or previous scan information */
3868671400Serapheim Dimitropoulos	pool_scan_stat_t ps;
3878671400Serapheim Dimitropoulos	if (spa_scan_get_stats(spa, &ps) == 0) {
3888671400Serapheim Dimitropoulos		fnvlist_add_uint64_array(nvl,
3898671400Serapheim Dimitropoulos		    ZPOOL_CONFIG_SCAN_STATS, (uint64_t *)&ps,
3908671400Serapheim Dimitropoulos		    sizeof (pool_scan_stat_t) / sizeof (uint64_t));
3918671400Serapheim Dimitropoulos	}
3928671400Serapheim Dimitropoulos
3938671400Serapheim Dimitropoulos	pool_removal_stat_t prs;
3948671400Serapheim Dimitropoulos	if (spa_removal_get_stats(spa, &prs) == 0) {
3958671400Serapheim Dimitropoulos		fnvlist_add_uint64_array(nvl,
3968671400Serapheim Dimitropoulos		    ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t *)&prs,
3978671400Serapheim Dimitropoulos		    sizeof (prs) / sizeof (uint64_t));
3988671400Serapheim Dimitropoulos	}
3998671400Serapheim Dimitropoulos
4008671400Serapheim Dimitropoulos	pool_checkpoint_stat_t pcs;
4018671400Serapheim Dimitropoulos	if (spa_checkpoint_get_stats(spa, &pcs) == 0) {
4028671400Serapheim Dimitropoulos		fnvlist_add_uint64_array(nvl,
4038671400Serapheim Dimitropoulos		    ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t *)&pcs,
4048671400Serapheim Dimitropoulos		    sizeof (pcs) / sizeof (uint64_t));
4058671400Serapheim Dimitropoulos	}
4068671400Serapheim Dimitropoulos}
4078671400Serapheim Dimitropoulos
408fa9e406ahrens/*
409fa9e406ahrens * Generate the nvlist representing this vdev's config.
410fa9e406ahrens */
411fa9e406ahrensnvlist_t *
41299653d4eschrockvdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
4133f9d6adLin Ling    vdev_config_flag_t flags)
414fa9e406ahrens{
415fa9e406ahrens	nvlist_t *nv = NULL;
4165cabbc6Prashanth Sreenivasa	vdev_indirect_config_t *vic = &vd->vdev_indirect_config;
417fa9e406ahrens
418b4952e1George Wilson	nv = fnvlist_alloc();
419fa9e406ahrens
420b4952e1George Wilson	fnvlist_add_string(nv, ZPOOL_CONFIG_TYPE, vd->vdev_ops->vdev_op_type);
4213f9d6adLin Ling	if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)))
422b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_ID, vd->vdev_id);
423b4952e1George Wilson	fnvlist_add_uint64(nv, ZPOOL_CONFIG_GUID, vd->vdev_guid);
424fa9e406ahrens
425fa9e406ahrens	if (vd->vdev_path != NULL)
426b4952e1George Wilson		fnvlist_add_string(nv, ZPOOL_CONFIG_PATH, vd->vdev_path);
427fa9e406ahrens
428fa9e406ahrens	if (vd->vdev_devid != NULL)
429b4952e1George Wilson		fnvlist_add_string(nv, ZPOOL_CONFIG_DEVID, vd->vdev_devid);
430fa9e406ahrens
4313d7072feschrock	if (vd->vdev_physpath != NULL)
432b4952e1George Wilson		fnvlist_add_string(nv, ZPOOL_CONFIG_PHYS_PATH,
433b4952e1George Wilson		    vd->vdev_physpath);
4343d7072feschrock
4356809eb4Eric Schrock	if (vd->vdev_fru != NULL)
436b4952e1George Wilson		fnvlist_add_string(nv, ZPOOL_CONFIG_FRU, vd->vdev_fru);
4376809eb4Eric Schrock
43899653d4eschrock	if (vd->vdev_nparity != 0) {
43999653d4eschrock		ASSERT(strcmp(vd->vdev_ops->vdev_op_type,
44099653d4eschrock		    VDEV_TYPE_RAIDZ) == 0);
44199653d4eschrock
44299653d4eschrock		/*
44399653d4eschrock		 * Make sure someone hasn't managed to sneak a fancy new vdev
44499653d4eschrock		 * into a crufty old storage pool.
44599653d4eschrock		 */
44699653d4eschrock		ASSERT(vd->vdev_nparity == 1 ||
447f94275cAdam Leventhal		    (vd->vdev_nparity <= 2 &&
448f94275cAdam Leventhal		    spa_version(spa) >= SPA_VERSION_RAIDZ2) ||
449f94275cAdam Leventhal		    (vd->vdev_nparity <= 3 &&
450f94275cAdam Leventhal		    spa_version(spa) >= SPA_VERSION_RAIDZ3));
45199653d4eschrock
45299653d4eschrock		/*
45399653d4eschrock		 * Note that we'll add the nparity tag even on storage pools
45499653d4eschrock		 * that only support a single parity device -- older software
45599653d4eschrock		 * will just ignore it.
45699653d4eschrock		 */
457b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_NPARITY, vd->vdev_nparity);
45899653d4eschrock	}
45999653d4eschrock
460afefbcdeschrock	if (vd->vdev_wholedisk != -1ULL)
461b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
462b4952e1George Wilson		    vd->vdev_wholedisk);
463afefbcdeschrock
4646f79381Pavel Zakharov	if (vd->vdev_not_present && !(flags & VDEV_CONFIG_MISSING))
465b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1);
466ea8dc4beschrock
46799653d4eschrock	if (vd->vdev_isspare)
468b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_SPARE, 1);
46999653d4eschrock
4703f9d6adLin Ling	if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)) &&
4713f9d6adLin Ling	    vd == vd->vdev_top) {
472b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_ARRAY,
473b4952e1George Wilson		    vd->vdev_ms_array);
474b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_SHIFT,
475b4952e1George Wilson		    vd->vdev_ms_shift);
476b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_ASHIFT, vd->vdev_ashift);
477b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_ASIZE,
478b4952e1George Wilson		    vd->vdev_asize);
479b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_LOG, vd->vdev_islog);
4805cabbc6Prashanth Sreenivasa		if (vd->vdev_removing) {
481b4952e1George Wilson			fnvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVING,
482b4952e1George Wilson			    vd->vdev_removing);
4835cabbc6Prashanth Sreenivasa		}
484663207aDon Brady
485663207aDon Brady		/* zpool command expects alloc class data */
486663207aDon Brady		if (getstats && vd->vdev_alloc_bias != VDEV_BIAS_NONE) {
487663207aDon Brady			const char *bias = NULL;
488663207aDon Brady
489663207aDon Brady			switch (vd->vdev_alloc_bias) {
490663207aDon Brady			case VDEV_BIAS_LOG:
491663207aDon Brady				bias = VDEV_ALLOC_BIAS_LOG;
492663207aDon Brady				break;
493663207aDon Brady			case VDEV_BIAS_SPECIAL:
494663207aDon Brady				bias = VDEV_ALLOC_BIAS_SPECIAL;
495663207aDon Brady				break;
496663207aDon Brady			case VDEV_BIAS_DEDUP:
497663207aDon Brady				bias = VDEV_ALLOC_BIAS_DEDUP;
498663207aDon Brady				break;
499663207aDon Brady			default:
500663207aDon Brady				ASSERT3U(vd->vdev_alloc_bias, ==,
501663207aDon Brady				    VDEV_BIAS_NONE);
502663207aDon Brady			}
503663207aDon Brady			fnvlist_add_string(nv, ZPOOL_CONFIG_ALLOCATION_BIAS,
504663207aDon Brady			    bias);
505663207aDon Brady		}
506fa9e406ahrens	}
507fa9e406ahrens
5080713e23George Wilson	if (vd->vdev_dtl_sm != NULL) {
509b4952e1George Wilson		fnvlist_add_uint64(nv, ZPOOL_CONFIG_DTL,
5100713e23George Wilson		    space_map_object(vd->vdev_dtl_sm));
5110713e23George Wilson	}
512fa9e406ahrens
5135cabbc6Prashanth Sreenivasa	if (vic->vic_mapping_object != 0) {
5145cabbc6Prashanth Sreenivasa		fnvlist_add_uint64(nv, ZPOOL_CONFIG_INDIRECT_OBJECT,
5155cabbc6Prashanth Sreenivasa		    vic->vic_mapping_object);
5165cabbc6Prashanth Sreenivasa	}
5175cabbc6Prashanth Sreenivasa
5185cabbc6Prashanth Sreenivasa	if (vic->vic_births_object != 0) {
5195cabbc6Prashanth Sreenivasa		fnvlist_add_uint64(nv, ZPOOL_CONFIG_INDIRECT_BIRTHS,
5205cabbc6Prashanth Sreenivasa		    vic->vic_births_object);
5215cabbc6Prashanth Sreenivasa	}
5225cabbc6Prashanth Sreenivasa
5235cabbc6Prashanth Sreenivasa	if (vic->vic_prev_i