spa_config.c revision 2f8aaab38e6371ad39ed90a1211ba8921acbb4d5
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/spa_impl.h>
#include <sys/vdev_impl.h>
#include <sys/zfs_ioctl.h>
#include <sys/systeminfo.h>
#ifdef _KERNEL
#endif
/*
* Pool configuration repository.
*
* Pool configuration is stored as a packed nvlist on the filesystem. By
* default, all pools are stored in /etc/zfs/zpool.cache and loaded on boot
* (when the ZFS module is loaded). Pools can also have the 'cachefile'
* property set that allows them to be stored in an alternate location until
* the control of external software.
*
* For each cache file, we have a single nvlist which holds all the
* configuration information. When the module loads, we read this information
* from /etc/zfs/zpool.cache and populate the SPA namespace. This namespace is
* maintained independently in spa.c. Whenever the namespace is modified, or
* the configuration of a pool is changed, we call spa_config_sync(), which
* walks through all the active pools and writes the configuration to disk.
*/
/*
* This can be overridden in userland to preserve an alternate namespace for
* userland pools when doing testing.
*/
const char *spa_config_dir = ZPOOL_CACHE_DIR;
/*
* Called when the module is first loaded, this routine loads the configuration
* file into the SPA namespace. It does not actually open or load the pools; it
* only populates the namespace.
*/
void
spa_config_load(void)
{
char pathname[128];
/*
* Open the configuration file.
*/
return;
goto out;
/*
* Read the nvlist from the file.
*/
goto out;
/*
* Unpack the nvlist.
*/
goto out;
/*
* Iterate over all elements in the nvlist, creating a new spa_t for
* each one with the specified configuration.
*/
continue;
continue;
/*
* We blindly duplicate the configuration here. If it's
* invalid, we will catch it when the pool is first opened.
*/
}
out:
}
/*
* This function is called when destroying or exporting a pool. It walks the
* list of active pools, and searches for any that match the given cache file.
* If there is only one cachefile, then the file is removed immediately,
* because we won't see the pool when iterating in spa_config_sync().
*/
void
{
char pathname[128];
return;
count++;
} else {
if (spa->spa_config_dir &&
count++;
}
}
if (count == 1) {
}
}
}
typedef struct spa_config_entry {
const char *sc_dir;
const char *sc_file;
static void
{
return;
}
if (spa->spa_config_dir) {
} else {
}
return;
}
break;
}
KM_SLEEP) == 0);
}
spa->spa_config) == 0);
}
static void
{
char *buf;
char pathname[128];
char pathname2[128];
/*
* Pack the configuration into a buffer.
*/
KM_SLEEP) == 0);
/*
* Write the configuration to disk. We need to do the traditional
* 'write to temporary file, sync, move over original' to make sure we
* always have a consistent view of the data.
*/
goto out;
}
out:
}
/*
* Synchronize all pools to disk. This must be called with the namespace lock
* held.
*/
void
spa_config_sync(void)
{
/*
* Add all known pools to the configuration list, ignoring those with
* alternate root paths.
*/
}
}
/*
* Sigh. Inside a local zone, we don't have access to /etc/zfs/zpool.cache,
* and we don't want to allow the local zone to see all the pools anyway.
* So we have to invent the ZFS_IOC_CONFIG ioctl to grab the configuration
* information for all pool visible within the zone.
*/
nvlist_t *
{
if (*generation == spa_config_generation)
return (NULL);
if (INGLOBALZONE(curproc) ||
spa->spa_config) == 0);
}
}
return (pools);
}
void
{
}
/*
* 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 *
{
unsigned long hostid = 0;
/*
* If txg is -1, report the current value of spa->spa_config_txg.
*/
if (txg == -1ULL)
spa_version(spa)) == 0);
txg) == 0);
if (hostid != 0) {
hostid) == 0);
}
if (vd->vdev_isspare)
1ULL) == 0);
if (vd->vdev_islog)
1ULL) == 0);
}
return (config);
}
/*
* Update all disk labels, generate a fresh config based on the current
* in-core state, and sync the global config cache.
*/
void
{
int c;
if (what == SPA_CONFIG_UPDATE_POOL) {
} else {
/*
* If we have top-level vdevs that were added but have
* not yet been prepared for allocation, do that now.
* (It's safe now because the config cache is up to date,
* so it will be able to translate the new DVAs.)
* See comments in spa_vdev_add() for full details.
*/
for (c = 0; c < rvd->vdev_children; c++) {
if (tvd->vdev_ms_array == 0) {
}
}
}
/*
* Wait for the mosconfig to be regenerated and synced.
*/
/*
* Update the global config cache to reflect the new mosconfig.
*/
if (what == SPA_CONFIG_UPDATE_POOL)
}