xref: /illumos-gate/usr/src/uts/common/fs/zfs/spa_config.c (revision e7cbe64f)
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  */
2199653d4eSeschrock 
22fa9e4066Sahrens /*
23*e7cbe64fSgw  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24fa9e4066Sahrens  * Use is subject to license terms.
25fa9e4066Sahrens  */
26fa9e4066Sahrens 
27fa9e4066Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28fa9e4066Sahrens 
29fa9e4066Sahrens #include <sys/spa.h>
30fa9e4066Sahrens #include <sys/spa_impl.h>
31fa9e4066Sahrens #include <sys/nvpair.h>
32fa9e4066Sahrens #include <sys/uio.h>
33fa9e4066Sahrens #include <sys/fs/zfs.h>
34fa9e4066Sahrens #include <sys/vdev_impl.h>
35fa9e4066Sahrens #include <sys/zfs_ioctl.h>
3695173954Sek #include <sys/utsname.h>
3795173954Sek #include <sys/systeminfo.h>
3895173954Sek #include <sys/sunddi.h>
39ea8dc4b6Seschrock #ifdef _KERNEL
40ea8dc4b6Seschrock #include <sys/kobj.h>
41ea8dc4b6Seschrock #endif
42ea8dc4b6Seschrock 
43fa9e4066Sahrens /*
44fa9e4066Sahrens  * Pool configuration repository.
45fa9e4066Sahrens  *
462f8aaab3Seschrock  * Pool configuration is stored as a packed nvlist on the filesystem.  By
472f8aaab3Seschrock  * default, all pools are stored in /etc/zfs/zpool.cache and loaded on boot
482f8aaab3Seschrock  * (when the ZFS module is loaded).  Pools can also have the 'cachefile'
492f8aaab3Seschrock  * property set that allows them to be stored in an alternate location until
502f8aaab3Seschrock  * the control of external software.
51fa9e4066Sahrens  *
522f8aaab3Seschrock  * For each cache file, we have a single nvlist which holds all the
532f8aaab3Seschrock  * configuration information.  When the module loads, we read this information
542f8aaab3Seschrock  * from /etc/zfs/zpool.cache and populate the SPA namespace.  This namespace is
552f8aaab3Seschrock  * maintained independently in spa.c.  Whenever the namespace is modified, or
562f8aaab3Seschrock  * the configuration of a pool is changed, we call spa_config_sync(), which
572f8aaab3Seschrock  * walks through all the active pools and writes the configuration to disk.
58fa9e4066Sahrens  */
59fa9e4066Sahrens 
60fa9e4066Sahrens static uint64_t spa_config_generation = 1;
61fa9e4066Sahrens 
62fa9e4066Sahrens /*
63fa9e4066Sahrens  * This can be overridden in userland to preserve an alternate namespace for
64fa9e4066Sahrens  * userland pools when doing testing.
65fa9e4066Sahrens  */
66fa9e4066Sahrens const char *spa_config_dir = ZPOOL_CACHE_DIR;
67fa9e4066Sahrens 
68fa9e4066Sahrens /*
69fa9e4066Sahrens  * Called when the module is first loaded, this routine loads the configuration
70fa9e4066Sahrens  * file into the SPA namespace.  It does not actually open or load the pools; it
71fa9e4066Sahrens  * only populates the namespace.
72fa9e4066Sahrens  */
73fa9e4066Sahrens void
74fa9e4066Sahrens spa_config_load(void)
75fa9e4066Sahrens {
76fa9e4066Sahrens 	void *buf = NULL;
77fa9e4066Sahrens 	nvlist_t *nvlist, *child;
78fa9e4066Sahrens 	nvpair_t *nvpair;
79fa9e4066Sahrens 	spa_t *spa;
80fa9e4066Sahrens 	char pathname[128];
81ea8dc4b6Seschrock 	struct _buf *file;
82b1b8ab34Slling 	uint64_t fsize;
83fa9e4066Sahrens 
84fa9e4066Sahrens 	/*
85fa9e4066Sahrens 	 * Open the configuration file.
86fa9e4066Sahrens 	 */
87ea8dc4b6Seschrock 	(void) snprintf(pathname, sizeof (pathname), "%s%s/%s",
880373e76bSbonwick 	    (rootdir != NULL) ? "./" : "", spa_config_dir, ZPOOL_CACHE_FILE);
89ea8dc4b6Seschrock 
90ea8dc4b6Seschrock 	file = kobj_open_file(pathname);
91ea8dc4b6Seschrock 	if (file == (struct _buf *)-1)
92fa9e4066Sahrens 		return;
93fa9e4066Sahrens 
94b1b8ab34Slling 	if (kobj_get_filesize(file, &fsize) != 0)
95fa9e4066Sahrens 		goto out;
96fa9e4066Sahrens 
97b1b8ab34Slling 	buf = kmem_alloc(fsize, KM_SLEEP);
98fa9e4066Sahrens 
99ea8dc4b6Seschrock 	/*
100ea8dc4b6Seschrock 	 * Read the nvlist from the file.
101ea8dc4b6Seschrock 	 */
102b1b8ab34Slling 	if (kobj_read_file(file, buf, fsize, 0) < 0)
103fa9e4066Sahrens 		goto out;
104fa9e4066Sahrens 
105fa9e4066Sahrens 	/*
106fa9e4066Sahrens 	 * Unpack the nvlist.
107fa9e4066Sahrens 	 */
108b1b8ab34Slling 	if (nvlist_unpack(buf, fsize, &nvlist, KM_SLEEP) != 0)
109fa9e4066Sahrens 		goto out;
110fa9e4066Sahrens 
111fa9e4066Sahrens 	/*
112fa9e4066Sahrens 	 * Iterate over all elements in the nvlist, creating a new spa_t for
113fa9e4066Sahrens 	 * each one with the specified configuration.
114fa9e4066Sahrens 	 */
115fa9e4066Sahrens 	mutex_enter(&spa_namespace_lock);
116fa9e4066Sahrens 	nvpair = NULL;
117fa9e4066Sahrens 	while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) {
118fa9e4066Sahrens 
119fa9e4066Sahrens 		if (nvpair_type(nvpair) != DATA_TYPE_NVLIST)
120fa9e4066Sahrens 			continue;
121fa9e4066Sahrens 
122fa9e4066Sahrens 		VERIFY(nvpair_value_nvlist(nvpair, &child) == 0);
123fa9e4066Sahrens 
124fa9e4066Sahrens 		if (spa_lookup(nvpair_name(nvpair)) != NULL)
125fa9e4066Sahrens 			continue;
1260373e76bSbonwick 		spa = spa_add(nvpair_name(nvpair), NULL);
127fa9e4066Sahrens 
128fa9e4066Sahrens 		/*
129fa9e4066Sahrens 		 * We blindly duplicate the configuration here.  If it's
130fa9e4066Sahrens 		 * invalid, we will catch it when the pool is first opened.
131fa9e4066Sahrens 		 */
132fa9e4066Sahrens 		VERIFY(nvlist_dup(child, &spa->spa_config, 0) == 0);
133fa9e4066Sahrens 	}
134fa9e4066Sahrens 	mutex_exit(&spa_namespace_lock);
135fa9e4066Sahrens 
136fa9e4066Sahrens 	nvlist_free(nvlist);
137fa9e4066Sahrens 
138fa9e4066Sahrens out:
139fa9e4066Sahrens 	if (buf != NULL)
140b1b8ab34Slling 		kmem_free(buf, fsize);
141fa9e4066Sahrens 
142ea8dc4b6Seschrock 	kobj_close_file(file);
143fa9e4066Sahrens }
144fa9e4066Sahrens 
145fa9e4066Sahrens /*
1462f8aaab3Seschrock  * This function is called when destroying or exporting a pool.  It walks the
1472f8aaab3Seschrock  * list of active pools, and searches for any that match the given cache file.
1482f8aaab3Seschrock  * If there is only one cachefile, then the file is removed immediately,
1492f8aaab3Seschrock  * because we won't see the pool when iterating in spa_config_sync().
150fa9e4066Sahrens  */
151fa9e4066Sahrens void
1522f8aaab3Seschrock spa_config_check(const char *dir, const char *file)
153fa9e4066Sahrens {
1542f8aaab3Seschrock 	size_t count = 0;
155fa9e4066Sahrens 	char pathname[128];
1562f8aaab3Seschrock 	spa_t *spa;
157fa9e4066Sahrens 
1582f8aaab3Seschrock 	if (dir != NULL && strcmp(dir, "none") == 0)
1592f8aaab3Seschrock 		return;
160fa9e4066Sahrens 
1612f8aaab3Seschrock 	ASSERT(MUTEX_HELD(&spa_namespace_lock));
162fa9e4066Sahrens 	spa = NULL;
163fa9e4066Sahrens 	while ((spa = spa_next(spa)) != NULL) {
1642f8aaab3Seschrock 		if (dir == NULL) {
1652f8aaab3Seschrock 			if (spa->spa_config_dir == NULL)
1662f8aaab3Seschrock 				count++;
1672f8aaab3Seschrock 		} else {
1682f8aaab3Seschrock 			if (spa->spa_config_dir &&
1692f8aaab3Seschrock 			    strcmp(spa->spa_config_dir, dir) == 0 &&
1702f8aaab3Seschrock 			    strcmp(spa->spa_config_file, file) == 0)
1712f8aaab3Seschrock 				count++;
172990b4856Slling 		}
1732f8aaab3Seschrock 	}
1742f8aaab3Seschrock 
1752f8aaab3Seschrock 	if (count == 1) {
1762f8aaab3Seschrock 		if (dir == NULL) {
1772f8aaab3Seschrock 			dir = spa_config_dir;
1782f8aaab3Seschrock 			file = ZPOOL_CACHE_FILE;
1792f8aaab3Seschrock 		}
1802f8aaab3Seschrock 
1812f8aaab3Seschrock 		(void) snprintf(pathname, sizeof (pathname),
1822f8aaab3Seschrock 		    "%s/%s", dir, file);
1832f8aaab3Seschrock 		(void) vn_remove(pathname, UIO_SYSSPACE, RMFILE);
1842f8aaab3Seschrock 	}
1852f8aaab3Seschrock }
1862f8aaab3Seschrock 
1872f8aaab3Seschrock typedef struct spa_config_entry {
1882f8aaab3Seschrock 	list_t		sc_link;
1892f8aaab3Seschrock 	const char	*sc_dir;
1902f8aaab3Seschrock 	const char	*sc_file;
1912f8aaab3Seschrock 	nvlist_t	*sc_nvl;
1922f8aaab3Seschrock } spa_config_entry_t;
1932f8aaab3Seschrock 
1942f8aaab3Seschrock static void
1952f8aaab3Seschrock spa_config_entry_add(list_t *listp, spa_t *spa)
1962f8aaab3Seschrock {
1972f8aaab3Seschrock 	spa_config_entry_t *entry;
1982f8aaab3Seschrock 	const char *dir, *file;
1992f8aaab3Seschrock 
2002f8aaab3Seschrock 	mutex_enter(&spa->spa_config_cache_lock);
2012f8aaab3Seschrock 	if (!spa->spa_config || !spa->spa_name) {
202fa9e4066Sahrens 		mutex_exit(&spa->spa_config_cache_lock);
2032f8aaab3Seschrock 		return;
2042f8aaab3Seschrock 	}
2052f8aaab3Seschrock 
2062f8aaab3Seschrock 	if (spa->spa_config_dir) {
2072f8aaab3Seschrock 		dir = spa->spa_config_dir;
2082f8aaab3Seschrock 		file = spa->spa_config_file;
2092f8aaab3Seschrock 	} else {
2102f8aaab3Seschrock 		dir = spa_config_dir;
2112f8aaab3Seschrock 		file = ZPOOL_CACHE_FILE;
2122f8aaab3Seschrock 	}
2132f8aaab3Seschrock 
2142f8aaab3Seschrock 	if (strcmp(dir, "none") == 0) {
2152f8aaab3Seschrock 		mutex_exit(&spa->spa_config_cache_lock);
2162f8aaab3Seschrock 		return;
2172f8aaab3Seschrock 	}
2182f8aaab3Seschrock 
2192f8aaab3Seschrock 	for (entry = list_head(listp); entry != NULL;
2202f8aaab3Seschrock 	    entry = list_next(listp, entry)) {
2212f8aaab3Seschrock 		if (strcmp(entry->sc_dir, dir) == 0 &&
2222f8aaab3Seschrock 		    strcmp(entry->sc_file, file) == 0)
2232f8aaab3Seschrock 			break;
224fa9e4066Sahrens 	}
225fa9e4066Sahrens 
2262f8aaab3Seschrock 	if (entry == NULL) {
2272f8aaab3Seschrock 		entry = kmem_alloc(sizeof (spa_config_entry_t), KM_SLEEP);
2282f8aaab3Seschrock 		entry->sc_dir = dir;
2292f8aaab3Seschrock 		entry->sc_file = file;
2302f8aaab3Seschrock 		VERIFY(nvlist_alloc(&entry->sc_nvl, NV_UNIQUE_NAME,
2312f8aaab3Seschrock 		    KM_SLEEP) == 0);
2322f8aaab3Seschrock 		list_insert_tail(listp, entry);
2332f8aaab3Seschrock 	}
2342f8aaab3Seschrock 
2352f8aaab3Seschrock 	VERIFY(nvlist_add_nvlist(entry->sc_nvl, spa->spa_name,
2362f8aaab3Seschrock 	    spa->spa_config) == 0);
2372f8aaab3Seschrock 	mutex_exit(&spa->spa_config_cache_lock);
2382f8aaab3Seschrock }
2392f8aaab3Seschrock 
2402f8aaab3Seschrock static void
2412f8aaab3Seschrock spa_config_entry_write(spa_config_entry_t *entry)
2422f8aaab3Seschrock {
2432f8aaab3Seschrock 	nvlist_t *config = entry->sc_nvl;
2442f8aaab3Seschrock 	size_t buflen;
2452f8aaab3Seschrock 	char *buf;
2462f8aaab3Seschrock 	vnode_t *vp;
2472f8aaab3Seschrock 	int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX;
2482f8aaab3Seschrock 	char pathname[128];
2492f8aaab3Seschrock 	char pathname2[128];
2502f8aaab3Seschrock 
251fa9e4066Sahrens 	/*
252fa9e4066Sahrens 	 * Pack the configuration into a buffer.
253fa9e4066Sahrens 	 */
254fa9e4066Sahrens 	VERIFY(nvlist_size(config, &buflen, NV_ENCODE_XDR) == 0);
255fa9e4066Sahrens 
256fa9e4066Sahrens 	buf = kmem_alloc(buflen, KM_SLEEP);
257fa9e4066Sahrens 
258ea8dc4b6Seschrock 	VERIFY(nvlist_pack(config, &buf, &buflen, NV_ENCODE_XDR,
259ea8dc4b6Seschrock 	    KM_SLEEP) == 0);
260fa9e4066Sahrens 
261fa9e4066Sahrens 	/*
262fa9e4066Sahrens 	 * Write the configuration to disk.  We need to do the traditional
263fa9e4066Sahrens 	 * 'write to temporary file, sync, move over original' to make sure we
264fa9e4066Sahrens 	 * always have a consistent view of the data.
265fa9e4066Sahrens 	 */
2662f8aaab3Seschrock 	(void) snprintf(pathname, sizeof (pathname), "%s/.%s", entry->sc_dir,
2672f8aaab3Seschrock 	    entry->sc_file);
268fa9e4066Sahrens 
269fa9e4066Sahrens 	if (vn_open(pathname, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0) != 0)
270fa9e4066Sahrens 		goto out;
271fa9e4066Sahrens 
272fa9e4066Sahrens 	if (vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE,
273fa9e4066Sahrens 	    0, RLIM64_INFINITY, kcred, NULL) == 0 &&
274da6c28aaSamw 	    VOP_FSYNC(vp, FSYNC, kcred, NULL) == 0) {
275fa9e4066Sahrens 		(void) snprintf(pathname2, sizeof (pathname2), "%s/%s",
2762f8aaab3Seschrock 		    entry->sc_dir, entry->sc_file);
277fa9e4066Sahrens 		(void) vn_rename(pathname, pathname2, UIO_SYSSPACE);
278fa9e4066Sahrens 	}
279fa9e4066Sahrens 
280da6c28aaSamw 	(void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL);
281fa9e4066Sahrens 	VN_RELE(vp);
282fa9e4066Sahrens 
283fa9e4066Sahrens out:
284fa9e4066Sahrens 	(void) vn_remove(pathname, UIO_SYSSPACE, RMFILE);
285fa9e4066Sahrens 	kmem_free(buf, buflen);
2862f8aaab3Seschrock }
2872f8aaab3Seschrock 
2882f8aaab3Seschrock /*
2892f8aaab3Seschrock  * Synchronize all pools to disk.  This must be called with the namespace lock
2902f8aaab3Seschrock  * held.
2912f8aaab3Seschrock  */
2922f8aaab3Seschrock void
2932f8aaab3Seschrock spa_config_sync(void)
2942f8aaab3Seschrock {
2952f8aaab3Seschrock 	spa_t *spa = NULL;
2962f8aaab3Seschrock 	list_t files = { 0 };
2972f8aaab3Seschrock 	spa_config_entry_t *entry;
2982f8aaab3Seschrock 
2992f8aaab3Seschrock 	ASSERT(MUTEX_HELD(&spa_namespace_lock));
3002f8aaab3Seschrock 
3012f8aaab3Seschrock 	list_create(&files, sizeof (spa_config_entry_t),
3022f8aaab3Seschrock 	    offsetof(spa_config_entry_t, sc_link));
3032f8aaab3Seschrock 
3042f8aaab3Seschrock 	/*
3052f8aaab3Seschrock 	 * Add all known pools to the configuration list, ignoring those with
3062f8aaab3Seschrock 	 * alternate root paths.
3072f8aaab3Seschrock 	 */
3082f8aaab3Seschrock 	spa = NULL;
3092f8aaab3Seschrock 	while ((spa = spa_next(spa)) != NULL)
3102f8aaab3Seschrock 		spa_config_entry_add(&files, spa);
3112f8aaab3Seschrock 
3122f8aaab3Seschrock 	while ((entry = list_head(&files)) != NULL) {
3132f8aaab3Seschrock 		spa_config_entry_write(entry);
3142f8aaab3Seschrock 		list_remove(&files, entry);
3152f8aaab3Seschrock 		nvlist_free(entry->sc_nvl);
3162f8aaab3Seschrock 		kmem_free(entry, sizeof (spa_config_entry_t));
3172f8aaab3Seschrock 	}
3182f8aaab3Seschrock 
3192f8aaab3Seschrock 	spa_config_generation++;
320fa9e4066Sahrens }
321fa9e4066Sahrens 
322fa9e4066Sahrens /*
3230373e76bSbonwick  * Sigh.  Inside a local zone, we don't have access to /etc/zfs/zpool.cache,
324fa9e4066Sahrens  * and we don't want to allow the local zone to see all the pools anyway.
325fa9e4066Sahrens  * So we have to invent the ZFS_IOC_CONFIG ioctl to grab the configuration
326fa9e4066Sahrens  * information for all pool visible within the zone.
327fa9e4066Sahrens  */
328fa9e4066Sahrens nvlist_t *
329fa9e4066Sahrens spa_all_configs(uint64_t *generation)
330fa9e4066Sahrens {
331fa9e4066Sahrens 	nvlist_t *pools;
332fa9e4066Sahrens 	spa_t *spa;
333fa9e4066Sahrens 
334fa9e4066Sahrens 	if (*generation == spa_config_generation)
335fa9e4066Sahrens 		return (NULL);
336fa9e4066Sahrens 
337ea8dc4b6Seschrock 	VERIFY(nvlist_alloc(&pools, NV_UNIQUE_NAME, KM_SLEEP) == 0);
338fa9e4066Sahrens 
339fa9e4066Sahrens 	spa = NULL;
340fa9e4066Sahrens 	mutex_enter(&spa_namespace_lock);
341fa9e4066Sahrens 	while ((spa = spa_next(spa)) != NULL) {
342fa9e4066Sahrens 		if (INGLOBALZONE(curproc) ||
343fa9e4066Sahrens 		    zone_dataset_visible(spa_name(spa), NULL)) {
344fa9e4066Sahrens 			mutex_enter(&spa->spa_config_cache_lock);
345fa9e4066Sahrens 			VERIFY(nvlist_add_nvlist(pools, spa_name(spa),
346fa9e4066Sahrens 			    spa->spa_config) == 0);
347fa9e4066Sahrens 			mutex_exit(&spa->spa_config_cache_lock);
348fa9e4066Sahrens 		}
349fa9e4066Sahrens 	}
350fa9e4066Sahrens 	mutex_exit(&spa_namespace_lock);
351fa9e4066Sahrens 
352fa9e4066Sahrens 	*generation = spa_config_generation;
353fa9e4066Sahrens 
354fa9e4066Sahrens 	return (pools);
355fa9e4066Sahrens }
356fa9e4066Sahrens 
357fa9e4066Sahrens void
358fa9e4066Sahrens spa_config_set(spa_t *spa, nvlist_t *config)
359fa9e4066Sahrens {
360fa9e4066Sahrens 	mutex_enter(&spa->spa_config_cache_lock);
361fa9e4066Sahrens 	if (spa->spa_config != NULL)
362fa9e4066Sahrens 		nvlist_free(spa->spa_config);
363fa9e4066Sahrens 	spa->spa_config = config;
364fa9e4066Sahrens 	mutex_exit(&spa->spa_config_cache_lock);
365fa9e4066Sahrens }
366fa9e4066Sahrens 
367fa9e4066Sahrens /*
368fa9e4066Sahrens  * Generate the pool's configuration based on the current in-core state.
369fa9e4066Sahrens  * We infer whether to generate a complete config or just one top-level config
370fa9e4066Sahrens  * based on whether vd is the root vdev.
371fa9e4066Sahrens  */
372fa9e4066Sahrens nvlist_t *
373fa9e4066Sahrens spa_config_generate(spa_t *spa, vdev_t *vd, uint64_t txg, int getstats)
374fa9e4066Sahrens {
375fa9e4066Sahrens 	nvlist_t *config, *nvroot;
376fa9e4066Sahrens 	vdev_t *rvd = spa->spa_root_vdev;
37795173954Sek 	unsigned long hostid = 0;
378fa9e4066Sahrens 
37991ebeef5Sahrens 	ASSERT(spa_config_held(spa, RW_READER) ||
38091ebeef5Sahrens 	    spa_config_held(spa, RW_WRITER));
3810373e76bSbonwick 
382fa9e4066Sahrens 	if (vd == NULL)
383fa9e4066Sahrens 		vd = rvd;
384fa9e4066Sahrens 
385fa9e4066Sahrens 	/*
386fa9e4066Sahrens 	 * If txg is -1, report the current value of spa->spa_config_txg.
387fa9e4066Sahrens 	 */
388fa9e4066Sahrens 	if (txg == -1ULL)
389fa9e4066Sahrens 		txg = spa->spa_config_txg;
390fa9e4066Sahrens 
391ea8dc4b6Seschrock 	VERIFY(nvlist_alloc(&config, NV_UNIQUE_NAME, KM_SLEEP) == 0);
392fa9e4066Sahrens 
393fa9e4066Sahrens 	VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_VERSION,
39499653d4eSeschrock 	    spa_version(spa)) == 0);
395fa9e4066Sahrens 	VERIFY(nvlist_add_string(config, ZPOOL_CONFIG_POOL_NAME,
396fa9e4066Sahrens 	    spa_name(spa)) == 0);
397fa9e4066Sahrens 	VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_POOL_STATE,
398fa9e4066Sahrens 	    spa_state(spa)) == 0);
399fa9e4066Sahrens 	VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_POOL_TXG,
400fa9e4066Sahrens 	    txg) == 0);
401fa9e4066Sahrens 	VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_POOL_GUID,
402fa9e4066Sahrens 	    spa_guid(spa)) == 0);
40395173954Sek 	(void) ddi_strtoul(hw_serial, NULL, 10, &hostid);
40417194a52Slling 	if (hostid != 0) {
40517194a52Slling 		VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_HOSTID,
4068654d025Sperrin 		    hostid) == 0);
40717194a52Slling 	}
40895173954Sek 	VERIFY(nvlist_add_string(config, ZPOOL_CONFIG_HOSTNAME,
40995173954Sek 	    utsname.nodename) == 0);
410fa9e4066Sahrens 
411fa9e4066Sahrens 	if (vd != rvd) {
412fa9e4066Sahrens 		VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_TOP_GUID,
413fa9e4066Sahrens 		    vd->vdev_top->vdev_guid) == 0);
414fa9e4066Sahrens 		VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_GUID,
415fa9e4066Sahrens 		    vd->vdev_guid) == 0);
41699653d4eSeschrock 		if (vd->vdev_isspare)
41799653d4eSeschrock 			VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_IS_SPARE,
41899653d4eSeschrock 			    1ULL) == 0);
4198654d025Sperrin 		if (vd->vdev_islog)
4208654d025Sperrin 			VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_IS_LOG,
4218654d025Sperrin 			    1ULL) == 0);
422fa9e4066Sahrens 		vd = vd->vdev_top;		/* label contains top config */
423fa9e4066Sahrens 	}
424fa9e4066Sahrens 
425fa94a07fSbrendan 	nvroot = vdev_config_generate(spa, vd, getstats, B_FALSE, B_FALSE);
426fa9e4066Sahrens 	VERIFY(nvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, nvroot) == 0);
427fa9e4066Sahrens 	nvlist_free(nvroot);
428fa9e4066Sahrens 
429fa9e4066Sahrens 	return (config);
430fa9e4066Sahrens }
4310373e76bSbonwick 
4320373e76bSbonwick /*
433*e7cbe64fSgw  * For a pool that's not currently a booting rootpool, update all disk labels,
434*e7cbe64fSgw  * generate a fresh config based on the current in-core state, and sync the
435*e7cbe64fSgw  * global config cache.
4360373e76bSbonwick  */
4370373e76bSbonwick void
4380373e76bSbonwick spa_config_update(spa_t *spa, int what)
439*e7cbe64fSgw {
440*e7cbe64fSgw 	spa_config_update_common(spa, what, FALSE);
441*e7cbe64fSgw }
442*e7cbe64fSgw 
443*e7cbe64fSgw /*
444*e7cbe64fSgw  * Update all disk labels, generate a fresh config based on the current
445*e7cbe64fSgw  * in-core state, and sync the global config cache (do not sync the config
446*e7cbe64fSgw  * cache if this is a booting rootpool).
447*e7cbe64fSgw  */
448*e7cbe64fSgw void
449*e7cbe64fSgw spa_config_update_common(spa_t *spa, int what, boolean_t isroot)
4500373e76bSbonwick {
4510373e76bSbonwick 	vdev_t *rvd = spa->spa_root_vdev;
4520373e76bSbonwick 	uint64_t txg;
4530373e76bSbonwick 	int c;
4540373e76bSbonwick 
4550373e76bSbonwick 	ASSERT(MUTEX_HELD(&spa_namespace_lock));
4560373e76bSbonwick 
4570373e76bSbonwick 	spa_config_enter(spa, RW_WRITER, FTAG);
4580373e76bSbonwick 	txg = spa_last_synced_txg(spa) + 1;
4590373e76bSbonwick 	if (what == SPA_CONFIG_UPDATE_POOL) {
4600373e76bSbonwick 		vdev_config_dirty(rvd);
4610373e76bSbonwick 	} else {
4620373e76bSbonwick 		/*
4630373e76bSbonwick 		 * If we have top-level vdevs that were added but have
4640373e76bSbonwick 		 * not yet been prepared for allocation, do that now.
4650373e76bSbonwick 		 * (It's safe now because the config cache is up to date,
4660373e76bSbonwick 		 * so it will be able to translate the new DVAs.)
4670373e76bSbonwick 		 * See comments in spa_vdev_add() for full details.
4680373e76bSbonwick 		 */
4690373e76bSbonwick 		for (c = 0; c < rvd->vdev_children; c++) {
4700373e76bSbonwick 			vdev_t *tvd = rvd->vdev_child[c];
4710373e76bSbonwick 			if (tvd->vdev_ms_array == 0) {
4720373e76bSbonwick 				vdev_init(tvd, txg);
4730373e76bSbonwick 				vdev_config_dirty(tvd);
4740373e76bSbonwick 			}
4750373e76bSbonwick 		}
4760373e76bSbonwick 	}
4770373e76bSbonwick 	spa_config_exit(spa, FTAG);
4780373e76bSbonwick 
4790373e76bSbonwick 	/*
4800373e76bSbonwick 	 * Wait for the mosconfig to be regenerated and synced.
4810373e76bSbonwick 	 */
4820373e76bSbonwick 	txg_wait_synced(spa->spa_dsl_pool, txg);
4830373e76bSbonwick 
4840373e76bSbonwick 	/*
4850373e76bSbonwick 	 * Update the global config cache to reflect the new mosconfig.
4860373e76bSbonwick 	 */
487*e7cbe64fSgw 	if (!isroot)
488*e7cbe64fSgw 		spa_config_sync();
4890373e76bSbonwick 
4900373e76bSbonwick 	if (what == SPA_CONFIG_UPDATE_POOL)
491*e7cbe64fSgw 		spa_config_update_common(spa, SPA_CONFIG_UPDATE_VDEVS, isroot);
4920373e76bSbonwick }
493