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-- |
789 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
1544 | 5 |
* Common Development and Distribution License (the "License"). |
6 |
* You may not use this file except in compliance with the License. |
|
789 | 7 |
* |
8 |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 |
* or http://www.opensolaris.org/os/licensing. |
|
10 |
* See the License for the specific language governing permissions |
|
11 |
* and limitations under the License. |
|
12 |
* |
|
13 |
* When distributing Covered Code, include this CDDL HEADER in each |
|
14 |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 |
* If applicable, add the following below this CDDL HEADER, with the |
|
16 |
* fields enclosed by brackets "[]" replaced with your own identifying |
|
17 |
* information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 |
* |
|
19 |
* CDDL HEADER END |
|
20 |
*/ |
|
2082 | 21 |
|
789 | 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 | 24 |
*/ |
25 |
||
26 |
/* |
|
27 |
* Functions to convert between a list of vdevs and an nvlist representing the |
|
28 |
* configuration. Each entry in the list can be one of: |
|
29 |
* |
|
30 |
* Device vdevs |
|
31 |
* disk=(path=..., devid=...) |
|
32 |
* file=(path=...) |
|
33 |
* |
|
34 |
* Group vdevs |
|
2082 | 35 |
* raidz[1|2]=(...) |
789 | 36 |
* mirror=(...) |
37 |
* |
|
2082 | 38 |
* Hot spares |
39 |
* |
|
789 | 40 |
* While the underlying implementation supports it, group vdevs cannot contain |
41 |
* other group vdevs. All userland verification of devices is contained within |
|
42 |
* this file. If successful, the nvlist returned can be passed directly to the |
|
43 |
* kernel; we've done as much verification as possible in userland. |
|
44 |
* |
|
2082 | 45 |
* Hot spares are a special case, and passed down as an array of disk vdevs, at |
46 |
* the same level as the root of the vdev tree. |
|
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 | 50 |
* |
51 |
* 1. Construct the vdev specification. Performs syntax validation and |
|
52 |
* makes sure each device is valid. |
|
53 |
* 2. Check for devices in use. Using libdiskmgt, makes sure that no |
|
54 |
* devices are also in use. Some can be overridden using the 'force' |
|
55 |
* flag, others cannot. |
|
56 |
* 3. Check for replication errors if the 'force' flag is not specified. |
|
57 |
* validates that the replication level is consistent across the |
|
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 | 60 |
*/ |
61 |
||
62 |
#include <assert.h> |
|
63 |
#include <devid.h> |
|
64 |
#include <errno.h> |
|
65 |
#include <fcntl.h> |
|
66 |
#include <libdiskmgt.h> |
|
67 |
#include <libintl.h> |
|
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 | 70 |
#include <stdio.h> |
71 |
#include <string.h> |
|
72 |
#include <unistd.h> |
|
73 |
#include <sys/efi_partition.h> |
|
74 |
#include <sys/stat.h> |
|
75 |
#include <sys/vtoc.h> |
|
76 |
#include <sys/mntent.h> |
|
77 |
||
78 |
#include "zpool_util.h" |
|
79 |
||
80 |
#define DISK_ROOT "/dev/dsk" |
|
81 |
#define RDISK_ROOT "/dev/rdsk" |
|
82 |
#define BACKUP_SLICE "s2" |
|
83 |
||
84 |
/* |
|
85 |
* For any given vdev specification, we can have multiple errors. The |
|
86 |
* vdev_error() function keeps track of whether we have seen an error yet, and |
|
87 |
* prints out a header if its the first error we've seen. |
|
88 |
*/ |
|
2082 | 89 |
boolean_t error_seen; |
90 |
boolean_t is_force; |
|
789 | 91 |
|
2082 | 92 |
/*PRINTFLIKE1*/ |
93 |
static void |
|
789 | 94 |
vdev_error(const char *fmt, ...) |
95 |
{ |
|
96 |
va_list ap; |
|
97 |
||
98 |
if (!error_seen) { |
|
99 |
(void) fprintf(stderr, gettext("invalid vdev specification\n")); |
|
100 |
if (!is_force) |
|
101 |
(void) fprintf(stderr, gettext("use '-f' to override " |
|
102 |
"the following errors:\n")); |
|
103 |
else |
|
104 |
(void) fprintf(stderr, gettext("the following errors " |
|
105 |
"must be manually repaired:\n")); |
|
2082 | 106 |
error_seen = B_TRUE; |
789 | 107 |
} |
108 |
||
109 |
va_start(ap, fmt); |
|
110 |
(void) vfprintf(stderr, fmt, ap); |
|
111 |
va_end(ap); |
|
112 |
} |
|
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 | 116 |
{ |
1544 | 117 |
/* |
2082 | 118 |
* ENXIO/ENODEV is a valid error message if the device doesn't live in |
1544 | 119 |
* /dev/dsk. Don't bother printing an error message in this case. |
120 |
*/ |
|
2082 | 121 |
if (error == ENXIO || error == ENODEV) |
1544 | 122 |
return; |
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 | 126 |
} |
127 |
||
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 | 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 | 132 |
check_slice(const char *path, int force, boolean_t wholedisk, boolean_t isspare) |
789 | 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 | 136 |
dm_who_type_t who; |
789 | 137 |
|
4946 | 138 |
if (force) |
139 |
who = DM_WHO_ZPOOL_FORCE; |
|
140 |
else if (isspare) |
|
141 |
who = DM_WHO_ZPOOL_SPARE; |
|
142 |
else |
|
143 |
who = DM_WHO_ZPOOL; |
|
144 |
||
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 | 153 |
} |
154 |
} |
|
155 |
||
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 | 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 | 173 |
} |
174 |
||
4082
2e3825fd8bb5
6372011 libdiskmgt needs to build appropriate .po file
mmusante
parents:
3741
diff
changeset
|
175 |
return (0); |
789 | 176 |
} |
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 | 179 |
/* |
180 |
* Validate a whole disk. Iterate over all slices on the disk and make sure |
|
181 |
* that none is in use by calling check_slice(). |
|
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 | 184 |
check_disk(const char *name, dm_descriptor_t disk, int force, int isspare) |
789 | 185 |
{ |
186 |
dm_descriptor_t *drive, *media, *slice; |
|
187 |
int err = 0; |
|
188 |
int i; |
|
189 |
int ret; |
|
190 |
||
191 |
/* |
|
192 |
* Get the drive associated with this disk. This should never fail, |
|
193 |
* because we already have an alias handle open for the device. |
|
194 |
*/ |
|
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 | 201 |
|
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 | 209 |
|
210 |
dm_free_descriptors(drive); |
|
211 |
||
212 |
/* |
|
213 |
* It is possible that the user has specified a removable media drive, |
|
214 |
* and the media is not present. |
|
215 |
*/ |
|
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 | 218 |
vdev_error(gettext("'%s' has no media in drive\n"), name); |
219 |
return (-1); |
|
220 |
} |
|
221 |
||
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 | 229 |
|
230 |
dm_free_descriptors(media); |
|
231 |
||
232 |
ret = 0; |
|
233 |
||
234 |
/* |
|
235 |
* Iterate over all slices and report any errors. We don't care about |
|
236 |
* overlapping slices because we are using the whole disk. |
|
237 |
*/ |
|
238 |
for (i = 0; slice[i] != NULL; i++) { |
|
2082 | 239 |
char *name = dm_get_name(slice[i], &err); |
240 |
||
241 |
if (check_slice(name, force, B_TRUE, isspare) != 0) |
|
789 | 242 |
ret = -1; |
2082 | 243 |
|
244 |
dm_free_name(name); |
|
789 | 245 |
} |
246 |
||
247 |
dm_free_descriptors(slice); |
|
248 |
return (ret); |
|
249 |
} |
|
250 |
||
251 |
/* |
|
1352
b7039548de2f
6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents:
1171
diff
changeset
|
252 |
* Validate a device. |
789 | 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 | 255 |
check_device(const char *path, boolean_t force, boolean_t isspare) |
789 | 256 |
{ |
257 |
dm_descriptor_t desc; |
|
258 |
int err; |
|
1352
b7039548de2f
6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents:
1171
diff
changeset
|
259 |
char *dev; |
789 | 260 |
|
261 |
/* |
|
262 |
* For whole disks, libdiskmgt does not include the leading dev path. |
|
263 |
*/ |
|
264 |
dev = strrchr(path, '/'); |
|
265 |
assert(dev != NULL); |
|
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 | 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 | 271 |
} |
272 |
||
2082 | 273 |
return (check_slice(path, force, B_FALSE, isspare)); |
789 | 274 |
} |
275 |
||
276 |
/* |
|
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 | 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 | 281 |
check_file(const char *file, boolean_t force, boolean_t isspare) |
789 | 282 |
{ |
1352
b7039548de2f
6343802 zpool(1M) should make better use of libdiskmgt
eschrock
parents:
1171
diff
changeset
|
283 |
char *name; |
789 | 284 |
int fd; |
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 | 288 |
boolean_t inuse; |
789 | 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 | 299 |
if ((fd = open(file, O_RDONLY)) < 0) |
300 |
return (0); |
|
301 |
||
2082 | 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 | 323 |
/* |
324 |
* Allow hot spares to be shared between pools. |
|
325 |
*/ |
|
326 |
if (state == POOL_STATE_SPARE && isspare) |
|
327 |
return (0); |
|
328 |
||
329 |
if (state == POOL_STATE_ACTIVE || |
|
330 |
state == POOL_STATE_SPARE || !force) { |
|
331 |
switch (state) { |
|
332 |
case POOL_STATE_SPARE: |
|
333 |
vdev_error(gettext("%s is reserved as a hot " |
|
334 |
"spare for pool %s\n"), file, name); |
|
335 |
break; |
|
336 |
default: |
|
337 |
vdev_error(gettext("%s is part of %s pool " |
|
338 |
"'%s'\n"), file, desc, name); |
|
339 |
break; |
|
340 |
} |
|
789 | 341 |
ret = -1; |
342 |
} |
|
343 |
||
344 |
free(name); |
|
345 |
} |
|
346 |
||
347 |
(void) close(fd); |
|
348 |
return (ret); |
|
349 |
} |
|
350 |
||
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 | 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 | 378 |
} |
379 |
||
380 |
/* |
|
381 |
* Create a leaf vdev. Determine if this is a file or a device. If it's a |
|
382 |
* device, fill in the device id to make a complete nvlist. Valid forms for a |
|
383 |
* leaf vdev are: |
|
384 |
* |
|
385 |
* /dev/dsk/xxx Complete disk path |
|
386 |
* /xxx Full path to file |
|
387 |
* xxx Shorthand for /dev/dsk/xxx |
|
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 | 390 |
make_leaf_vdev(const char *arg, uint64_t is_log) |
789 | 391 |
{ |
392 |
char path[MAXPATHLEN]; |
|
393 |
struct stat64 statbuf; |
|
394 |
nvlist_t *vdev = NULL; |
|
395 |
char *type = NULL; |
|
2082 | 396 |
boolean_t wholedisk = B_FALSE; |
789 | 397 |
|
398 |
/* |
|
399 |
* Determine what type of vdev this is, and put the full path into |
|
400 |
* 'path'. We detect whether this is a device of file afterwards by |
|
401 |
* checking the st_mode of the file. |
|
402 |
*/ |
|
403 |
if (arg[0] == '/') { |
|
404 |
/* |
|
405 |
* Complete device or file path. Exact type is determined by |
|
406 |
* examining the file descriptor afterwards. |
|
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 | 410 |
(void) fprintf(stderr, |
411 |
gettext("cannot open '%s': %s\n"), |
|
412 |
arg, strerror(errno)); |
|
413 |
return (NULL); |
|
414 |
} |
|
415 |
||
416 |
(void) strlcpy(path, arg, sizeof (path)); |
|
417 |
} else { |
|
418 |
/* |
|
419 |
* This may be a short path for a device, or it could be total |
|
420 |
* gibberish. Check to see if it's a known device in |
|
421 |
* /dev/dsk/. As part of this check, see if we've been given a |
|
422 |
* an entire disk (minus the slice number). |
|
423 |
*/ |
|
424 |
(void) snprintf(path, sizeof (path), "%s/%s", DISK_ROOT, |
|
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 | 428 |
/* |
429 |
* If we got ENOENT, then the user gave us |
|
430 |
* gibberish, so try to direct them with a |
|
431 |
* reasonable error message. Otherwise, |
|
432 |
* regurgitate strerror() since it's the best we |
|
433 |
* can do. |
|
434 |
*/ |
|
435 |
if (errno == ENOENT) { |
|
436 |
(void) fprintf(stderr, |
|
437 |
gettext("cannot open '%s': no such " |
|
438 |
"device in %s\n"), arg, DISK_ROOT); |
|
439 |
(void) fprintf(stderr, |
|
440 |
gettext("must be a full path or " |
|
441 |
"shorthand device name\n")); |
|
442 |
return (NULL); |
|
443 |
} else { |
|
444 |
(void) fprintf(stderr, |
|
445 |
gettext("cannot open '%s': %s\n"), |
|
446 |
path, strerror(errno)); |
|
447 |
return (NULL); |
|
448 |
} |
|
449 |
} |
|
450 |
} |
|
451 |
||
452 |
/* |
|
453 |
* Determine whether this is a device or a file. |
|
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 | 456 |
type = VDEV_TYPE_DISK; |
457 |
} else if (S_ISREG(statbuf.st_mode)) { |
|
458 |
type = VDEV_TYPE_FILE; |
|
459 |
} else { |
|
460 |
(void) fprintf(stderr, gettext("cannot use '%s': must be a " |
|
461 |
"block device or regular file\n"), path); |
|
462 |
return (NULL); |
|
463 |
} |
|
464 |
||
465 |
/* |
|
466 |
* Finally, we have the complete device or file, and we know that it is |
|
467 |
* acceptable to use. Construct the nvlist to describe this vdev. All |
|
468 |
* vdevs have a 'path' element, and devices also have a 'devid' element. |
|
469 |
*/ |
|
470 |
verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0); |
|
471 |
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0); |
|
472 |
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0); |
|
4527 | 473 |
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0); |
1171 | 474 |
if (strcmp(type, VDEV_TYPE_DISK) == 0) |
475 |
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, |
|
476 |
(uint64_t)wholedisk) == 0); |
|
789 | 477 |
|
478 |
/* |
|
479 |
* For a whole disk, defer getting its devid until after labeling it. |
|
480 |
*/ |
|
481 |
if (S_ISBLK(statbuf.st_mode) && !wholedisk) { |
|
482 |
/* |
|
483 |
* Get the devid for the device. |
|
484 |
*/ |
|
485 |
int fd; |
|
486 |
ddi_devid_t devid; |
|
487 |
char *minor = NULL, *devid_str = NULL; |
|
488 |
||
489 |
if ((fd = open(path, O_RDONLY)) < 0) { |
|
490 |
(void) fprintf(stderr, gettext("cannot open '%s': " |
|
491 |
"%s\n"), path, strerror(errno)); |
|
492 |
nvlist_free(vdev); |
|
493 |
return (NULL); |
|
494 |
} |
|
495 |
||
496 |
if (devid_get(fd, &devid) == 0) { |
|
497 |
if (devid_get_minor_name(fd, &minor) == 0 && |
|
498 |
(devid_str = devid_str_encode(devid, minor)) != |
|
499 |
NULL) { |
|
500 |
verify(nvlist_add_string(vdev, |
|
501 |
ZPOOL_CONFIG_DEVID, devid_str) == 0); |
|
502 |
} |
|
503 |
if (devid_str != NULL) |
|
504 |
devid_str_free(devid_str); |
|
505 |
if (minor != NULL) |
|
506 |
devid_str_free(minor); |
|
507 |
devid_free(devid); |
|
508 |
} |
|
509 |
||
510 |
(void) close(fd); |
|
511 |
} |
|
512 |
||
513 |
return (vdev); |
|
514 |
} |
|
515 |
||
516 |
/* |
|
517 |
* Go through and verify the replication level of the pool is consistent. |
|
518 |
* Performs the following checks: |
|
519 |
* |
|
520 |
* For the new spec, verifies that devices in mirrors and raidz are the |
|
521 |
* same size. |
|
522 |
* |
|
523 |
* If the current configuration already has inconsistent replication |
|
524 |
* levels, ignore any other potential problems in the new spec. |
|
525 |
* |
|
526 |
* Otherwise, make sure that the current spec (if there is one) and the new |
|
527 |
* spec have consistent replication levels. |
|
528 |
*/ |
|
529 |
typedef struct replication_level { |
|
2082 | 530 |
char *zprl_type; |
531 |
uint64_t zprl_children; |
|
532 |
uint64_t zprl_parity; |
|
789 | 533 |
} replication_level_t; |
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 | 537 |
/* |
538 |
* Given a list of toplevel vdevs, return the current replication level. If |
|
539 |
* the config is inconsistent, then NULL is returned. If 'fatal' is set, then |
|
540 |
* an error message will be displayed for each self-inconsistent vdev. |
|
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 | 543 |
get_replication(nvlist_t *nvroot, boolean_t fatal) |
789 | 544 |
{ |
545 |
nvlist_t **top; |
|
546 |
uint_t t, toplevels; |
|
547 |
nvlist_t **child; |
|
548 |
uint_t c, children; |
|
549 |
nvlist_t *nv; |
|
550 |
char *type; |
|
551 |
replication_level_t lastrep, rep, *ret; |
|
2082 | 552 |
boolean_t dontreport; |
789 | 553 |
|
554 |
ret = safe_malloc(sizeof (replication_level_t)); |
|
555 |
||
556 |
verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, |
|
557 |
&top, &toplevels) == 0); |
|
558 |
||
2082 | 559 |
lastrep.zprl_type = NULL; |
789 | 560 |
for (t = 0; t < toplevels; t++) { |
4527 | 561 |
uint64_t is_log = B_FALSE; |
562 |
||
789 | 563 |
nv = top[t]; |
564 |
||
4527 | 565 |
/* |
566 |
* For separate logs we ignore the top level vdev replication |
|
567 |
* constraints. |
|
568 |
*/ |
|
569 |
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log); |
|
570 |
if (is_log) |
|
571 |
continue; |
|
572 |
||
573 |
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, |
|
574 |
&type) == 0); |
|
789 | 575 |
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, |
576 |
&child, &children) != 0) { |
|
577 |
/* |
|
578 |
* This is a 'file' or 'disk' vdev. |
|
579 |
*/ |
|
2082 | 580 |
rep.zprl_type = type; |
581 |
rep.zprl_children = 1; |
|
582 |
rep.zprl_parity = 0; |
|
789 | 583 |
} else { |
584 |
uint64_t vdev_size; |
|
585 |
||
586 |
/* |
|
587 |
* This is a mirror or RAID-Z vdev. Go through and make |
|
588 |
* sure the contents are all the same (files vs. disks), |
|
589 |
* keeping track of the number of elements in the |
|
590 |
* process. |
|
591 |
* |
|
592 |
* We also check that the size of each vdev (if it can |
|
593 |
* be determined) is the same. |
|
594 |
*/ |
|
2082 | 595 |
rep.zprl_type = type; |
596 |
rep.zprl_children = 0; |
|
597 |
||
598 |
if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { |
|
599 |
verify(nvlist_lookup_uint64(nv, |
|
600 |
ZPOOL_CONFIG_NPARITY, |
|
601 |
&rep.zprl_parity) == 0); |
|
602 |
assert(rep.zprl_parity != 0); |
|
603 |
} else { |
|
604 |
rep.zprl_parity = 0; |
|
605 |
} |
|
789 | 606 |
|
607 |
/* |
|
4527 | 608 |
* The 'dontreport' variable indicates that we've |
789 | 609 |
* already reported an error for this spec, so don't |
610 |
* bother doing it again. |
|
611 |
*/ |
|
612 |
type = NULL; |
|
613 |
dontreport = 0; |
|
614 |
vdev_size = -1ULL; |
|
615 |
for (c = 0; c < children; c++) { |
|
616 |
nvlist_t *cnv = child[c]; |
|
617 |
char *path; |
|
618 |
struct stat64 statbuf; |
|
619 |
uint64_t size = -1ULL; |
|
620 |
char *childtype; |
|
621 |
int fd, err; |
|
622 |
||
2082 | 623 |
rep.zprl_children++; |
789 | 624 |
|
625 |
verify(nvlist_lookup_string(cnv, |
|
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 | 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 | 649 |
verify(nvlist_lookup_string(cnv, |
650 |
ZPOOL_CONFIG_PATH, &path) == 0); |
|
651 |
||
652 |
/* |
|
653 |
* If we have a raidz/mirror that combines disks |
|
654 |
* with files, report it as an error. |
|
655 |
*/ |
|
656 |
if (!dontreport && type != NULL && |
|
657 |
strcmp(type, childtype) != 0) { |
|
658 |
if (ret != NULL) |
|
659 |
free(ret); |
|
660 |
ret = NULL; |
|
661 |
if (fatal) |
|
662 |
vdev_error(gettext( |
|
663 |
"mismatched replication " |
|
664 |
"level: %s contains both " |
|
665 |
"files and devices\n"), |
|
2082 | 666 |
rep.zprl_type); |
789 | 667 |
else |
668 |
return (NULL); |
|
2082 | 669 |
dontreport = B_TRUE; |
789 | 670 |
} |
671 |
||
672 |
/* |
|
673 |
* According to stat(2), the value of 'st_size' |
|
674 |
* is undefined for block devices and character |
|
675 |
* devices. But there is no effective way to |
|
676 |
* determine the real size in userland. |
|
677 |
* |
|
678 |
* Instead, we'll take advantage of an |
|
679 |
* implementation detail of spec_size(). If the |
|
680 |
* device is currently open, then we (should) |
|
681 |
* return a valid size. |
|
682 |
* |
|
683 |
* If we still don't get a valid size (indicated |
|
684 |
* by a size of 0 or MAXOFFSET_T), then ignore |
|
685 |
* this device altogether. |
|
686 |
*/ |
|
687 |
if ((fd = open(path, O_RDONLY)) >= 0) { |
|
688 |
err = fstat64(fd, &statbuf); |
|
689 |
(void) close(fd); |
|
690 |
} else { |
|
691 |
err = stat64(path, &statbuf); |
|
692 |
} |
|
693 |
||
694 |
if (err != 0 || |
|
695 |
statbuf.st_size == 0 || |
|
696 |
statbuf.st_size == MAXOFFSET_T) |
|
697 |
continue; |
|
698 |
||
699 |
size = statbuf.st_size; |
|
700 |
||
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 | 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 | 711 |
if (ret != NULL) |
712 |
free(ret); |
|
713 |
ret = NULL; |
|
714 |
if (fatal) |
|
715 |
vdev_error(gettext( |
|
716 |
"%s contains devices of " |
|
717 |
"different sizes\n"), |
|
2082 | 718 |
rep.zprl_type); |
789 | 719 |
else |
720 |
return (NULL); |
|
2082 | 721 |
dontreport = B_TRUE; |
789 | 722 |
} |
723 |
||
724 |
type = childtype; |
|
725 |
vdev_size = size; |
|
726 |
} |
|
727 |
} |
|
728 |
||
729 |
/* |
|
730 |
* At this point, we have the replication of the last toplevel |
|
731 |
* vdev in 'rep'. Compare it to 'lastrep' to see if its |
|
732 |
* different. |
|
733 |
*/ |
|
2082 | 734 |
if (lastrep.zprl_type != NULL) { |
735 |
if (strcmp(lastrep.zprl_type, rep.zprl_type) != 0) { |
|
789 | 736 |
if (ret != NULL) |
737 |
free(ret); |
|
738 |
ret = NULL; |
|
739 |
if (fatal) |
|
740 |
vdev_error(gettext( |
|
2082 | 741 |
"mismatched replication level: " |
742 |
"both %s and %s vdevs are " |
|
789 | 743 |
"present\n"), |
2082 | 744 |
lastrep.zprl_type, rep.zprl_type); |
789 | 745 |
else |
746 |
return (NULL); |
|
2082 | 747 |
} else if (lastrep.zprl_parity != rep.zprl_parity) { |
789 | 748 |
if (ret) |
749 |
free(ret); |
|
750 |
ret = NULL; |
|
751 |
if (fatal) |
|
752 |
vdev_error(gettext( |
|
2082 | 753 |
"mismatched replication level: " |
754 |
"both %llu and %llu device parity " |
|
755 |
"%s vdevs are present\n"), |
|
756 |
lastrep.zprl_parity, |
|
757 |
rep.zprl_parity, |
|
758 |
rep.zprl_type); |
|
759 |
else |
|
760 |
return (NULL); |
|
761 |
} else if (lastrep.zprl_children != rep.zprl_children) { |
|
762 |
if (ret) |
|
763 |
free(ret); |
|
764 |
ret = NULL; |
|
765 |
if (fatal) |
|
766 |
vdev_error(gettext( |
|
767 |
"mismatched replication level: " |
|
768 |
"both %llu-way and %llu-way %s " |
|
789 | 769 |
"vdevs are present\n"), |
2082 | 770 |
lastrep.zprl_children, |
771 |
rep.zprl_children, |
|
772 |
rep.zprl_type); |
|
789 | 773 |
else |
774 |
return (NULL); |
|
775 |
} |
|
776 |
} |
|
777 |
lastrep = rep; |
|
778 |
} |
|
779 |
||
2082 | 780 |
if (ret != NULL) |
781 |
*ret = rep; |
|
789 | 782 |
|
783 |
return (ret); |
|
784 |
} |
|
785 |
||
786 |
/* |
|
787 |
* Check the replication level of the vdev spec against the current pool. Calls |
|
788 |
* get_replication() to make sure the new spec is self-consistent. If the pool |
|
789 |
* has a consistent replication level, then we ignore any errors. Otherwise, |
|
790 |
* report any difference between the two. |
|
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 | 793 |
check_replication(nvlist_t *config, nvlist_t *newroot) |
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 | 797 |
replication_level_t *current = NULL, *new; |
798 |
int ret; |
|
799 |
||
800 |
/* |
|
801 |
* If we have a current pool configuration, check to see if it's |
|
802 |
* self-consistent. If not, simply return success. |
|
803 |
*/ |
|
804 |
if (config != NULL) { |
|
805 |
nvlist_t *nvroot; |
|
806 |
||
807 |
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, |
|
808 |
&nvroot) == 0); |
|
2082 | 809 |
if ((current = get_replication(nvroot, B_FALSE)) == NULL) |
789 | 810 |
return (0); |
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 | 821 |
|
822 |
/* |
|
4527 | 823 |
* If all we have is logs then there's no replication level to check. |
824 |
*/ |
|
825 |
if (num_logs(newroot) == children) { |
|
826 |
free(current); |
|
827 |
return (0); |
|
828 |
} |
|
829 |
||
830 |
/* |
|
789 | 831 |
* Get the replication level of the new vdev spec, reporting any |
832 |
* inconsistencies found. |
|
833 |
*/ |
|
2082 | 834 |
if ((new = get_replication(newroot, B_TRUE)) == NULL) { |
789 | 835 |
free(current); |
836 |
return (-1); |
|
837 |
} |
|
838 |
||
839 |
/* |
|
840 |
* Check to see if the new vdev spec matches the replication level of |
|
841 |
* the current pool. |
|
842 |
*/ |
|
843 |
ret = 0; |
|
844 |
if (current != NULL) { |
|
2082 | 845 |
if (strcmp(current->zprl_type, new->zprl_type) != 0) { |
846 |
vdev_error(gettext( |
|
847 |
"mismatched replication level: pool uses %s " |
|
848 |
"and new vdev is %s\n"), |
|
849 |
current->zprl_type, new->zprl_type); |
|
850 |
ret = -1; |
|
851 |
} else if (current->zprl_parity != new->zprl_parity) { |
|
789 | 852 |
vdev_error(gettext( |
2082 | 853 |
"mismatched replication level: pool uses %llu " |
854 |
"device parity and new vdev uses %llu\n"), |
|
855 |
current->zprl_parity, new->zprl_parity); |
|
856 |
ret = -1; |
|
857 |
} else if (current->zprl_children != new->zprl_children) { |
|
858 |
vdev_error(gettext( |
|
859 |
"mismatched replication level: pool uses %llu-way " |
|
860 |
"%s and new vdev uses %llu-way %s\n"), |
|
861 |
current->zprl_children, current->zprl_type, |
|
862 |
new->zprl_children, new->zprl_type); |
|
789 | 863 |
ret = -1; |
864 |
} |
|
865 |
} |
|
866 |
||
867 |
free(new); |
|
868 |
if (current != NULL) |
|
869 |
free(current); |
|
870 |
||
871 |
return (ret); |
|
872 |
} |
|
873 |
||
874 |
/* |
|
875 |
* Go through and find any whole disks in the vdev specification, labelling them |
|
876 |
* as appropriate. When constructing the vdev spec, we were unable to open this |
|
877 |
* device in order to provide a devid. Now that we have labelled the disk and |
|
878 |
* know that slice 0 is valid, we can construct the devid now. |
|
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 | 881 |
* devid already (because we were able to open the whole disk). Otherwise, we |
882 |
* need to get the devid after we label the disk. |
|
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 | 886 |
{ |
887 |
nvlist_t **child; |
|
888 |
uint_t c, children; |
|
889 |
char *type, *path, *diskname; |
|
890 |
char buf[MAXPATHLEN]; |
|
1171 | 891 |
uint64_t wholedisk; |
789 | 892 |
int fd; |
893 |
int ret; |
|
894 |
ddi_devid_t devid; |
|
895 |
char *minor = NULL, *devid_str = NULL; |
|
896 |
||
897 |
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); |
|
898 |
||
899 |
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, |
|
900 |
&child, &children) != 0) { |
|
901 |
||
902 |
if (strcmp(type, VDEV_TYPE_DISK) != 0) |
|
903 |
return (0); |
|
904 |
||
905 |
/* |
|
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 | 908 |
* slice and stat()ing the device. |
909 |
*/ |
|
910 |
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); |
|
1171 | 911 |
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, |
912 |
&wholedisk) != 0 || !wholedisk) |
|
789 | 913 |
return (0); |
914 |
||
915 |
diskname = strrchr(path, '/'); |
|
916 |
assert(diskname != NULL); |
|
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 | 919 |
return (-1); |
920 |
||
921 |
/* |
|
922 |
* Fill in the devid, now that we've labeled the disk. |
|
923 |
*/ |
|
924 |
(void) snprintf(buf, sizeof (buf), "%ss0", path); |
|
925 |
if ((fd = open(buf, O_RDONLY)) < 0) { |
|
926 |
(void) fprintf(stderr, |
|
927 |
gettext("cannot open '%s': %s\n"), |
|
928 |
buf, strerror(errno)); |
|
929 |
return (-1); |
|
930 |
} |
|
931 |
||
932 |
if (devid_get(fd, &devid) == 0) { |
|
933 |
if (devid_get_minor_name(fd, &minor) == 0 && |
|
934 |
(devid_str = devid_str_encode(devid, minor)) != |
|
935 |
NULL) { |
|
936 |
verify(nvlist_add_string(nv, |
|
937 |
ZPOOL_CONFIG_DEVID, devid_str) == 0); |
|
938 |
} |
|
939 |
if (devid_str != NULL) |
|
940 |
devid_str_free(devid_str); |
|
941 |
if (minor != NULL) |
|
942 |
devid_str_free(minor); |
|
943 |
devid_free(devid); |
|
944 |
} |
|
945 |
||
1171 | 946 |
/* |
947 |
* Update the path to refer to the 's0' slice. The presence of |
|
948 |
* the 'whole_disk' field indicates to the CLI that we should |
|
949 |
* chop off the slice number when displaying the device in |
|
950 |
* future output. |
|
951 |
*/ |
|
952 |
verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, buf) == 0); |
|
953 |
||
789 | 954 |
(void) close(fd); |
955 |
||
956 |
return (0); |
|
957 |
} |
|
958 |
||
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 | 961 |
return (ret); |
962 |
||
2082 | 963 |
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, |
964 |
&child, &children) == 0) |
|
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 | 967 |
return (ret); |
968 |
||
5450 | 969 |
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, |
970 |
&child, &children) == 0) |
|
971 |
for (c = 0; c < children; c++) |
|
972 |
if ((ret = make_disks(zhp, child[c])) != 0) |
|
973 |
return (ret); |
|
974 |
||
789 | 975 |
return (0); |
976 |
} |
|
977 |
||
978 |
/* |
|
2082 | 979 |
* Determine if the given path is a hot spare within the given configuration. |
980 |
*/ |
|
981 |
static boolean_t |
|
982 |
is_spare(nvlist_t *config, const char *path) |
|
983 |
{ |
|
984 |
int fd; |
|
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 | 987 |
nvlist_t *label; |
988 |
uint64_t guid, spareguid; |
|
989 |
nvlist_t *nvroot; |
|
990 |
nvlist_t **spares; |
|
991 |
uint_t i, nspares; |
|
992 |
boolean_t inuse; |
|
993 |
||
994 |
if ((fd = open(path, O_RDONLY)) < 0) |
|
995 |
return (B_FALSE); |
|
996 |
||
997 |
if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) != 0 || |
|
998 |
!inuse || |
|
999 |
state != POOL_STATE_SPARE || |
|
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 | 1002 |
(void) close(fd); |
1003 |
return (B_FALSE); |
|
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 | 1007 |
|
1008 |
verify(nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &guid) == 0); |
|
1009 |
nvlist_free(label); |
|
1010 |
||
1011 |
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, |
|
1012 |
&nvroot) == 0); |
|
1013 |
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, |
|
1014 |
&spares, &nspares) == 0) { |
|
1015 |
for (i = 0; i < nspares; i++) { |
|
1016 |
verify(nvlist_lookup_uint64(spares[i], |
|
1017 |
ZPOOL_CONFIG_GUID, &spareguid) == 0); |
|
1018 |
if (spareguid == guid) |
|
1019 |
return (B_TRUE); |
|
1020 |
} |
|
1021 |
} |
|
1022 |
||
1023 |
return (B_FALSE); |
|
1024 |
} |
|
1025 |
||
1026 |
/* |
|
789 | 1027 |
* Go through and find any devices that are in use. We rely on libdiskmgt for |
1028 |
* the majority of this task. |
|
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 | 1033 |
{ |
1034 |
nvlist_t **child; |
|
1035 |
uint_t c, children; |
|
1036 |
char *type, *path; |
|
1037 |
int ret; |
|
2082 | 1038 |
char buf[MAXPATHLEN]; |
1039 |
uint64_t wholedisk; |
|
789 | 1040 |
|
1041 |
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); |
|
1042 |
||
1043 |
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, |
|
1044 |
&child, &children) != 0) { |
|
1045 |
||
1046 |
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); |
|
1047 |
||
2082 | 1048 |
/* |
1049 |
* As a generic check, we look to see if this is a replace of a |
|
1050 |
* hot spare within the same pool. If so, we allow it |
|
1051 |
* regardless of what libdiskmgt or zpool_in_use() says. |
|
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 | 1054 |
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, |
1055 |
&wholedisk) == 0 && wholedisk) |
|
1056 |
(void) snprintf(buf, sizeof (buf), "%ss0", |
|
1057 |
path); |
|
1058 |
else |
|
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 | 1061 |
if (is_spare(config, buf)) |
1062 |
return (0); |
|
1063 |
} |
|
1064 |
||
789 | 1065 |
if (strcmp(type, VDEV_TYPE_DISK) == 0) |
2082 | 1066 |
ret = check_device(path, force, isspare); |
789 | 1067 |
|
1068 |
if (strcmp(type, VDEV_TYPE_FILE) == 0) |
|
2082 | 1069 |
ret = check_file(path, force, isspare); |
789 | 1070 |
|
1071 |
return (ret); |
|
1072 |
} |
|
1073 |
||
1074 |
for (c = 0; c < children; c++) |
|
2082 | 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 | 1077 |
return (ret); |
1078 |
||
2082 | 1079 |
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, |
1080 |
&child, &children) == 0) |
|
1081 |
for (c = 0; c < children; c++) |
|
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 | 1084 |
return (ret); |
5450 | 1085 |
|
1086 |
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, |
|
1087 |
&child, &children) == 0) |
|
1088 |
for (c = 0; c < children; c++) |
|
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 | 1091 |
return (ret); |
1092 |
||
789 | 1093 |
return (0); |
1094 |
} |
|
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 | 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 | 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 | 1120 |
return (VDEV_TYPE_RAIDZ); |
1121 |
} |
|
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 | 1125 |
|
1126 |
if (strcmp(type, "mirror") == 0) { |
|
1127 |
if (mindev != NULL) |
|
1128 |
*mindev = 2; |
|
1129 |
return (VDEV_TYPE_MIRROR); |
|
1130 |
} |
|
1131 |
||
1132 |
if (strcmp(type, "spare") == 0) { |
|
1133 |
if (mindev != NULL) |
|
1134 |
*mindev = 1; |
|
1135 |
return (VDEV_TYPE_SPARE); |
|
1136 |
} |
|
1137 |
||
4527 | 1138 |
if (strcmp(type, "log") == 0) { |
1139 |
if (mindev != NULL) |
|
1140 |
*mindev = 1; |
|
1141 |
return (VDEV_TYPE_LOG); |
|
1142 |
} |
|
1143 |
||
5450 | 1144 |
if (strcmp(type, "cache") == 0) { |
1145 |
if (mindev != NULL) |
|
1146 |
*mindev = 1; |
|
1147 |
return (VDEV_TYPE_L2CACHE); |
|
1148 |
} |
|
1149 |
||
2082 | 1150 |
return (NULL); |
1151 |
} |
|
1152 |
||
789 | 1153 |
/* |
1154 |
* Construct a syntactically valid vdev specification, |
|
1155 |
* and ensure that all devices and files exist and can be opened. |
|
1156 |
* Note: we don't bother freeing anything in the error paths |
|
1157 |
* because the program is just going to exit anyway. |
|
1158 |
*/ |
|
1159 |
nvlist_t * |
|
1160 |
construct_spec(int argc, char **argv) |
|
1161 |
{ |
|
5450 | 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 | 1164 |
const char *type; |
4527 | 1165 |
uint64_t is_log; |
1166 |
boolean_t seen_logs; |
|
789 | 1167 |
|
1168 |
top = NULL; |
|
1169 |
toplevels = 0; |
|
2082 | 1170 |
spares = NULL; |
5450 | 1171 |
l2cache = NULL; |
2082 | 1172 |
nspares = 0; |
4527 | 1173 |
nlogs = 0; |
5450 | 1174 |
nl2cache = 0; |
4527 | 1175 |
is_log = B_FALSE; |
1176 |
seen_logs = B_FALSE; |
|
789 | 1177 |
|
1178 |
while (argc > 0) { |
|
1179 |
nv = NULL; |
|
1180 |
||
1181 |
/* |
|
1182 |
* If it's a mirror or raidz, the subsequent arguments are |
|
1183 |
* its leaves -- until we encounter the next mirror or raidz. |
|
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 | 1186 |
nvlist_t **child = NULL; |
1187 |
int c, children = 0; |
|
789 | 1188 |
|
4527 | 1189 |
if (strcmp(type, VDEV_TYPE_SPARE) == 0) { |
1190 |
if (spares != NULL) { |
|
1191 |
(void) fprintf(stderr, |
|
1192 |
gettext("invalid vdev " |
|
1193 |
"specification: 'spare' can be " |
|
1194 |
"specified only once\n")); |
|
1195 |
return (NULL); |
|
1196 |
} |
|
1197 |
is_log = B_FALSE; |
|
1198 |
} |
|
1199 |
||
1200 |
if (strcmp(type, VDEV_TYPE_LOG) == 0) { |
|
1201 |
if (seen_logs) { |
|
1202 |
(void) fprintf(stderr, |
|
1203 |
gettext("invalid vdev " |
|
1204 |
"specification: 'log' can be " |
|
1205 |
"specified only once\n")); |
|
1206 |
return (NULL); |
|
1207 |
} |
|
1208 |
seen_logs = B_TRUE; |
|
1209 |
is_log = B_TRUE; |
|
1210 |
argc--; |
|
1211 |
argv++; |
|
1212 |
/* |
|
1213 |
* A log is not a real grouping device. |
|
1214 |
* We just set is_log and continue. |
|
1215 |
*/ |
|
1216 |
continue; |
|
1217 |
} |
|
1218 |
||
5450 | 1219 |
if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) { |
1220 |
if (l2cache != NULL) { |
|
1221 |
(void) fprintf(stderr, |
|
1222 |
gettext("invalid vdev " |
|
1223 |
"specification: 'cache' can be " |
|
1224 |
"specified only once\n")); |
|
1225 |
return (NULL); |
|
1226 |
} |
|
1227 |
is_log = B_FALSE; |
|
1228 |
} |
|
1229 |
||
4527 | 1230 |
if (is_log) { |
1231 |
if (strcmp(type, VDEV_TYPE_MIRROR) != 0) { |
|
1232 |
(void) fprintf(stderr, |
|
1233 |
gettext("invalid vdev " |
|
1234 |
"specification: unsupported 'log' " |
|
1235 |
"device: %s\n"), type); |
|
1236 |
return (NULL); |
|
1237 |
} |
|
1238 |
nlogs++; |
|
2082 | 1239 |
} |
789 | 1240 |
|
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 | 1243 |
break; |
1244 |
children++; |
|
1245 |
child = realloc(child, |
|
1246 |
children * sizeof (nvlist_t *)); |
|
1247 |
if (child == NULL) |
|
2856 | 1248 |
zpool_no_memory(); |
4527 | 1249 |
if ((nv = make_leaf_vdev(argv[c], B_FALSE)) |
1250 |
== NULL) |
|
789 | 1251 |
return (NULL); |
1252 |
child[children - 1] = nv; |
|
1253 |
} |
|
1254 |
||
2082 | 1255 |
if (children < mindev) { |
1256 |
(void) fprintf(stderr, gettext("invalid vdev " |
|
1257 |
"specification: %s requires at least %d " |
|
1258 |
"devices\n"), argv[0], mindev); |
|
1259 |
return (NULL); |
|
1260 |
} |
|
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 | 1269 |
argc -= c; |
1270 |
argv += c; |
|
1271 |
||
2082 | 1272 |
if (strcmp(type, VDEV_TYPE_SPARE) == 0) { |
1273 |
spares = child; |
|
1274 |
nspares = children; |
|
1275 |
continue; |
|
5450 | 1276 |
} else if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) { |
1277 |
l2cache = child; |
|
1278 |
nl2cache = children; |
|
1279 |
continue; |
|
2082 | 1280 |
} else { |
1281 |
verify(nvlist_alloc(&nv, NV_UNIQUE_NAME, |
|
1282 |
0) == 0); |
|
1283 |
verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE, |
|
1284 |
type) == 0); |
|
4527 | 1285 |
verify(nvlist_add_uint64(nv, |
1286 |
ZPOOL_CONFIG_IS_LOG, is_log) == 0); |
|
2082 | 1287 |
if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { |
1288 |
verify(nvlist_add_uint64(nv, |
|
1289 |
ZPOOL_CONFIG_NPARITY, |
|
1290 |
mindev - 1) == 0); |
|
1291 |
} |
|
1292 |
verify(nvlist_add_nvlist_array(nv, |
|
1293 |
ZPOOL_CONFIG_CHILDREN, child, |
|
1294 |
children) == 0); |
|
1295 |
||
1296 |
for (c = 0; c < children; c++) |
|
1297 |
nvlist_free(child[c]); |
|
1298 |
free(child); |
|
789 | 1299 |
} |
1300 |
} else { |
|
1301 |
/* |
|
1302 |
* We have a device. Pass off to make_leaf_vdev() to |
|
1303 |
* construct the appropriate nvlist describing the vdev. |
|
1304 |
*/ |
|
4527 | 1305 |
if ((nv = make_leaf_vdev(argv[0], is_log)) == NULL) |
789 | 1306 |
return (NULL); |
4527 | 1307 |
if (is_log) |
1308 |
nlogs++; |
|
789 | 1309 |
argc--; |
1310 |
argv++; |
|
1311 |
} |
|
1312 |
||
1313 |
toplevels++; |
|
1314 |
top = realloc(top, toplevels * sizeof (nvlist_t *)); |
|
1315 |
if (top == NULL) |
|
2856 | 1316 |
zpool_no_memory(); |
789 | 1317 |
top[toplevels - 1] = nv; |
1318 |
} |
|
1319 |
||
5450 | 1320 |
if (toplevels == 0 && nspares == 0 && nl2cache == 0) { |
2082 | 1321 |
(void) fprintf(stderr, gettext("invalid vdev " |
1322 |
"specification: at least one toplevel vdev must be " |
|
1323 |
"specified\n")); |
|
1324 |
return (NULL); |
|
1325 |
} |
|
1326 |
||
4527 | 1327 |
if (seen_logs && nlogs == 0) { |
1328 |
(void) fprintf(stderr, gettext("invalid vdev specification: " |
|
1329 |
"log requires at least 1 device\n")); |
|
1330 |
return (NULL); |
|
1331 |
} |
|
1332 |
||
789 | 1333 |
/* |
1334 |
* Finally, create nvroot and add all top-level vdevs to it. |
|
1335 |
*/ |
|
1336 |
verify(nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) == 0); |
|
1337 |
verify(nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE, |
|
1338 |
VDEV_TYPE_ROOT) == 0); |
|
1339 |
verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, |
|
1340 |
top, toplevels) == 0); |
|
2082 | 1341 |
if (nspares != 0) |
1342 |
verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, |
|
1343 |
spares, nspares) == 0); |
|
5450 | 1344 |
if (nl2cache != 0) |
1345 |
verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, |
|
1346 |
l2cache, nl2cache) == 0); |
|
789 | 1347 |
|
1348 |
for (t = 0; t < toplevels; t++) |
|
1349 |
nvlist_free(top[t]); |
|
2082 | 1350 |
for (t = 0; t < nspares; t++) |
1351 |
nvlist_free(spares[t]); |
|
5450 | 1352 |
for (t = 0; t < nl2cache; t++) |
1353 |
nvlist_free(l2cache[t]); |
|
2082 | 1354 |
if (spares) |
1355 |
free(spares); |
|
5450 | 1356 |
if (l2cache) |
1357 |
free(l2cache); |
|
789 | 1358 |
free(top); |
1359 |
||
1360 |
return (nvroot); |
|
1361 |
} |
|
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 | 1410 |
/* |
1411 |
* Get and validate the contents of the given vdev specification. This ensures |
|
1412 |
* that the nvlist returned is well-formed, that all the devices exist, and that |
|
1413 |
* they are not currently in use by any other known consumer. The 'poolconfig' |
|
1414 |
* parameter is the current configuration of the pool when adding devices |
|
1415 |
* existing pool, and is used to perform additional checks, such as changing the |
|
1416 |
* replication level of the pool. It can be 'NULL' to indicate that this is a |
|
1417 |
* new pool. The 'force' flag controls whether devices should be forcefully |
|
1418 |
* added, even if they appear in use. |
|
1419 |
*/ |
|
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 | 1423 |
{ |
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 | 1426 |
is_force = force; |
1427 |
||
1428 |
/* |
|
1429 |
* Construct the vdev specification. If this is successful, we know |
|
1430 |
* that we have a valid specification, and that all devices can be |
|
1431 |
* opened. |
|
1432 |
*/ |
|
1433 |
if ((newroot = construct_spec(argc, argv)) == NULL) |
|
1434 |
return (NULL); |
|
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 | 1439 |
/* |
1440 |
* Validate each device to make sure that its not shared with another |
|
1441 |
* subsystem. We do this even if 'force' is set, because there are some |
|
1442 |
* uses (such as a dedicated dump device) that even '-f' cannot |
|
1443 |
* override. |
|
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 | 1446 |
nvlist_free(newroot); |
1447 |
return (NULL); |
|
1448 |
} |
|
1449 |
||
1450 |
/* |
|
1451 |
* Check the replication level of the given vdevs and report any errors |
|
1452 |
* found. We include the existing pool spec, if any, as we need to |
|
1453 |
* catch changes against the existing replication level. |
|
1454 |
*/ |
|
1455 |
if (check_rep && check_replication(poolconfig, newroot) != 0) { |
|
1456 |
nvlist_free(newroot); |
|
1457 |
return (NULL); |
|
1458 |
} |
|
1459 |
||
1460 |
/* |
|
1461 |
* Run through the vdev specification and label any whole disks found. |
|
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 | 1464 |
nvlist_free(newroot); |
1465 |
return (NULL); |
|
1466 |
} |
|
1467 |
||
1468 |
return (newroot); |
|
1469 |
} |