libzfs_config.c revision ea8dc4b6d2251b437950c0056bc626b311c73c27
/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* The pool configuration repository is stored in /etc/zfs/zpool.cache as a
* single packed nvlist. While it would be nice to just read in this
* file from userland, this wouldn't work from a local zone. So we have to have
* a zpool ioctl to return the complete configuration for all pools. In the
* global zone, this will be identical to reading the file and unpacking it in
* userland.
*/
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <libintl.h>
#include <libuutil.h>
#include "libzfs_impl.h"
static uu_avl_t *namespace_avl;
static uint64_t namespace_generation;
typedef struct config_node {
char *cn_name;
/* ARGSUSED */
static int
config_node_compare(const void *a, const void *b, void *unused)
{
int ret;
if (ret < 0)
return (-1);
else if (ret > 0)
return (1);
else
return (0);
}
/*
* Loads the pool namespace, or re-loads it if the cache has changed.
*/
static void
{
if (namespace_generation == 0) {
/*
* This is the first time we've accessed the configuration
* cache. Initialize the AVL tree and then fall through to the
* common code.
*/
sizeof (config_node_t),
no_memory();
UU_DEFAULT)) == NULL)
no_memory();
}
/*
* Issue the ZFS_IOC_POOL_CONFIGS ioctl.
* This can fail for one of two reasons:
*
* EEXIST The generation counts match, nothing to do.
* ENOMEM The zc_config_dst buffer isn't large enough to
* hold the config; zc_config_dst_size will have
* been modified to tell us how much to allocate.
*/
for (;;) {
switch (errno) {
case EEXIST:
/*
* The namespace hasn't changed.
*/
return;
case ENOMEM:
break;
default:
}
} else {
break;
}
}
/*
* Clear out any existing configuration information.
*/
no_memory();
}
}
}
/*
* Retrive the configuration for the given pool. The configuration is a nvlist
* describing the vdevs, as well as the statistics associated with each one.
*/
nvlist_t *
{
if (oldconfig)
return (zhp->zpool_config);
}
/*
* Refresh the vdev statistics associated with the given pool. This is used in
* iostat to show configuration changes and determine the delta from the last
* time the function was called. This function can fail, in case the pool has
* been destroyed.
*/
int
{
int error;
if (zhp->zpool_config_size == 0)
for (;;) {
/*
* The real error is returned in the zc_cookie field.
*/
break;
}
} else {
return (errno);
}
}
ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0);
ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0);
} else {
}
}
return (error);
}
/*
* Iterate over all pools in the system.
*/
int
{
int ret;
continue;
return (ret);
}
return (0);
}
/*
* Iterate over root datasets, calling the given function for each. The zfs
* handle passed each time must be explicitly closed by the callback.
*/
int
{
int ret;
continue;
return (ret);
}
return (0);
}