usr/src/cmd/zpool/zpool_vdev.c
author Lin Ling <Lin.Ling@Sun.COM>
Mon, 03 May 2010 14:54:08 -0700
changeset 12296 7cf402a7f374
parent 11422 42768837421d
permissions -rw-r--r--
6675946 'zpool status' should show the progress of resilvering for individual disk. 6683750 scrub -s have to wait until resilver completed? 6841252 Resilvering not restartable - causing an excess reboot delay 6855073 spa scrub stats (eg %done) are reset on reboot 6891824 7410 NAS head "continually resilvering" following HDD replacement 6899970 scrub/resilver percent complete reporting in zpool status can be overly optimistic 6940889 add interval (count) args to zpool list 6944623 dbuf_read_done() locking performance improvement 6946760 mutex problem in bplist_enqueue() 6391915 RFE: provide interval arg to zpool status to monitor resilvering 6946512 want zfs_send() to pass back debug info 6943992 'zpool scrub' should not restart the existing scrub silently 6878281 zpool should store the time of last scrub/resilver and other zpool status info in pool properties. 6935158 Assertion failed: used <= spa_get_dspace(dd->dd_pool->dp_spa) 6944388 dsl_dataset_snapshot_reserve_space() causes dp_write_limit=max
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
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1352
diff changeset
     5
 * Common Development and Distribution License (the "License").
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1352
diff changeset
     6
 * You may not use this file except in compliance with the License.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    21
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    22
/*
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
    23
 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 */
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
 * Functions to convert between a list of vdevs and an nvlist representing the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
 * configuration.  Each entry in the list can be one of:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
 * 	Device vdevs
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
 * 		disk=(path=..., devid=...)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
 * 		file=(path=...)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
 * 	Group vdevs
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    35
 * 		raidz[1|2]=(...)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
 * 		mirror=(...)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
 *
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    38
 * 	Hot spares
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    39
 *
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
 * While the underlying implementation supports it, group vdevs cannot contain
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
 * other group vdevs.  All userland verification of devices is contained within
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
 * this file.  If successful, the nvlist returned can be passed directly to the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
 * kernel; we've done as much verification as possible in userland.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
 *
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    45
 * Hot spares are a special case, and passed down as an array of disk vdevs, at
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    46
 * the same level as the root of the vdev tree.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    47
 *
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
    48
 * The only function exported by this file is 'make_root_vdev'.  The
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
    49
 * function performs several passes:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
 * 	1. Construct the vdev specification.  Performs syntax validation and
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
 *         makes sure each device is valid.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
 * 	2. Check for devices in use.  Using libdiskmgt, makes sure that no
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
 *         devices are also in use.  Some can be overridden using the 'force'
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
 *         flag, others cannot.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
 * 	3. Check for replication errors if the 'force' flag is not specified.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
 *         validates that the replication level is consistent across the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
 *         entire pool.
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
    59
 * 	4. Call libzfs to label any whole disks with an EFI label.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
#include <assert.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
#include <devid.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
#include <errno.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
#include <fcntl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
#include <libdiskmgt.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
#include <libintl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
#include <libnvpair.h>
10105
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
    69
#include <limits.h>
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
#include <stdio.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
#include <string.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
#include <unistd.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
#include <sys/efi_partition.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
#include <sys/stat.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
#include <sys/vtoc.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
#include <sys/mntent.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
#include "zpool_util.h"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    80
#define	DISK_ROOT	"/dev/dsk"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
#define	RDISK_ROOT	"/dev/rdsk"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
#define	BACKUP_SLICE	"s2"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
 * For any given vdev specification, we can have multiple errors.  The
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
 * vdev_error() function keeps track of whether we have seen an error yet, and
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
 * prints out a header if its the first error we've seen.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    89
boolean_t error_seen;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    90
boolean_t is_force;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    92
/*PRINTFLIKE1*/
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
    93
static void
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
vdev_error(const char *fmt, ...)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
	va_list ap;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
	if (!error_seen) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
		(void) fprintf(stderr, gettext("invalid vdev specification\n"));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
		if (!is_force)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
			(void) fprintf(stderr, gettext("use '-f' to override "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
			    "the following errors:\n"));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
		else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
			(void) fprintf(stderr, gettext("the following errors "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
			    "must be manually repaired:\n"));
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   106
		error_seen = B_TRUE;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
	va_start(ap, fmt);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
	(void) vfprintf(stderr, fmt, ap);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
	va_end(ap);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   114
