FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c
/*
 * Synchronize pool configuration to disk.  This must be called with the
 * namespace lock held. Synchronizing the pool cache is typically done after
 * the configuration has been synced to the MOS. This exposes a window where
 * the MOS config will have been updated but the cache file has not. If
 * the system were to crash at that instant then the cached config may not
 * contain the correct information to open the pool and an explicity import
 * would be required.
 */
Synchronize pool configuration to disk.  This must be called with the
namespace lock held. Synchronizing the pool cache is typically done after
the configuration has been synced to the MOS. This exposes a window where
the MOS config will have been updated but the cache file has not. If
the system were to crash at that instant then the cached config may not
contain the correct information to open the pool and an explicity import
would be required.
Synchronize pool configuration to disk . This must be called with the namespace lock held . Synchronizing the pool cache is typically done after the configuration has been synced to the MOS . This exposes a window where the MOS config will have been updated but the cache file has not . If the system were to crash at that instant then the cached config may not contain the correct information to open the pool and an explicity import would be required .
void
spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
{
	spa_config_dirent_t *dp, *tdp;
	nvlist_t *nvl;
	boolean_t ccw_failure;
	int error;
	ASSERT(MUTEX_HELD(&spa_namespace_lock));
	if (rootdir == NULL || !(spa_mode_global & FWRITE))
		return;
	ccw_failure = B_FALSE;
	for (dp = list_head(&target->spa_config_list); dp != NULL;
	    dp = list_next(&target->spa_config_list, dp)) {
		spa_t *spa = NULL;
		if (dp->scd_path == NULL)
			continue;
		nvl = NULL;
		while ((spa = spa_next(spa)) != NULL) {
			nvlist_t *nvroot = NULL;
			if ((spa == target && removing) ||
			    (spa_state(spa) == POOL_STATE_ACTIVE &&
			    !spa_writeable(spa)))
				continue;
			mutex_enter(&spa->spa_props_lock);
			tdp = list_head(&spa->spa_config_list);
			if (spa->spa_config == NULL ||
			    tdp->scd_path == NULL ||
			    strcmp(tdp->scd_path, dp->scd_path) != 0) {
				mutex_exit(&spa->spa_props_lock);
				continue;
			}
			if (nvl == NULL)
				nvl = fnvlist_alloc();
			fnvlist_add_nvlist(nvl, spa->spa_name,
			    spa->spa_config);
			mutex_exit(&spa->spa_props_lock);
			if (nvlist_lookup_nvlist(nvl, spa->spa_name, &nvroot) == 0)
				spa_config_clean(nvroot);
		}
		error = spa_config_write(dp, nvl);
		if (error != 0)
			ccw_failure = B_TRUE;
		nvlist_free(nvl);
	}
	if (ccw_failure) {
		if (target->spa_ccw_fail_time == 0) {
			zfs_ereport_post(FM_EREPORT_ZFS_CONFIG_CACHE_WRITE,
			    target, NULL, NULL, 0, 0);
		}
		target->spa_ccw_fail_time = gethrtime();
		spa_async_request(target, SPA_ASYNC_CONFIG_UPDATE);
	} else {
		target->spa_ccw_fail_time = 0;
	}
	dp = list_head(&target->spa_config_list);
	while ((tdp = list_next(&target->spa_config_list, dp)) != NULL) {
		list_remove(&target->spa_config_list, tdp);
		if (tdp->scd_path != NULL)
			spa_strfree(tdp->scd_path);
		kmem_free(tdp, sizeof (spa_config_dirent_t));
	}
	spa_config_generation++;
	if (postsysevent)
		spa_event_notify(target, NULL, ESC_ZFS_CONFIG_SYNC);
}
void spa_config_sync ( spa_t * target , boolean_t removing , boolean_t postsysevent ) { spa_config_dirent_t * dp , * tdp ; nvlist_t * nvl ; boolean_t ccw_failure ; int error ; ASSERT ( MUTEX_HELD ( & spa_namespace_lock ) ) ; if ( rootdir == NULL || ! ( spa_mode_global & FWRITE ) ) return ; ccw_failure = B_FALSE ; for ( dp = list_head ( & target -> spa_config_list ) ; dp != NULL ; dp = list_next ( & target -> spa_config_list , dp ) ) { spa_t * spa = NULL ; if ( dp -> scd_path == NULL ) continue ; nvl = NULL ; while ( ( spa = spa_next ( spa ) ) != NULL ) { nvlist_t * nvroot = NULL ; if ( ( spa == target && removing ) || ( spa_state ( spa ) == POOL_STATE_ACTIVE && ! spa_writeable ( spa ) ) ) continue ; mutex_enter ( & spa -> spa_props_lock ) ; tdp = list_head ( & spa -> spa_config_list ) ; if ( spa -> spa_config == NULL || tdp -> scd_path == NULL || strcmp ( tdp -> scd_path , dp -> scd_path ) != 0 ) { mutex_exit ( & spa -> spa_props_lock ) ; continue ; } if ( nvl == NULL ) nvl = fnvlist_alloc ( ) ; fnvlist_add_nvlist ( nvl , spa -> spa_name , spa -> spa_config ) ; mutex_exit ( & spa -> spa_props_lock ) ; if ( nvlist_lookup_nvlist ( nvl , spa -> spa_name , & nvroot ) == 0 ) spa_config_clean ( nvroot ) ; } error = spa_config_write ( dp , nvl ) ; if ( error != 0 ) ccw_failure = B_TRUE ; nvlist_free ( nvl ) ; } if ( ccw_failure ) { if ( target -> spa_ccw_fail_time == 0 ) { zfs_ereport_post ( FM_EREPORT_ZFS_CONFIG_CACHE_WRITE , target , NULL , NULL , 0 , 0 ) ; } target -> spa_ccw_fail_time = gethrtime ( ) ; spa_async_request ( target , SPA_ASYNC_CONFIG_UPDATE ) ; } else { target -> spa_ccw_fail_time = 0 ; } dp = list_head ( & target -> spa_config_list ) ; while ( ( tdp = list_next ( & target -> spa_config_list , dp ) ) != NULL ) { list_remove ( & target -> spa_config_list , tdp ) ; if ( tdp -> scd_path != NULL ) spa_strfree ( tdp -> scd_path ) ; kmem_free ( tdp , sizeof ( spa_config_dirent_t ) ) ; } spa_config_generation ++ ; if ( postsysevent ) spa_event_notify ( target , NULL , ESC_ZFS_CONFIG_SYNC ) ; }
Synchronize pool configuration to disk.
Synchronize pool configuration to disk .
/*
	 * Iterate over all cachefiles for the pool, past or present.  When the
	 * cachefile is changed, the new one is pushed onto this list, allowing
	 * us to update previous cachefiles that no longer contain this pool.
	 */ /*
		 * Iterate over all pools, adding any matching pools to 'nvl'.
		 */ /*
			 * Skip over our own pool if we're about to remove
			 * ourselves from the spa namespace or any pool that
			 * is readonly. Since we cannot guarantee that a
			 * readonly pool would successfully import upon reboot,
			 * we don't allow them to be written to the cache file.
			 */ /*
		 * Keep trying so that configuration data is
		 * written if/when any temporary filesystem
		 * resource issues are resolved.
		 */ /*
		 * Do not rate limit future attempts to update
		 * the config cache.
		 */ /*
	 * Remove any config entries older than the current one.
	 */