1d8ab6e1Don Brady/*
2d8ab6e1Don Brady * CDDL HEADER START
3d8ab6e1Don Brady *
4d8ab6e1Don Brady * The contents of this file are subject to the terms of the
5d8ab6e1Don Brady * Common Development and Distribution License (the "License").
6d8ab6e1Don Brady * You may not use this file except in compliance with the License.
7d8ab6e1Don Brady *
8d8ab6e1Don Brady * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d8ab6e1Don Brady * or http://www.opensolaris.org/os/licensing.
10d8ab6e1Don Brady * See the License for the specific language governing permissions
11d8ab6e1Don Brady * and limitations under the License.
12d8ab6e1Don Brady *
13d8ab6e1Don Brady * When distributing Covered Code, include this CDDL HEADER in each
14d8ab6e1Don Brady * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d8ab6e1Don Brady * If applicable, add the following below this CDDL HEADER, with the
16d8ab6e1Don Brady * fields enclosed by brackets "[]" replaced with your own identifying
17d8ab6e1Don Brady * information: Portions Copyright [yyyy] [name of copyright owner]
18d8ab6e1Don Brady *
19d8ab6e1Don Brady * CDDL HEADER END
20d8ab6e1Don Brady */
21d8ab6e1Don Brady
22d8ab6e1Don Brady/*
23d8ab6e1Don Brady * Copyright 2017 Nexenta Systems, Inc.
24d8ab6e1Don Brady * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
25d8ab6e1Don Brady * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
26d8ab6e1Don Brady * Copyright 2015 RackTop Systems.
27d8ab6e1Don Brady * Copyright (c) 2016, Intel Corporation.
28d8ab6e1Don Brady */
29d8ab6e1Don Brady
30d8ab6e1Don Brady/*
31d8ab6e1Don Brady * Pool import support functions.
32d8ab6e1Don Brady *
33d8ab6e1Don Brady * Used by zpool, ztest, zdb, and zhack to locate importable configs. Since
34d8ab6e1Don Brady * these commands are expected to run in the global zone, we can assume
35d8ab6e1Don Brady * that the devices are all readable when called.
36d8ab6e1Don Brady *
37d8ab6e1Don Brady * To import a pool, we rely on reading the configuration information from the
38d8ab6e1Don Brady * ZFS label of each device.  If we successfully read the label, then we
39d8ab6e1Don Brady * organize the configuration information in the following hierarchy:
40d8ab6e1Don Brady *
41d8ab6e1Don Brady *	pool guid -> toplevel vdev guid -> label txg
42d8ab6e1Don Brady *
43d8ab6e1Don Brady * Duplicate entries matching this same tuple will be discarded.  Once we have
44d8ab6e1Don Brady * examined every device, we pick the best label txg config for each toplevel
45d8ab6e1Don Brady * vdev.  We then arrange these toplevel vdevs into a complete pool config, and
46d8ab6e1Don Brady * update any paths that have changed.  Finally, we attempt to import the pool
47d8ab6e1Don Brady * using our derived config, and record the results.
48d8ab6e1Don Brady */
49d8ab6e1Don Brady
50d8ab6e1Don Brady#include <stdio.h>
51d8ab6e1Don Brady#include <stdarg.h>
52d8ab6e1Don Brady#include <assert.h>
53d8ab6e1Don Brady#include <ctype.h>
54d8ab6e1Don Brady#include <devid.h>
55d8ab6e1Don Brady#include <dirent.h>
56d8ab6e1Don Brady#include <errno.h>
57d8ab6e1Don Brady#include <libintl.h>
58d8ab6e1Don Brady#include <stddef.h>
59d8ab6e1Don Brady#include <stdlib.h>
60d8ab6e1Don Brady#include <string.h>
61d8ab6e1Don Brady#include <sys/stat.h>
62d8ab6e1Don Brady#include <unistd.h>
63d8ab6e1Don Brady#include <fcntl.h>
64d8ab6e1Don Brady#include <sys/vtoc.h>
65d8ab6e1Don Brady#include <sys/dktp/fdisk.h>
66d8ab6e1Don Brady#include <sys/efi_partition.h>
67d8ab6e1Don Brady#include <sys/vdev_impl.h>
68d8ab6e1Don Brady#include <sys/fs/zfs.h>
69d8ab6e1Don Brady
70d8ab6e1Don Brady#include <thread_pool.h>
71d8ab6e1Don Brady#include <libzutil.h>
72d8ab6e1Don Brady#include <libnvpair.h>
73d8ab6e1Don Brady
74d8ab6e1Don Brady#include "zutil_import.h"
75d8ab6e1Don Brady
76d8ab6e1Don Brady#ifdef NDEBUG
77d8ab6e1Don Brady#define	verify(EX)	((void)(EX))
78d8ab6e1Don Brady#else
79d8ab6e1Don Brady#define	verify(EX)	assert(EX)
80d8ab6e1Don Brady#endif
81d8ab6e1Don Brady
82d8ab6e1Don Brady/*PRINTFLIKE2*/
83d8ab6e1Don Bradystatic void
84d8ab6e1Don Bradyzutil_error_aux(libpc_handle_t *hdl, const char *fmt, ...)
85d8ab6e1Don Brady{
86d8ab6e1Don Brady	va_list ap;
87d8ab6e1Don Brady
88d8ab6e1Don Brady	va_start(ap, fmt);
89d8ab6e1Don Brady
90d8ab6e1Don Brady	(void) vsnprintf(hdl->lpc_desc, sizeof (hdl->lpc_desc), fmt, ap);
91d8ab6e1Don Brady	hdl->lpc_desc_active = B_TRUE;
92d8ab6e1Don Brady
93d8ab6e1Don Brady	va_end(ap);
94d8ab6e1Don Brady}
95d8ab6e1Don Brady
96d8ab6e1Don Bradystatic void
97d8ab6e1Don Bradyzutil_verror(libpc_handle_t *hdl, const char *error, const char *fmt,
98d8ab6e1Don Brady    va_list ap)
99d8ab6e1Don Brady{
100d8ab6e1Don Brady	char action[1024];
101d8ab6e1Don Brady
102d8ab6e1Don Brady	(void) vsnprintf(action, sizeof (action), fmt, ap);
103d8ab6e1Don Brady
104d8ab6e1Don Brady	if (hdl->lpc_desc_active)
105d8ab6e1Don Brady		hdl->lpc_desc_active = B_FALSE;
106d8ab6e1Don Brady	else
107d8ab6e1Don Brady		hdl->lpc_desc[0] = '\0';
108d8ab6e1Don Brady
109d8ab6e1Don Brady	if (hdl->lpc_printerr) {
110d8ab6e1Don Brady		if (hdl->lpc_desc[0] != '\0')
111d8ab6e1Don Brady			error = hdl->lpc_desc;
112d8ab6e1Don Brady
113d8ab6e1Don Brady		(void) fprintf(stderr, "%s: %s\n", action, error);
114d8ab6e1Don Brady	}
115d8ab6e1Don Brady}
116d8ab6e1Don Brady
117d8ab6e1Don Brady/*PRINTFLIKE3*/
118d8ab6e1Don Bradystatic int
119d8ab6e1Don Bradyzutil_error_fmt(libpc_handle_t *hdl, const char *error, const char *fmt, ...)
120d8ab6e1Don Brady{
121d8ab6e1Don Brady	va_list ap;
122d8ab6e1Don Brady
123d8ab6e1Don Brady	va_start(ap, fmt);
124d8ab6e1Don Brady
125d8ab6e1Don Brady	zutil_verror(hdl, error, fmt, ap);
126d8ab6e1Don Brady
127d8ab6e1Don Brady	va_end(ap);
128d8ab6e1Don Brady
129d8ab6e1Don Brady	return (-1);
130d8ab6e1Don Brady}
131d8ab6e1Don Brady
132d8ab6e1Don Bradystatic int
133d8ab6e1Don Bradyzutil_error(libpc_handle_t *hdl, const char *error, const char *msg)
134d8ab6e1Don Brady{
135d8ab6e1Don Brady	return (zutil_error_fmt(hdl, error, "%s", msg));
136d8ab6e1Don Brady}
137d8ab6e1Don Brady
138d8ab6e1Don Bradystatic int
139d8ab6e1Don Bradyzutil_no_memory(libpc_handle_t *hdl)
140d8ab6e1Don Brady{
141d8ab6e1Don Brady	(void) zutil_error(hdl, EZFS_NOMEM, "internal error");
142d8ab6e1Don Brady	exit(1);
143d8ab6e1Don Brady}
144d8ab6e1Don Brady
145d8ab6e1Don Bradyvoid *
146d8ab6e1Don Bradyzutil_alloc(libpc_handle_t *hdl, size_t size)
147d8ab6e1Don Brady{
148d8ab6e1Don Brady	void *data;
149d8ab6e1Don Brady
150d8ab6e1Don Brady	if ((data = calloc(1, size)) == NULL)
151d8ab6e1Don Brady		(void) zutil_no_memory(hdl);
152d8ab6e1Don Brady
153d8ab6e1Don Brady	return (data);
154d8ab6e1Don Brady}
155d8ab6e1Don Brady
156d8ab6e1Don Bradychar *
157d8ab6e1Don Bradyzutil_strdup(libpc_handle_t *hdl, const char *str)
158d8ab6e1Don Brady{
159d8ab6e1Don Brady	char *ret;
160d8ab6e1Don Brady
161d8ab6e1Don Brady	if ((ret = strdup(str)) == NULL)
162d8ab6e1Don Brady		(void) zutil_no_memory(hdl);
163d8ab6e1Don Brady
164d8ab6e1Don Brady	return (ret);
165d8ab6e1Don Brady}
166d8ab6e1Don Brady
167d8ab6e1Don Brady/*
168d8ab6e1Don Brady * Intermediate structures used to gather configuration information.
169d8ab6e1Don Brady */
170d8ab6e1Don Bradytypedef struct config_entry {
171d8ab6e1Don Brady	uint64_t		ce_txg;
172d8ab6e1Don Brady	nvlist_t		*ce_config;
173d8ab6e1Don Brady	struct config_entry	*ce_next;
174d8ab6e1Don Brady} config_entry_t;
175d8ab6e1Don Brady
176d8ab6e1Don Bradytypedef struct vdev_entry {
177d8ab6e1Don Brady	uint64_t		ve_guid;
178d8ab6e1Don Brady	config_entry_t		*ve_configs;
179d8ab6e1Don Brady	struct vdev_entry	*ve_next;
180d8ab6e1Don Brady} vdev_entry_t;
181d8ab6e1Don Brady
182d8ab6e1Don Bradytypedef struct pool_entry {
183d8ab6e1Don Brady	uint64_t		pe_guid;
184d8ab6e1Don Brady	vdev_entry_t		*pe_vdevs;
185d8ab6e1Don Brady	struct pool_entry	*pe_next;
186d8ab6e1Don Brady} pool_entry_t;
187d8ab6e1Don Brady
188d8ab6e1Don Bradytypedef struct name_entry {
189d8ab6e1Don Brady	char			*ne_name;
190d8ab6e1Don Brady	uint64_t		ne_guid;
191d8ab6e1Don Brady	struct name_entry	*ne_next;
192d8ab6e1Don Brady} name_entry_t;
193d8ab6e1Don Brady
194d8ab6e1Don Bradytypedef struct pool_list {
195d8ab6e1Don Brady	pool_entry_t		*pools;
196d8ab6e1Don Brady	name_entry_t		*names;
197d8ab6e1Don Brady} pool_list_t;
198d8ab6e1Don Brady
199d8ab6e1Don Brady/*
200d8ab6e1Don Brady * Go through and fix up any path and/or devid information for the given vdev
201d8ab6e1Don Brady * configuration.
202d8ab6e1Don Brady */
203d8ab6e1Don Bradystatic int
204d8ab6e1Don Bradyfix_paths(nvlist_t *nv, name_entry_t *names)
205d8ab6e1Don Brady{
206d8ab6e1Don Brady	nvlist_t **child;
207d8ab6e1Don Brady	uint_t c, children;
208d8ab6e1Don Brady	uint64_t guid;
209d8ab6e1Don Brady	name_entry_t *ne, *best;
210d8ab6e1Don Brady	char *path, *devid;
211d8ab6e1Don Brady	int matched;
212d8ab6e1Don Brady
213d8ab6e1Don Brady	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
214d8ab6e1Don Brady	    &child, &children) == 0) {
215d8ab6e1Don Brady		for (c = 0; c < children; c++)
216d8ab6e1Don Brady			if (fix_paths(child[c], names) != 0)
217d8ab6e1Don Brady				return (-1);
218d8ab6e1Don Brady		return (0);
219d8ab6e1Don Brady	}
220d8ab6e1Don Brady
221d8ab6e1Don Brady	/*
222d8ab6e1Don Brady	 * This is a leaf (file or disk) vdev.  In either case, go through
223d8ab6e1Don Brady	 * the name list and see if we find a matching guid.  If so, replace
224d8ab6e1Don Brady	 * the path and see if we can calculate a new devid.
225d8ab6e1Don Brady	 *
226d8ab6e1Don Brady	 * There may be multiple names associated with a particular guid, in
227d8ab6e1Don Brady	 * which case we have overlapping slices or multiple paths to the same
228d8ab6e1Don Brady	 * disk.  If this is the case, then we want to pick the path that is
229d8ab6e1Don Brady	 * the most similar to the original, where "most similar" is the number
230d8ab6e1Don Brady	 * of matching characters starting from the end of the path.  This will
231d8ab6e1Don Brady	 * preserve slice numbers even if the disks have been reorganized, and
232d8ab6e1Don Brady	 * will also catch preferred disk names if multiple paths exist.
233d8ab6e1Don Brady	 */
234d8ab6e1Don Brady	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0);
235d8ab6e1Don Brady	if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0)
236d8ab6e1Don Brady		path = NULL;
237d8ab6e1Don Brady
238d8ab6e1Don Brady	matched = 0;
239d8ab6e1Don Brady	best = NULL;
240d8ab6e1Don Brady	for (ne = names; ne != NULL; ne = ne->ne_next) {
241d8ab6e1Don Brady		if (ne->ne_guid == guid) {
242d8ab6e1Don Brady			const char *src, *dst;
243d8ab6e1Don Brady			int count;
244d8ab6e1Don Brady
245d8ab6e1Don Brady			if (path == NULL) {
246d8ab6e1Don Brady				best = ne;
247d8ab6e1Don Brady				break;
248d8ab6e1Don Brady			}
249d8ab6e1Don Brady
250d8ab6e1Don Brady			src = ne->ne_name + strlen(ne->ne_name) - 1;
251d8ab6e1Don Brady			dst = path + strlen(path) - 1;
252d8ab6e1Don Brady			for (count = 0; src >= ne->ne_name && dst >= path;
253d8ab6e1Don Brady			    src--, dst--, count++)
254d8ab6e1Don Brady				if (*src != *dst)
255d8ab6e1Don Brady					break;
256d8ab6e1Don Brady
257d8ab6e1Don Brady			/*
258d8ab6e1Don Brady			 * At this point, 'count' is the number of characters
259d8ab6e1Don Brady			 * matched from the end.
260d8ab6e1Don Brady			 */
261d8ab6e1Don Brady			if (count > matched || best == NULL) {
262d8ab6e1Don Brady				best = ne;
263d8ab6e1Don Brady				matched = count;
264d8ab6e1Don Brady			}
265d8ab6e1Don Brady		}
266d8ab6e1Don Brady	}
267d8ab6e1Don Brady
268d8ab6e1Don Brady	if (best == NULL)
269d8ab6e1Don Brady		return (0);
270d8ab6e1Don Brady
271d8ab6e1Don Brady	if (nvlist_add_string(nv, ZPOOL_CONFIG_PATH, best->ne_name) != 0)
272d8ab6e1Don Brady		return (-1);
273d8ab6e1Don Brady
274d8ab6e1Don Brady	if ((devid = devid_str_from_path(best->ne_name)) == NULL) {
275d8ab6e1Don Brady		(void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID);
276d8ab6e1Don Brady	} else {
277d8ab6e1Don Brady		if (nvlist_add_string(nv, ZPOOL_CONFIG_DEVID, devid) != 0) {
278d8ab6e1Don Brady			devid_str_free(devid);
279d8ab6e1Don Brady			return (-1);
280d8ab6e1Don Brady		}
281d8ab6e1Don Brady		devid_str_free(devid);
282d8ab6e1Don Brady	}
283d8ab6e1Don Brady
284d8ab6e1Don Brady	return (0);
285d8ab6e1Don Brady}
286d8ab6e1Don Brady
287d8ab6e1Don Brady/*
288d8ab6e1Don Brady * Add the given configuration to the list of known devices.
289d8ab6e1Don Brady */
290d8ab6e1Don Bradystatic int
291d8ab6e1Don Bradyadd_config(libpc_handle_t *hdl, pool_list_t *pl, const char *path,
292d8ab6e1Don Brady    int order, int num_labels, nvlist_t *config)
293d8ab6e1Don Brady{
294d8ab6e1Don Brady	uint64_t pool_guid, vdev_guid, top_guid, txg, state;
295d8ab6e1Don Brady	pool_entry_t *pe;
296d8ab6e1Don Brady	vdev_entry_t *ve;
297d8ab6e1Don Brady	config_entry_t *ce;
298d8ab6e1Don Brady	name_entry_t *ne;
299d8ab6e1Don Brady
300d8ab6e1Don Brady	/*
301d8ab6e1Don Brady	 * If this is a hot spare not currently in use or level 2 cache
302d8ab6e1Don Brady	 * device, add it to the list of names to translate, but don't do
303d8ab6e1Don Brady	 * anything else.
304d8ab6e1Don Brady	 */
305d8ab6e1Don Brady	if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
306d8ab6e1Don Brady	    &state) == 0 &&
307d8ab6e1Don Brady	    (state == POOL_STATE_SPARE || state == POOL_STATE_L2CACHE) &&
308d8ab6e1Don Brady	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, &vdev_guid) == 0) {
309d8ab6e1Don Brady		if ((ne = zutil_alloc(hdl, sizeof (name_entry_t))) == NULL)
310d8ab6e1Don Brady			return (-1);
311d8ab6e1Don Brady
312d8ab6e1Don Brady		if ((ne->ne_name = zutil_strdup(hdl, path)) == NULL) {
313d8ab6e1Don Brady			free(ne);
314d8ab6e1Don Brady			return (-1);
315d8ab6e1Don Brady		}
316d8ab6e1Don Brady
317d8ab6e1Don Brady		ne->ne_guid = vdev_guid;
318d8ab6e1Don Brady		ne->ne_next = pl->names;
319d8ab6e1Don Brady		pl->names = ne;
320d8ab6e1Don Brady
321d8ab6e1Don Brady		return (0);
322d8ab6e1Don Brady	}
323d8ab6e1Don Brady
324d8ab6e1Don Brady	/*
325d8ab6e1Don Brady	 * If we have a valid config but cannot read any of these fields, then
326d8ab6e1Don Brady	 * it means we have a half-initialized label.  In vdev_label_init()
327d8ab6e1Don Brady	 * we write a label with txg == 0 so that we can identify the device
328d8ab6e1Don Brady	 * in case the user refers to the same disk later on.  If we fail to
329d8ab6e1Don Brady	 * create the pool, we'll be left with a label in this state
330d8ab6e1Don Brady	 * which should not be considered part of a valid pool.
331d8ab6e1Don Brady	 */
332d8ab6e1Don Brady	if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
333d8ab6e1Don Brady	    &pool_guid) != 0 ||
334d8ab6e1Don Brady	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID,
335d8ab6e1Don Brady	    &vdev_guid) != 0 ||
336d8ab6e1Don Brady	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_TOP_GUID,
337d8ab6e1Don Brady	    &top_guid) != 0 ||
338d8ab6e1Don Brady	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG,
339d8ab6e1Don Brady	    &txg) != 0 || txg == 0) {
340d8ab6e1Don Brady		return (0);
341d8ab6e1Don Brady	}
342d8ab6e1Don Brady
343d8ab6e1Don Brady	/*
344d8ab6e1Don Brady	 * First, see if we know about this pool.  If not, then add it to the
345d8ab6e1Don Brady	 * list of known pools.
346d8ab6e1Don Brady	 */
347d8ab6e1Don Brady	for (pe = pl->pools; pe != NULL; pe = pe->pe_next) {
348d8ab6e1Don Brady		if (pe->pe_guid == pool_guid)
349d8ab6e1Don Brady			break;
350d8ab6e1Don Brady	}
351d8ab6e1Don Brady
352d8ab6e1Don Brady	if (pe == NULL) {
353d8ab6e1Don Brady		if ((pe = zutil_alloc(hdl, sizeof (pool_entry_t))) == NULL) {
354d8ab6e1Don Brady			return (-1);
355d8ab6e1Don Brady		}
356d8ab6e1Don Brady		pe->pe_guid = pool_guid;
357d8ab6e1Don Brady		pe->pe_next = pl->pools;
358d8ab6e1Don Brady		pl->pools = pe;
359d8ab6e1Don Brady	}
360d8ab6e1Don Brady
361d8ab6e1Don Brady	/*
362d8ab6e1Don Brady	 * Second, see if we know about this toplevel vdev.  Add it if its
363d8ab6e1Don Brady	 * missing.
364d8ab6e1Don Brady	 */
365d8ab6e1Don Brady	for (ve = pe->pe_vdevs; ve != NULL; ve = ve->ve_next) {
366d8ab6e1Don Brady		if (ve->ve_guid == top_guid)
367d8ab6e1Don Brady			break;
368d8ab6e1Don Brady	}
369d8ab6e1Don Brady
370d8ab6e1Don Brady	if (ve == NULL) {
371d8ab6e1Don Brady		if ((ve = zutil_alloc(hdl, sizeof (vdev_entry_t))) == NULL) {
372d8ab6e1Don Brady			return (-1);
373d8ab6e1Don Brady		}
374d8ab6e1Don Brady		ve->ve_guid = top_guid;
375d8ab6e1Don Brady		ve->ve_next = pe->pe_vdevs;
376d8ab6e1Don Brady		pe->pe_vdevs = ve;
377d8ab6e1Don Brady	}
378d8ab6e1Don Brady
379d8ab6e1Don Brady	/*
380d8ab6e1Don Brady	 * Third, see if we have a config with a matching transaction group.  If
381d8ab6e1Don Brady	 * so, then we do nothing.  Otherwise, add it to the list of known
382d8ab6e1Don Brady	 * configs.
383d8ab6e1Don Brady	 */
384d8ab6e1Don Brady	for (ce = ve->ve_configs; ce != NULL; ce = ce->ce_next) {
385d8ab6e1Don Brady		if (ce->ce_txg == txg)
386d8ab6e1Don Brady			break;
387d8ab6e1Don Brady	}
388d8ab6e1Don Brady
389d8ab6e1Don Brady	if (ce == NULL) {
390d8ab6e1Don Brady		if ((ce = zutil_alloc(hdl, sizeof (config_entry_t))) == NULL) {
391d8ab6e1Don Brady			return (-1);
392d8ab6e1Don Brady		}
393d8ab6e1Don Brady		ce->ce_txg = txg;
394d8ab6e1Don Brady		ce->ce_config = fnvlist_dup(config);
395d8ab6e1Don Brady		ce->ce_next = ve->ve_configs;
396d8ab6e1Don Brady		ve->ve_configs = ce;
397d8ab6e1Don Brady	}
398d8ab6e1Don Brady
399d8ab6e1Don Brady	/*
400d8ab6e1Don Brady	 * At this point we've successfully added our config to the list of
401d8ab6e1Don Brady	 * known configs.  The last thing to do is add the vdev guid -> path
402d8ab6e1Don Brady	 * mappings so that we can fix up the configuration as necessary before
403d8ab6e1Don Brady	 * doing the import.
404d8ab6e1Don Brady	 */
405d8ab6e1Don Brady	if ((ne = zutil_alloc(hdl, sizeof (name_entry_t))) == NULL)
406d8ab6e1Don Brady		return (-1);
407d8ab6e1Don Brady
408d8ab6e1Don Brady	if ((ne->ne_name = zutil_strdup(hdl, path)) == NULL) {
409d8ab6e1Don Brady		free(ne);
410d8ab6e1Don Brady		return (-1);
411d8ab6e1Don Brady	}
412d8ab6e1Don Brady
413d8ab6e1Don Brady	ne->ne_guid = vdev_guid;
414d8ab6e1Don Brady	ne->ne_next = pl->names;
415d8ab6e1Don Brady	pl->names = ne;
416d8ab6e1Don Brady
417d8ab6e1Don Brady	return (0);
418d8ab6e1Don Brady}
419d8ab6e1Don Brady
420d8ab6e1Don Brady/*
421d8ab6e1Don Brady * Returns true if the named pool matches the given GUID.
422d8ab6e1Don Brady */
423d8ab6e1Don Bradystatic int
424d8ab6e1Don Bradyzutil_pool_active(libpc_handle_t *hdl, const char *name, uint64_t guid,
425d8ab6e1Don Brady    boolean_t *isactive)
426d8ab6e1Don Brady{
427d8ab6e1Don Brady	ASSERT(hdl->lpc_ops->pco_pool_active != NULL);
428d8ab6e1Don Brady
429d8ab6e1Don Brady	int error = hdl->lpc_ops->pco_pool_active(hdl->lpc_lib_handle, name,
430d8ab6e1Don Brady	    guid, isactive);
431d8ab6e1Don Brady
432d8ab6e1Don Brady	return (error);
433d8ab6e1Don Brady}
434d8ab6e1Don Brady
435d8ab6e1Don Bradystatic nvlist_t *
436d8ab6e1Don Bradyzutil_refresh_config(libpc_handle_t *hdl, nvlist_t *tryconfig)
437d8ab6e1Don Brady{
438d8ab6e1Don Brady	ASSERT(hdl->lpc_ops->pco_refresh_config != NULL);
439d8ab6e1Don Brady
440d8ab6e1Don Brady	return (hdl->lpc_ops->pco_refresh_config(hdl->lpc_lib_handle,
441d8ab6e1Don Brady	    tryconfig));
442d8ab6e1Don Brady}
443d8ab6e1Don Brady
444d8ab6e1Don Brady/*
445d8ab6e1Don Brady * Determine if the vdev id is a hole in the namespace.
446d8ab6e1Don Brady */
447d8ab6e1Don Bradystatic boolean_t
448d8ab6e1Don Bradyvdev_is_hole(uint64_t *hole_array, uint_t holes, uint_t id)
449d8ab6e1Don Brady{
450d8ab6e1Don Brady	for (int c = 0; c < holes; c++) {
451d8ab6e1Don Brady
452d8ab6e1Don Brady		/* Top-level is a hole */
453d8ab6e1Don Brady		if (hole_array[c] == id)
454d8ab6e1Don Brady			return (B_TRUE);
455d8ab6e1Don Brady	}
456d8ab6e1Don Brady	return (B_FALSE);
457d8ab6e1Don Brady}
458d8ab6e1Don Brady
459d8ab6e1Don Brady/*
460d8ab6e1Don Brady * Convert our list of pools into the definitive set of configurations.  We
461d8ab6e1Don Brady * start by picking the best config for each toplevel vdev.  Once that's done,
462d8ab6e1Don Brady * we assemble the toplevel vdevs into a full config for the pool.  We make a
463d8ab6e1Don Brady * pass to fix up any incorrect paths, and then add it to the main list to
464d8ab6e1Don Brady * return to the user.
465d8ab6e1Don Brady */
466d8ab6e1Don Bradystatic nvlist_t *
467d8ab6e1Don Bradyget_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok,
468d8ab6e1Don Brady    nvlist_t *policy)
469d8ab6e1Don Brady{
470d8ab6e1Don Brady	pool_entry_t *pe;
471d8ab6e1Don Brady	vdev_entry_t *ve;
472d8ab6e1Don Brady	config_entry_t *ce;
473d8ab6e1Don Brady	nvlist_t *ret = NULL, *config = NULL, *tmp = NULL, *nvtop, *nvroot;
474d8ab6e1Don Brady	nvlist_t **spares, **l2cache;
475d8ab6e1Don Brady	uint_t i, nspares, nl2cache;
476d8ab6e1Don Brady	boolean_t config_seen;
477d8ab6e1Don Brady	uint64_t best_txg;
478d8ab6e1Don Brady	char *name, *hostname = NULL;
479d8ab6e1Don Brady	uint64_t guid;
480d8ab6e1Don Brady	uint_t children = 0;
481d8ab6e1Don Brady	nvlist_t **child = NULL;
482d8ab6e1Don Brady	uint_t holes;
483d8ab6e1Don Brady	uint64_t *hole_array, max_id;
484d8ab6e1Don Brady	uint_t c;
485d8ab6e1Don Brady	boolean_t isactive;
486d8ab6e1Don Brady	uint64_t hostid;
487d8ab6e1Don Brady	nvlist_t *nvl;
488d8ab6e1Don Brady	boolean_t found_one = B_FALSE;
489d8ab6e1Don Brady	boolean_t valid_top_config = B_FALSE;
490d8ab6e1Don Brady
491d8ab6e1Don Brady	if (nvlist_alloc(&ret, 0, 0) != 0)
492d8ab6e1Don Brady		goto nomem;
493d8ab6e1Don Brady
494d8ab6e1Don Brady	for (pe = pl->pools; pe != NULL; pe = pe->pe_next) {
495d8ab6e1Don Brady		uint64_t id, max_txg = 0;
496d8ab6e1Don Brady
497d8ab6e1Don Brady		if (nvlist_alloc(&config, NV_UNIQUE_NAME, 0) != 0)
498d8ab6e1Don Brady			goto nomem;
499d8ab6e1Don Brady		config_seen = B_FALSE;
500d8ab6e1Don Brady
501d8ab6e1Don Brady		/*
502d8ab6e1Don Brady		 * Iterate over all toplevel vdevs.  Grab the pool configuration
503d8ab6e1Don Brady		 * from the first one we find, and then go through the rest and
504d8ab6e1Don Brady		 * add them as necessary to the 'vdevs' member of the config.
505d8ab6e1Don Brady		 */
506d8ab6e1Don Brady		for (ve = pe->pe_vdevs; ve != NULL; ve = ve->ve_next) {
507d8ab6e1Don Brady
508d8ab6e1Don Brady			/*
509d8ab6e1Don Brady			 * Determine the best configuration for this vdev by
510d8ab6e1Don Brady			 * selecting the config with the latest transaction
511d8ab6e1Don Brady			 * group.
512d8ab6e1Don Brady			 */
513d8ab6e1Don Brady			best_txg = 0;
514d8ab6e1Don Brady			for (ce = ve->ve_configs; ce != NULL;
515d8ab6e1Don Brady			    ce = ce->ce_next) {
516d8ab6e1Don Brady
517d8ab6e1Don Brady				if (ce->ce_txg > best_txg) {
518d8ab6e1Don Brady					tmp = ce->ce_config;
519d8ab6e1Don Brady					best_txg = ce->ce_txg;
520d8ab6e1Don Brady				}
521d8ab6e1Don Brady			}
522d8ab6e1Don Brady
523d8ab6e1Don Brady			/*
524d8ab6e1Don Brady			 * We rely on the fact that the max txg for the
525d8ab6e1Don Brady			 * pool will contain the most up-to-date information
526d8ab6e1Don Brady			 * about the valid top-levels in the vdev namespace.
527d8ab6e1Don Brady			 */
528d8ab6e1Don Brady			if (best_txg > max_txg) {
529d8ab6e1Don Brady				(void) nvlist_remove(config,
530d8ab6e1Don Brady				    ZPOOL_CONFIG_VDEV_CHILDREN,
531d8ab6e1Don Brady				    DATA_TYPE_UINT64);
532d8ab6e1Don Brady				(void) nvlist_remove(config,
533d8ab6e1Don Brady				    ZPOOL_CONFIG_HOLE_ARRAY,
534d8ab6e1Don Brady				    DATA_TYPE_UINT64_ARRAY);
535d8ab6e1Don Brady
536d8ab6e1Don Brady				max_txg = best_txg;
537d8ab6e1Don Brady				hole_array = NULL;
538d8ab6e1Don Brady				holes = 0;
539d8ab6e1Don Brady				max_id = 0;
540d8ab6e1Don Brady				valid_top_config = B_FALSE;
541d8ab6e1Don Brady
542d8ab6e1Don Brady				if (nvlist_lookup_uint64(tmp,
543d8ab6e1Don Brady				    ZPOOL_CONFIG_VDEV_CHILDREN, &max_id) == 0) {
544d8ab6e1Don Brady					verify(nvlist_add_uint64(config,
545d8ab6e1Don Brady					    ZPOOL_CONFIG_VDEV_CHILDREN,
546d8ab6e1Don Brady					    max_id) == 0);
547d8ab6e1Don Brady					valid_top_config = B_TRUE;
548d8ab6e1Don Brady				}
549d8ab6e1Don Brady
550d8ab6e1Don Brady				if (nvlist_lookup_uint64_array(tmp,
551d8ab6e1Don Brady				    ZPOOL_CONFIG_HOLE_ARRAY, &hole_array,
552d8ab6e1Don Brady				    &holes) == 0) {
553d8ab6e1Don Brady					verify(nvlist_add_uint64_array(config,
554d8ab6e1Don Brady					    ZPOOL_CONFIG_HOLE_ARRAY,
555d8ab6e1Don Brady					    hole_array, holes) == 0);
556d8ab6e1Don Brady				}
557d8ab6e1Don Brady			}
558d8ab6e1Don Brady
559d8ab6e1Don Brady			if (!config_seen) {
560d8ab6e1Don Brady				/*
561d8ab6e1Don Brady				 * Copy the relevant pieces of data to the pool
562d8ab6e1Don Brady				 * configuration:
563d8ab6e1Don Brady				 *
564d8ab6e1Don Brady				 *	version
565d8ab6e1Don Brady				 *	pool guid
566d8ab6e1Don Brady				 *	name
567d8ab6e1Don Brady				 *	comment (if available)
568d8ab6e1Don Brady				 *	pool state
569d8ab6e1Don Brady				 *	hostid (if available)
570d8ab6e1Don Brady				 *	hostname (if available)
571d8ab6e1Don Brady				 */
572d8ab6e1Don Brady				uint64_t state, version;
573d8ab6e1Don Brady				char *comment = NULL;
574d8ab6e1Don Brady
575d8ab6e1Don Brady				version = fnvlist_lookup_uint64(tmp,
576d8ab6e1Don Brady				    ZPOOL_CONFIG_VERSION);
577d8ab6e1Don Brady				fnvlist_add_uint64(config,
578d8ab6e1Don Brady				    ZPOOL_CONFIG_VERSION, version);
579d8ab6e1Don Brady				guid = fnvlist_lookup_uint64(tmp,
580d8ab6e1Don Brady				    ZPOOL_CONFIG_POOL_GUID);
581d8ab6e1Don Brady				fnvlist_add_uint64(config,
582d8ab6e1Don Brady				    ZPOOL_CONFIG_POOL_GUID, guid);
583d8ab6e1Don Brady				name = fnvlist_lookup_string(tmp,
584d8ab6e1Don Brady				    ZPOOL_CONFIG_POOL_NAME);
585d8ab6e1Don Brady				fnvlist_add_string(config,
586d8ab6e1Don Brady				    ZPOOL_CONFIG_POOL_NAME, name);
587d8ab6e1Don Brady
588d8ab6e1Don Brady				if (nvlist_lookup_string(tmp,
589d8ab6e1Don Brady				    ZPOOL_CONFIG_COMMENT, &comment) == 0)
590d8ab6e1Don Brady					fnvlist_add_string(config,
591d8ab6e1Don Brady					    ZPOOL_CONFIG_COMMENT, comment);
592d8ab6e1Don Brady
593d8ab6e1Don Brady				state = fnvlist_lookup_uint64(tmp,
594d8ab6e1Don Brady				    ZPOOL_CONFIG_POOL_STATE);
595d8ab6e1Don Brady				fnvlist_add_uint64(config,
596d8ab6e1Don Brady				    ZPOOL_CONFIG_POOL_STATE, state);
597d8ab6e1Don Brady
598d8ab6e1Don Brady				hostid = 0;
599d8ab6e1Don Brady				if (nvlist_lookup_uint64(tmp,
600d8ab6e1Don Brady				    ZPOOL_CONFIG_HOSTID, &hostid) == 0) {
601d8ab6e1Don Brady					fnvlist_add_uint64(config,
602d8ab6e1Don Brady					    ZPOOL_CONFIG_HOSTID, hostid);
603d8ab6e1Don Brady					hostname = fnvlist_lookup_string(tmp,
604d8ab6e1Don Brady					    ZPOOL_CONFIG_HOSTNAME);
605d8ab6e1Don Brady					fnvlist_add_string(config,
606d8ab6e1Don Brady					    ZPOOL_CONFIG_HOSTNAME, hostname);
607d8ab6e1Don Brady				}
608d8ab6e1Don Brady
609d8ab6e1Don Brady				config_seen = B_TRUE;
610d8ab6e1Don Brady			}
611d8ab6e1Don Brady
612d8ab6e1Don Brady			/*
613d8ab6e1Don Brady			 * Add this top-level vdev to the child array.
614d8ab6e1Don Brady			 */
615d8ab6e1Don Brady			verify(nvlist_lookup_nvlist(tmp,
616d8ab6e1Don Brady			    ZPOOL_CONFIG_VDEV_TREE, &nvtop) == 0);
617d8ab6e1Don Brady			verify(nvlist_lookup_uint64(nvtop, ZPOOL_CONFIG_ID,
618d8ab6e1Don Brady			    &id) == 0);
619d8ab6e1Don Brady
620d8ab6e1Don Brady			if (id >= children) {
621d8ab6e1Don Brady				nvlist_t **newchild;
622d8ab6e1Don Brady
623d8ab6e1Don Brady				newchild = zutil_alloc(hdl, (id + 1) *
624d8ab6e1Don Brady				    sizeof (nvlist_t *));
625d8ab6e1Don Brady				if (newchild == NULL)
626d8ab6e1Don Brady					goto nomem;
627d8ab6e1Don Brady
628d8ab6e1Don Brady				for (c = 0; c < children; c++)
629d8ab6e1Don Brady					newchild[c] = child[c];
630d8ab6e1Don Brady
631d8ab6e1Don Brady				free(child);
632d8ab6e1Don Brady				child = newchild;
633d8ab6e1Don Brady				children = id + 1;
634d8ab6e1Don Brady			}
635d8ab6e1Don Brady			if (nvlist_dup(nvtop, &child[id], 0) != 0)
636d8ab6e1Don Brady				goto nomem;
637d8ab6e1Don Brady
638d8ab6e1Don Brady		}
639d8ab6e1Don Brady
640d8ab6e1Don Brady		/*
641d8ab6e1Don Brady		 * If we have information about all the top-levels then
642d8ab6e1Don Brady		 * clean up the nvlist which we've constructed. This
643d8ab6e1Don Brady		 * means removing any extraneous devices that are
644d8ab6e1Don Brady		 * beyond the valid range or adding devices to the end
645d8ab6e1Don Brady		 * of our array which appear to be missing.
646d8ab6e1Don Brady		 */
647d8ab6e1Don Brady		if (valid_top_config) {
648d8ab6e1Don Brady			if (max_id < children) {
649d8ab6e1Don Brady				for (c = max_id; c < children; c++)
650d8ab6e1Don Brady					nvlist_free(child[c]);
651d8ab6e1Don Brady				children = max_id;
652d8ab6e1Don Brady			} else if (max_id > children) {
653d8ab6e1Don Brady				nvlist_t **newchild;
654d8ab6e1Don Brady
655d8ab6e1Don Brady				newchild = zutil_alloc(hdl, (max_id) *
656d8ab6e1Don Brady				    sizeof (nvlist_t *));
657d8ab6e1Don Brady				if (newchild == NULL)
658d8ab6e1Don Brady					goto nomem;
659d8ab6e1Don Brady
660d8ab6e1Don Brady				for (c = 0; c < children; c++)
661d8ab6e1Don Brady					newchild[c] = child[c];
662d8ab6e1Don Brady
663d8ab6e1Don Brady				free(child);
664d8ab6e1Don Brady				child = newchild;
665d8ab6e1Don Brady				children = max_id;
666d8ab6e1Don Brady			}
667d8ab6e1Don Brady		}
668d8ab6e1Don Brady
669d8ab6e1Don Brady		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
670d8ab6e1Don Brady		    &guid) == 0);
671d8ab6e1Don Brady
672d8ab6e1Don Brady		/*
673d8ab6e1Don Brady		 * The vdev namespace may contain holes as a result of
674d8ab6e1Don Brady		 * device removal. We must add them back into the vdev
675d8ab6e1Don Brady		 * tree before we process any missing devices.
676d8ab6e1Don Brady		 */
677d8ab6e1Don Brady		if (holes > 0) {
678d8ab6e1Don Brady			ASSERT(valid_top_config);
679d8ab6e1Don Brady
680d8ab6e1Don Brady			for (c = 0; c < children; c++) {
681d8ab6e1Don Brady				nvlist_t *holey;
682d8ab6e1Don Brady
683d8ab6e1Don Brady				if (child[c] != NULL ||
684d8ab6e1Don Brady				    !vdev_is_hole(hole_array, holes, c))
685d8ab6e1Don Brady					continue;
686d8ab6e1Don Brady
687d8ab6e1Don Brady				if (nvlist_alloc(&holey, NV_UNIQUE_NAME,
688d8ab6e1Don Brady				    0) != 0)
689d8ab6e1Don Brady					goto nomem;
690d8ab6e1Don Brady
691d8ab6e1Don Brady				/*
692d8ab6e1Don Brady				 * Holes in the namespace are treated as
693d8ab6e1Don Brady				 * "hole" top-level vdevs and have a
694d8ab6e1Don Brady				 * special flag set on them.
695d8ab6e1Don Brady				 */
696d8ab6e1Don Brady				if (nvlist_add_string(holey,
697d8ab6e1Don Brady				    ZPOOL_CONFIG_TYPE,
698d8ab6e1Don Brady				    VDEV_TYPE_HOLE) != 0 ||
699d8ab6e1Don Brady				    nvlist_add_uint64(holey,
700d8ab6e1Don Brady				    ZPOOL_CONFIG_ID, c) != 0 ||
701d8ab6e1Don Brady				    nvlist_add_uint64(holey,
702d8ab6e1Don Brady				    ZPOOL_CONFIG_GUID, 0ULL) != 0) {
703d8ab6e1Don Brady					nvlist_free(holey);
704d8ab6e1Don Brady					goto nomem;
705d8ab6e1Don Brady				}
706d8ab6e1Don Brady				child[c] = holey;
707d8ab6e1Don Brady			}
708d8ab6e1Don Brady		}
709d8ab6e1Don Brady
710d8ab6e1Don Brady		/*
711d8ab6e1Don Brady		 * Look for any missing top-level vdevs.  If this is the case,
712d8ab6e1Don Brady		 * create a faked up 'missing' vdev as a placeholder.  We cannot
713d8ab6e1Don Brady		 * simply compress the child array, because the kernel performs
714d8ab6e1Don Brady		 * certain checks to make sure the vdev IDs match their location
715d8ab6e1Don Brady		 * in the configuration.
716d8ab6e1Don Brady		 */
717d8ab6e1Don Brady		for (c = 0; c < children; c++) {
718d8ab6e1Don Brady			if (child[c] == NULL) {
719d8ab6e1Don Brady				nvlist_t *missing;
720d8ab6e1Don Brady				if (nvlist_alloc(&missing, NV_UNIQUE_NAME,
721d8ab6e1Don Brady				    0) != 0)
722d8ab6e1Don Brady					goto nomem;
723d8ab6e1Don Brady				if (nvlist_add_string(missing,
724d8ab6e1Don Brady				    ZPOOL_CONFIG_TYPE,
725d8ab6e1Don Brady				    VDEV_TYPE_MISSING) != 0 ||
726d8ab6e1Don Brady				    nvlist_add_uint64(missing,
727d8ab6e1Don Brady				    ZPOOL_CONFIG_ID, c) != 0 ||
728d8ab6e1Don Brady				    nvlist_add_uint64(missing,
729d8ab6e1Don Brady				    ZPOOL_CONFIG_GUID, 0ULL) != 0) {
730d8ab6e1Don Brady					nvlist_free(missing);
731d8ab6e1Don Brady					goto nomem;
732d8ab6e1Don Brady				}
733d8ab6e1Don Brady				child[c] = missing;
734d8ab6e1Don Brady			}
735d8ab6e1Don Brady		}
736d8ab6e1Don Brady
737d8ab6e1Don Brady		/*
738d8ab6e1Don Brady		 * Put all of this pool's top-level vdevs into a root vdev.
739d8ab6e1Don Brady		 */
740d8ab6e1Don Brady		if (nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) != 0)
741d8ab6e1Don Brady			goto nomem;
742d8ab6e1Don Brady		if (nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE,
743d8ab6e1Don Brady		    VDEV_TYPE_ROOT) != 0 ||
744d8ab6e1Don Brady		    nvlist_add_uint64(nvroot, ZPOOL_CONFIG_ID, 0ULL) != 0 ||
745d8ab6e1Don Brady		    nvlist_add_uint64(nvroot, ZPOOL_CONFIG_GUID, guid) != 0 ||
746d8ab6e1Don Brady		    nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
747d8ab6e1Don Brady		    child, children) != 0) {
748d8ab6e1Don Brady			nvlist_free(nvroot);
749d8ab6e1Don Brady			goto nomem;
750d8ab6e1Don Brady		}
751d8ab6e1Don Brady
752d8ab6e1Don Brady		for (c = 0; c < children; c++)
753d8ab6e1Don Brady			nvlist_free(child[c]);
754d8ab6e1Don Brady		free(child);
755d8ab6e1Don Brady		children = 0;
756d8ab6e1Don Brady		child = NULL;
757d8ab6e1Don Brady
758d8ab6e1Don Brady		/*
759d8ab6e1Don Brady		 * Go through and fix up any paths and/or devids based on our
760d8ab6e1Don Brady		 * known list of vdev GUID -> path mappings.
761d8ab6e1Don Brady		 */
762d8ab6e1Don Brady		if (fix_paths(nvroot, pl->names) != 0) {
763d8ab6e1Don Brady			nvlist_free(nvroot);
764d8ab6e1Don Brady			goto nomem;
765d8ab6e1Don Brady		}
766d8ab6e1Don Brady
767d8ab6e1Don Brady		/*