FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c
/*
 * Generate the pool's configuration based on the current in-core state.
 *
 * We infer whether to generate a complete config or just one top-level config
 * based on whether vd is the root vdev.
 */
Generate the pool's configuration based on the current in-core state.
We infer whether to generate a complete config or just one top-level config
based on whether vd is the root vdev.
Generate the pool ' s configuration based on the current in - core state . We infer whether to generate a complete config or just one top - level config based on whether vd is the root vdev .
nvlist_t *
spa_config_generate(spa_t *spa, vdev_t *vd, uint64_t txg, int getstats)
{
	nvlist_t *config, *nvroot;
	vdev_t *rvd = spa->spa_root_vdev;
	unsigned long hostid = 0;
	boolean_t locked = B_FALSE;
	uint64_t split_guid;
	if (vd == NULL) {
		vd = rvd;
		locked = B_TRUE;
		spa_config_enter(spa, SCL_CONFIG | SCL_STATE, FTAG, RW_READER);
	}
	ASSERT(spa_config_held(spa, SCL_CONFIG | SCL_STATE, RW_READER) ==
	    (SCL_CONFIG | SCL_STATE));
	if (txg == -1ULL)
		txg = spa->spa_config_txg;
	config = fnvlist_alloc();
	fnvlist_add_uint64(config, ZPOOL_CONFIG_VERSION, spa_version(spa));
	fnvlist_add_string(config, ZPOOL_CONFIG_POOL_NAME, spa_name(spa));
	fnvlist_add_uint64(config, ZPOOL_CONFIG_POOL_STATE, spa_state(spa));
	fnvlist_add_uint64(config, ZPOOL_CONFIG_POOL_TXG, txg);
	fnvlist_add_uint64(config, ZPOOL_CONFIG_POOL_GUID, spa_guid(spa));
	if (spa->spa_comment != NULL) {
		fnvlist_add_string(config, ZPOOL_CONFIG_COMMENT,
		    spa->spa_comment);
	}
#ifdef	_KERNEL
	hostid = zone_get_hostid(NULL);
#else	
	(void) ddi_strtoul(hw_serial, NULL, 10, &hostid);
#endif	
	if (hostid != 0) {
		fnvlist_add_uint64(config, ZPOOL_CONFIG_HOSTID, hostid);
	}
	fnvlist_add_string(config, ZPOOL_CONFIG_HOSTNAME, utsname.nodename);
	int config_gen_flags = 0;
	if (vd != rvd) {
		fnvlist_add_uint64(config, ZPOOL_CONFIG_TOP_GUID,
		    vd->vdev_top->vdev_guid);
		fnvlist_add_uint64(config, ZPOOL_CONFIG_GUID,
		    vd->vdev_guid);
		if (vd->vdev_isspare) {
			fnvlist_add_uint64(config,
			    ZPOOL_CONFIG_IS_SPARE, 1ULL);
		}
		if (vd->vdev_islog) {
			fnvlist_add_uint64(config,
			    ZPOOL_CONFIG_IS_LOG, 1ULL);
		}
		vd = vd->vdev_top;		
	} else {
		if (spa->spa_config_splitting != NULL)
			fnvlist_add_nvlist(config, ZPOOL_CONFIG_SPLIT,
			    spa->spa_config_splitting);
		fnvlist_add_boolean(config,
		    ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS);
		config_gen_flags |= VDEV_CONFIG_MOS;
	}
	vdev_top_config_generate(spa, config);
	if (spa->spa_config_splitting != NULL &&
	    nvlist_lookup_uint64(spa->spa_config_splitting,
	    ZPOOL_CONFIG_SPLIT_GUID, &split_guid) == 0) {
		fnvlist_add_uint64(config, ZPOOL_CONFIG_SPLIT_GUID,
		    split_guid);
	}
	nvroot = vdev_config_generate(spa, vd, getstats, config_gen_flags);
	fnvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, nvroot);
	nvlist_free(nvroot);
	fnvlist_add_nvlist(config, ZPOOL_CONFIG_FEATURES_FOR_READ,
	    spa->spa_label_features);
	if (getstats && spa_load_state(spa) == SPA_LOAD_NONE) {
		ddt_histogram_t *ddh;
		ddt_stat_t *dds;
		ddt_object_t *ddo;
		ddh = kmem_zalloc(sizeof (ddt_histogram_t), KM_SLEEP);
		ddt_get_dedup_histogram(spa, ddh);
		fnvlist_add_uint64_array(config,
		    ZPOOL_CONFIG_DDT_HISTOGRAM,
		    (uint64_t *)ddh, sizeof (*ddh) / sizeof (uint64_t));
		kmem_free(ddh, sizeof (ddt_histogram_t));
		ddo = kmem_zalloc(sizeof (ddt_object_t), KM_SLEEP);
		ddt_get_dedup_object_stats(spa, ddo);
		fnvlist_add_uint64_array(config,
		    ZPOOL_CONFIG_DDT_OBJ_STATS,
		    (uint64_t *)ddo, sizeof (*ddo) / sizeof (uint64_t));
		kmem_free(ddo, sizeof (ddt_object_t));
		dds = kmem_zalloc(sizeof (ddt_stat_t), KM_SLEEP);
		ddt_get_dedup_stats(spa, dds);
		fnvlist_add_uint64_array(config,
		    ZPOOL_CONFIG_DDT_STATS,
		    (uint64_t *)dds, sizeof (*dds) / sizeof (uint64_t));
		kmem_free(dds, sizeof (ddt_stat_t));
	}
	if (locked)
		spa_config_exit(spa, SCL_CONFIG | SCL_STATE, FTAG);
	return (config);
}
nvlist_t * spa_config_generate ( spa_t * spa , vdev_t * vd , uint64_t txg , int getstats ) { nvlist_t * config , * nvroot ; vdev_t * rvd = spa -> spa_root_vdev ; unsigned long hostid = 0 ; boolean_t locked = B_FALSE ; uint64_t split_guid ; if ( vd == NULL ) { vd = rvd ; locked = B_TRUE ; spa_config_enter ( spa , SCL_CONFIG | SCL_STATE , FTAG , RW_READER ) ; } ASSERT ( spa_config_held ( spa , SCL_CONFIG | SCL_STATE , RW_READER ) == ( SCL_CONFIG | SCL_STATE ) ) ; if ( txg == -1ULL ) txg = spa -> spa_config_txg ; config = fnvlist_alloc ( ) ; fnvlist_add_uint64 ( config , ZPOOL_CONFIG_VERSION , spa_version ( spa ) ) ; fnvlist_add_string ( config , ZPOOL_CONFIG_POOL_NAME , spa_name ( spa ) ) ; fnvlist_add_uint64 ( config , ZPOOL_CONFIG_POOL_STATE , spa_state ( spa ) ) ; fnvlist_add_uint64 ( config , ZPOOL_CONFIG_POOL_TXG , txg ) ; fnvlist_add_uint64 ( config , ZPOOL_CONFIG_POOL_GUID , spa_guid ( spa ) ) ; if ( spa -> spa_comment != NULL ) { fnvlist_add_string ( config , ZPOOL_CONFIG_COMMENT , spa -> spa_comment ) ; } #ifdef _KERNEL hostid = zone_get_hostid ( NULL ) ; #else ( void ) ddi_strtoul ( hw_serial , NULL , 10 , & hostid ) ; #endif if ( hostid != 0 ) { fnvlist_add_uint64 ( config , ZPOOL_CONFIG_HOSTID , hostid ) ; } fnvlist_add_string ( config , ZPOOL_CONFIG_HOSTNAME , utsname . nodename ) ; int config_gen_flags = 0 ; if ( vd != rvd ) { fnvlist_add_uint64 ( config , ZPOOL_CONFIG_TOP_GUID , vd -> vdev_top -> vdev_guid ) ; fnvlist_add_uint64 ( config , ZPOOL_CONFIG_GUID , vd -> vdev_guid ) ; if ( vd -> vdev_isspare ) { fnvlist_add_uint64 ( config , ZPOOL_CONFIG_IS_SPARE , 1ULL ) ; } if ( vd -> vdev_islog ) { fnvlist_add_uint64 ( config , ZPOOL_CONFIG_IS_LOG , 1ULL ) ; } vd = vd -> vdev_top ; } else { if ( spa -> spa_config_splitting != NULL ) fnvlist_add_nvlist ( config , ZPOOL_CONFIG_SPLIT , spa -> spa_config_splitting ) ; fnvlist_add_boolean ( config , ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS ) ; config_gen_flags |= VDEV_CONFIG_MOS ; } vdev_top_config_generate ( spa , config ) ; if ( spa -> spa_config_splitting != NULL && nvlist_lookup_uint64 ( spa -> spa_config_splitting , ZPOOL_CONFIG_SPLIT_GUID , & split_guid ) == 0 ) { fnvlist_add_uint64 ( config , ZPOOL_CONFIG_SPLIT_GUID , split_guid ) ; } nvroot = vdev_config_generate ( spa , vd , getstats , config_gen_flags ) ; fnvlist_add_nvlist ( config , ZPOOL_CONFIG_VDEV_TREE , nvroot ) ; nvlist_free ( nvroot ) ; fnvlist_add_nvlist ( config , ZPOOL_CONFIG_FEATURES_FOR_READ , spa -> spa_label_features ) ; if ( getstats && spa_load_state ( spa ) == SPA_LOAD_NONE ) { ddt_histogram_t * ddh ; ddt_stat_t * dds ; ddt_object_t * ddo ; ddh = kmem_zalloc ( sizeof ( ddt_histogram_t ) , KM_SLEEP ) ; ddt_get_dedup_histogram ( spa , ddh ) ; fnvlist_add_uint64_array ( config , ZPOOL_CONFIG_DDT_HISTOGRAM , ( uint64_t * ) ddh , sizeof ( * ddh ) / sizeof ( uint64_t ) ) ; kmem_free ( ddh , sizeof ( ddt_histogram_t ) ) ; ddo = kmem_zalloc ( sizeof ( ddt_object_t ) , KM_SLEEP ) ; ddt_get_dedup_object_stats ( spa , ddo ) ; fnvlist_add_uint64_array ( config , ZPOOL_CONFIG_DDT_OBJ_STATS , ( uint64_t * ) ddo , sizeof ( * ddo ) / sizeof ( uint64_t ) ) ; kmem_free ( ddo , sizeof ( ddt_object_t ) ) ; dds = kmem_zalloc ( sizeof ( ddt_stat_t ) , KM_SLEEP ) ; ddt_get_dedup_stats ( spa , dds ) ; fnvlist_add_uint64_array ( config , ZPOOL_CONFIG_DDT_STATS , ( uint64_t * ) dds , sizeof ( * dds ) / sizeof ( uint64_t ) ) ; kmem_free ( dds , sizeof ( ddt_stat_t ) ) ; } if ( locked ) spa_config_exit ( spa , SCL_CONFIG | SCL_STATE , FTAG ) ; return ( config ) ; }
Generate the pool's configuration based on the current in-core state.
Generate the pool ' s configuration based on the current in - core state .
/*
	 * If txg is -1, report the current value of spa->spa_config_txg.
	 */ /* _KERNEL */ /*
	 * We're emulating the system's hostid in userland, so we can't use
	 * zone_get_hostid().
	 */ /* _KERNEL */ /* label contains top config */ /*
		 * Only add the (potentially large) split information
		 * in the mos config, and not in the vdev labels
		 */ /*
	 * Add the top-level config.  We even add this on pools which
	 * don't support holes in the namespace.
	 */ /*
	 * If we're splitting, record the original pool's guid.
	 */ /*
	 * Store what's necessary for reading the MOS in the label.
	 */