static void
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   115
libdiskmgt_error(int error)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   116
{
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1352
diff changeset
   117
	/*
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   118
	 * ENXIO/ENODEV is a valid error message if the device doesn't live in
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1352
diff changeset
   119
	 * /dev/dsk.  Don't bother printing an error message in this case.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1352
diff changeset
   120
	 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   121
	if (error == ENXIO || error == ENODEV)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1352
diff changeset
   122
		return;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1352
diff changeset
   123
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   124
	(void) fprintf(stderr, gettext("warning: device in use checking "
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   125
	    "failed: %s\n"), strerror(error));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   127
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   128
/*
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   129
 * Validate a device, passing the bulk of the work off to libdiskmgt.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   130
 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   131
static int
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   132
check_slice(const char *path, int force, boolean_t wholedisk, boolean_t isspare)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   133
{
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   134
	char *msg;
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   135
	int error = 0;
4946
57ac8d0ceca8 6573276 spare device inuse check problem
mmusante
parents: 4529
diff changeset
   136
	dm_who_type_t who;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
4946
57ac8d0ceca8 6573276 spare device inuse check problem
mmusante
parents: 4529
diff changeset
   138
	if (force)
57ac8d0ceca8 6573276 spare device inuse check problem
mmusante
parents: 4529
diff changeset
   139
		who = DM_WHO_ZPOOL_FORCE;
57ac8d0ceca8 6573276 spare device inuse check problem
mmusante
parents: 4529
diff changeset
   140
	else if (isspare)
57ac8d0ceca8 6573276 spare device inuse check problem
mmusante
parents: 4529
diff changeset
   141
		who = DM_WHO_ZPOOL_SPARE;
57ac8d0ceca8 6573276 spare device inuse check problem
mmusante
parents: 4529
diff changeset
   142
	else
57ac8d0ceca8 6573276 spare device inuse check problem
mmusante
parents: 4529
diff changeset
   143
		who = DM_WHO_ZPOOL;
57ac8d0ceca8 6573276 spare device inuse check problem
mmusante
parents: 4529
diff changeset
   144
57ac8d0ceca8 6573276 spare device inuse check problem
mmusante
parents: 4529
diff changeset
   145
	if (dm_inuse((char *)path, &msg, who, &error) || error) {
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   146
		if (error != 0) {
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   147
			libdiskmgt_error(error);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   148
			return (0);
3741
806e933bf124 6441384 zpool import action message is not correctly localized
mmusante
parents: 3265
diff changeset
   149
		} else {
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   150
			vdev_error("%s", msg);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   151
			free(msg);
4082
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   152
			return (-1);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
	/*
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   157
	 * If we're given a whole disk, ignore overlapping slices since we're
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   158
	 * about to label it anyway.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
	 */
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   160
	error = 0;
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   161
	if (!wholedisk && !force &&
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   162
	    (dm_isoverlapping((char *)path, &msg, &error) || error)) {
4082
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   163
		if (error == 0) {
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   164
			/* dm_isoverlapping returned -1 */
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   165
			vdev_error(gettext("%s overlaps with %s\n"), path, msg);
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   166
			free(msg);
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   167
			return (-1);
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   168
		} else if (error != ENODEV) {
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   169
			/* libdiskmgt's devcache only handles physical drives */
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   170
			libdiskmgt_error(error);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   171
			return (0);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   172
		}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
4082
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   175
	return (0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   178
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
 * Validate a whole disk.  Iterate over all slices on the disk and make sure
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
 * that none is in use by calling check_slice().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   183
static int
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   184
check_disk(const char *name, dm_descriptor_t disk, int force, int isspare)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
	dm_descriptor_t *drive, *media, *slice;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
	int err = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
	int ret;
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
	 * Get the drive associated with this disk.  This should never fail,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
	 * because we already have an alias handle open for the device.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
	if ((drive = dm_get_associated_descriptors(disk, DM_DRIVE,
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   196
	    &err)) == NULL || *drive == NULL) {
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   197
		if (err)
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   198
			libdiskmgt_error(err);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   199
		return (0);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   200
	}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
	if ((media = dm_get_associated_descriptors(*drive, DM_MEDIA,
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   203
	    &err)) == NULL) {
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   204
		dm_free_descriptors(drive);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   205
		if (err)
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   206
			libdiskmgt_error(err);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   207
		return (0);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   208
	}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
	dm_free_descriptors(drive);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
	 * It is possible that the user has specified a removable media drive,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
	 * and the media is not present.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
	if (*media == NULL) {
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   217
		dm_free_descriptors(media);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
		vdev_error(gettext("'%s' has no media in drive\n"), name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
		return (-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
	if ((slice = dm_get_associated_descriptors(*media, DM_SLICE,
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   223
	    &err)) == NULL) {
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   224
		dm_free_descriptors(media);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   225
		if (err)
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   226
			libdiskmgt_error(err);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   227
		return (0);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   228
	}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
	dm_free_descriptors(media);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
	ret = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
	 * Iterate over all slices and report any errors.  We don't care about
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
	 * overlapping slices because we are using the whole disk.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
	for (i = 0; slice[i] != NULL; i++) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   239
		char *name = dm_get_name(slice[i], &err);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   240
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   241
		if (check_slice(name, force, B_TRUE, isspare) != 0)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
			ret = -1;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   243
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   244
		dm_free_name(name);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
	dm_free_descriptors(slice);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
	return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
/*
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   252
 * Validate a device.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   254
static int
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   255
check_device(const char *path, boolean_t force, boolean_t isspare)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
	dm_descriptor_t desc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
	int err;
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   259
	char *dev;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
	 * For whole disks, libdiskmgt does not include the leading dev path.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
	dev = strrchr(path, '/');
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
	assert(dev != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
	dev++;
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   267
	if ((desc = dm_get_descriptor_by_name(DM_ALIAS, dev, &err)) != NULL) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   268
		err = check_disk(path, desc, force, isspare);
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   269
		dm_free_descriptor(desc);
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   270
		return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   273
	return (check_slice(path, force, B_FALSE, isspare));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
 * Check that a file is valid.  All we can do in this case is check that it's
4082
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   278
 * not in use by another pool, and not in use by swap.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   280
static int
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   281
check_file(const char *file, boolean_t force, boolean_t isspare)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
{
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   283
	char  *name;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
	int fd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
	int ret = 0;
4082
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   286
	int err;
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   287
	pool_state_t state;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   288
	boolean_t inuse;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
4082
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   290
	if (dm_inuse_swap(file, &err)) {
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   291
		if (err)
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   292
			libdiskmgt_error(err);
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   293
		else
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   294
			vdev_error(gettext("%s is currently used by swap. "
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   295
			    "Please see swap(1M).\n"), file);
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   296
		return (-1);
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   297
	}
2e3825fd8bb5 6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents: 3741
diff changeset
   298
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   299
	if ((fd = open(file, O_RDONLY)) < 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   302
	if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) == 0 && inuse) {
1352
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   303
		const char *desc;
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   304
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   305
		switch (state) {
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   306
		case POOL_STATE_ACTIVE:
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   307
			desc = gettext("active");
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   308
			break;
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   309
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   310
		case POOL_STATE_EXPORTED:
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   311
			desc = gettext("exported");
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   312
			break;
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   313
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   314
		case POOL_STATE_POTENTIALLY_ACTIVE:
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   315
			desc = gettext("potentially active");
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   316
			break;
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   317
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   318
		default:
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   319
			desc = gettext("unknown");
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   320
			break;
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   321
		}
b7039548de2f 6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents: 1171
diff changeset
   322
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   323
		/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   324
		 * Allow hot spares to be shared between pools.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   325
		 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   326
		if (state == POOL_STATE_SPARE && isspare)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   327
			return (0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   328
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   329
		if (state == POOL_STATE_ACTIVE ||
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   330
		    state == POOL_STATE_SPARE || !force) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   331
			switch (state) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   332
			case POOL_STATE_SPARE:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   333
				vdev_error(gettext("%s is reserved as a hot "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   334
				    "spare for pool %s\n"), file, name);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   335
				break;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   336
			default:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   337
				vdev_error(gettext("%s is part of %s pool "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   338
				    "'%s'\n"), file, desc, name);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   339
				break;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   340
			}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   341
			ret = -1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   342
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   343
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   344
		free(name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   345
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   346
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   347
	(void) close(fd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   348
	return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   349
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   350
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   351
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   352
/*
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   353
 * By "whole disk" we mean an entire physical disk (something we can
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   354
 * label, toggle the write cache on, etc.) as opposed to the full
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   355
 * capacity of a pseudo-device such as lofi or did.  We act as if we
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   356
 * are labeling the disk, which should be a pretty good test of whether
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   357
 * it's a viable device or not.  Returns B_TRUE if it is and B_FALSE if
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   358
 * it isn't.
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   359
 */
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   360
static boolean_t
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   361
is_whole_disk(const char *arg)
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   362
{
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   363
	struct dk_gpt *label;
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   364
	int	fd;
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   365
	char	path[MAXPATHLEN];
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   367
	(void) snprintf(path, sizeof (path), "%s%s%s",
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   368
	    RDISK_ROOT, strrchr(arg, '/'), BACKUP_SLICE);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   369
	if ((fd = open(path, O_RDWR | O_NDELAY)) < 0)
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   370
		return (B_FALSE);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   371
	if (efi_alloc_and_init(fd, EFI_NUMPAR, &label) != 0) {
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   372
		(void) close(fd);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   373
		return (B_FALSE);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   374
	}
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   375
	efi_free(label);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   376
	(void) close(fd);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   377
	return (B_TRUE);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   378
}
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
 * Create a leaf vdev.  Determine if this is a file or a device.  If it's a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   382
 * device, fill in the device id to make a complete nvlist.  Valid forms for a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   383
 * leaf vdev are:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   384
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   385
 * 	/dev/dsk/xxx	Complete disk path
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   386
 * 	/xxx		Full path to file
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   387
 * 	xxx		Shorthand for /dev/dsk/xxx
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   388
 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   389
static nvlist_t *
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   390
make_leaf_vdev(const char *arg, uint64_t is_log)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   391
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   392
	char path[MAXPATHLEN];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   393
	struct stat64 statbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   394
	nvlist_t *vdev = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   395
	char *type = NULL;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   396
	boolean_t wholedisk = B_FALSE;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   398
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   399
	 * Determine what type of vdev this is, and put the full path into
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   400
	 * 'path'.  We detect whether this is a device of file afterwards by
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   401
	 * checking the st_mode of the file.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   402
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   403
	if (arg[0] == '/') {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   404
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   405
		 * Complete device or file path.  Exact type is determined by
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   406
		 * examining the file descriptor afterwards.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
		 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   408
		wholedisk = is_whole_disk(arg);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   409
		if (!wholedisk && (stat64(arg, &statbuf) != 0)) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
			(void) fprintf(stderr,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   411
			    gettext("cannot open '%s': %s\n"),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   412
			    arg, strerror(errno));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   413
			return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   414
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   415
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   416
		(void) strlcpy(path, arg, sizeof (path));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   417
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   418
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   419
		 * This may be a short path for a device, or it could be total
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   420
		 * gibberish.  Check to see if it's a known device in
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   421
		 * /dev/dsk/.  As part of this check, see if we've been given a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   422
		 * an entire disk (minus the slice number).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   423
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   424
		(void) snprintf(path, sizeof (path), "%s/%s", DISK_ROOT,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   425
		    arg);
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   426
		wholedisk = is_whole_disk(path);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   427
		if (!wholedisk && (stat64(path, &statbuf) != 0)) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   428
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   429
			 * If we got ENOENT, then the user gave us
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   430
			 * gibberish, so try to direct them with a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   431
			 * reasonable error message.  Otherwise,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   432
			 * regurgitate strerror() since it's the best we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   433
			 * can do.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   434
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   435
			if (errno == ENOENT) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   436
				(void) fprintf(stderr,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   437
				    gettext("cannot open '%s': no such "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   438
				    "device in %s\n"), arg, DISK_ROOT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   439
				(void) fprintf(stderr,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   440
				    gettext("must be a full path or "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   441
				    "shorthand device name\n"));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   442
				return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   443
			} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   444
				(void) fprintf(stderr,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   445
				    gettext("cannot open '%s': %s\n"),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   446
				    path, strerror(errno));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   447
				return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   448
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   449
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   450
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   451
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   452
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   453
	 * Determine whether this is a device or a file.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   454
	 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   455
	if (wholedisk || S_ISBLK(statbuf.st_mode)) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   456
		type = VDEV_TYPE_DISK;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   457
	} else if (S_ISREG(statbuf.st_mode)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   458
		type = VDEV_TYPE_FILE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   459
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   460
		(void) fprintf(stderr, gettext("cannot use '%s': must be a "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   461
		    "block device or regular file\n"), path);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   462
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   463
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   464
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   465
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   466
	 * Finally, we have the complete device or file, and we know that it is
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   467
	 * acceptable to use.  Construct the nvlist to describe this vdev.  All
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   468
	 * vdevs have a 'path' element, and devices also have a 'devid' element.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   469
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   470
	verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   471
	verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   472
	verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   473
	verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   474
	if (strcmp(type, VDEV_TYPE_DISK) == 0)
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   475
		verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   476
		    (uint64_t)wholedisk) == 0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   477
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   478
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   479
	 * For a whole disk, defer getting its devid until after labeling it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   480
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   481
	if (S_ISBLK(statbuf.st_mode) && !wholedisk) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   482
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   483
		 * Get the devid for the device.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   484
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   485
		int fd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   486
		ddi_devid_t devid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   487
		char *minor = NULL, *devid_str = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   488
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   489
		if ((fd = open(path, O_RDONLY)) < 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   490
			(void) fprintf(stderr, gettext("cannot open '%s': "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   491
			    "%s\n"), path, strerror(errno));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   492
			nvlist_free(vdev);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   493
			return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   494
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   495
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   496
		if (devid_get(fd, &devid) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   497
			if (devid_get_minor_name(fd, &minor) == 0 &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   498
			    (devid_str = devid_str_encode(devid, minor)) !=
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   499
			    NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   500
				verify(nvlist_add_string(vdev,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   501
				    ZPOOL_CONFIG_DEVID, devid_str) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   502
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   503
			if (devid_str != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   504
				devid_str_free(devid_str);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   505
			if (minor != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   506
				devid_str_free(minor);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   507
			devid_free(devid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   508
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   509
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   510
		(void) close(fd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   511
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   512
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   513
	return (vdev);
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
 * Go through and verify the replication level of the pool is consistent.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   518
 * Performs the following checks:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   519
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   520
 * 	For the new spec, verifies that devices in mirrors and raidz are the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   521
 * 	same size.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   522
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   523
 * 	If the current configuration already has inconsistent replication
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   524
 * 	levels, ignore any other potential problems in the new spec.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   525
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   526
 * 	Otherwise, make sure that the current spec (if there is one) and the new
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   527
 * 	spec have consistent replication levels.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   528
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   529
typedef struct replication_level {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   530
	char *zprl_type;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   531
	uint64_t zprl_children;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   532
	uint64_t zprl_parity;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   533
} replication_level_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   534
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   535
#define	ZPOOL_FUZZ	(16 * 1024 * 1024)
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   536
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   537
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   538
 * Given a list of toplevel vdevs, return the current replication level.  If
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   539
 * the config is inconsistent, then NULL is returned.  If 'fatal' is set, then
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   540
 * an error message will be displayed for each self-inconsistent vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   541
 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   542
static replication_level_t *
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   543
get_replication(nvlist_t *nvroot, boolean_t fatal)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   544
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   545
	nvlist_t **top;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   546
	uint_t t, toplevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   547
	nvlist_t **child;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   548
	uint_t c, children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   549
	nvlist_t *nv;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   550
	char *type;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   551
	replication_level_t lastrep, rep, *ret;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   552
	boolean_t dontreport;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   553
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   554
	ret = safe_malloc(sizeof (replication_level_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   555
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   556
	verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   557
	    &top, &toplevels) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   558
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   559
	lastrep.zprl_type = NULL;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   560
	for (t = 0; t < toplevels; t++) {
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   561
		uint64_t is_log = B_FALSE;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   562
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   563
		nv = top[t];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   564
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   565
		/*
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   566
		 * For separate logs we ignore the top level vdev replication
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   567
		 * constraints.
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   568
		 */
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   569
		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log);
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   570
		if (is_log)
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   571
			continue;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   572
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   573
		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE,
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   574
		    &type) == 0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   575
		if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
		    &child, &children) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   577
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   578
			 * This is a 'file' or 'disk' vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   579
			 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   580
			rep.zprl_type = type;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   581
			rep.zprl_children = 1;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   582
			rep.zprl_parity = 0;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   584
			uint64_t vdev_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   585
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   586
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
			 * This is a mirror or RAID-Z vdev.  Go through and make
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   588
			 * sure the contents are all the same (files vs. disks),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
			 * keeping track of the number of elements in the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
			 * process.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
			 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
			 * We also check that the size of each vdev (if it can
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   593
			 * be determined) is the same.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
			 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   595
			rep.zprl_type = type;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   596
			rep.zprl_children = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   597
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   598
			if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   599
				verify(nvlist_lookup_uint64(nv,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   600
				    ZPOOL_CONFIG_NPARITY,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   601
				    &rep.zprl_parity) == 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   602
				assert(rep.zprl_parity != 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   603
			} else {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   604
				rep.zprl_parity = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   605
			}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
			/*
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   608
			 * The 'dontreport' variable indicates that we've
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
			 * already reported an error for this spec, so don't
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
			 * bother doing it again.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
			type = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
			dontreport = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   614
			vdev_size = -1ULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   615
			for (c = 0; c < children; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   616
				nvlist_t *cnv = child[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   617
				char *path;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   618
				struct stat64 statbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   619
				uint64_t size = -1ULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   620
				char *childtype;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   621
				int fd, err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   622
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   623
				rep.zprl_children++;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   624
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   625
				verify(nvlist_lookup_string(cnv,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   626
				    ZPOOL_CONFIG_TYPE, &childtype) == 0);
2142
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   627
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   628
				/*
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   629
				 * If this is a replacing or spare vdev, then
2142
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   630
				 * get the real first child of the vdev.
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   631
				 */
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   632
				if (strcmp(childtype,
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   633
				    VDEV_TYPE_REPLACING) == 0 ||
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   634
				    strcmp(childtype, VDEV_TYPE_SPARE) == 0) {
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   635
					nvlist_t **rchild;
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   636
					uint_t rchildren;
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   637
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   638
					verify(nvlist_lookup_nvlist_array(cnv,
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   639
					    ZPOOL_CONFIG_CHILDREN, &rchild,
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   640
					    &rchildren) == 0);
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   641
					assert(rchildren == 2);
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   642
					cnv = rchild[0];
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   643
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   644
					verify(nvlist_lookup_string(cnv,
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   645
					    ZPOOL_CONFIG_TYPE,
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   646
					    &childtype) == 0);
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   647
				}
f6e0487aa9a3 6433264 crash when adding spare: nvlist_lookup_string(cnv, "path", &path) == 0
eschrock
parents: 2082
diff changeset
   648
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   649
				verify(nvlist_lookup_string(cnv,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   650
				    ZPOOL_CONFIG_PATH, &path) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   651
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   652
				/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   653
				 * If we have a raidz/mirror that combines disks
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   654
				 * with files, report it as an error.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   655
				 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   656
				if (!dontreport && type != NULL &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   657
				    strcmp(type, childtype) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   658
					if (ret != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   659
						free(ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   660
					ret = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   661
					if (fatal)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   662
						vdev_error(gettext(
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   663
						    "mismatched replication "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   664
						    "level: %s contains both "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   665
						    "files and devices\n"),
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   666
						    rep.zprl_type);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   667
					else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   668
						return (NULL);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   669
					dontreport = B_TRUE;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   670
				}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   671
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   672
				/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   673
				 * According to stat(2), the value of 'st_size'
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   674
				 * is undefined for block devices and character
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   675
				 * devices.  But there is no effective way to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   676
				 * determine the real size in userland.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   677
				 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   678
				 * Instead, we'll take advantage of an
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   679
				 * implementation detail of spec_size().  If the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   680
				 * device is currently open, then we (should)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   681
				 * return a valid size.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   682
				 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   683
				 * If we still don't get a valid size (indicated
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   684
				 * by a size of 0 or MAXOFFSET_T), then ignore
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   685
				 * this device altogether.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   686
				 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   687
				if ((fd = open(path, O_RDONLY)) >= 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   688
					err = fstat64(fd, &statbuf);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   689
					(void) close(fd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   690
				} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   691
					err = stat64(path, &statbuf);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   692
				}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   693
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   694
				if (err != 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   695
				    statbuf.st_size == 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   696
				    statbuf.st_size == MAXOFFSET_T)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   697
					continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   698
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   699
				size = statbuf.st_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   700
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   701
				/*
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   702
				 * Also make sure that devices and
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   703
				 * slices have a consistent size.  If
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   704
				 * they differ by a significant amount
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   705
				 * (~16MB) then report an error.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   706
				 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   707
				if (!dontreport &&
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   708
				    (vdev_size != -1ULL &&
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   709
				    (labs(size - vdev_size) >
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   710
				    ZPOOL_FUZZ))) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   711
					if (ret != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   712
						free(ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   713
					ret = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   714
					if (fatal)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   715
						vdev_error(gettext(
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   716
						    "%s contains devices of "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   717
						    "different sizes\n"),
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   718
						    rep.zprl_type);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   719
					else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   720
						return (NULL);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   721
					dontreport = B_TRUE;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   722
				}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   723
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   724
				type = childtype;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   725
				vdev_size = size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   726
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   727
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   728
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   729
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   730
		 * At this point, we have the replication of the last toplevel
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   731
		 * vdev in 'rep'.  Compare it to 'lastrep' to see if its
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   732
		 * different.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   733
		 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   734
		if (lastrep.zprl_type != NULL) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   735
			if (strcmp(lastrep.zprl_type, rep.zprl_type) != 0) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   736
				if (ret != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   737
					free(ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   738
				ret = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   739
				if (fatal)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   740
					vdev_error(gettext(
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   741
					    "mismatched replication level: "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   742
					    "both %s and %s vdevs are "
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   743
					    "present\n"),
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   744
					    lastrep.zprl_type, rep.zprl_type);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   745
				else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   746
					return (NULL);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   747
			} else if (lastrep.zprl_parity != rep.zprl_parity) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   748
				if (ret)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   749
					free(ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   750
				ret = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   751
				if (fatal)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   752
					vdev_error(gettext(
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   753
					    "mismatched replication level: "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   754
					    "both %llu and %llu device parity "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   755
					    "%s vdevs are present\n"),
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   756
					    lastrep.zprl_parity,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   757
					    rep.zprl_parity,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   758
					    rep.zprl_type);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   759
				else
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   760
					return (NULL);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   761
			} else if (lastrep.zprl_children != rep.zprl_children) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   762
				if (ret)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   763
					free(ret);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   764
				ret = NULL;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   765
				if (fatal)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   766
					vdev_error(gettext(
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   767
					    "mismatched replication level: "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   768
					    "both %llu-way and %llu-way %s "
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   769
					    "vdevs are present\n"),
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   770
					    lastrep.zprl_children,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   771
					    rep.zprl_children,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   772
					    rep.zprl_type);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   773
				else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   774
					return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   775
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   776
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   777
		lastrep = rep;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   778
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   779
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   780
	if (ret != NULL)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   781
		*ret = rep;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   782
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   783
	return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   784
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   785
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   786
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   787
 * Check the replication level of the vdev spec against the current pool.  Calls
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   788
 * get_replication() to make sure the new spec is self-consistent.  If the pool
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   789
 * has a consistent replication level, then we ignore any errors.  Otherwise,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   790
 * report any difference between the two.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   791
 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   792
static int
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   793
check_replication(nvlist_t *config, nvlist_t *newroot)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   794
{
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   795
	nvlist_t **child;
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   796
	uint_t	children;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   797
	replication_level_t *current = NULL, *new;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   798
	int ret;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   799
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   800
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   801
	 * If we have a current pool configuration, check to see if it's
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   802
	 * self-consistent.  If not, simply return success.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   803
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   804
	if (config != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   805
		nvlist_t *nvroot;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   806
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   807
		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   808
		    &nvroot) == 0);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   809
		if ((current = get_replication(nvroot, B_FALSE)) == NULL)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   810
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   811
	}
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   812
	/*
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   813
	 * for spares there may be no children, and therefore no
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   814
	 * replication level to check
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   815
	 */
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   816
	if ((nvlist_lookup_nvlist_array(newroot, ZPOOL_CONFIG_CHILDREN,
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   817
	    &child, &children) != 0) || (children == 0)) {
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   818
		free(current);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   819
		return (0);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   820
	}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   821
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   822
	/*
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   823
	 * If all we have is logs then there's no replication level to check.
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   824
	 */
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   825
	if (num_logs(newroot) == children) {
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   826
		free(current);
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   827
		return (0);
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   828
	}
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   829
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
   830
	/*
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   831
	 * Get the replication level of the new vdev spec, reporting any
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   832
	 * inconsistencies found.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   833
	 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   834
	if ((new = get_replication(newroot, B_TRUE)) == NULL) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   835
		free(current);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   836
		return (-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   837
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   838
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   839
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   840
	 * Check to see if the new vdev spec matches the replication level of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   841
	 * the current pool.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   842
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   843
	ret = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   844
	if (current != NULL) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   845
		if (strcmp(current->zprl_type, new->zprl_type) != 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   846
			vdev_error(gettext(
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   847
			    "mismatched replication level: pool uses %s "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   848
			    "and new vdev is %s\n"),
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   849
			    current->zprl_type, new->zprl_type);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   850
			ret = -1;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   851
		} else if (current->zprl_parity != new->zprl_parity) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   852
			vdev_error(gettext(
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   853
			    "mismatched replication level: pool uses %llu "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   854
			    "device parity and new vdev uses %llu\n"),
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   855
			    current->zprl_parity, new->zprl_parity);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   856
			ret = -1;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   857
		} else if (current->zprl_children != new->zprl_children) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   858
			vdev_error(gettext(
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   859
			    "mismatched replication level: pool uses %llu-way "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   860
			    "%s and new vdev uses %llu-way %s\n"),
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   861
			    current->zprl_children, current->zprl_type,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   862
			    new->zprl_children, new->zprl_type);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   863
			ret = -1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   864
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   865
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   866
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   867
	free(new);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   868
	if (current != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   869
		free(current);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   870
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   871
	return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   872
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   873
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   874
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   875
 * Go through and find any whole disks in the vdev specification, labelling them
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   876
 * as appropriate.  When constructing the vdev spec, we were unable to open this
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   877
 * device in order to provide a devid.  Now that we have labelled the disk and
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   878
 * know that slice 0 is valid, we can construct the devid now.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   879
 *
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   880
 * If the disk was already labeled with an EFI label, we will have gotten the
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   881
 * devid already (because we were able to open the whole disk).  Otherwise, we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   882
 * need to get the devid after we label the disk.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   883
 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   884
static int
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   885
make_disks(zpool_handle_t *zhp, nvlist_t *nv)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   886
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   887
	nvlist_t **child;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   888
	uint_t c, children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   889
	char *type, *path, *diskname;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   890
	char buf[MAXPATHLEN];
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   891
	uint64_t wholedisk;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   892
	int fd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   893
	int ret;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   894
	ddi_devid_t devid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   895
	char *minor = NULL, *devid_str = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   896
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   897
	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   898
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   899
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   900
	    &child, &children) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   901
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   902
		if (strcmp(type, VDEV_TYPE_DISK) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   903
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   904
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   905
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   906
		 * We have a disk device.  Get the path to the device
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   907
		 * and see if it's a whole disk by appending the backup
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   908
		 * slice and stat()ing the device.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   909
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   910
		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   911
		if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   912
		    &wholedisk) != 0 || !wholedisk)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   913
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   914
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   915
		diskname = strrchr(path, '/');
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   916
		assert(diskname != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   917
		diskname++;
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   918
		if (zpool_label_disk(g_zfs, zhp, diskname) == -1)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   919
			return (-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   920
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   921
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   922
		 * Fill in the devid, now that we've labeled the disk.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   923
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   924
		(void) snprintf(buf, sizeof (buf), "%ss0", path);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   925
		if ((fd = open(buf, O_RDONLY)) < 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   926
			(void) fprintf(stderr,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   927
			    gettext("cannot open '%s': %s\n"),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   928
			    buf, strerror(errno));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   929
			return (-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   930
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   931
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   932
		if (devid_get(fd, &devid) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   933
			if (devid_get_minor_name(fd, &minor) == 0 &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   934
			    (devid_str = devid_str_encode(devid, minor)) !=
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   935
			    NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   936
				verify(nvlist_add_string(nv,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   937
				    ZPOOL_CONFIG_DEVID, devid_str) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   938
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   939
			if (devid_str != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   940
				devid_str_free(devid_str);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   941
			if (minor != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   942
				devid_str_free(minor);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   943
			devid_free(devid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   944
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   945
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   946
		/*
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   947
		 * Update the path to refer to the 's0' slice.  The presence of
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   948
		 * the 'whole_disk' field indicates to the CLI that we should
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   949
		 * chop off the slice number when displaying the device in
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   950
		 * future output.
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   951
		 */
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   952
		verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, buf) == 0);
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   953
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   954
		(void) close(fd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   955
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   956
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   957
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   958
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   959
	for (c = 0; c < children; c++)
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   960
		if ((ret = make_disks(zhp, child[c])) != 0)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   961
			return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   962
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   963
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   964
	    &child, &children) == 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   965
		for (c = 0; c < children; c++)
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
   966
			if ((ret = make_disks(zhp, child[c])) != 0)
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   967
				return (ret);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   968
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
   969
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
   970
	    &child, &children) == 0)
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
   971
		for (c = 0; c < children; c++)
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
   972
			if ((ret = make_disks(zhp, child[c])) != 0)
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
   973
				return (ret);
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
   974
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   975
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   976
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   977
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   978
/*
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   979
 * Determine if the given path is a hot spare within the given configuration.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   980
 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   981
static boolean_t
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   982
is_spare(nvlist_t *config, const char *path)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   983
{
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   984
	int fd;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   985
	pool_state_t state;
3265
967e0fca6143 6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents: 2856
diff changeset
   986
	char *name = NULL;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   987
	nvlist_t *label;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   988
	uint64_t guid, spareguid;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   989
	nvlist_t *nvroot;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   990
	nvlist_t **spares;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   991
	uint_t i, nspares;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   992
	boolean_t inuse;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   993
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   994
	if ((fd = open(path, O_RDONLY)) < 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   995
		return (B_FALSE);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   996
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   997
	if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) != 0 ||
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   998
	    !inuse ||
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
   999
	    state != POOL_STATE_SPARE ||
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1000
	    zpool_read_label(fd, &label) != 0) {
3265
967e0fca6143 6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents: 2856
diff changeset
  1001
		free(name);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1002
		(void) close(fd);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1003
		return (B_FALSE);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1004
	}
3265
967e0fca6143 6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents: 2856
diff changeset
  1005
	free(name);
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1006
	(void) close(fd);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1007
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1008
	verify(nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &guid) == 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1009
	nvlist_free(label);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1010
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1011
	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1012
	    &nvroot) == 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1013
	if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1014
	    &spares, &nspares) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1015
		for (i = 0; i < nspares; i++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1016
			verify(nvlist_lookup_uint64(spares[i],
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1017
			    ZPOOL_CONFIG_GUID, &spareguid) == 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1018
			if (spareguid == guid)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1019
				return (B_TRUE);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1020
		}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1021
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1022
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1023
	return (B_FALSE);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1024
}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1025
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1026
/*
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1027
 * Go through and find any devices that are in use.  We rely on libdiskmgt for
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1028
 * the majority of this task.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1029
 */
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
  1030
static int
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1031
check_in_use(nvlist_t *config, nvlist_t *nv, boolean_t force,
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1032
    boolean_t replacing, boolean_t isspare)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1033
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1034
	nvlist_t **child;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1035
	uint_t c, children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1036
	char *type, *path;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1037
	int ret;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1038
	char buf[MAXPATHLEN];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1039
	uint64_t wholedisk;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1040
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1041
	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1042
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1043
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1044
	    &child, &children) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1045
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1046
		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1047
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1048
		/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1049
		 * As a generic check, we look to see if this is a replace of a
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1050
		 * hot spare within the same pool.  If so, we allow it
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1051
		 * regardless of what libdiskmgt or zpool_in_use() says.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1052
		 */
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1053
		if (replacing) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1054
			if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1055
			    &wholedisk) == 0 && wholedisk)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1056
				(void) snprintf(buf, sizeof (buf), "%ss0",
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1057
				    path);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1058
			else
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1059
				(void) strlcpy(buf, path, sizeof (buf));
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1060
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1061
			if (is_spare(config, buf))
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1062
				return (0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1063
		}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1064
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1065
		if (strcmp(type, VDEV_TYPE_DISK) == 0)
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1066
			ret = check_device(path, force, isspare);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1067
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1068
		if (strcmp(type, VDEV_TYPE_FILE) == 0)
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1069
			ret = check_file(path, force, isspare);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1070
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1071
		return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1072
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1073
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1074
	for (c = 0; c < children; c++)
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1075
		if ((ret = check_in_use(config, child[c], force,
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1076
		    replacing, B_FALSE)) != 0)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1077
			return (ret);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1078
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1079
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1080
	    &child, &children) == 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1081
		for (c = 0; c < children; c++)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1082
			if ((ret = check_in_use(config, child[c], force,
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1083
			    replacing, B_TRUE)) != 0)
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1084
				return (ret);
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1085
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1086
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1087
	    &child, &children) == 0)
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1088
		for (c = 0; c < children; c++)
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1089
			if ((ret = check_in_use(config, child[c], force,
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1090
			    replacing, B_FALSE)) != 0)
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1091
				return (ret);
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1092
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1093
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1094
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1095
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
  1096
static const char *
10105
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1097
is_grouping(const char *type, int *mindev, int *maxdev)
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1098
{
10105
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1099
	if (strncmp(type, "raidz", 5) == 0) {
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1100
		const char *p = type + 5;
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1101
		char *end;
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1102
		long nparity;
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1103
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1104
		if (*p == '\0') {
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1105
			nparity = 1;
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1106
		} else if (*p == '0') {
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1107
			return (NULL); /* no zero prefixes allowed */
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1108
		} else {
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1109
			errno = 0;
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1110
			nparity = strtol(p, &end, 10);
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1111
			if (errno != 0 || nparity < 1 || nparity >= 255 ||
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1112
			    *end != '\0')
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1113
				return (NULL);
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1114
		}
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1115
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1116
		if (mindev != NULL)
10105
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1117
			*mindev = nparity + 1;
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1118
		if (maxdev != NULL)
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1119
			*maxdev = 255;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1120
		return (VDEV_TYPE_RAIDZ);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1121
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1122
10105
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1123
	if (maxdev != NULL)
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1124
		*maxdev = INT_MAX;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1125
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1126
	if (strcmp(type, "mirror") == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1127
		if (mindev != NULL)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1128
			*mindev = 2;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1129
		return (VDEV_TYPE_MIRROR);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1130
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1131
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1132
	if (strcmp(type, "spare") == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1133
		if (mindev != NULL)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1134
			*mindev = 1;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1135
		return (VDEV_TYPE_SPARE);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1136
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1137
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1138
	if (strcmp(type, "log") == 0) {
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1139
		if (mindev != NULL)
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1140
			*mindev = 1;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1141
		return (VDEV_TYPE_LOG);
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1142
	}
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1143
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1144
	if (strcmp(type, "cache") == 0) {
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1145
		if (mindev != NULL)
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1146
			*mindev = 1;
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1147
		return (VDEV_TYPE_L2CACHE);
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1148
	}
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1149
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1150
	return (NULL);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1151
}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1152
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1153
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1154
 * Construct a syntactically valid vdev specification,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1155
 * and ensure that all devices and files exist and can be opened.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1156
 * Note: we don't bother freeing anything in the error paths
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1157
 * because the program is just going to exit anyway.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1158
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1159
nvlist_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1160
construct_spec(int argc, char **argv)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1161
{
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1162
	nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
10105
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1163
	int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1164
	const char *type;
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1165
	uint64_t is_log;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1166
	boolean_t seen_logs;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1167
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1168
	top = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1169
	toplevels = 0;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1170
	spares = NULL;
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1171
	l2cache = NULL;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1172
	nspares = 0;
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1173
	nlogs = 0;
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1174
	nl2cache = 0;
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1175
	is_log = B_FALSE;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1176
	seen_logs = B_FALSE;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1177
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1178
	while (argc > 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1179
		nv = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1180
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1181
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1182
		 * If it's a mirror or raidz, the subsequent arguments are
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1183
		 * its leaves -- until we encounter the next mirror or raidz.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1184
		 */
10105
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1185
		if ((type = is_grouping(argv[0], &mindev, &maxdev)) != NULL) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1186
			nvlist_t **child = NULL;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1187
			int c, children = 0;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1188
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1189
			if (strcmp(type, VDEV_TYPE_SPARE) == 0) {
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1190
				if (spares != NULL) {
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1191
					(void) fprintf(stderr,
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1192
					    gettext("invalid vdev "
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1193
					    "specification: 'spare' can be "
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1194
					    "specified only once\n"));
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1195
					return (NULL);
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1196
				}
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1197
				is_log = B_FALSE;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1198
			}
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1199
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1200
			if (strcmp(type, VDEV_TYPE_LOG) == 0) {
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1201
				if (seen_logs) {
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1202
					(void) fprintf(stderr,
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1203
					    gettext("invalid vdev "
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1204
					    "specification: 'log' can be "
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1205
					    "specified only once\n"));
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1206
					return (NULL);
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1207
				}
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1208
				seen_logs = B_TRUE;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1209
				is_log = B_TRUE;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1210
				argc--;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1211
				argv++;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1212
				/*
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1213
				 * A log is not a real grouping device.
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1214
				 * We just set is_log and continue.
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1215
				 */
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1216
				continue;
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1217
			}
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1218
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1219
			if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1220
				if (l2cache != NULL) {
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1221
					(void) fprintf(stderr,
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1222
					    gettext("invalid vdev "
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1223
					    "specification: 'cache' can be "
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1224
					    "specified only once\n"));
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1225
					return (NULL);
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1226
				}
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1227
				is_log = B_FALSE;
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1228
			}
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1229
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1230
			if (is_log) {
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1231
				if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1232
					(void) fprintf(stderr,
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1233
					    gettext("invalid vdev "
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1234
					    "specification: unsupported 'log' "
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1235
					    "device: %s\n"), type);
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1236
					return (NULL);
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1237
				}
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1238
				nlogs++;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1239
			}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1240
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1241
			for (c = 1; c < argc; c++) {
10105
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1242
				if (is_grouping(argv[c], NULL, NULL) != NULL)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1243
					break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1244
				children++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1245
				child = realloc(child,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1246
				    children * sizeof (nvlist_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1247
				if (child == NULL)
2856
6f4d5ee1906a 6463348 ZFS code could be more portable
nd150628
parents: 2142
diff changeset
  1248
					zpool_no_memory();
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1249
				if ((nv = make_leaf_vdev(argv[c], B_FALSE))
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1250
				    == NULL)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1251
					return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1252
				child[children - 1] = nv;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1253
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1254
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1255
			if (children < mindev) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1256
				(void) fprintf(stderr, gettext("invalid vdev "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1257
				    "specification: %s requires at least %d "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1258
				    "devices\n"), argv[0], mindev);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1259
				return (NULL);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1260
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1261
10105
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1262
			if (children > maxdev) {
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1263
				(void) fprintf(stderr, gettext("invalid vdev "
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1264
				    "specification: %s supports no more than "
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1265
				    "%d devices\n"), argv[0], maxdev);
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1266
				return (NULL);
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1267
			}
17811c723fb4 6854612 triple-parity RAID-Z
Adam Leventhal <adam.leventhal@sun.com>
parents: 7343
diff changeset
  1268
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1269
			argc -= c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1270
			argv += c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1271
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1272
			if (strcmp(type, VDEV_TYPE_SPARE) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1273
				spares = child;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1274
				nspares = children;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1275
				continue;
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1276
			} else if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1277
				l2cache = child;
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1278
				nl2cache = children;
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1279
				continue;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1280
			} else {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1281
				verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1282
				    0) == 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1283
				verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1284
				    type) == 0);
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1285
				verify(nvlist_add_uint64(nv,
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1286
				    ZPOOL_CONFIG_IS_LOG, is_log) == 0);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1287
				if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1288
					verify(nvlist_add_uint64(nv,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1289
					    ZPOOL_CONFIG_NPARITY,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1290
					    mindev - 1) == 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1291
				}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1292
				verify(nvlist_add_nvlist_array(nv,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1293
				    ZPOOL_CONFIG_CHILDREN, child,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1294
				    children) == 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1295
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1296
				for (c = 0; c < children; c++)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1297
					nvlist_free(child[c]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1298
				free(child);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1299
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1300
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1301
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1302
			 * We have a device.  Pass off to make_leaf_vdev() to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1303
			 * construct the appropriate nvlist describing the vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1304
			 */
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1305
			if ((nv = make_leaf_vdev(argv[0], is_log)) == NULL)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1306
				return (NULL);
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1307
			if (is_log)
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1308
				nlogs++;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1309
			argc--;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1310
			argv++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1311
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1312
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1313
		toplevels++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1314
		top = realloc(top, toplevels * sizeof (nvlist_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1315
		if (top == NULL)
2856
6f4d5ee1906a 6463348 ZFS code could be more portable
nd150628
parents: 2142
diff changeset
  1316
			zpool_no_memory();
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1317
		top[toplevels - 1] = nv;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1318
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1319
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1320
	if (toplevels == 0 && nspares == 0 && nl2cache == 0) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1321
		(void) fprintf(stderr, gettext("invalid vdev "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1322
		    "specification: at least one toplevel vdev must be "
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1323
		    "specified\n"));
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1324
		return (NULL);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1325
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1326
4527
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1327
	if (seen_logs && nlogs == 0) {
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1328
		(void) fprintf(stderr, gettext("invalid vdev specification: "
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1329
		    "log requires at least 1 device\n"));
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1330
		return (NULL);
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1331
	}
5d5b6ba91b17 PSARC 2007/171 ZFS Separate Intent Log
perrin
parents: 4276
diff changeset
  1332
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1333
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1334
	 * Finally, create nvroot and add all top-level vdevs to it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1335
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1336
	verify(nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1337
	verify(nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1338
	    VDEV_TYPE_ROOT) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1339
	verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1340
	    top, toplevels) == 0);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1341
	if (nspares != 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1342
		verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1343
		    spares, nspares) == 0);
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1344
	if (nl2cache != 0)
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1345
		verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1346
		    l2cache, nl2cache) == 0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1347
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1348
	for (t = 0; t < toplevels; t++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1349
		nvlist_free(top[t]);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1350
	for (t = 0; t < nspares; t++)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1351
		nvlist_free(spares[t]);
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1352
	for (t = 0; t < nl2cache; t++)
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1353
		nvlist_free(l2cache[t]);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1354
	if (spares)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1544
diff changeset
  1355
		free(spares);
5450
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1356
	if (l2cache)
b25030891c44 PSARC 2007/618 ZFS L2ARC
brendan
parents: 4946
diff changeset
  1357
		free(l2cache);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1358
	free(top);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1359
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1360
	return (nvroot);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1361
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1362
11422
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1363
nvlist_t *
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1364
split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props,
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1365
    splitflags_t flags, int argc, char **argv)
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1366
{
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1367
	nvlist_t *newroot = NULL, **child;
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1368
	uint_t c, children;
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1369
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1370
	if (argc > 0) {
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1371
		if ((newroot = construct_spec(argc, argv)) == NULL) {
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1372
			(void) fprintf(stderr, gettext("Unable to build a "
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1373
			    "pool from the specified devices\n"));
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1374
			return (NULL);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1375
		}
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1376
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1377
		if (!flags.dryrun && make_disks(zhp, newroot) != 0) {
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1378
			nvlist_free(newroot);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1379
			return (NULL);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1380
		}
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1381
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1382
		/* avoid any tricks in the spec */
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1383
		verify(nvlist_lookup_nvlist_array(newroot,
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1384
		    ZPOOL_CONFIG_CHILDREN, &child, &children) == 0);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1385
		for (c = 0; c < children; c++) {
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1386
			char *path;
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1387
			const char *type;
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1388
			int min, max;
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1389
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1390
			verify(nvlist_lookup_string(child[c],
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1391
			    ZPOOL_CONFIG_PATH, &path) == 0);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1392
			if ((type = is_grouping(path, &min, &max)) != NULL) {
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1393
				(void) fprintf(stderr, gettext("Cannot use "
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1394
				    "'%s' as a device for splitting\n"), type);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1395
				nvlist_free(newroot);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1396
				return (NULL);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1397
			}
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1398
		}
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1399
	}
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1400
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1401
	if (zpool_vdev_split(zhp, newname, &newroot, props, flags) != 0) {
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1402
		if (newroot != NULL)
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1403
			nvlist_free(newroot);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1404
		return (NULL);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1405
	}
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1406
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1407
	return (newroot);
42768837421d PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents: 10105
diff changeset
  1408
}
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
  1409
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1410
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1411
 * Get and validate the contents of the given vdev specification.  This ensures
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1412
 * that the nvlist returned is well-formed, that all the devices exist, and that
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1413
 * they are not currently in use by any other known consumer.  The 'poolconfig'
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1414
 * parameter is the current configuration of the pool when adding devices
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1415
 * existing pool, and is used to perform additional checks, such as changing the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1416
 * replication level of the pool.  It can be 'NULL' to indicate that this is a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1417
 * new pool.  The 'force' flag controls whether devices should be forcefully
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1418
 * added, even if they appear in use.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1419
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1420
nvlist_t *
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
  1421
make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1422
    boolean_t replacing, boolean_t dryrun, int argc, char **argv)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1423
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1424
	nvlist_t *newroot;
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
  1425
	nvlist_t *poolconfig = NULL;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1426
	is_force = force;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1427
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1428
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1429
	 * Construct the vdev specification.  If this is successful, we know
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1430
	 * that we have a valid specification, and that all devices can be
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1431
	 * opened.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1432
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1433
	if ((newroot = construct_spec(argc, argv)) == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1434
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1435
4276
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
  1436
	if (zhp && ((poolconfig = zpool_get_config(zhp, NULL)) == NULL))
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
  1437
		return (NULL);
c42d49ffb16f 6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents: 4082
diff changeset
  1438
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1439
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1440
	 * Validate each device to make sure that its not shared with another
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1441
	 * subsystem.  We do this even if 'force' is set, because there are some
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1442
	 * uses (such as a dedicated dump device) that even '-f' cannot
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1443
	 * override.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1444
	 */
12296
7cf402a7f374 6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents: 11422
diff changeset
  1445
	if (check_in_use(poolconfig, newroot, force, replacing, B_FALSE) != 0) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1446
		nvlist_free(newroot);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1447
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1448
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1449
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1450
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1451
	 * Check the replication level of the given vdevs and report any errors
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1452
	 * found.  We include the existing pool spec, if any, as we need to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1453
	 * catch changes against the existing replication level.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1454
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1455
	if (check_rep && check_replication(poolconfig, newroot) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1456
		nvlist_free(newroot);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1457
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1458
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1459
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1460
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1461
	 * Run through the vdev specification and label any whole disks found.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1462
	 */
7343
168aa3b38fe5 6563009 zpool create -n writes new label
Eric Taylor <Eric.Taylor@Sun.COM>
parents: 5450
diff changeset
  1463
	if (!dryrun && make_disks(zhp, newroot) != 0) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1464
		nvlist_free(newroot);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1465
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1466
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1467
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1468
	return (newroot);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1469
}