usr/src/lib/libzfs/common/libzfs_import.c
author ahrens
Mon, 31 Oct 2005 11:33:35 -0800
changeset 789 b348f31ed315
child 952 12ec54aa046e
permissions -rw-r--r--
PSARC 2002/240 ZFS 6338653 Integrate ZFS PSARC 2004/652 - DKIOCFLUSH 5096886 Write caching disks need mechanism to flush cache to physical media
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     1
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     2
 * CDDL HEADER START
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     3
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 * with the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    22
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
 * Pool import support functions.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
 * To import a pool, we rely on reading the configuration information from the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
 * ZFS label of each device.  If we successfully read the label, then we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
 * organize the configuration information in the following hierarchy:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    35
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
 * 	pool guid -> toplevel vdev guid -> label txg
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
 * Duplicate entries matching this same tuple will be discarded.  Once we have
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
 * examined every device, we pick the best label txg config for each toplevel
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
 * vdev.  We then arrange these toplevel vdevs into a complete pool config, and
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
 * update any paths that have changed.  Finally, we attempt to import the pool
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
 * using our derived config, and record the results.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
#include <devid.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
#include <dirent.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
#include <errno.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
#include <libintl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
#include <stdlib.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
#include <string.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
#include <sys/stat.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
#include <unistd.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
#include <fcntl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
#include <sys/vdev_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
#include "libzfs.h"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
#include "libzfs_impl.h"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
 * Intermediate structures used to gather configuration information.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
typedef struct config_entry {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
	uint64_t		ce_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
	nvlist_t		*ce_config;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
	struct config_entry	*ce_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
} config_entry_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
typedef struct vdev_entry {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
	uint64_t		ve_guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
	config_entry_t		*ve_configs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
	struct vdev_entry	*ve_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
} vdev_entry_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
typedef struct pool_entry {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
	uint64_t		pe_guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
	vdev_entry_t		*pe_vdevs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
	struct pool_entry	*pe_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
} pool_entry_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    80
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
typedef struct name_entry {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
	const char		*ne_name;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
	uint64_t		ne_guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
	struct name_entry	*ne_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
} name_entry_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
typedef struct pool_list {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
	pool_entry_t		*pools;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    89
	name_entry_t		*names;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    90
} pool_list_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
static char *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
get_devid(const char *path)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
	int fd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
	ddi_devid_t devid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
	char *minor, *ret;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
	if ((fd = open(path, O_RDONLY)) < 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
	minor = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
	ret = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
	if (devid_get(fd, &devid) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
		if (devid_get_minor_name(fd, &minor) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   106
			ret = devid_str_encode(devid, minor);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
		if (minor != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
			devid_str_free(minor);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
		devid_free(devid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
	return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   116
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   117
 * Go through and fix up any path and/or devid information for the given vdev
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   118
 * configuration.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   119
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   120
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   121
fix_paths(nvlist_t *nv, name_entry_t *names)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   122
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   123
	nvlist_t **child;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   124
	uint_t c, children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   125
	uint64_t guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
	name_entry_t *ne;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   127
	char *devid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   128
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   129
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   130
	    &child, &children) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   131
		for (c = 0; c < children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   132
			fix_paths(child[c], names);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   133
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
	 * This is a leaf (file or disk) vdev.  In either case, go through
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
	 * the name list and see if we find a matching guid.  If so, replace
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   139
	 * the path and see if we can calculate a new devid.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   140
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   141
	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   142
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   143
	for (ne = names; ne != NULL; ne = ne->ne_next)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   144
		if (ne->ne_guid == guid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
	if (ne == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
	verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, ne->ne_name) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
	if ((devid = get_devid(ne->ne_name)) == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
		(void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
		verify(nvlist_add_string(nv, ZPOOL_CONFIG_DEVID, devid) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
		devid_str_free(devid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   157
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   158
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   160
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   161
 * Add the given configuration to the list of known devices.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   162
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   163
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   164
add_config(pool_list_t *pl, const char *path, nvlist_t *config)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   165
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   166
	uint64_t pool_guid, vdev_guid, top_guid, txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   167
	pool_entry_t *pe;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   168
	vdev_entry_t *ve;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   169
	config_entry_t *ce;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   170
	name_entry_t *ne;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   171
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   172
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
	 * If we have a valid config but cannot read any of these fields, then
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
	 * it means we have a half-initialized label.  In vdev_label_init()
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   175
	 * we write a label with txg == 0 so that we can identify the device
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
	 * in case the user refers to the same disk later on.  If we fail to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
	 * create the pool, we'll be left with a label in this state
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
	 * which should not be considered part of a valid pool.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
	if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
	    &pool_guid) != 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
	    &vdev_guid) != 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   184
	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_TOP_GUID,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
	    &top_guid) != 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
	    &txg) != 0 || txg == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
		nvlist_free(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   192
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
	 * First, see if we know about this pool.  If not, then add it to the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
	 * list of known pools.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
	for (pe = pl->pools; pe != NULL; pe = pe->pe_next) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
		if (pe->pe_guid == pool_guid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
	if (pe == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
		pe = zfs_malloc(sizeof (pool_entry_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
		pe->pe_guid = pool_guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
		pe->pe_next = pl->pools;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
		pl->pools = pe;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
	 * Second, see if we know about this toplevel vdev.  Add it if its
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
	 * missing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
	for (ve = pe->pe_vdevs; ve != NULL; ve = ve->ve_next) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
		if (ve->ve_guid == top_guid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
	if (ve == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
		ve = zfs_malloc(sizeof (vdev_entry_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
		ve->ve_guid = top_guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
		ve->ve_next = pe->pe_vdevs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
		pe->pe_vdevs = ve;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
	 * Third, see if we have a config with a matching transaction group.  If
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
	 * so, then we do nothing.  Otherwise, add it to the list of known
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
	 * configs.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
	for (ce = ve->ve_configs; ce != NULL; ce = ce->ce_next) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
		if (ce->ce_txg == txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
	if (ce == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
		ce = zfs_malloc(sizeof (config_entry_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
		ce->ce_txg = txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
		ce->ce_config = config;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
		ce->ce_next = ve->ve_configs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
		ve->ve_configs = ce;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   240
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
		nvlist_free(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
	 * At this point we've successfully added our config to the list of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
	 * known configs.  The last thing to do is add the vdev guid -> path
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
	 * mappings so that we can fix up the configuration as necessary before
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
	 * doing the import.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
	ne = zfs_malloc(sizeof (name_entry_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
	ne->ne_name = zfs_strdup(path);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
	ne->ne_guid = vdev_guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   254
	ne->ne_next = pl->names;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
	pl->names = ne;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   259
 * Convert our list of pools into the definitive set of configurations.  We
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
 * start by picking the best config for each toplevel vdev.  Once that's done,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
 * we assemble the toplevel vdevs into a full config for the pool.  We make a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
 * pass to fix up any incorrect paths, and then add it to the main list to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
 * return to the user.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
static nvlist_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
get_configs(pool_list_t *pl)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
	pool_entry_t *pe, *penext;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
	vdev_entry_t *ve, *venext;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
	config_entry_t *ce, *cenext;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
	nvlist_t *ret, *config, *tmp, *nvtop, *nvroot;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
	int config_seen;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   273
	uint64_t best_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
	char *name;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
	zfs_cmd_t zc = { 0 };
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
	uint64_t guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
	char *packed;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   278
	size_t len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
	verify(nvlist_alloc(&ret, 0, 0) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
	for (pe = pl->pools; pe != NULL; pe = penext) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
		uint_t c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
		uint_t children = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
		uint64_t id;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
		nvlist_t **child = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
		penext = pe->pe_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
		verify(nvlist_alloc(&config, NV_UNIQUE_NAME, 0) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
		config_seen = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   294
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
		 * Iterate over all toplevel vdevs.  Grab the pool configuration
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   296
		 * from the first one we find, and then go through the rest and
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   297
		 * add them as necessary to the 'vdevs' member of the config.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   298
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   299
		for (ve = pe->pe_vdevs; ve != NULL; ve = venext) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
			venext = ve->ve_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   302
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   303
			 * Determine the best configuration for this vdev by
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   304
			 * selecting the config with the latest transaction
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   305
			 * group.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   306
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   307
			best_txg = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
			for (ce = ve->ve_configs; ce != NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
			    ce = ce->ce_next) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   310
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   311
				if (ce->ce_txg > best_txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   312
					tmp = ce->ce_config;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   313
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   314
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   315
			if (!config_seen) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   316
				/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   317
				 * Copy the relevant pieces of data to the pool
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
				 * configuration:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
				 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   320
				 * 	pool guid
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   321
				 * 	name
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   322
				 * 	pool state
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   323
				 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
				uint64_t state;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   325
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   326
				verify(nvlist_lookup_uint64(tmp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   327
				    ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   328
				verify(nvlist_add_uint64(config,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   329
				    ZPOOL_CONFIG_POOL_GUID, guid) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   330
				verify(nvlist_lookup_string(tmp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   331
				    ZPOOL_CONFIG_POOL_NAME, &name) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   332
				verify(nvlist_add_string(config,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   333
				    ZPOOL_CONFIG_POOL_NAME, name) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   334
				verify(nvlist_lookup_uint64(tmp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   335
				    ZPOOL_CONFIG_POOL_STATE, &state) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   336
				verify(nvlist_add_uint64(config,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   337
				    ZPOOL_CONFIG_POOL_STATE, state) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   338
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   339
				config_seen = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   340
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   341
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   342
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   343
			 * Add this top-level vdev to the child array.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   344
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   345
			verify(nvlist_lookup_nvlist(tmp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   346
			    ZPOOL_CONFIG_VDEV_TREE, &nvtop) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   347
			verify(nvlist_lookup_uint64(nvtop, ZPOOL_CONFIG_ID,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   348
			    &id) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   349
			if (id >= children) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   350
				nvlist_t **newchild;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   351
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   352
				newchild = zfs_malloc((id + 1) *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   353
				    sizeof (nvlist_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   354
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   355
				for (c = 0; c < children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   356
					newchild[c] = child[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   357
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   358
				free(child);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   359
				child = newchild;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   360
				children = id + 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   361
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   362
			verify(nvlist_dup(nvtop, &child[id], 0) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   363
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   364
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   365
			 * Go through and free all config information.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   367
			for (ce = ve->ve_configs; ce != NULL; ce = cenext) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   368
				cenext = ce->ce_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   369
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   370
				nvlist_free(ce->ce_config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   371
				free(ce);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   372
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   373
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   374
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   375
			 * Free this vdev entry, since it has now been merged
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   376
			 * into the main config.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   377
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   378
			free(ve);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   379
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   380
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   381
		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   382
		    &guid) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   383
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   384
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   385
		 * Look for any missing top-level vdevs.  If this is the case,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   386
		 * create a faked up 'missing' vdev as a placeholder.  We cannot
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   387
		 * simply compress the child array, because the kernel performs
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   388
		 * certain checks to make sure the vdev IDs match their location
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   389
		 * in the configuration.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   390
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   391
		for (c = 0; c < children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   392
			if (child[c] == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   393
				nvlist_t *missing;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   394
				verify(nvlist_alloc(&missing, NV_UNIQUE_NAME,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   395
				    0) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   396
				verify(nvlist_add_string(missing,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
				    ZPOOL_CONFIG_TYPE, VDEV_TYPE_MISSING) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   398
				verify(nvlist_add_uint64(missing,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   399
				    ZPOOL_CONFIG_ID, c) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   400
				verify(nvlist_add_uint64(missing,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   401
				    ZPOOL_CONFIG_GUID, 0ULL) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   402
				child[c] = missing;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   403
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   404
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   405
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   406
		 * Put all of this pool's top-level vdevs into a root vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   408
		verify(nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   409
		verify(nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
		    VDEV_TYPE_ROOT) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   411
		verify(nvlist_add_uint64(nvroot, ZPOOL_CONFIG_ID, 0ULL) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   412
		verify(nvlist_add_uint64(nvroot, ZPOOL_CONFIG_GUID, guid) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   413
		verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   414
		    child, children) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   415
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   416
		for (c = 0; c < children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   417
			nvlist_free(child[c]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   418
		free(child);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   419
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   420
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   421
		 * Go through and fix up any paths and/or devids based on our
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   422
		 * known list of vdev GUID -> path mappings.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   423
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   424
		fix_paths(nvroot, pl->names);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   425
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   426
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   427
		 * Add the root vdev to this pool's configuration.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   428
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   429
		verify(nvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   430
		    nvroot) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   431
		nvlist_free(nvroot);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   432
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   433
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   434
		 * Free this pool entry.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   435
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   436
		free(pe);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   437
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   438
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   439
		 * Determine if this pool is currently active, in which case we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   440
		 * can't actually import it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   441
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   442
		verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   443
		    &name) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   444
		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   445
		    &guid) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   446
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   447
		(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   448
		if (ioctl(zfs_fd, ZFS_IOC_POOL_GUID, &zc) == 0 &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   449
		    guid == zc.zc_pool_guid) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   450
			nvlist_free(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   451
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   452
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   453
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   454
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   455
		 * Try to do the import in order to get vdev state.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   456
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   457
		if ((err = nvlist_size(config, &len, NV_ENCODE_NATIVE)) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   458
			zfs_baderror(err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   459
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   460
		packed = zfs_malloc(len);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   461
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   462
		if ((err = nvlist_pack(config, &packed, &len,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   463
		    NV_ENCODE_NATIVE, 0)) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   464
			zfs_baderror(err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   465
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   466
		nvlist_free(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   467
		config = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   468
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   469
		zc.zc_config_src_size = len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   470
		zc.zc_config_src = (uint64_t)(uintptr_t)packed;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   471
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   472
		zc.zc_config_dst_size = 2 * len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   473
		zc.zc_config_dst = (uint64_t)(uintptr_t)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   474
		    zfs_malloc(zc.zc_config_dst_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   475
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   476
		while ((err = ioctl(zfs_fd, ZFS_IOC_POOL_TRYIMPORT,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   477
		    &zc)) != 0 && errno == ENOMEM) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   478
			free((void *)(uintptr_t)zc.zc_config_dst);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   479
			zc.zc_config_dst = (uint64_t)(uintptr_t)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   480
			    zfs_malloc(zc.zc_config_dst_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   481
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   482
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   483
		free(packed);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   484
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   485
		if (err)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   486
			zfs_baderror(errno);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   487
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   488
		verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   489
		    zc.zc_config_dst_size, &config, 0) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   490
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   491
		set_pool_health(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   492
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   493
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   494
		 * Add this pool to the list of configs.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   495
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   496
		verify(nvlist_add_nvlist(ret, name, config) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   497
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   498
		nvlist_free(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   499
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   500
		free((void *)(uintptr_t)zc.zc_config_dst);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   501
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   502
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   503
	return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   504
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   505
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   506
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   507
 * Return the offset of the given label.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   508
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   509
static uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   510
label_offset(size_t size, int l)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   511
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   512
	return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   513
	    0 : size - VDEV_LABELS * sizeof (vdev_label_t)));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   514
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   515
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   516
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   517
 * Given a file descriptor, read the label information and return an nvlist
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   518
 * describing the configuration, if there is one.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   519
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   520
nvlist_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   521
zpool_read_label(int fd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   522
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   523
	struct stat64 statbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   524
	int l;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   525
	vdev_label_t *label;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   526
	nvlist_t *config;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   527
	uint64_t version, state, txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   528
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   529
	if (fstat64(fd, &statbuf) == -1)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   530
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   531
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   532
	label = zfs_malloc(sizeof (vdev_label_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   533
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   534
	for (l = 0; l < VDEV_LABELS; l++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   535
		if (pread(fd, label, sizeof (vdev_label_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   536
		    label_offset(statbuf.st_size, l)) != sizeof (vdev_label_t))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   537
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   538
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   539
		if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   540
		    sizeof (label->vl_vdev_phys.vp_nvlist), &config, 0) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   541
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   542
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   543
		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   544
		    &version) != 0 || version != UBERBLOCK_VERSION) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   545
			nvlist_free(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   546
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   547
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   548
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   549
		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   550
		    &state) != 0 || state > POOL_STATE_EXPORTED) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   551
			nvlist_free(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   552
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   553
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   554
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   555
		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   556
		    &txg) != 0 || txg == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   557
			nvlist_free(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   558
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   559
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   560
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   561
		free(label);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   562
		return (config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   563
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   564
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   565
	free(label);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   566
	return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   567
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   568
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   569
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   570
 * Given a list of directories to search, find all pools stored on disk.  This
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   571
 * includes partial pools which are not available to import.  If no args are
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   572
 * given (argc is 0), then the default directory (/dev/dsk) is searched.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   573
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   574
nvlist_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   575
zpool_find_import(int argc, char **argv)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   577
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   578
	DIR *dirp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   579
	struct dirent64 *dp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   580
	char path[MAXPATHLEN];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   581
	struct stat64 statbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   582
	nvlist_t *ret, *config;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
	static char *default_dir = "/dev/dsk";
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   584
	int fd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   585
	pool_list_t pools = { 0 };
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   586
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
	if (argc == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   588
		argc = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
		argv = &default_dir;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   593
	 * Go through and read the label configuration information from every
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
	 * possible device, organizing the information according to pool GUID
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   595
	 * and toplevel GUID.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   596
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   597
	for (i = 0; i < argc; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   598
		if (argv[i][0] != '/') {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   599
			zfs_error(dgettext(TEXT_DOMAIN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   600
			    "cannot open '%s': must be an absolute path"),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   601
			    argv[i]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   602
			return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   603
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   604
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   605
		if ((dirp = opendir(argv[i])) == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
			zfs_error(dgettext(TEXT_DOMAIN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
			    "cannot open '%s': %s"), argv[i],
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   608
			    strerror(errno));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
			return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
		 * This is not MT-safe, but we have no MT consumers of libzfs
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   614
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   615
		while ((dp = readdir64(dirp)) != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   616
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   617
			(void) snprintf(path, sizeof (path), "%s/%s",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   618
			    argv[i], dp->d_name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   619
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   620
			if (stat64(path, &statbuf) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   621
				continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   622
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   623
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   624
			 * Ignore directories (which includes "." and "..").
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   625
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   626
			if (S_ISDIR(statbuf.st_mode))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   627
				continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   628
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   629
			if ((fd = open64(path, O_RDONLY)) < 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   630
				continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   631
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   632
			config = zpool_read_label(fd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   633
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   634
			(void) close(fd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   635
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   636
			if (config != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   637
				add_config(&pools, path, config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   638
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   639
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   640
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   641
	ret = get_configs(&pools);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   642
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   643
	return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   644
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   645
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   646
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   647
find_guid(nvlist_t *nv, uint64_t guid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   648
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   649
	uint64_t tmp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   650
	nvlist_t **child;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   651
	uint_t c, children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   652
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   653
	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &tmp) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   654
	if (tmp == guid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   655
		return (TRUE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   656
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   657
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   658
	    &child, &children) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   659
		for (c = 0; c < children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   660
			if (find_guid(child[c], guid))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   661
				return (TRUE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   662
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   663
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   664
	return (FALSE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   665
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   666
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   667
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   668
 * Determines if the pool is in use.  If so, it returns TRUE and the state of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   669
 * the pool as well as the name of the pool.  Both strings are allocated and
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   670
 * must be freed by the caller.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   671
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   672
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   673
zpool_in_use(int fd, char **statestr, char **namestr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   674
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   675
	nvlist_t *config;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   676
	uint64_t state;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   677
	char *name;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   678
	int ret;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   679
	zfs_cmd_t zc = { 0 };
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   680
	uint64_t guid, vdev_guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   681
	zpool_handle_t *zhp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   682
	nvlist_t *pool_config;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   683
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   684
	if ((config = zpool_read_label(fd)) == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   685
		return (FALSE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   686
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   687
	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   688
	    &name) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   689
	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   690
	    &state) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   691
	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   692
	    &guid) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   693
	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   694
	    &vdev_guid) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   695
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   696
	switch (state) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   697
	case POOL_STATE_EXPORTED:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   698
		*statestr = zfs_strdup(dgettext(TEXT_DOMAIN, "exported"));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   699
		*namestr = zfs_strdup(name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   700
		ret = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   701
		break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   702
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   703
	case POOL_STATE_ACTIVE:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   704
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   705
		 * For an active pool, we have to determine if it's really part
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   706
		 * of an active pool (in which case the pool will exist and the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   707
		 * guid will be the same), or whether it's part of an active
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   708
		 * pool that was disconnected without being explicitly exported.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   709
		 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   710
		 * We use the direct ioctl() first to avoid triggering an error
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   711
		 * message if the pool cannot be opened.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   712
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   713
		(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   714
		if (ioctl(zfs_fd, ZFS_IOC_POOL_GUID, &zc) == 0 &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   715
		    guid == zc.zc_pool_guid) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   716
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   717
			 * Because the device may have been removed while
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   718
			 * offlined, we only report it as active if the vdev is
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   719
			 * still present in the config.  Otherwise, pretend like
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   720
			 * it's not in use.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   721
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   722
			if ((zhp = zpool_open_canfail(name)) != NULL &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   723
			    (pool_config = zpool_get_config(zhp)) != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   724
				nvlist_t *nvroot;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   725
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   726
				verify(nvlist_lookup_nvlist(pool_config,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   727
				    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   728
				if (find_guid(nvroot, vdev_guid)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   729
					*statestr = zfs_strdup(
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   730
					    dgettext(TEXT_DOMAIN, "active"));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   731
					*namestr = zfs_strdup(name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   732
					ret = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   733
				} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   734
					ret = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   735
				}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   736
			} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   737
				ret = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   738
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   739
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   740
			*statestr = zfs_strdup(dgettext(TEXT_DOMAIN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   741
			    "potentially active"));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   742
			*namestr = zfs_strdup(name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   743
			ret = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   744
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   745
		break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   746
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   747
	default:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   748
		ret = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   749
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   750
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   751
	nvlist_free(config);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   752
	return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   753
}