1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or https://opensource.org/licenses/CDDL-1.0.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
28 * Copyright (c) 2018 Datto Inc.
29 * Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
30 * Copyright (c) 2017, Intel Corporation.
31 * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
32 * Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
33 * Copyright (c) 2021, 2023, Klara Inc.
34 * Copyright (c) 2025 Hewlett Packard Enterprise Development LP.
35 */
36
37 #include <errno.h>
38 #include <libintl.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <strings.h>
42 #include <unistd.h>
43 #include <libgen.h>
44 #include <zone.h>
45 #include <sys/stat.h>
46 #include <sys/efi_partition.h>
47 #include <sys/systeminfo.h>
48 #include <sys/zfs_ioctl.h>
49 #include <sys/zfs_sysfs.h>
50 #include <sys/vdev_disk.h>
51 #include <sys/types.h>
52 #include <dlfcn.h>
53 #include <libzutil.h>
54 #include <fcntl.h>
55
56 #include "zfs_namecheck.h"
57 #include "zfs_prop.h"
58 #include "libzfs_impl.h"
59 #include "zfs_comutil.h"
60 #include "zfeature_common.h"
61
62 static boolean_t zpool_vdev_is_interior(const char *name);
63
64 typedef struct prop_flags {
65 unsigned int create:1; /* Validate property on creation */
66 unsigned int import:1; /* Validate property on import */
67 unsigned int vdevprop:1; /* Validate property as a VDEV property */
68 } prop_flags_t;
69
70 /*
71 * ====================================================================
72 * zpool property functions
73 * ====================================================================
74 */
75
76 static int
zpool_get_all_props(zpool_handle_t * zhp)77 zpool_get_all_props(zpool_handle_t *zhp)
78 {
79 zfs_cmd_t zc = {"\0"};
80 libzfs_handle_t *hdl = zhp->zpool_hdl;
81
82 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
83
84 if (zhp->zpool_n_propnames > 0) {
85 nvlist_t *innvl = fnvlist_alloc();
86 fnvlist_add_string_array(innvl, ZPOOL_GET_PROPS_NAMES,
87 zhp->zpool_propnames, zhp->zpool_n_propnames);
88 zcmd_write_src_nvlist(hdl, &zc, innvl);
89 fnvlist_free(innvl);
90 }
91
92 zcmd_alloc_dst_nvlist(hdl, &zc, 0);
93
94 while (zfs_ioctl(hdl, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) {
95 if (errno == ENOMEM)
96 zcmd_expand_dst_nvlist(hdl, &zc);
97 else {
98 zcmd_free_nvlists(&zc);
99 return (-1);
100 }
101 }
102
103 if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) {
104 zcmd_free_nvlists(&zc);
105 return (-1);
106 }
107
108 zcmd_free_nvlists(&zc);
109
110 return (0);
111 }
112
113 int
zpool_props_refresh(zpool_handle_t * zhp)114 zpool_props_refresh(zpool_handle_t *zhp)
115 {
116 nvlist_t *old_props;
117
118 old_props = zhp->zpool_props;
119
120 if (zpool_get_all_props(zhp) != 0)
121 return (-1);
122
123 nvlist_free(old_props);
124 return (0);
125 }
126
127 static const char *
zpool_get_prop_string(zpool_handle_t * zhp,zpool_prop_t prop,zprop_source_t * src)128 zpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop,
129 zprop_source_t *src)
130 {
131 nvlist_t *nv, *nvl;
132 const char *value;
133 zprop_source_t source;
134
135 nvl = zhp->zpool_props;
136 if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
137 source = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
138 value = fnvlist_lookup_string(nv, ZPROP_VALUE);
139 } else {
140 source = ZPROP_SRC_DEFAULT;
141 if ((value = zpool_prop_default_string(prop)) == NULL)
142 value = "-";
143 }
144
145 if (src)
146 *src = source;
147
148 return (value);
149 }
150
151 uint64_t
zpool_get_prop_int(zpool_handle_t * zhp,zpool_prop_t prop,zprop_source_t * src)152 zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src)
153 {
154 nvlist_t *nv, *nvl;
155 uint64_t value;
156 zprop_source_t source;
157
158 if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) {
159 /*
160 * zpool_get_all_props() has most likely failed because
161 * the pool is faulted, but if all we need is the top level
162 * vdev's guid then get it from the zhp config nvlist.
163 */
164 if ((prop == ZPOOL_PROP_GUID) &&
165 (nvlist_lookup_nvlist(zhp->zpool_config,
166 ZPOOL_CONFIG_VDEV_TREE, &nv) == 0) &&
167 (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value)
168 == 0)) {
169 return (value);
170 }
171 return (zpool_prop_default_numeric(prop));
172 }
173
174 nvl = zhp->zpool_props;
175 if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
176 source = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
177 value = fnvlist_lookup_uint64(nv, ZPROP_VALUE);
178 } else {
179 source = ZPROP_SRC_DEFAULT;
180 value = zpool_prop_default_numeric(prop);
181 }
182
183 if (src)
184 *src = source;
185
186 return (value);
187 }
188
189 /*
190 * Map VDEV STATE to printed strings.
191 */
192 const char *
zpool_state_to_name(vdev_state_t state,vdev_aux_t aux)193 zpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
194 {
195 switch (state) {
196 case VDEV_STATE_CLOSED:
197 case VDEV_STATE_OFFLINE:
198 return (gettext("OFFLINE"));
199 case VDEV_STATE_REMOVED:
200 return (gettext("REMOVED"));
201 case VDEV_STATE_CANT_OPEN:
202 if (aux == VDEV_AUX_CORRUPT_DATA || aux == VDEV_AUX_BAD_LOG)
203 return (gettext("FAULTED"));
204 else if (aux == VDEV_AUX_SPLIT_POOL)
205 return (gettext("SPLIT"));
206 else
207 return (gettext("UNAVAIL"));
208 case VDEV_STATE_FAULTED:
209 return (gettext("FAULTED"));
210 case VDEV_STATE_DEGRADED:
211 return (gettext("DEGRADED"));
212 case VDEV_STATE_HEALTHY:
213 return (gettext("ONLINE"));
214
215 default:
216 break;
217 }
218
219 return (gettext("UNKNOWN"));
220 }
221
222 /*
223 * Map POOL STATE to printed strings.
224 */
225 const char *
zpool_pool_state_to_name(pool_state_t state)226 zpool_pool_state_to_name(pool_state_t state)
227 {
228 switch (state) {
229 default:
230 break;
231 case POOL_STATE_ACTIVE:
232 return (gettext("ACTIVE"));
233 case POOL_STATE_EXPORTED:
234 return (gettext("EXPORTED"));
235 case POOL_STATE_DESTROYED:
236 return (gettext("DESTROYED"));
237 case POOL_STATE_SPARE:
238 return (gettext("SPARE"));
239 case POOL_STATE_L2CACHE:
240 return (gettext("L2CACHE"));
241 case POOL_STATE_UNINITIALIZED:
242 return (gettext("UNINITIALIZED"));
243 case POOL_STATE_UNAVAIL:
244 return (gettext("UNAVAIL"));
245 case POOL_STATE_POTENTIALLY_ACTIVE:
246 return (gettext("POTENTIALLY_ACTIVE"));
247 }
248
249 return (gettext("UNKNOWN"));
250 }
251
252 /*
253 * Given a pool handle, return the pool health string ("ONLINE", "DEGRADED",
254 * "SUSPENDED", etc).
255 */
256 const char *
zpool_get_state_str(zpool_handle_t * zhp)257 zpool_get_state_str(zpool_handle_t *zhp)
258 {
259 zpool_errata_t errata;
260 zpool_status_t status;
261 const char *str;
262
263 status = zpool_get_status(zhp, NULL, &errata);
264
265 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
266 str = gettext("FAULTED");
267 } else if (status == ZPOOL_STATUS_IO_FAILURE_WAIT ||
268 status == ZPOOL_STATUS_IO_FAILURE_CONTINUE ||
269 status == ZPOOL_STATUS_IO_FAILURE_MMP) {
270 str = gettext("SUSPENDED");
271 } else {
272 nvlist_t *nvroot = fnvlist_lookup_nvlist(
273 zpool_get_config(zhp, NULL), ZPOOL_CONFIG_VDEV_TREE);
274 uint_t vsc;
275 vdev_stat_t *vs = (vdev_stat_t *)fnvlist_lookup_uint64_array(
276 nvroot, ZPOOL_CONFIG_VDEV_STATS, &vsc);
277 str = zpool_state_to_name(vs->vs_state, vs->vs_aux);
278 }
279 return (str);
280 }
281
282 /*
283 * Get a zpool property value for 'prop' and return the value in
284 * a pre-allocated buffer.
285 */
286 int
zpool_get_prop(zpool_handle_t * zhp,zpool_prop_t prop,char * buf,size_t len,zprop_source_t * srctype,boolean_t literal)287 zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
288 size_t len, zprop_source_t *srctype, boolean_t literal)
289 {
290 uint64_t intval;
291 const char *strval;
292 zprop_source_t src = ZPROP_SRC_NONE;
293
294 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
295 switch (prop) {
296 case ZPOOL_PROP_NAME:
297 (void) strlcpy(buf, zpool_get_name(zhp), len);
298 break;
299
300 case ZPOOL_PROP_HEALTH:
301 (void) strlcpy(buf, zpool_get_state_str(zhp), len);
302 break;
303
304 case ZPOOL_PROP_GUID:
305 intval = zpool_get_prop_int(zhp, prop, &src);
306 (void) snprintf(buf, len, "%llu", (u_longlong_t)intval);
307 break;
308
309 case ZPOOL_PROP_ALTROOT:
310 case ZPOOL_PROP_CACHEFILE:
311 case ZPOOL_PROP_COMMENT:
312 case ZPOOL_PROP_COMPATIBILITY:
313 if (zhp->zpool_props != NULL ||
314 zpool_get_all_props(zhp) == 0) {
315 (void) strlcpy(buf,
316 zpool_get_prop_string(zhp, prop, &src),
317 len);
318 break;
319 }
320 zfs_fallthrough;
321 default:
322 (void) strlcpy(buf, "-", len);
323 break;
324 }
325
326 if (srctype != NULL)
327 *srctype = src;
328 return (0);
329 }
330
331 /*
332 * ZPOOL_PROP_DEDUPCACHED can be fetched by name only using
333 * the ZPOOL_GET_PROPS_NAMES mechanism
334 */
335 if (prop == ZPOOL_PROP_DEDUPCACHED) {
336 zpool_add_propname(zhp, ZPOOL_DEDUPCACHED_PROP_NAME);
337 (void) zpool_props_refresh(zhp);
338 }
339
340 if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
341 prop != ZPOOL_PROP_NAME)
342 return (-1);
343
344 switch (zpool_prop_get_type(prop)) {
345 case PROP_TYPE_STRING:
346 (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src),
347 len);
348 break;
349
350 case PROP_TYPE_NUMBER:
351 intval = zpool_get_prop_int(zhp, prop, &src);
352
353 switch (prop) {
354 case ZPOOL_PROP_DEDUP_TABLE_QUOTA:
355 /*
356 * If dedup quota is 0, we translate this into 'none'
357 * (unless literal is set). And if it is UINT64_MAX
358 * we translate that as 'automatic' (limit to size of
359 * the dedicated dedup VDEV. Otherwise, fall throught
360 * into the regular number formating.
361 */
362 if (intval == 0) {
363 (void) strlcpy(buf, literal ? "0" : "none",
364 len);
365 break;
366 } else if (intval == UINT64_MAX) {
367 (void) strlcpy(buf, "auto", len);
368 break;
369 }
370 zfs_fallthrough;
371
372 case ZPOOL_PROP_SIZE:
373 case ZPOOL_PROP_NORMAL_SIZE:
374 case ZPOOL_PROP_SPECIAL_SIZE:
375 case ZPOOL_PROP_DEDUP_SIZE:
376 case ZPOOL_PROP_LOG_SIZE:
377 case ZPOOL_PROP_ELOG_SIZE:
378 case ZPOOL_PROP_SELOG_SIZE:
379 case ZPOOL_PROP_ALLOCATED:
380 case ZPOOL_PROP_NORMAL_ALLOCATED:
381 case ZPOOL_PROP_SPECIAL_ALLOCATED:
382 case ZPOOL_PROP_DEDUP_ALLOCATED:
383 case ZPOOL_PROP_LOG_ALLOCATED:
384 case ZPOOL_PROP_ELOG_ALLOCATED:
385 case ZPOOL_PROP_SELOG_ALLOCATED:
386 case ZPOOL_PROP_AVAILABLE:
387 case ZPOOL_PROP_NORMAL_AVAILABLE:
388 case ZPOOL_PROP_SPECIAL_AVAILABLE:
389 case ZPOOL_PROP_DEDUP_AVAILABLE:
390 case ZPOOL_PROP_LOG_AVAILABLE:
391 case ZPOOL_PROP_ELOG_AVAILABLE:
392 case ZPOOL_PROP_SELOG_AVAILABLE:
393 case ZPOOL_PROP_FREE:
394 case ZPOOL_PROP_NORMAL_FREE:
395 case ZPOOL_PROP_SPECIAL_FREE:
396 case ZPOOL_PROP_DEDUP_FREE:
397 case ZPOOL_PROP_LOG_FREE:
398 case ZPOOL_PROP_ELOG_FREE:
399 case ZPOOL_PROP_SELOG_FREE:
400 case ZPOOL_PROP_USABLE:
401 case ZPOOL_PROP_NORMAL_USABLE:
402 case ZPOOL_PROP_SPECIAL_USABLE:
403 case ZPOOL_PROP_DEDUP_USABLE:
404 case ZPOOL_PROP_LOG_USABLE:
405 case ZPOOL_PROP_ELOG_USABLE:
406 case ZPOOL_PROP_SELOG_USABLE:
407 case ZPOOL_PROP_USED:
408 case ZPOOL_PROP_NORMAL_USED:
409 case ZPOOL_PROP_SPECIAL_USED:
410 case ZPOOL_PROP_DEDUP_USED:
411 case ZPOOL_PROP_LOG_USED:
412 case ZPOOL_PROP_ELOG_USED:
413 case ZPOOL_PROP_SELOG_USED:
414 case ZPOOL_PROP_FREEING:
415 case ZPOOL_PROP_LEAKED:
416 case ZPOOL_PROP_ASHIFT:
417 case ZPOOL_PROP_MAXBLOCKSIZE:
418 case ZPOOL_PROP_MAXDNODESIZE:
419 case ZPOOL_PROP_BCLONESAVED:
420 case ZPOOL_PROP_BCLONEUSED:
421 case ZPOOL_PROP_DEDUP_TABLE_SIZE:
422 case ZPOOL_PROP_DEDUPUSED:
423 case ZPOOL_PROP_DEDUPSAVED:
424 case ZPOOL_PROP_DEDUPCACHED:
425 if (literal)
426 (void) snprintf(buf, len, "%llu",
427 (u_longlong_t)intval);
428 else
429 (void) zfs_nicenum(intval, buf, len);
430 break;
431
432 case ZPOOL_PROP_EXPANDSZ:
433 case ZPOOL_PROP_NORMAL_EXPANDSZ:
434 case ZPOOL_PROP_SPECIAL_EXPANDSZ:
435 case ZPOOL_PROP_DEDUP_EXPANDSZ:
436 case ZPOOL_PROP_LOG_EXPANDSZ:
437 case ZPOOL_PROP_ELOG_EXPANDSZ:
438 case ZPOOL_PROP_SELOG_EXPANDSZ:
439 case ZPOOL_PROP_CHECKPOINT:
440 if (intval == 0) {
441 (void) strlcpy(buf, "-", len);
442 } else if (literal) {
443 (void) snprintf(buf, len, "%llu",
444 (u_longlong_t)intval);
445 } else {
446 (void) zfs_nicebytes(intval, buf, len);
447 }
448 break;
449
450 case ZPOOL_PROP_CAPACITY:
451 case ZPOOL_PROP_NORMAL_CAPACITY:
452 case ZPOOL_PROP_SPECIAL_CAPACITY:
453 case ZPOOL_PROP_DEDUP_CAPACITY:
454 case ZPOOL_PROP_LOG_CAPACITY:
455 case ZPOOL_PROP_ELOG_CAPACITY:
456 case ZPOOL_PROP_SELOG_CAPACITY:
457 if (literal) {
458 (void) snprintf(buf, len, "%llu",
459 (u_longlong_t)intval);
460 } else {
461 (void) snprintf(buf, len, "%llu%%",
462 (u_longlong_t)intval);
463 }
464 break;
465
466 case ZPOOL_PROP_FRAGMENTATION:
467 case ZPOOL_PROP_NORMAL_FRAGMENTATION:
468 case ZPOOL_PROP_SPECIAL_FRAGMENTATION:
469 case ZPOOL_PROP_DEDUP_FRAGMENTATION:
470 case ZPOOL_PROP_LOG_FRAGMENTATION:
471 case ZPOOL_PROP_ELOG_FRAGMENTATION:
472 case ZPOOL_PROP_SELOG_FRAGMENTATION:
473 if (intval == ZFS_FRAG_INVALID) {
474 (void) strlcpy(buf, "-", len);
475 } else if (literal) {
476 (void) snprintf(buf, len, "%llu",
477 (u_longlong_t)intval);
478 } else {
479 (void) snprintf(buf, len, "%llu%%",
480 (u_longlong_t)intval);
481 }
482 break;
483
484 case ZPOOL_PROP_BCLONERATIO:
485 case ZPOOL_PROP_DEDUPRATIO:
486 if (literal)
487 (void) snprintf(buf, len, "%llu.%02llu",
488 (u_longlong_t)(intval / 100),
489 (u_longlong_t)(intval % 100));
490 else
491 (void) snprintf(buf, len, "%llu.%02llux",
492 (u_longlong_t)(intval / 100),
493 (u_longlong_t)(intval % 100));
494 break;
495
496 case ZPOOL_PROP_HEALTH:
497 (void) strlcpy(buf, zpool_get_state_str(zhp), len);
498 break;
499 case ZPOOL_PROP_VERSION:
500 if (intval >= SPA_VERSION_FEATURES) {
501 (void) snprintf(buf, len, "-");
502 break;
503 }
504 zfs_fallthrough;
505 default:
506 (void) snprintf(buf, len, "%llu", (u_longlong_t)intval);
507 }
508 break;
509
510 case PROP_TYPE_INDEX:
511 intval = zpool_get_prop_int(zhp, prop, &src);
512 if (zpool_prop_index_to_string(prop, intval, &strval)
513 != 0)
514 return (-1);
515 (void) strlcpy(buf, strval, len);
516 break;
517
518 default:
519 abort();
520 }
521
522 if (srctype)
523 *srctype = src;
524
525 return (0);
526 }
527
528 /*
529 * Get a zpool property value for 'propname' and return the value in
530 * a pre-allocated buffer.
531 */
532 int
zpool_get_userprop(zpool_handle_t * zhp,const char * propname,char * buf,size_t len,zprop_source_t * srctype)533 zpool_get_userprop(zpool_handle_t *zhp, const char *propname, char *buf,
534 size_t len, zprop_source_t *srctype)
535 {
536 nvlist_t *nv;
537 uint64_t ival;
538 const char *value;
539 zprop_source_t source = ZPROP_SRC_LOCAL;
540
541 if (zhp->zpool_props == NULL)
542 zpool_get_all_props(zhp);
543
544 if (nvlist_lookup_nvlist(zhp->zpool_props, propname, &nv) == 0) {
545 if (nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0)
546 source = ival;
547 verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
548 } else {
549 source = ZPROP_SRC_DEFAULT;
550 value = "-";
551 }
552
553 if (srctype)
554 *srctype = source;
555
556 (void) strlcpy(buf, value, len);
557
558 return (0);
559 }
560
561 /*
562 * Check if the bootfs name has the same pool name as it is set to.
563 * Assuming bootfs is a valid dataset name.
564 */
565 static boolean_t
bootfs_name_valid(const char * pool,const char * bootfs)566 bootfs_name_valid(const char *pool, const char *bootfs)
567 {
568 int len = strlen(pool);
569 if (bootfs[0] == '\0')
570 return (B_TRUE);
571
572 if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM|ZFS_TYPE_SNAPSHOT))
573 return (B_FALSE);
574
575 if (strncmp(pool, bootfs, len) == 0 &&
576 (bootfs[len] == '/' || bootfs[len] == '\0'))
577 return (B_TRUE);
578
579 return (B_FALSE);
580 }
581
582 /*
583 * Given an nvlist of zpool properties to be set, validate that they are
584 * correct, and parse any numeric properties (index, boolean, etc) if they are
585 * specified as strings.
586 */
587 static nvlist_t *
zpool_valid_proplist(libzfs_handle_t * hdl,const char * poolname,nvlist_t * props,uint64_t version,prop_flags_t flags,char * errbuf)588 zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
589 nvlist_t *props, uint64_t version, prop_flags_t flags, char *errbuf)
590 {
591 nvpair_t *elem;
592 nvlist_t *retprops;
593 zpool_prop_t prop;
594 const char *strval;
595 uint64_t intval;
596 const char *check;
597 struct stat64 statbuf;
598 zpool_handle_t *zhp;
599 char *parent, *slash;
600 char report[1024];
601
602 if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
603 (void) no_memory(hdl);
604 return (NULL);
605 }
606
607 elem = NULL;
608 while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
609 const char *propname = nvpair_name(elem);
610
611 if (flags.vdevprop && zpool_prop_vdev(propname)) {
612 vdev_prop_t vprop = vdev_name_to_prop(propname);
613
614 if (vdev_prop_readonly(vprop)) {
615 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
616 "is readonly"), propname);
617 (void) zfs_error(hdl, EZFS_PROPREADONLY,
618 errbuf);
619 goto error;
620 }
621
622 if (zprop_parse_value(hdl, elem, vprop, ZFS_TYPE_VDEV,
623 retprops, &strval, &intval, errbuf) != 0)
624 goto error;
625
626 continue;
627 } else if (flags.vdevprop && vdev_prop_user(propname)) {
628 if (nvlist_add_nvpair(retprops, elem) != 0) {
629 (void) no_memory(hdl);
630 goto error;
631 }
632 continue;
633 } else if (flags.vdevprop) {
634 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
635 "invalid property: '%s'"), propname);
636 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
637 goto error;
638 }
639
640 prop = zpool_name_to_prop(propname);
641 if (prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname)) {
642 int err;
643 char *fname = strchr(propname, '@') + 1;
644
645 err = zfeature_lookup_name(fname, NULL);
646 if (err != 0) {
647 ASSERT3U(err, ==, ENOENT);
648 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
649 "feature '%s' unsupported by kernel"),
650 fname);
651 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
652 goto error;
653 }
654
655 if (nvpair_type(elem) != DATA_TYPE_STRING) {
656 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
657 "'%s' must be a string"), propname);
658 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
659 goto error;
660 }
661
662 (void) nvpair_value_string(elem, &strval);
663 if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0 &&
664 strcmp(strval, ZFS_FEATURE_DISABLED) != 0) {
665 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
666 "property '%s' can only be set to "
667 "'enabled' or 'disabled'"), propname);
668 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
669 goto error;
670 }
671
672 if (!flags.create &&
673 strcmp(strval, ZFS_FEATURE_DISABLED) == 0) {
674 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
675 "property '%s' can only be set to "
676 "'disabled' at creation time"), propname);
677 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
678 goto error;
679 }
680
681 if (nvlist_add_uint64(retprops, propname, 0) != 0) {
682 (void) no_memory(hdl);
683 goto error;
684 }
685 continue;
686 } else if (prop == ZPOOL_PROP_INVAL &&
687 zfs_prop_user(propname)) {
688 /*
689 * This is a user property: make sure it's a
690 * string, and that it's less than ZAP_MAXNAMELEN.
691 */
692 if (nvpair_type(elem) != DATA_TYPE_STRING) {
693 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
694 "'%s' must be a string"), propname);
695 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
696 goto error;
697 }
698
699 if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
700 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
701 "property name '%s' is too long"),
702 propname);
703 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
704 goto error;
705 }
706
707 (void) nvpair_value_string(elem, &strval);
708
709 if (strlen(strval) >= ZFS_MAXPROPLEN) {
710 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
711 "property value '%s' is too long"),
712 strval);
713 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
714 goto error;
715 }
716
717 if (nvlist_add_string(retprops, propname,
718 strval) != 0) {
719 (void) no_memory(hdl);
720 goto error;
721 }
722
723 continue;
724 }
725
726 /*
727 * Make sure this property is valid and applies to this type.
728 */
729 if (prop == ZPOOL_PROP_INVAL) {
730 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
731 "invalid property '%s'"), propname);
732 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
733 goto error;
734 }
735
736 if (zpool_prop_readonly(prop)) {
737 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
738 "is readonly"), propname);
739 (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
740 goto error;
741 }
742
743 if (!flags.create && zpool_prop_setonce(prop)) {
744 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
745 "property '%s' can only be set at "
746 "creation time"), propname);
747 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
748 goto error;
749 }
750
751 if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops,
752 &strval, &intval, errbuf) != 0)
753 goto error;
754
755 /*
756 * Perform additional checking for specific properties.
757 */
758 switch (prop) {
759 case ZPOOL_PROP_VERSION:
760 if (intval < version ||
761 !SPA_VERSION_IS_SUPPORTED(intval)) {
762 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
763 "property '%s' number %llu is invalid."),
764 propname, (unsigned long long)intval);
765 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
766 goto error;
767 }
768 break;
769
770 case ZPOOL_PROP_ASHIFT:
771 if (intval != 0 &&
772 (intval < ASHIFT_MIN || intval > ASHIFT_MAX)) {
773 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
774 "property '%s' number %llu is invalid, "
775 "only values between %" PRId32 " and %"
776 PRId32 " are allowed."),
777 propname, (unsigned long long)intval,
778 ASHIFT_MIN, ASHIFT_MAX);
779 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
780 goto error;
781 }
782 break;
783
784 case ZPOOL_PROP_BOOTFS:
785 if (flags.create || flags.import) {
786 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
787 "property '%s' cannot be set at creation "
788 "or import time"), propname);
789 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
790 goto error;
791 }
792
793 if (version < SPA_VERSION_BOOTFS) {
794 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
795 "pool must be upgraded to support "
796 "'%s' property"), propname);
797 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
798 goto error;
799 }
800
801 /*
802 * bootfs property value has to be a dataset name and
803 * the dataset has to be in the same pool as it sets to.
804 */
805 if (!bootfs_name_valid(poolname, strval)) {
806 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
807 "is an invalid name"), strval);
808 (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
809 goto error;
810 }
811
812 if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) {
813 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
814 "could not open pool '%s'"), poolname);
815 (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
816 goto error;
817 }
818 zpool_close(zhp);
819 break;
820
821 case ZPOOL_PROP_ALTROOT:
822 if (!flags.create && !flags.import) {
823 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
824 "property '%s' can only be set during pool "
825 "creation or import"), propname);
826 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
827 goto error;
828 }
829
830 if (strval[0] != '/') {
831 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
832 "bad alternate root '%s'"), strval);
833 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
834 goto error;
835 }
836 break;
837
838 case ZPOOL_PROP_CACHEFILE:
839 if (strval[0] == '\0')
840 break;
841
842 if (strcmp(strval, "none") == 0)
843 break;
844
845 if (strval[0] != '/') {
846 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
847 "property '%s' must be empty, an "
848 "absolute path, or 'none'"), propname);
849 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
850 goto error;
851 }
852
853 parent = strdup(strval);
854 if (parent == NULL) {
855 (void) zfs_error(hdl, EZFS_NOMEM, errbuf);
856 goto error;
857 }
858 slash = strrchr(parent, '/');
859
860 if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
861 strcmp(slash, "/..") == 0) {
862 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
863 "'%s' is not a valid file"), parent);
864 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
865 free(parent);
866 goto error;
867 }
868
869 *slash = '\0';
870
871 if (parent[0] != '\0' &&
872 (stat64(parent, &statbuf) != 0 ||
873 !S_ISDIR(statbuf.st_mode))) {
874 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
875 "'%s' is not a valid directory"),
876 parent);
877 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
878 free(parent);
879 goto error;
880 }
881 free(parent);
882
883 break;
884
885 case ZPOOL_PROP_COMPATIBILITY:
886 switch (zpool_load_compat(strval, NULL, report, 1024)) {
887 case ZPOOL_COMPATIBILITY_OK:
888 case ZPOOL_COMPATIBILITY_WARNTOKEN:
889 break;
890 case ZPOOL_COMPATIBILITY_BADFILE:
891 case ZPOOL_COMPATIBILITY_BADTOKEN:
892 case ZPOOL_COMPATIBILITY_NOFILES:
893 zfs_error_aux(hdl, "%s", report);
894 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
895 goto error;
896 }
897 break;
898
899 case ZPOOL_PROP_COMMENT:
900 for (check = strval; *check != '\0'; check++) {
901 if (!isprint(*check)) {
902 zfs_error_aux(hdl,
903 dgettext(TEXT_DOMAIN,
904 "comment may only have printable "
905 "characters"));
906 (void) zfs_error(hdl, EZFS_BADPROP,
907 errbuf);
908 goto error;
909 }
910 }
911 if (strlen(strval) > ZPROP_MAX_COMMENT) {
912 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
913 "comment must not exceed %d characters"),
914 ZPROP_MAX_COMMENT);
915 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
916 goto error;
917 }
918 break;
919 case ZPOOL_PROP_READONLY:
920 if (!flags.import) {
921 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
922 "property '%s' can only be set at "
923 "import time"), propname);
924 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
925 goto error;
926 }
927 break;
928 case ZPOOL_PROP_MULTIHOST:
929 if (get_system_hostid() == 0) {
930 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
931 "requires a non-zero system hostid"));
932 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
933 goto error;
934 }
935 break;
936 case ZPOOL_PROP_DEDUPDITTO:
937 printf("Note: property '%s' no longer has "
938 "any effect\n", propname);
939 break;
940
941 default:
942 break;
943 }
944 }
945
946 return (retprops);
947 error:
948 nvlist_free(retprops);
949 return (NULL);
950 }
951
952 /*
953 * Set zpool property : propname=propval.
954 */
955 int
zpool_set_prop(zpool_handle_t * zhp,const char * propname,const char * propval)956 zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
957 {
958 zfs_cmd_t zc = {"\0"};
959 int ret;
960 char errbuf[ERRBUFLEN];
961 nvlist_t *nvl = NULL;
962 nvlist_t *realprops;
963 uint64_t version;
964 prop_flags_t flags = { 0 };
965
966 (void) snprintf(errbuf, sizeof (errbuf),
967 dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
968 zhp->zpool_name);
969
970 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
971 return (no_memory(zhp->zpool_hdl));
972
973 if (nvlist_add_string(nvl, propname, propval) != 0) {
974 nvlist_free(nvl);
975 return (no_memory(zhp->zpool_hdl));
976 }
977
978 version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
979 if ((realprops = zpool_valid_proplist(zhp->zpool_hdl,
980 zhp->zpool_name, nvl, version, flags, errbuf)) == NULL) {
981 nvlist_free(nvl);
982 return (-1);
983 }
984
985 nvlist_free(nvl);
986 nvl = realprops;
987
988 /*
989 * Execute the corresponding ioctl() to set this property.
990 */
991 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
992
993 zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl);
994
995 ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc);
996
997 zcmd_free_nvlists(&zc);
998 nvlist_free(nvl);
999
1000 if (ret)
1001 (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
1002 else
1003 (void) zpool_props_refresh(zhp);
1004
1005 return (ret);
1006 }
1007
1008 int
zpool_expand_proplist(zpool_handle_t * zhp,zprop_list_t ** plp,zfs_type_t type,boolean_t literal)1009 zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
1010 zfs_type_t type, boolean_t literal)
1011 {
1012 libzfs_handle_t *hdl = zhp->zpool_hdl;
1013 zprop_list_t *entry;
1014 char buf[ZFS_MAXPROPLEN];
1015 nvlist_t *features = NULL;
1016 nvpair_t *nvp;
1017 zprop_list_t **last;
1018 boolean_t firstexpand = (NULL == *plp);
1019 int i;
1020
1021 if (zprop_expand_list(hdl, plp, type) != 0)
1022 return (-1);
1023
1024 if (type == ZFS_TYPE_VDEV)
1025 return (0);
1026
1027 last = plp;
1028 while (*last != NULL)
1029 last = &(*last)->pl_next;
1030
1031 if ((*plp)->pl_all)
1032 features = zpool_get_features(zhp);
1033
1034 if ((*plp)->pl_all && firstexpand) {
1035 /* Handle userprops in the all properties case */
1036 if (zhp->zpool_props == NULL && zpool_props_refresh(zhp))
1037 return (-1);
1038
1039 nvp = NULL;
1040 while ((nvp = nvlist_next_nvpair(zhp->zpool_props, nvp)) !=
1041 NULL) {
1042 const char *propname = nvpair_name(nvp);
1043
1044 if (!zfs_prop_user(propname))
1045 continue;
1046
1047 entry = zfs_alloc(hdl, sizeof (zprop_list_t));
1048 entry->pl_prop = ZPROP_USERPROP;
1049 entry->pl_user_prop = zfs_strdup(hdl, propname);
1050 entry->pl_width = strlen(entry->pl_user_prop);
1051 entry->pl_all = B_TRUE;
1052
1053 *last = entry;
1054 last = &entry->pl_next;
1055 }
1056
1057 for (i = 0; i < SPA_FEATURES; i++) {
1058 entry = zfs_alloc(hdl, sizeof (zprop_list_t));
1059 entry->pl_prop = ZPROP_USERPROP;
1060 entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s",
1061 spa_feature_table[i].fi_uname);
1062 entry->pl_width = strlen(entry->pl_user_prop);
1063 entry->pl_all = B_TRUE;
1064
1065 *last = entry;
1066 last = &entry->pl_next;
1067 }
1068 }
1069
1070 /* add any unsupported features */
1071 for (nvp = nvlist_next_nvpair(features, NULL);
1072 nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) {
1073 char *propname;
1074 boolean_t found;
1075
1076 if (zfeature_is_supported(nvpair_name(nvp)))
1077 continue;
1078
1079 propname = zfs_asprintf(hdl, "unsupported@%s",
1080 nvpair_name(nvp));
1081
1082 /*
1083 * Before adding the property to the list make sure that no
1084 * other pool already added the same property.
1085 */
1086 found = B_FALSE;
1087 entry = *plp;
1088 while (entry != NULL) {
1089 if (entry->pl_user_prop != NULL &&
1090 strcmp(propname, entry->pl_user_prop) == 0) {
1091 found = B_TRUE;
1092 break;
1093 }
1094 entry = entry->pl_next;
1095 }
1096 if (found) {
1097 free(propname);
1098 continue;
1099 }
1100
1101 entry = zfs_alloc(hdl, sizeof (zprop_list_t));
1102 entry->pl_prop = ZPROP_USERPROP;
1103 entry->pl_user_prop = propname;
1104 entry->pl_width = strlen(entry->pl_user_prop);
1105 entry->pl_all = B_TRUE;
1106
1107 *last = entry;
1108 last = &entry->pl_next;
1109 }
1110
1111 for (entry = *plp; entry != NULL; entry = entry->pl_next) {
1112 if (entry->pl_fixed && !literal)
1113 continue;
1114
1115 if (entry->pl_prop != ZPROP_USERPROP &&
1116 zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
1117 NULL, literal) == 0) {
1118 if (strlen(buf) > entry->pl_width)
1119 entry->pl_width = strlen(buf);
1120 } else if (entry->pl_prop == ZPROP_INVAL &&
1121 zfs_prop_user(entry->pl_user_prop) &&
1122 zpool_get_userprop(zhp, entry->pl_user_prop, buf,
1123 sizeof (buf), NULL) == 0) {
1124 if (strlen(buf) > entry->pl_width)
1125 entry->pl_width = strlen(buf);
1126 }
1127 }
1128
1129 return (0);
1130 }
1131
1132 int
vdev_expand_proplist(zpool_handle_t * zhp,const char * vdevname,zprop_list_t ** plp)1133 vdev_expand_proplist(zpool_handle_t *zhp, const char *vdevname,
1134 zprop_list_t **plp)
1135 {
1136 zprop_list_t *entry;
1137 char buf[ZFS_MAXPROPLEN];
1138 const char *strval = NULL;
1139 int err = 0;
1140 nvpair_t *elem = NULL;
1141 nvlist_t *vprops = NULL;
1142 nvlist_t *propval = NULL;
1143 const char *propname;
1144 vdev_prop_t prop;
1145 zprop_list_t **last;
1146
1147 for (entry = *plp; entry != NULL; entry = entry->pl_next) {
1148 if (entry->pl_fixed)
1149 continue;
1150
1151 if (zpool_get_vdev_prop(zhp, vdevname, entry->pl_prop,
1152 entry->pl_user_prop, buf, sizeof (buf), NULL,
1153 B_FALSE) == 0) {
1154 if (strlen(buf) > entry->pl_width)
1155 entry->pl_width = strlen(buf);
1156 }
1157 if (entry->pl_prop == VDEV_PROP_NAME &&
1158 strlen(vdevname) > entry->pl_width)
1159 entry->pl_width = strlen(vdevname);
1160 }
1161
1162 /* Handle the all properties case */
1163 last = plp;
1164 if (*last != NULL && (*last)->pl_all == B_TRUE) {
1165 while (*last != NULL)
1166 last = &(*last)->pl_next;
1167
1168 err = zpool_get_all_vdev_props(zhp, vdevname, &vprops);
1169 if (err != 0)
1170 return (err);
1171
1172 while ((elem = nvlist_next_nvpair(vprops, elem)) != NULL) {
1173 propname = nvpair_name(elem);
1174
1175 /* Skip properties that are not user defined */
1176 if ((prop = vdev_name_to_prop(propname)) !=
1177 VDEV_PROP_USERPROP)
1178 continue;
1179
1180 if (nvpair_value_nvlist(elem, &propval) != 0)
1181 continue;
1182
1183 strval = fnvlist_lookup_string(propval, ZPROP_VALUE);
1184
1185 entry = zfs_alloc(zhp->zpool_hdl,
1186 sizeof (zprop_list_t));
1187 entry->pl_prop = prop;
1188 entry->pl_user_prop = zfs_strdup(zhp->zpool_hdl,
1189 propname);
1190 entry->pl_width = strlen(strval);
1191 entry->pl_all = B_TRUE;
1192 *last = entry;
1193 last = &entry->pl_next;
1194 }
1195 }
1196
1197 return (0);
1198 }
1199
1200 /*
1201 * Get the state for the given feature on the given ZFS pool.
1202 */
1203 int
zpool_prop_get_feature(zpool_handle_t * zhp,const char * propname,char * buf,size_t len)1204 zpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf,
1205 size_t len)
1206 {
1207 uint64_t refcount;
1208 boolean_t found = B_FALSE;
1209 nvlist_t *features = zpool_get_features(zhp);
1210 boolean_t supported;
1211 const char *feature = strchr(propname, '@') + 1;
1212
1213 supported = zpool_prop_feature(propname);
1214 ASSERT(supported || zpool_prop_unsupported(propname));
1215
1216 /*
1217 * Convert from feature name to feature guid. This conversion is
1218 * unnecessary for unsupported@... properties because they already
1219 * use guids.
1220 */
1221 if (supported) {
1222 int ret;
1223 spa_feature_t fid;
1224
1225 ret = zfeature_lookup_name(feature, &fid);
1226 if (ret != 0) {
1227 (void) strlcpy(buf, "-", len);
1228 return (ENOTSUP);
1229 }
1230 feature = spa_feature_table[fid].fi_guid;
1231 }
1232
1233 if (nvlist_lookup_uint64(features, feature, &refcount) == 0)
1234 found = B_TRUE;
1235
1236 if (supported) {
1237 if (!found) {
1238 (void) strlcpy(buf, ZFS_FEATURE_DISABLED, len);
1239 } else {
1240 if (refcount == 0)
1241 (void) strlcpy(buf, ZFS_FEATURE_ENABLED, len);
1242 else
1243 (void) strlcpy(buf, ZFS_FEATURE_ACTIVE, len);
1244 }
1245 } else {
1246 if (found) {
1247 if (refcount == 0) {
1248 (void) strcpy(buf, ZFS_UNSUPPORTED_INACTIVE);
1249 } else {
1250 (void) strcpy(buf, ZFS_UNSUPPORTED_READONLY);
1251 }
1252 } else {
1253 (void) strlcpy(buf, "-", len);
1254 return (ENOTSUP);
1255 }
1256 }
1257
1258 return (0);
1259 }
1260
1261 /*
1262 * Validate the given pool name, optionally putting an extended error message in
1263 * 'buf'.
1264 */
1265 boolean_t
zpool_name_valid(libzfs_handle_t * hdl,boolean_t isopen,const char * pool)1266 zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
1267 {
1268 namecheck_err_t why;
1269 char what;
1270 int ret;
1271
1272 ret = pool_namecheck(pool, &why, &what);
1273
1274 /*
1275 * The rules for reserved pool names were extended at a later point.
1276 * But we need to support users with existing pools that may now be
1277 * invalid. So we only check for this expanded set of names during a
1278 * create (or import), and only in userland.
1279 */
1280 if (ret == 0 && !isopen &&
1281 (strncmp(pool, "mirror", 6) == 0 ||
1282 strncmp(pool, "raidz", 5) == 0 ||
1283 strncmp(pool, "draid", 5) == 0 ||
1284 strncmp(pool, "spare", 5) == 0 ||
1285 strcmp(pool, "log") == 0)) {
1286 if (hdl != NULL)
1287 zfs_error_aux(hdl,
1288 dgettext(TEXT_DOMAIN, "name is reserved"));
1289 return (B_FALSE);
1290 }
1291
1292
1293 if (ret != 0) {
1294 if (hdl != NULL) {
1295 switch (why) {
1296 case NAME_ERR_TOOLONG:
1297 zfs_error_aux(hdl,
1298 dgettext(TEXT_DOMAIN, "name is too long"));
1299 break;
1300
1301 case NAME_ERR_INVALCHAR:
1302 zfs_error_aux(hdl,
1303 dgettext(TEXT_DOMAIN, "invalid character "
1304 "'%c' in pool name"), what);
1305 break;
1306
1307 case NAME_ERR_NOLETTER:
1308 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1309 "name must begin with a letter"));
1310 break;
1311
1312 case NAME_ERR_RESERVED:
1313 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1314 "name is reserved"));
1315 break;
1316
1317 case NAME_ERR_DISKLIKE:
1318 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1319 "pool name is reserved"));
1320 break;
1321
1322 case NAME_ERR_LEADING_SLASH:
1323 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1324 "leading slash in name"));
1325 break;
1326
1327 case NAME_ERR_EMPTY_COMPONENT:
1328 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1329 "empty component in name"));
1330 break;
1331
1332 case NAME_ERR_TRAILING_SLASH:
1333 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1334 "trailing slash in name"));
1335 break;
1336
1337 case NAME_ERR_MULTIPLE_DELIMITERS:
1338 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1339 "multiple '@' and/or '#' delimiters in "
1340 "name"));
1341 break;
1342
1343 case NAME_ERR_NO_AT:
1344 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1345 "permission set is missing '@'"));
1346 break;
1347
1348 default:
1349 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1350 "(%d) not defined"), why);
1351 break;
1352 }
1353 }
1354 return (B_FALSE);
1355 }
1356
1357 return (B_TRUE);
1358 }
1359
1360 /*
1361 * Open a handle to the given pool, even if the pool is currently in the FAULTED
1362 * state.
1363 */
1364 zpool_handle_t *
zpool_open_canfail(libzfs_handle_t * hdl,const char * pool)1365 zpool_open_canfail(libzfs_handle_t *hdl, const char *pool)
1366 {
1367 zpool_handle_t *zhp;
1368 boolean_t missing;
1369
1370 /*
1371 * Make sure the pool name is valid.
1372 */
1373 if (!zpool_name_valid(hdl, B_TRUE, pool)) {
1374 (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME,
1375 dgettext(TEXT_DOMAIN, "cannot open '%s'"),
1376 pool);
1377 return (NULL);
1378 }
1379
1380 zhp = zfs_alloc(hdl, sizeof (zpool_handle_t));
1381
1382 zhp->zpool_hdl = hdl;
1383 (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
1384
1385 if (zpool_refresh_stats(zhp, &missing) != 0) {
1386 zpool_close(zhp);
1387 return (NULL);
1388 }
1389
1390 if (missing) {
1391 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool"));
1392 (void) zfs_error_fmt(hdl, EZFS_NOENT,
1393 dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool);
1394 zpool_close(zhp);
1395 return (NULL);
1396 }
1397
1398 return (zhp);
1399 }
1400
1401 /*
1402 * Like the above, but silent on error. Used when iterating over pools (because
1403 * the configuration cache may be out of date).
1404 */
1405 int
zpool_open_silent(libzfs_handle_t * hdl,const char * pool,zpool_handle_t ** ret)1406 zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret)
1407 {
1408 zpool_handle_t *zhp;
1409 boolean_t missing;
1410
1411 zhp = zfs_alloc(hdl, sizeof (zpool_handle_t));
1412
1413 zhp->zpool_hdl = hdl;
1414 (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
1415
1416 if (zpool_refresh_stats(zhp, &missing) != 0) {
1417 zpool_close(zhp);
1418 return (-1);
1419 }
1420
1421 if (missing) {
1422 zpool_close(zhp);
1423 *ret = NULL;
1424 return (0);
1425 }
1426
1427 *ret = zhp;
1428 return (0);
1429 }
1430
1431 /*
1432 * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
1433 * state.
1434 */
1435 zpool_handle_t *
zpool_open(libzfs_handle_t * hdl,const char * pool)1436 zpool_open(libzfs_handle_t *hdl, const char *pool)
1437 {
1438 zpool_handle_t *zhp;
1439
1440 if ((zhp = zpool_open_canfail(hdl, pool)) == NULL)
1441 return (NULL);
1442
1443 if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
1444 (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
1445 dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name);
1446 zpool_close(zhp);
1447 return (NULL);
1448 }
1449
1450 return (zhp);
1451 }
1452
1453 /*
1454 * Close the handle. Simply frees the memory associated with the handle.
1455 */
1456 void
zpool_close(zpool_handle_t * zhp)1457 zpool_close(zpool_handle_t *zhp)
1458 {
1459 nvlist_free(zhp->zpool_config);
1460 nvlist_free(zhp->zpool_old_config);
1461 nvlist_free(zhp->zpool_props);
1462 free(zhp);
1463 }
1464
1465 /*
1466 * Return the name of the pool.
1467 */
1468 const char *
zpool_get_name(zpool_handle_t * zhp)1469 zpool_get_name(zpool_handle_t *zhp)
1470 {
1471 return (zhp->zpool_name);
1472 }
1473
1474
1475 /*
1476 * Return the state of the pool (ACTIVE or UNAVAILABLE)
1477 */
1478 int
zpool_get_state(zpool_handle_t * zhp)1479 zpool_get_state(zpool_handle_t *zhp)
1480 {
1481 return (zhp->zpool_state);
1482 }
1483
1484 /*
1485 * Check if vdev list contains a dRAID vdev
1486 */
1487 static boolean_t
zpool_has_draid_vdev(nvlist_t * nvroot)1488 zpool_has_draid_vdev(nvlist_t *nvroot)
1489 {
1490 nvlist_t **child;
1491 uint_t children;
1492
1493 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
1494 &child, &children) == 0) {
1495 for (uint_t c = 0; c < children; c++) {
1496 const char *type;
1497
1498 if (nvlist_lookup_string(child[c],
1499 ZPOOL_CONFIG_TYPE, &type) == 0 &&
1500 strcmp(type, VDEV_TYPE_DRAID) == 0) {
1501 return (B_TRUE);
1502 }
1503 }
1504 }
1505 return (B_FALSE);
1506 }
1507
1508 /*
1509 * Output a dRAID top-level vdev name in to the provided buffer.
1510 */
1511 static char *
zpool_draid_name(char * name,int len,uint64_t data,uint64_t parity,uint64_t spares,uint64_t children)1512 zpool_draid_name(char *name, int len, uint64_t data, uint64_t parity,
1513 uint64_t spares, uint64_t children)
1514 {
1515 snprintf(name, len, "%s%llu:%llud:%lluc:%llus",
1516 VDEV_TYPE_DRAID, (u_longlong_t)parity, (u_longlong_t)data,
1517 (u_longlong_t)children, (u_longlong_t)spares);
1518
1519 return (name);
1520 }
1521
1522 /*
1523 * Return B_TRUE if the provided name is a dRAID spare name.
1524 */
1525 boolean_t
zpool_is_draid_spare(const char * name)1526 zpool_is_draid_spare(const char *name)
1527 {
1528 uint64_t spare_id, parity, vdev_id;
1529
1530 if (sscanf(name, VDEV_TYPE_DRAID "%llu-%llu-%llu",
1531 (u_longlong_t *)&parity, (u_longlong_t *)&vdev_id,
1532 (u_longlong_t *)&spare_id) == 3) {
1533 return (B_TRUE);
1534 }
1535
1536 return (B_FALSE);
1537 }
1538
1539 /*
1540 * Create the named pool, using the provided vdev list. It is assumed
1541 * that the consumer has already validated the contents of the nvlist, so we
1542 * don't have to worry about error semantics.
1543 */
1544 int
zpool_create(libzfs_handle_t * hdl,const char * pool,nvlist_t * nvroot,nvlist_t * props,nvlist_t * fsprops)1545 zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
1546 nvlist_t *props, nvlist_t *fsprops)
1547 {
1548 zfs_cmd_t zc = {"\0"};
1549 nvlist_t *zc_fsprops = NULL;
1550 nvlist_t *zc_props = NULL;
1551 nvlist_t *hidden_args = NULL;
1552 uint8_t *wkeydata = NULL;
1553 uint_t wkeylen = 0;
1554 char errbuf[ERRBUFLEN];
1555 int ret = -1;
1556
1557 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1558 "cannot create '%s'"), pool);
1559
1560 if (!zpool_name_valid(hdl, B_FALSE, pool))
1561 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
1562
1563 zcmd_write_conf_nvlist(hdl, &zc, nvroot);
1564
1565 if (props) {
1566 prop_flags_t flags = { .create = B_TRUE, .import = B_FALSE };
1567
1568 if ((zc_props = zpool_valid_proplist(hdl, pool, props,
1569 SPA_VERSION_1, flags, errbuf)) == NULL) {
1570 goto create_failed;
1571 }
1572 }
1573
1574 if (fsprops) {
1575 uint64_t zoned;
1576 const char *zonestr;
1577
1578 zoned = ((nvlist_lookup_string(fsprops,
1579 zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) &&
1580 strcmp(zonestr, "on") == 0);
1581
1582 if ((zc_fsprops = zfs_valid_proplist(hdl, ZFS_TYPE_FILESYSTEM,
1583 fsprops, zoned, NULL, NULL, B_TRUE, errbuf)) == NULL) {
1584 goto create_failed;
1585 }
1586
1587 if (!zc_props &&
1588 (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) {
1589 goto create_failed;
1590 }
1591 if (zfs_crypto_create(hdl, NULL, zc_fsprops, props, B_TRUE,
1592 &wkeydata, &wkeylen) != 0) {
1593 zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf);
1594 goto create_failed;
1595 }
1596 if (nvlist_add_nvlist(zc_props,
1597 ZPOOL_ROOTFS_PROPS, zc_fsprops) != 0) {
1598 goto create_failed;
1599 }
1600 if (wkeydata != NULL) {
1601 if (nvlist_alloc(&hidden_args, NV_UNIQUE_NAME, 0) != 0)
1602 goto create_failed;
1603
1604 if (nvlist_add_uint8_array(hidden_args, "wkeydata",
1605 wkeydata, wkeylen) != 0)
1606 goto create_failed;
1607
1608 if (nvlist_add_nvlist(zc_props, ZPOOL_HIDDEN_ARGS,
1609 hidden_args) != 0)
1610 goto create_failed;
1611 }
1612 }
1613
1614 if (zc_props)
1615 zcmd_write_src_nvlist(hdl, &zc, zc_props);
1616
1617 (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
1618
1619 if ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc)) != 0) {
1620
1621 zcmd_free_nvlists(&zc);
1622 nvlist_free(zc_props);
1623 nvlist_free(zc_fsprops);
1624 nvlist_free(hidden_args);
1625 if (wkeydata != NULL)
1626 free(wkeydata);
1627
1628 switch (errno) {
1629 case EBUSY:
1630 /*
1631 * This can happen if the user has specified the same
1632 * device multiple times. We can't reliably detect this
1633 * until we try to add it and see we already have a
1634 * label. This can also happen under if the device is
1635 * part of an active md or lvm device.
1636 */
1637 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1638 "one or more vdevs refer to the same device, or "
1639 "one of\nthe devices is part of an active md or "
1640 "lvm device"));
1641 return (zfs_error(hdl, EZFS_BADDEV, errbuf));
1642
1643 case ERANGE:
1644 /*
1645 * This happens if the record size is smaller or larger
1646 * than the allowed size range, or not a power of 2.
1647 *
1648 * NOTE: although zfs_valid_proplist is called earlier,
1649 * this case may have slipped through since the
1650 * pool does not exist yet and it is therefore
1651 * impossible to read properties e.g. max blocksize
1652 * from the pool.
1653 */
1654 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1655 "record size invalid"));
1656 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
1657
1658 case EOVERFLOW:
1659 /*
1660 * This occurs when one of the devices is below
1661 * SPA_MINDEVSIZE. Unfortunately, we can't detect which
1662 * device was the problem device since there's no
1663 * reliable way to determine device size from userland.
1664 */
1665 {
1666 char buf[64];
1667
1668 zfs_nicebytes(SPA_MINDEVSIZE, buf,
1669 sizeof (buf));
1670
1671 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1672 "one or more devices is less than the "
1673 "minimum size (%s)"), buf);
1674 }
1675 return (zfs_error(hdl, EZFS_BADDEV, errbuf));
1676
1677 case ENOSPC:
1678 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1679 "one or more devices is out of space"));
1680 return (zfs_error(hdl, EZFS_BADDEV, errbuf));
1681
1682 case EINVAL:
1683 if (zpool_has_draid_vdev(nvroot) &&
1684 zfeature_lookup_name("draid", NULL) != 0) {
1685 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1686 "dRAID vdevs are unsupported by the "
1687 "kernel"));
1688 return (zfs_error(hdl, EZFS_BADDEV, errbuf));
1689 } else {
1690 return (zpool_standard_error(hdl, errno,
1691 errbuf));
1692 }
1693
1694 case ENXIO:
1695 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1696 "one or more devices could not be opened"));
1697 return (zfs_error(hdl, EZFS_BADDEV, errbuf));
1698
1699 case EDOM:
1700 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1701 "block size out of range or does not match"));
1702 return (zfs_error(hdl, EZFS_BADDEV, errbuf));
1703
1704 default:
1705 return (zpool_standard_error(hdl, errno, errbuf));
1706 }
1707 }
1708
1709 create_failed:
1710 zcmd_free_nvlists(&zc);
1711 nvlist_free(zc_props);
1712 nvlist_free(zc_fsprops);
1713 nvlist_free(hidden_args);
1714 if (wkeydata != NULL)
1715 free(wkeydata);
1716 return (ret);
1717 }
1718
1719 /*
1720 * Destroy the given pool. It is up to the caller to ensure that there are no
1721 * datasets left in the pool.
1722 */
1723 int
zpool_destroy(zpool_handle_t * zhp,const char * log_str)1724 zpool_destroy(zpool_handle_t *zhp, const char *log_str)
1725 {
1726 zfs_cmd_t zc = {"\0"};
1727 zfs_handle_t *zfp = NULL;
1728 libzfs_handle_t *hdl = zhp->zpool_hdl;
1729 char errbuf[ERRBUFLEN];
1730
1731 if (zhp->zpool_state == POOL_STATE_ACTIVE &&
1732 (zfp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL)
1733 return (-1);
1734
1735 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1736 zc.zc_history = (uint64_t)(uintptr_t)log_str;
1737
1738 if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
1739 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1740 "cannot destroy '%s'"), zhp->zpool_name);
1741
1742 if (errno == EROFS) {
1743 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1744 "one or more devices is read only"));
1745 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
1746 } else {
1747 (void) zpool_standard_error(hdl, errno, errbuf);
1748 }
1749
1750 if (zfp)
1751 zfs_close(zfp);
1752 return (-1);
1753 }
1754
1755 if (zfp) {
1756 remove_mountpoint(zfp);
1757 zfs_close(zfp);
1758 }
1759
1760 return (0);
1761 }
1762
1763 /*
1764 * Create a checkpoint in the given pool.
1765 */
1766 int
zpool_checkpoint(zpool_handle_t * zhp)1767 zpool_checkpoint(zpool_handle_t *zhp)
1768 {
1769 libzfs_handle_t *hdl = zhp->zpool_hdl;
1770 char errbuf[ERRBUFLEN];
1771 int error;
1772
1773 error = lzc_pool_checkpoint(zhp->zpool_name);
1774 if (error != 0) {
1775 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1776 "cannot checkpoint '%s'"), zhp->zpool_name);
1777 (void) zpool_standard_error(hdl, error, errbuf);
1778 return (-1);
1779 }
1780
1781 return (0);
1782 }
1783
1784 /*
1785 * Discard the checkpoint from the given pool.
1786 */
1787 int
zpool_discard_checkpoint(zpool_handle_t * zhp)1788 zpool_discard_checkpoint(zpool_handle_t *zhp)
1789 {
1790 libzfs_handle_t *hdl = zhp->zpool_hdl;
1791 char errbuf[ERRBUFLEN];
1792 int error;
1793
1794 error = lzc_pool_checkpoint_discard(zhp->zpool_name);
1795 if (error != 0) {
1796 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1797 "cannot discard checkpoint in '%s'"), zhp->zpool_name);
1798 (void) zpool_standard_error(hdl, error, errbuf);
1799 return (-1);
1800 }
1801
1802 return (0);
1803 }
1804
1805 /*
1806 * Load data type for the given pool.
1807 */
1808 int
zpool_prefetch(zpool_handle_t * zhp,zpool_prefetch_type_t type)1809 zpool_prefetch(zpool_handle_t *zhp, zpool_prefetch_type_t type)
1810 {
1811 libzfs_handle_t *hdl = zhp->zpool_hdl;
1812 char msg[1024];
1813 int error;
1814
1815 error = lzc_pool_prefetch(zhp->zpool_name, type);
1816 if (error != 0) {
1817 const char *typename = "unknown";
1818 if (type == ZPOOL_PREFETCH_DDT)
1819 typename = "ddt";
1820 else if (type == ZPOOL_PREFETCH_BRT)
1821 typename = "brt";
1822 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1823 "cannot prefetch %s in '%s'"), typename, zhp->zpool_name);
1824 (void) zpool_standard_error(hdl, error, msg);
1825 return (-1);
1826 }
1827
1828 return (0);
1829 }
1830
1831 /*
1832 * Add the given vdevs to the pool. The caller must have already performed the
1833 * necessary verification to ensure that the vdev specification is well-formed.
1834 */
1835 int
zpool_add(zpool_handle_t * zhp,nvlist_t * nvroot,boolean_t check_ashift)1836 zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot, boolean_t check_ashift)
1837 {
1838 zfs_cmd_t zc = {"\0"};
1839 int ret;
1840 libzfs_handle_t *hdl = zhp->zpool_hdl;
1841 char errbuf[ERRBUFLEN];
1842 nvlist_t **spares, **l2cache;
1843 uint_t nspares, nl2cache;
1844
1845 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1846 "cannot add to '%s'"), zhp->zpool_name);
1847
1848 if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1849 SPA_VERSION_SPARES &&
1850 nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
1851 &spares, &nspares) == 0) {
1852 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
1853 "upgraded to add hot spares"));
1854 return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
1855 }
1856
1857 if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1858 SPA_VERSION_L2CACHE &&
1859 nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
1860 &l2cache, &nl2cache) == 0) {
1861 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
1862 "upgraded to add cache devices"));
1863 return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
1864 }
1865
1866 zcmd_write_conf_nvlist(hdl, &zc, nvroot);
1867 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1868 zc.zc_flags = check_ashift;
1869
1870 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) {
1871 switch (errno) {
1872 case EBUSY:
1873 /*
1874 * This can happen if the user has specified the same
1875 * device multiple times. We can't reliably detect this
1876 * until we try to add it and see we already have a
1877 * label.
1878 */
1879 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1880 "one or more vdevs refer to the same device"));
1881 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
1882 break;
1883
1884 case EINVAL:
1885
1886 if (zpool_has_draid_vdev(nvroot) &&
1887 zfeature_lookup_name("draid", NULL) != 0) {
1888 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1889 "dRAID vdevs are unsupported by the "
1890 "kernel"));
1891 } else {
1892 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1893 "invalid config; a pool with removing/"
1894 "removed vdevs does not support adding "
1895 "raidz or dRAID vdevs"));
1896 }
1897
1898 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
1899 break;
1900
1901 case EOVERFLOW:
1902 /*
1903 * This occurs when one of the devices is below
1904 * SPA_MINDEVSIZE. Unfortunately, we can't detect which
1905 * device was the problem device since there's no
1906 * reliable way to determine device size from userland.
1907 */
1908 {
1909 char buf[64];
1910
1911 zfs_nicebytes(SPA_MINDEVSIZE, buf,
1912 sizeof (buf));
1913
1914 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1915 "device is less than the minimum "
1916 "size (%s)"), buf);
1917 }
1918 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
1919 break;
1920
1921 case ENOTSUP:
1922 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1923 "pool must be upgraded to add these vdevs"));
1924 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
1925 break;
1926
1927 default:
1928 (void) zpool_standard_error(hdl, errno, errbuf);
1929 }
1930
1931 ret = -1;
1932 } else {
1933 ret = 0;
1934 }
1935
1936 zcmd_free_nvlists(&zc);
1937
1938 return (ret);
1939 }
1940
1941 /*
1942 * Exports the pool from the system. The caller must ensure that there are no
1943 * mounted datasets in the pool.
1944 */
1945 static int
zpool_export_common(zpool_handle_t * zhp,boolean_t force,boolean_t hardforce,const char * log_str)1946 zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
1947 const char *log_str)
1948 {
1949 zfs_cmd_t zc = {"\0"};
1950
1951 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1952 zc.zc_cookie = force;
1953 zc.zc_guid = hardforce;
1954 zc.zc_history = (uint64_t)(uintptr_t)log_str;
1955
1956 if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
1957 switch (errno) {
1958 case EXDEV:
1959 zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
1960 "use '-f' to override the following errors:\n"
1961 "'%s' has an active shared spare which could be"
1962 " used by other pools once '%s' is exported."),
1963 zhp->zpool_name, zhp->zpool_name);
1964 return (zfs_error_fmt(zhp->zpool_hdl, EZFS_ACTIVE_SPARE,
1965 dgettext(TEXT_DOMAIN, "cannot export '%s'"),
1966 zhp->zpool_name));
1967 default:
1968 return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
1969 dgettext(TEXT_DOMAIN, "cannot export '%s'"),
1970 zhp->zpool_name));
1971 }
1972 }
1973
1974 return (0);
1975 }
1976
1977 int
zpool_export(zpool_handle_t * zhp,boolean_t force,const char * log_str)1978 zpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str)
1979 {
1980 return (zpool_export_common(zhp, force, B_FALSE, log_str));
1981 }
1982
1983 int
zpool_export_force(zpool_handle_t * zhp,const char * log_str)1984 zpool_export_force(zpool_handle_t *zhp, const char *log_str)
1985 {
1986 return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str));
1987 }
1988
1989 static void
zpool_rewind_exclaim(libzfs_handle_t * hdl,const char * name,boolean_t dryrun,nvlist_t * config)1990 zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun,
1991 nvlist_t *config)
1992 {
1993 nvlist_t *nv = NULL;
1994 uint64_t rewindto;
1995 int64_t loss = -1;
1996 struct tm t;
1997 char timestr[128];
1998
1999 if (!hdl->libzfs_printerr || config == NULL)
2000 return;
2001
2002 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
2003 nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0) {
2004 return;
2005 }
2006
2007 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
2008 return;
2009 (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
2010
2011 if (localtime_r((time_t *)&rewindto, &t) != NULL &&
2012 ctime_r((time_t *)&rewindto, timestr) != NULL) {
2013 timestr[24] = 0;
2014 if (dryrun) {
2015 (void) printf(dgettext(TEXT_DOMAIN,
2016 "Would be able to return %s "
2017 "to its state as of %s.\n"),
2018 name, timestr);
2019 } else {
2020 (void) printf(dgettext(TEXT_DOMAIN,
2021 "Pool %s returned to its state as of %s.\n"),
2022 name, timestr);
2023 }
2024 if (loss > 120) {
2025 (void) printf(dgettext(TEXT_DOMAIN,
2026 "%s approximately %lld "),
2027 dryrun ? "Would discard" : "Discarded",
2028 ((longlong_t)loss + 30) / 60);
2029 (void) printf(dgettext(TEXT_DOMAIN,
2030 "minutes of transactions.\n"));
2031 } else if (loss > 0) {
2032 (void) printf(dgettext(TEXT_DOMAIN,
2033 "%s approximately %lld "),
2034 dryrun ? "Would discard" : "Discarded",
2035 (longlong_t)loss);
2036 (void) printf(dgettext(TEXT_DOMAIN,
2037 "seconds of transactions.\n"));
2038 }
2039 }
2040 }
2041
2042 void
zpool_explain_recover(libzfs_handle_t * hdl,const char * name,int reason,nvlist_t * config,char * buf,size_t size)2043 zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
2044 nvlist_t *config, char *buf, size_t size)
2045 {
2046 nvlist_t *nv = NULL;
2047 int64_t loss = -1;
2048 uint64_t edata = UINT64_MAX;
2049 uint64_t rewindto;
2050 struct tm t;
2051 char timestr[128], temp[1024];
2052
2053 if (!hdl->libzfs_printerr)
2054 return;
2055
2056 /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */
2057 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
2058 nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 ||
2059 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
2060 goto no_info;
2061
2062 (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
2063 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS,
2064 &edata);
2065
2066 (void) snprintf(buf, size, dgettext(TEXT_DOMAIN,
2067 "Recovery is possible, but will result in some data loss.\n"));
2068
2069 if (localtime_r((time_t *)&rewindto, &t) != NULL &&
2070 ctime_r((time_t *)&rewindto, timestr) != NULL) {
2071 timestr[24] = 0;
2072 (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN,
2073 "\tReturning the pool to its state as of %s\n"
2074 "\tshould correct the problem. "), timestr);
2075 (void) strlcat(buf, temp, size);
2076 } else {
2077 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2078 "\tReverting the pool to an earlier state "
2079 "should correct the problem.\n\t"), size);
2080 }
2081
2082 if (loss > 120) {
2083 (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN,
2084 "Approximately %lld minutes of data\n"
2085 "\tmust be discarded, irreversibly. "),
2086 ((longlong_t)loss + 30) / 60);
2087 (void) strlcat(buf, temp, size);
2088 } else if (loss > 0) {
2089 (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN,
2090 "Approximately %lld seconds of data\n"
2091 "\tmust be discarded, irreversibly. "),
2092 (longlong_t)loss);
2093 (void) strlcat(buf, temp, size);
2094 }
2095 if (edata != 0 && edata != UINT64_MAX) {
2096 if (edata == 1) {
2097 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2098 "After rewind, at least\n"
2099 "\tone persistent user-data error will remain. "),
2100 size);
2101 } else {
2102 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2103 "After rewind, several\n"
2104 "\tpersistent user-data errors will remain. "),
2105 size);
2106 }
2107 }
2108 (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN,
2109 "Recovery can be attempted\n\tby executing 'zpool %s -F %s'. "),
2110 reason >= 0 ? "clear" : "import", name);
2111 (void) strlcat(buf, temp, size);
2112
2113 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2114 "A scrub of the pool\n"
2115 "\tis strongly recommended after recovery.\n"), size);
2116 return;
2117
2118 no_info:
2119 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2120 "Ensure all pool devices are present and accessible, then "
2121 "retry the import.\n\tIf the problem persists, destroy and "
2122 "re-create the pool from a backup source.\n"), size);
2123 }
2124
2125 /*
2126 * zpool_import() is a contracted interface. Should be kept the same
2127 * if possible.
2128 *
2129 * Applications should use zpool_import_props() to import a pool with
2130 * new properties value to be set.
2131 */
2132 int
zpool_import(libzfs_handle_t * hdl,nvlist_t * config,const char * newname,char * altroot)2133 zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
2134 char *altroot)
2135 {
2136 nvlist_t *props = NULL;
2137 int ret;
2138
2139 if (altroot != NULL) {
2140 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
2141 return (zfs_error_fmt(hdl, EZFS_NOMEM,
2142 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
2143 newname));
2144 }
2145
2146 if (nvlist_add_string(props,
2147 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 ||
2148 nvlist_add_string(props,
2149 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) {
2150 nvlist_free(props);
2151 return (zfs_error_fmt(hdl, EZFS_NOMEM,
2152 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
2153 newname));
2154 }
2155 }
2156
2157 ret = zpool_import_props(hdl, config, newname, props,
2158 ZFS_IMPORT_NORMAL);
2159 nvlist_free(props);
2160 return (ret);
2161 }
2162
2163 static void
print_vdev_tree(libzfs_handle_t * hdl,const char * name,nvlist_t * nv,int indent)2164 print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv,
2165 int indent)
2166 {
2167 nvlist_t **child;
2168 uint_t c, children;
2169 char *vname;
2170 uint64_t is_log = 0;
2171
2172 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG,
2173 &is_log);
2174
2175 if (name != NULL)
2176 (void) printf("\t%*s%s%s\n", indent, "", name,
2177 is_log ? " [log]" : "");
2178
2179 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2180 &child, &children) != 0)
2181 return;
2182
2183 for (c = 0; c < children; c++) {
2184 vname = zpool_vdev_name(hdl, NULL, child[c], VDEV_NAME_TYPE_ID);
2185 print_vdev_tree(hdl, vname, child[c], indent + 2);
2186 free(vname);
2187 }
2188 }
2189
2190 void
zpool_collect_unsup_feat(nvlist_t * config,char * buf,size_t size)2191 zpool_collect_unsup_feat(nvlist_t *config, char *buf, size_t size)
2192 {
2193 nvlist_t *nvinfo, *unsup_feat;
2194 char temp[512];
2195
2196 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2197 unsup_feat = fnvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT);
2198
2199 for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL);
2200 nvp != NULL; nvp = nvlist_next_nvpair(unsup_feat, nvp)) {
2201 const char *desc = fnvpair_value_string(nvp);
2202 if (strlen(desc) > 0) {
2203 (void) snprintf(temp, 512, "\t%s (%s)\n",
2204 nvpair_name(nvp), desc);
2205 (void) strlcat(buf, temp, size);
2206 } else {
2207 (void) snprintf(temp, 512, "\t%s\n", nvpair_name(nvp));
2208 (void) strlcat(buf, temp, size);
2209 }
2210 }
2211 }
2212
2213 /*
2214 * Import the given pool using the known configuration and a list of
2215 * properties to be set. The configuration should have come from
2216 * zpool_find_import(). The 'newname' parameters control whether the pool
2217 * is imported with a different name.
2218 */
2219 int
zpool_import_props(libzfs_handle_t * hdl,nvlist_t * config,const char * newname,nvlist_t * props,int flags)2220 zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
2221 nvlist_t *props, int flags)
2222 {
2223 zfs_cmd_t zc = {"\0"};
2224 zpool_load_policy_t policy;
2225 nvlist_t *nv = NULL;
2226 nvlist_t *nvinfo = NULL;
2227 nvlist_t *missing = NULL;
2228 const char *thename;
2229 const char *origname;
2230 int ret;
2231 int error = 0;
2232 char buf[2048];
2233 char errbuf[ERRBUFLEN];
2234
2235 origname = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
2236
2237 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2238 "cannot import pool '%s'"), origname);
2239
2240 if (newname != NULL) {
2241 if (!zpool_name_valid(hdl, B_FALSE, newname))
2242 return (zfs_error_fmt(hdl, EZFS_INVALIDNAME,
2243 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
2244 newname));
2245 thename = newname;
2246 } else {
2247 thename = origname;
2248 }
2249
2250 if (props != NULL) {
2251 uint64_t version;
2252 prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
2253
2254 version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
2255
2256 if ((props = zpool_valid_proplist(hdl, origname,
2257 props, version, flags, errbuf)) == NULL)
2258 return (-1);
2259 zcmd_write_src_nvlist(hdl, &zc, props);
2260 nvlist_free(props);
2261 }
2262
2263 (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
2264
2265 zc.zc_guid = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID);
2266
2267 zcmd_write_conf_nvlist(hdl, &zc, config);
2268 zcmd_alloc_dst_nvlist(hdl, &zc, zc.zc_nvlist_conf_size * 2);
2269
2270 zc.zc_cookie = flags;
2271 while ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc)) != 0 &&
2272 errno == ENOMEM)
2273 zcmd_expand_dst_nvlist(hdl, &zc);
2274 if (ret != 0)
2275 error = errno;
2276
2277 (void) zcmd_read_dst_nvlist(hdl, &zc, &nv);
2278
2279 zcmd_free_nvlists(&zc);
2280
2281 zpool_get_load_policy(config, &policy);
2282
2283 if (getenv("ZFS_LOAD_INFO_DEBUG") && nv != NULL &&
2284 nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0) {
2285 dump_nvlist(nvinfo, 4);
2286 }
2287
2288 if (error) {
2289 char desc[1024];
2290 char aux[256];
2291
2292 /*
2293 * Dry-run failed, but we print out what success
2294 * looks like if we found a best txg
2295 */
2296 if (policy.zlp_rewind & ZPOOL_TRY_REWIND) {
2297 zpool_rewind_exclaim(hdl, newname ? origname : thename,
2298 B_TRUE, nv);
2299 nvlist_free(nv);
2300 return (-1);
2301 }
2302
2303 if (newname == NULL)
2304 (void) snprintf(desc, sizeof (desc),
2305 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
2306 thename);
2307 else
2308 (void) snprintf(desc, sizeof (desc),
2309 dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
2310 origname, thename);
2311
2312 switch (error) {
2313 case ENOTSUP:
2314 if (nv != NULL && nvlist_lookup_nvlist(nv,
2315 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
2316 nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) {
2317 (void) printf(dgettext(TEXT_DOMAIN, "This "
2318 "pool uses the following feature(s) not "
2319 "supported by this system:\n"));
2320 memset(buf, 0, 2048);
2321 zpool_collect_unsup_feat(nv, buf, 2048);
2322 (void) printf("%s", buf);
2323 if (nvlist_exists(nvinfo,
2324 ZPOOL_CONFIG_CAN_RDONLY)) {
2325 (void) printf(dgettext(TEXT_DOMAIN,
2326 "All unsupported features are only "
2327 "required for writing to the pool."
2328 "\nThe pool can be imported using "
2329 "'-o readonly=on'.\n"));
2330 }
2331 }
2332 /*
2333 * Unsupported version.
2334 */
2335 (void) zfs_error(hdl, EZFS_BADVERSION, desc);
2336 break;
2337
2338 case EREMOTEIO:
2339 if (nv != NULL && nvlist_lookup_nvlist(nv,
2340 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0) {
2341 const char *hostname = "<unknown>";
2342 uint64_t hostid = 0;
2343 mmp_state_t mmp_state;
2344
2345 mmp_state = fnvlist_lookup_uint64(nvinfo,
2346 ZPOOL_CONFIG_MMP_STATE);
2347
2348 if (nvlist_exists(nvinfo,
2349 ZPOOL_CONFIG_MMP_HOSTNAME))
2350 hostname = fnvlist_lookup_string(nvinfo,
2351 ZPOOL_CONFIG_MMP_HOSTNAME);
2352
2353 if (nvlist_exists(nvinfo,
2354 ZPOOL_CONFIG_MMP_HOSTID))
2355 hostid = fnvlist_lookup_uint64(nvinfo,
2356 ZPOOL_CONFIG_MMP_HOSTID);
2357
2358 if (mmp_state == MMP_STATE_ACTIVE) {
2359 (void) snprintf(aux, sizeof (aux),
2360 dgettext(TEXT_DOMAIN, "pool is imp"
2361 "orted on host '%s' (hostid=%lx).\n"
2362 "Export the pool on the other "
2363 "system, then run 'zpool import'."),
2364 hostname, (unsigned long) hostid);
2365 } else if (mmp_state == MMP_STATE_NO_HOSTID) {
2366 (void) snprintf(aux, sizeof (aux),
2367 dgettext(TEXT_DOMAIN, "pool has "
2368 "the multihost property on and "
2369 "the\nsystem's hostid is not set. "
2370 "Set a unique system hostid with "
2371 "the zgenhostid(8) command.\n"));
2372 }
2373
2374 (void) zfs_error_aux(hdl, "%s", aux);
2375 }
2376 (void) zfs_error(hdl, EZFS_ACTIVE_POOL, desc);
2377 break;
2378
2379 case EINVAL:
2380 (void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
2381 break;
2382
2383 case EROFS:
2384 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2385 "one or more devices is read only"));
2386 (void) zfs_error(hdl, EZFS_BADDEV, desc);
2387 break;
2388
2389 case ENXIO:
2390 if (nv && nvlist_lookup_nvlist(nv,
2391 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
2392 nvlist_lookup_nvlist(nvinfo,
2393 ZPOOL_CONFIG_MISSING_DEVICES, &missing) == 0) {
2394 (void) printf(dgettext(TEXT_DOMAIN,
2395 "The devices below are missing or "
2396 "corrupted, use '-m' to import the pool "
2397 "anyway:\n"));
2398 print_vdev_tree(hdl, NULL, missing, 2);
2399 (void) printf("\n");
2400 }
2401 (void) zpool_standard_error(hdl, error, desc);
2402 break;
2403
2404 case EEXIST:
2405 (void) zpool_standard_error(hdl, error, desc);
2406 break;
2407
2408 case EBUSY:
2409 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2410 "one or more devices are already in use\n"));
2411 (void) zfs_error(hdl, EZFS_BADDEV, desc);
2412 break;
2413 case ENAMETOOLONG:
2414 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2415 "new name of at least one dataset is longer than "
2416 "the maximum allowable length"));
2417 (void) zfs_error(hdl, EZFS_NAMETOOLONG, desc);
2418 break;
2419 default:
2420 (void) zpool_standard_error(hdl, error, desc);
2421 memset(buf, 0, 2048);
2422 zpool_explain_recover(hdl,
2423 newname ? origname : thename, -error, nv,
2424 buf, 2048);
2425 (void) printf("\t%s", buf);
2426 break;
2427 }
2428
2429 nvlist_free(nv);
2430 ret = -1;
2431 } else {
2432 zpool_handle_t *zhp;
2433
2434 /*
2435 * This should never fail, but play it safe anyway.
2436 */
2437 if (zpool_open_silent(hdl, thename, &zhp) != 0)
2438 ret = -1;
2439 else if (zhp != NULL)
2440 zpool_close(zhp);
2441 if (policy.zlp_rewind &
2442 (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
2443 zpool_rewind_exclaim(hdl, newname ? origname : thename,
2444 ((policy.zlp_rewind & ZPOOL_TRY_REWIND) != 0), nv);
2445 }
2446 nvlist_free(nv);
2447 }
2448
2449 return (ret);
2450 }
2451
2452 /*
2453 * Translate vdev names to guids. If a vdev_path is determined to be
2454 * unsuitable then a vd_errlist is allocated and the vdev path and errno
2455 * are added to it.
2456 */
2457 static int
zpool_translate_vdev_guids(zpool_handle_t * zhp,nvlist_t * vds,nvlist_t * vdev_guids,nvlist_t * guids_to_paths,nvlist_t ** vd_errlist)2458 zpool_translate_vdev_guids(zpool_handle_t *zhp, nvlist_t *vds,
2459 nvlist_t *vdev_guids, nvlist_t *guids_to_paths, nvlist_t **vd_errlist)
2460 {
2461 nvlist_t *errlist = NULL;
2462 int error = 0;
2463
2464 for (nvpair_t *elem = nvlist_next_nvpair(vds, NULL); elem != NULL;
2465 elem = nvlist_next_nvpair(vds, elem)) {
2466 boolean_t spare, cache;
2467
2468 const char *vd_path = nvpair_name(elem);
2469 nvlist_t *tgt = zpool_find_vdev(zhp, vd_path, &spare, &cache,
2470 NULL);
2471
2472 if ((tgt == NULL) || cache || spare) {
2473 if (errlist == NULL) {
2474 errlist = fnvlist_alloc();
2475 error = EINVAL;
2476 }
2477
2478 uint64_t err = (tgt == NULL) ? EZFS_NODEVICE :
2479 (spare ? EZFS_ISSPARE : EZFS_ISL2CACHE);
2480 fnvlist_add_int64(errlist, vd_path, err);
2481 continue;
2482 }
2483
2484 uint64_t guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
2485 fnvlist_add_uint64(vdev_guids, vd_path, guid);
2486
2487 char msg[MAXNAMELEN];
2488 (void) snprintf(msg, sizeof (msg), "%llu", (u_longlong_t)guid);
2489 fnvlist_add_string(guids_to_paths, msg, vd_path);
2490 }
2491
2492 if (error != 0) {
2493 verify(errlist != NULL);
2494 if (vd_errlist != NULL)
2495 *vd_errlist = errlist;
2496 else
2497 fnvlist_free(errlist);
2498 }
2499
2500 return (error);
2501 }
2502
2503 static int
xlate_init_err(int err)2504 xlate_init_err(int err)
2505 {
2506 switch (err) {
2507 case ENODEV:
2508 return (EZFS_NODEVICE);
2509 case EINVAL:
2510 case EROFS:
2511 return (EZFS_BADDEV);
2512 case EBUSY:
2513 return (EZFS_INITIALIZING);
2514 case ESRCH:
2515 return (EZFS_NO_INITIALIZE);
2516 }
2517 return (err);
2518 }
2519
2520 int
zpool_initialize_one(zpool_handle_t * zhp,void * data)2521 zpool_initialize_one(zpool_handle_t *zhp, void *data)
2522 {
2523 int error;
2524 libzfs_handle_t *hdl = zpool_get_handle(zhp);
2525 const char *pool_name = zpool_get_name(zhp);
2526 if (zpool_open_silent(hdl, pool_name, &zhp) != 0)
2527 return (-1);
2528 initialize_cbdata_t *cb = data;
2529 nvlist_t *vdevs = fnvlist_alloc();
2530
2531 nvlist_t *config = zpool_get_config(zhp, NULL);
2532 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
2533 ZPOOL_CONFIG_VDEV_TREE);
2534 zpool_collect_leaves(zhp, nvroot, vdevs);
2535 if (cb->wait)
2536 error = zpool_initialize_wait(zhp, cb->cmd_type, vdevs);
2537 else
2538 error = zpool_initialize(zhp, cb->cmd_type, vdevs);
2539 fnvlist_free(vdevs);
2540
2541 return (error);
2542 }
2543
2544 /*
2545 * Begin, suspend, cancel, or uninit (clear) the initialization (initializing
2546 * of all free blocks) for the given vdevs in the given pool.
2547 */
2548 static int
zpool_initialize_impl(zpool_handle_t * zhp,pool_initialize_func_t cmd_type,nvlist_t * vds,boolean_t wait)2549 zpool_initialize_impl(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
2550 nvlist_t *vds, boolean_t wait)
2551 {
2552 int err;
2553
2554 nvlist_t *vdev_guids = fnvlist_alloc();
2555 nvlist_t *guids_to_paths = fnvlist_alloc();
2556 nvlist_t *vd_errlist = NULL;
2557 nvlist_t *errlist;
2558 nvpair_t *elem;
2559
2560 err = zpool_translate_vdev_guids(zhp, vds, vdev_guids,
2561 guids_to_paths, &vd_errlist);
2562
2563 if (err != 0) {
2564 verify(vd_errlist != NULL);
2565 goto list_errors;
2566 }
2567
2568 err = lzc_initialize(zhp->zpool_name, cmd_type,
2569 vdev_guids, &errlist);
2570
2571 if (err != 0) {
2572 if (errlist != NULL && nvlist_lookup_nvlist(errlist,
2573 ZPOOL_INITIALIZE_VDEVS, &vd_errlist) == 0) {
2574 goto list_errors;
2575 }
2576
2577 if (err == EINVAL && cmd_type == POOL_INITIALIZE_UNINIT) {
2578 zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
2579 "uninitialize is not supported by kernel"));
2580 }
2581
2582 (void) zpool_standard_error(zhp->zpool_hdl, err,
2583 dgettext(TEXT_DOMAIN, "operation failed"));
2584 goto out;
2585 }
2586
2587 if (wait) {
2588 for (elem = nvlist_next_nvpair(vdev_guids, NULL); elem != NULL;
2589 elem = nvlist_next_nvpair(vdev_guids, elem)) {
2590
2591 uint64_t guid = fnvpair_value_uint64(elem);
2592
2593 err = lzc_wait_tag(zhp->zpool_name,
2594 ZPOOL_WAIT_INITIALIZE, guid, NULL);
2595 if (err != 0) {
2596 (void) zpool_standard_error_fmt(zhp->zpool_hdl,
2597 err, dgettext(TEXT_DOMAIN, "error "
2598 "waiting for '%s' to initialize"),
2599 nvpair_name(elem));
2600
2601 goto out;
2602 }
2603 }
2604 }
2605 goto out;
2606
2607 list_errors:
2608 for (elem = nvlist_next_nvpair(vd_errlist, NULL); elem != NULL;
2609 elem = nvlist_next_nvpair(vd_errlist, elem)) {
2610 int64_t vd_error = xlate_init_err(fnvpair_value_int64(elem));
2611 const char *path;
2612
2613 if (nvlist_lookup_string(guids_to_paths, nvpair_name(elem),
2614 &path) != 0)
2615 path = nvpair_name(elem);
2616
2617 (void) zfs_error_fmt(zhp->zpool_hdl, vd_error,
2618 "cannot initialize '%s'", path);
2619 }
2620
2621 out:
2622 fnvlist_free(vdev_guids);
2623 fnvlist_free(guids_to_paths);
2624
2625 if (vd_errlist != NULL)
2626 fnvlist_free(vd_errlist);
2627
2628 return (err == 0 ? 0 : -1);
2629 }
2630
2631 int
zpool_initialize(zpool_handle_t * zhp,pool_initialize_func_t cmd_type,nvlist_t * vds)2632 zpool_initialize(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
2633 nvlist_t *vds)
2634 {
2635 return (zpool_initialize_impl(zhp, cmd_type, vds, B_FALSE));
2636 }
2637
2638 int
zpool_initialize_wait(zpool_handle_t * zhp,pool_initialize_func_t cmd_type,nvlist_t * vds)2639 zpool_initialize_wait(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
2640 nvlist_t *vds)
2641 {
2642 return (zpool_initialize_impl(zhp, cmd_type, vds, B_TRUE));
2643 }
2644
2645 static int
xlate_trim_err(int err)2646 xlate_trim_err(int err)
2647 {
2648 switch (err) {
2649 case ENODEV:
2650 return (EZFS_NODEVICE);
2651 case EINVAL:
2652 case EROFS:
2653 return (EZFS_BADDEV);
2654 case EBUSY:
2655 return (EZFS_TRIMMING);
2656 case ESRCH:
2657 return (EZFS_NO_TRIM);
2658 case EOPNOTSUPP:
2659 return (EZFS_TRIM_NOTSUP);
2660 }
2661 return (err);
2662 }
2663
2664 void
zpool_collect_leaves(zpool_handle_t * zhp,nvlist_t * nvroot,nvlist_t * res)2665 zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
2666 {
2667 libzfs_handle_t *hdl = zhp->zpool_hdl;
2668 uint_t children = 0;
2669 nvlist_t **child;
2670 uint_t i;
2671
2672 (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
2673 &child, &children);
2674
2675 if (children == 0) {
2676 char *path = zpool_vdev_name(hdl, zhp, nvroot,
2677 VDEV_NAME_PATH);
2678
2679 if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 &&
2680 strcmp(path, VDEV_TYPE_HOLE) != 0)
2681 fnvlist_add_boolean(res, path);
2682
2683 free(path);
2684 return;
2685 }
2686
2687 for (i = 0; i < children; i++) {
2688 zpool_collect_leaves(zhp, child[i], res);
2689 }
2690 }
2691
2692 int
zpool_trim_one(zpool_handle_t * zhp,void * data)2693 zpool_trim_one(zpool_handle_t *zhp, void *data)
2694 {
2695 int error;
2696 libzfs_handle_t *hdl = zpool_get_handle(zhp);
2697 const char *pool_name = zpool_get_name(zhp);
2698 if (zpool_open_silent(hdl, pool_name, &zhp) != 0)
2699 return (-1);
2700
2701 trim_cbdata_t *cb = data;
2702 nvlist_t *vdevs = fnvlist_alloc();
2703
2704 /* no individual leaf vdevs specified, so add them all */
2705 nvlist_t *config = zpool_get_config(zhp, NULL);
2706 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
2707 ZPOOL_CONFIG_VDEV_TREE);
2708
2709 zpool_collect_leaves(zhp, nvroot, vdevs);
2710 error = zpool_trim(zhp, cb->cmd_type, vdevs, &cb->trim_flags);
2711 fnvlist_free(vdevs);
2712
2713 return (error);
2714 }
2715
2716 static int
zpool_trim_wait(zpool_handle_t * zhp,nvlist_t * vdev_guids)2717 zpool_trim_wait(zpool_handle_t *zhp, nvlist_t *vdev_guids)
2718 {
2719 int err;
2720 nvpair_t *elem;
2721
2722 for (elem = nvlist_next_nvpair(vdev_guids, NULL); elem != NULL;
2723 elem = nvlist_next_nvpair(vdev_guids, elem)) {
2724
2725 uint64_t guid = fnvpair_value_uint64(elem);
2726
2727 err = lzc_wait_tag(zhp->zpool_name,
2728 ZPOOL_WAIT_TRIM, guid, NULL);
2729 if (err != 0) {
2730 (void) zpool_standard_error_fmt(zhp->zpool_hdl,
2731 err, dgettext(TEXT_DOMAIN, "error "
2732 "waiting to trim '%s'"), nvpair_name(elem));
2733
2734 return (err);
2735 }
2736 }
2737 return (0);
2738 }
2739
2740 /*
2741 * Check errlist and report any errors, omitting ones which should be
2742 * suppressed. Returns B_TRUE if any errors were reported.
2743 */
2744 static boolean_t
check_trim_errs(zpool_handle_t * zhp,trimflags_t * trim_flags,nvlist_t * guids_to_paths,nvlist_t * vds,nvlist_t * errlist)2745 check_trim_errs(zpool_handle_t *zhp, trimflags_t *trim_flags,
2746 nvlist_t *guids_to_paths, nvlist_t *vds, nvlist_t *errlist)
2747 {
2748 nvpair_t *elem;
2749 boolean_t reported_errs = B_FALSE;
2750 int num_vds = 0;
2751 int num_suppressed_errs = 0;
2752
2753 for (elem = nvlist_next_nvpair(vds, NULL);
2754 elem != NULL; elem = nvlist_next_nvpair(vds, elem)) {
2755 num_vds++;
2756 }
2757
2758 for (elem = nvlist_next_nvpair(errlist, NULL);
2759 elem != NULL; elem = nvlist_next_nvpair(errlist, elem)) {
2760 int64_t vd_error = xlate_trim_err(fnvpair_value_int64(elem));
2761 const char *path;
2762
2763 /*
2764 * If only the pool was specified, and it was not a secure
2765 * trim then suppress warnings for individual vdevs which
2766 * do not support trimming.
2767 */
2768 if (vd_error == EZFS_TRIM_NOTSUP &&
2769 trim_flags->fullpool &&
2770 !trim_flags->secure) {
2771 num_suppressed_errs++;
2772 continue;
2773 }
2774
2775 reported_errs = B_TRUE;
2776 if (nvlist_lookup_string(guids_to_paths, nvpair_name(elem),
2777 &path) != 0)
2778 path = nvpair_name(elem);
2779
2780 (void) zfs_error_fmt(zhp->zpool_hdl, vd_error,
2781 "cannot trim '%s'", path);
2782 }
2783
2784 if (num_suppressed_errs == num_vds) {
2785 (void) zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
2786 "no devices in pool support trim operations"));
2787 (void) (zfs_error(zhp->zpool_hdl, EZFS_TRIM_NOTSUP,
2788 dgettext(TEXT_DOMAIN, "cannot trim")));
2789 reported_errs = B_TRUE;
2790 }
2791
2792 return (reported_errs);
2793 }
2794
2795 /*
2796 * Begin, suspend, or cancel the TRIM (discarding of all free blocks) for
2797 * the given vdevs in the given pool.
2798 */
2799 int
zpool_trim(zpool_handle_t * zhp,pool_trim_func_t cmd_type,nvlist_t * vds,trimflags_t * trim_flags)2800 zpool_trim(zpool_handle_t *zhp, pool_trim_func_t cmd_type, nvlist_t *vds,
2801 trimflags_t *trim_flags)
2802 {
2803 int err;
2804 int retval = 0;
2805
2806 nvlist_t *vdev_guids = fnvlist_alloc();
2807 nvlist_t *guids_to_paths = fnvlist_alloc();
2808 nvlist_t *errlist = NULL;
2809
2810 err = zpool_translate_vdev_guids(zhp, vds, vdev_guids,
2811 guids_to_paths, &errlist);
2812 if (err != 0) {
2813 check_trim_errs(zhp, trim_flags, guids_to_paths, vds, errlist);
2814 retval = -1;
2815 goto out;
2816 }
2817
2818 err = lzc_trim(zhp->zpool_name, cmd_type, trim_flags->rate,
2819 trim_flags->secure, vdev_guids, &errlist);
2820 if (err != 0) {
2821 nvlist_t *vd_errlist;
2822 if (errlist != NULL && nvlist_lookup_nvlist(errlist,
2823 ZPOOL_TRIM_VDEVS, &vd_errlist) == 0) {
2824 if (check_trim_errs(zhp, trim_flags, guids_to_paths,
2825 vds, vd_errlist)) {
2826 retval = -1;
2827 goto out;
2828 }
2829 } else {
2830 char errbuf[ERRBUFLEN];
2831
2832 (void) snprintf(errbuf, sizeof (errbuf),
2833 dgettext(TEXT_DOMAIN, "operation failed"));
2834 zpool_standard_error(zhp->zpool_hdl, err, errbuf);
2835 retval = -1;
2836 goto out;
2837 }
2838 }
2839
2840
2841 if (trim_flags->wait)
2842 retval = zpool_trim_wait(zhp, vdev_guids);
2843
2844 out:
2845 if (errlist != NULL)
2846 fnvlist_free(errlist);
2847 fnvlist_free(vdev_guids);
2848 fnvlist_free(guids_to_paths);
2849 return (retval);
2850 }
2851
2852 /*
2853 * Scan the pool.
2854 */
2855 int
zpool_scan(zpool_handle_t * zhp,pool_scan_func_t func,pool_scrub_cmd_t cmd)2856 zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) {
2857 return (zpool_scan_range(zhp, func, cmd, 0, 0));
2858 }
2859
2860 int
zpool_scan_range(zpool_handle_t * zhp,pool_scan_func_t func,pool_scrub_cmd_t cmd,time_t date_start,time_t date_end)2861 zpool_scan_range(zpool_handle_t *zhp, pool_scan_func_t func,
2862 pool_scrub_cmd_t cmd, time_t date_start, time_t date_end)
2863 {
2864 char errbuf[ERRBUFLEN];
2865 int err;
2866 libzfs_handle_t *hdl = zhp->zpool_hdl;
2867
2868 nvlist_t *args = fnvlist_alloc();
2869 fnvlist_add_uint64(args, "scan_type", (uint64_t)func);
2870 fnvlist_add_uint64(args, "scan_command", (uint64_t)cmd);
2871 if (date_start != 0 || date_end != 0) {
2872 fnvlist_add_uint64(args, "scan_date_start",
2873 (uint64_t)date_start);
2874 fnvlist_add_uint64(args, "scan_date_end", (uint64_t)date_end);
2875 }
2876
2877 err = lzc_scrub(ZFS_IOC_POOL_SCRUB, zhp->zpool_name, args, NULL);
2878 fnvlist_free(args);
2879
2880 if (err == 0) {
2881 return (0);
2882 } else if (err == ZFS_ERR_IOC_CMD_UNAVAIL) {
2883 zfs_cmd_t zc = {"\0"};
2884 (void) strlcpy(zc.zc_name, zhp->zpool_name,
2885 sizeof (zc.zc_name));
2886 zc.zc_cookie = func;
2887 zc.zc_flags = cmd;
2888
2889 if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0)
2890 return (0);
2891 }
2892
2893 /*
2894 * An ECANCELED on a scrub means one of the following:
2895 * 1. we resumed a paused scrub.
2896 * 2. we resumed a paused error scrub.
2897 * 3. Error scrub is not run because of no error log.
2898 *
2899 * Note that we no longer return ECANCELED in case 1 or 2. However, in
2900 * order to prevent problems where we have a newer userland than
2901 * kernel, we keep this check in place. That prevents erroneous
2902 * failures when an older kernel returns ECANCELED in those cases.
2903 */
2904 if (err == ECANCELED && (func == POOL_SCAN_SCRUB ||
2905 func == POOL_SCAN_ERRORSCRUB) && cmd == POOL_SCRUB_NORMAL)
2906 return (0);
2907 /*
2908 * The following cases have been handled here:
2909 * 1. Paused a scrub/error scrub if there is none in progress.
2910 */
2911 if (err == ENOENT && func != POOL_SCAN_NONE && cmd ==
2912 POOL_SCRUB_PAUSE) {
2913 return (0);
2914 }
2915
2916 ASSERT3U(func, >=, POOL_SCAN_NONE);
2917 ASSERT3U(func, <, POOL_SCAN_FUNCS);
2918
2919 if (func == POOL_SCAN_SCRUB || func == POOL_SCAN_ERRORSCRUB) {
2920 if (cmd == POOL_SCRUB_PAUSE) {
2921 (void) snprintf(errbuf, sizeof (errbuf),
2922 dgettext(TEXT_DOMAIN, "cannot pause scrubbing %s"),
2923 zhp->zpool_name);
2924 } else {
2925 assert(cmd == POOL_SCRUB_NORMAL);
2926 (void) snprintf(errbuf, sizeof (errbuf),
2927 dgettext(TEXT_DOMAIN, "cannot scrub %s"),
2928 zhp->zpool_name);
2929 }
2930 } else if (func == POOL_SCAN_RESILVER) {
2931 assert(cmd == POOL_SCRUB_NORMAL);
2932 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2933 "cannot restart resilver on %s"), zhp->zpool_name);
2934 } else if (func == POOL_SCAN_NONE) {
2935 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2936 "cannot cancel scrubbing %s"), zhp->zpool_name);
2937 } else {
2938 assert(!"unexpected result");
2939 }
2940
2941 /*
2942 * With EBUSY, six cases are possible:
2943 *
2944 * Current state Requested
2945 * 1. Normal Scrub Running Normal Scrub or Error Scrub
2946 * 2. Normal Scrub Paused Error Scrub
2947 * 3. Normal Scrub Paused Pause Normal Scrub
2948 * 4. Error Scrub Running Normal Scrub or Error Scrub
2949 * 5. Error Scrub Paused Pause Error Scrub
2950 * 6. Resilvering Anything else
2951 */
2952 if (err == EBUSY) {
2953 nvlist_t *nvroot;
2954 pool_scan_stat_t *ps = NULL;
2955 uint_t psc;
2956
2957 nvroot = fnvlist_lookup_nvlist(zhp->zpool_config,
2958 ZPOOL_CONFIG_VDEV_TREE);
2959 (void) nvlist_lookup_uint64_array(nvroot,
2960 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc);
2961 if (ps && ps->pss_func == POOL_SCAN_SCRUB &&
2962 ps->pss_state == DSS_SCANNING) {
2963 if (ps->pss_pass_scrub_pause == 0) {
2964 /* handles case 1 */
2965 assert(cmd == POOL_SCRUB_NORMAL);
2966 return (zfs_error(hdl, EZFS_SCRUBBING,
2967 errbuf));
2968 } else {
2969 if (func == POOL_SCAN_ERRORSCRUB) {
2970 /* handles case 2 */
2971 ASSERT3U(cmd, ==, POOL_SCRUB_NORMAL);
2972 return (zfs_error(hdl,
2973 EZFS_SCRUB_PAUSED_TO_CANCEL,
2974 errbuf));
2975 } else {
2976 /* handles case 3 */
2977 ASSERT3U(func, ==, POOL_SCAN_SCRUB);
2978 ASSERT3U(cmd, ==, POOL_SCRUB_PAUSE);
2979 return (zfs_error(hdl,
2980 EZFS_SCRUB_PAUSED, errbuf));
2981 }
2982 }
2983 } else if (ps &&
2984 ps->pss_error_scrub_func == POOL_SCAN_ERRORSCRUB &&
2985 ps->pss_error_scrub_state == DSS_ERRORSCRUBBING) {
2986 if (ps->pss_pass_error_scrub_pause == 0) {
2987 /* handles case 4 */
2988 ASSERT3U(cmd, ==, POOL_SCRUB_NORMAL);
2989 return (zfs_error(hdl, EZFS_ERRORSCRUBBING,
2990 errbuf));
2991 } else {
2992 /* handles case 5 */
2993 ASSERT3U(func, ==, POOL_SCAN_ERRORSCRUB);
2994 ASSERT3U(cmd, ==, POOL_SCRUB_PAUSE);
2995 return (zfs_error(hdl, EZFS_ERRORSCRUB_PAUSED,
2996 errbuf));
2997 }
2998 } else {
2999 /* handles case 6 */
3000 return (zfs_error(hdl, EZFS_RESILVERING, errbuf));
3001 }
3002 } else if (err == ENOENT) {
3003 return (zfs_error(hdl, EZFS_NO_SCRUB, errbuf));
3004 } else if (err == ENOTSUP && func == POOL_SCAN_RESILVER) {
3005 return (zfs_error(hdl, EZFS_NO_RESILVER_DEFER, errbuf));
3006 } else {
3007 return (zpool_standard_error(hdl, err, errbuf));
3008 }
3009 }
3010
3011 /*
3012 * Find a vdev that matches the search criteria specified. We use the
3013 * the nvpair name to determine how we should look for the device.
3014 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
3015 * spare; but FALSE if its an INUSE spare.
3016 *
3017 * If 'return_parent' is set, then return the *parent* of the vdev you're
3018 * searching for rather than the vdev itself.
3019 */
3020 static nvlist_t *
vdev_to_nvlist_iter(nvlist_t * nv,nvlist_t * search,boolean_t * avail_spare,boolean_t * l2cache,boolean_t * log,boolean_t return_parent)3021 vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
3022 boolean_t *l2cache, boolean_t *log, boolean_t return_parent)
3023 {
3024 uint_t c, children;
3025 nvlist_t **child;
3026 nvlist_t *ret;
3027 uint64_t is_log;
3028 const char *srchkey;
3029 nvpair_t *pair = nvlist_next_nvpair(search, NULL);
3030 const char *tmp = NULL;
3031 boolean_t is_root;
3032
3033 /* Nothing to look for */
3034 if (search == NULL || pair == NULL)
3035 return (NULL);
3036
3037 /* Obtain the key we will use to search */
3038 srchkey = nvpair_name(pair);
3039
3040 nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &tmp);
3041 if (strcmp(tmp, "root") == 0)
3042 is_root = B_TRUE;
3043 else
3044 is_root = B_FALSE;
3045
3046 switch (nvpair_type(pair)) {
3047 case DATA_TYPE_UINT64:
3048 if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
3049 uint64_t srchval = fnvpair_value_uint64(pair);
3050 uint64_t theguid = fnvlist_lookup_uint64(nv,
3051 ZPOOL_CONFIG_GUID);
3052 if (theguid == srchval)
3053 return (nv);
3054 }
3055 break;
3056
3057 case DATA_TYPE_STRING: {
3058 const char *srchval, *val;
3059
3060 srchval = fnvpair_value_string(pair);
3061 if (nvlist_lookup_string(nv, srchkey, &val) != 0)
3062 break;
3063
3064 /*
3065 * Search for the requested value. Special cases:
3066 *
3067 * - ZPOOL_CONFIG_PATH for whole disk entries. These end in
3068 * "-part1", or "p1". The suffix is hidden from the user,
3069 * but included in the string, so this matches around it.
3070 * - ZPOOL_CONFIG_PATH for short names zfs_strcmp_shortname()
3071 * is used to check all possible expanded paths.
3072 * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE).
3073 *
3074 * Otherwise, all other searches are simple string compares.
3075 */
3076 if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0) {
3077 uint64_t wholedisk = 0;
3078
3079 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
3080 &wholedisk);
3081 if (zfs_strcmp_pathname(srchval, val, wholedisk) == 0)
3082 return (nv);
3083
3084 } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0) {
3085 char *type, *idx, *end, *p;
3086 uint64_t id, vdev_id;
3087
3088 /*
3089 * Determine our vdev type, keeping in mind
3090 * that the srchval is composed of a type and
3091 * vdev id pair (i.e. mirror-4).
3092 */
3093 if ((type = strdup(srchval)) == NULL)
3094 return (NULL);
3095
3096 if ((p = strrchr(type, '-')) == NULL) {
3097 free(type);
3098 break;
3099 }
3100 idx = p + 1;
3101 *p = '\0';
3102
3103 /*
3104 * draid names are presented like: draid2:4d:6c:0s
3105 * We match them up to the first ':' so we can still
3106 * do the parity check below, but the other params
3107 * are ignored.
3108 */
3109 if ((p = strchr(type, ':')) != NULL) {
3110 if (strncmp(type, VDEV_TYPE_DRAID,
3111 strlen(VDEV_TYPE_DRAID)) == 0)
3112 *p = '\0';
3113 }
3114
3115 /*
3116 * If the types don't match then keep looking.
3117 */
3118 if (strncmp(val, type, strlen(val)) != 0) {
3119 free(type);
3120 break;
3121 }
3122
3123 verify(zpool_vdev_is_interior(type));
3124
3125 id = fnvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID);
3126 errno = 0;
3127 vdev_id = strtoull(idx, &end, 10);
3128
3129 /*
3130 * If we are looking for a raidz and a parity is
3131 * specified, make sure it matches.
3132 */
3133 int rzlen = strlen(VDEV_TYPE_RAIDZ);
3134 assert(rzlen == strlen(VDEV_TYPE_DRAID));
3135 int typlen = strlen(type);
3136 if ((strncmp(type, VDEV_TYPE_RAIDZ, rzlen) == 0 ||
3137 strncmp(type, VDEV_TYPE_DRAID, rzlen) == 0) &&
3138 typlen != rzlen) {
3139 uint64_t vdev_parity;
3140 int parity = *(type + rzlen) - '0';
3141
3142 if (parity <= 0 || parity > 3 ||
3143 (typlen - rzlen) != 1) {
3144 /*
3145 * Nonsense parity specified, can
3146 * never match
3147 */
3148 free(type);
3149 return (NULL);
3150 }
3151 vdev_parity = fnvlist_lookup_uint64(nv,
3152 ZPOOL_CONFIG_NPARITY);
3153 if ((int)vdev_parity != parity) {
3154 free(type);
3155 break;
3156 }
3157 }
3158
3159 free(type);
3160 if (errno != 0)
3161 return (NULL);
3162
3163 /*
3164 * Now verify that we have the correct vdev id.
3165 */
3166 if (vdev_id == id)
3167 return (nv);
3168 }
3169
3170 /*
3171 * Common case
3172 */
3173 if (strcmp(srchval, val) == 0)
3174 return (nv);
3175 break;
3176 }
3177
3178 default:
3179 break;
3180 }
3181
3182 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3183 &child, &children) != 0)
3184 return (NULL);
3185
3186 for (c = 0; c < children; c++) {
3187 if ((ret = vdev_to_nvlist_iter(child[c], search,
3188 avail_spare, l2cache, NULL, return_parent)) != NULL) {
3189 /*
3190 * The 'is_log' value is only set for the toplevel
3191 * vdev, not the leaf vdevs. So we always lookup the
3192 * log device from the root of the vdev tree (where
3193 * 'log' is non-NULL).
3194 */
3195 if (log != NULL &&
3196 nvlist_lookup_uint64(child[c],
3197 ZPOOL_CONFIG_IS_LOG, &is_log) == 0 &&
3198 is_log) {
3199 *log = B_TRUE;
3200 }
3201 return (ret && return_parent && !is_root ? nv : ret);
3202 }
3203 }
3204
3205 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
3206 &child, &children) == 0) {
3207 for (c = 0; c < children; c++) {
3208 if ((ret = vdev_to_nvlist_iter(child[c], search,
3209 avail_spare, l2cache, NULL, return_parent))
3210 != NULL) {
3211 *avail_spare = B_TRUE;
3212 return (ret && return_parent &&
3213 !is_root ? nv : ret);
3214 }
3215 }
3216 }
3217
3218 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3219 &child, &children) == 0) {
3220 for (c = 0; c < children; c++) {
3221 if ((ret = vdev_to_nvlist_iter(child[c], search,
3222 avail_spare, l2cache, NULL, return_parent))
3223 != NULL) {
3224 *l2cache = B_TRUE;
3225 return (ret && return_parent &&
3226 !is_root ? nv : ret);
3227 }
3228 }
3229 }
3230
3231 return (NULL);
3232 }
3233
3234 /*
3235 * Given a physical path or guid, find the associated vdev.
3236 */
3237 nvlist_t *
zpool_find_vdev_by_physpath(zpool_handle_t * zhp,const char * ppath,boolean_t * avail_spare,boolean_t * l2cache,boolean_t * log)3238 zpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath,
3239 boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
3240 {
3241 nvlist_t *search, *nvroot, *ret;
3242 uint64_t guid;
3243 char *end;
3244
3245 search = fnvlist_alloc();
3246
3247 guid = strtoull(ppath, &end, 0);
3248 if (guid != 0 && *end == '\0') {
3249 fnvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid);
3250 } else {
3251 fnvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath);
3252 }
3253
3254 nvroot = fnvlist_lookup_nvlist(zhp->zpool_config,
3255 ZPOOL_CONFIG_VDEV_TREE);
3256
3257 *avail_spare = B_FALSE;
3258 *l2cache = B_FALSE;
3259 if (log != NULL)
3260 *log = B_FALSE;
3261 ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log,
3262 B_FALSE);
3263 fnvlist_free(search);
3264
3265 return (ret);
3266 }
3267
3268 /*
3269 * Determine if we have an "interior" top-level vdev (i.e mirror/raidz).
3270 */
3271 static boolean_t
zpool_vdev_is_interior(const char * name)3272 zpool_vdev_is_interior(const char *name)
3273 {
3274 if (strncmp(name, VDEV_TYPE_RAIDZ, strlen(VDEV_TYPE_RAIDZ)) == 0 ||
3275 strncmp(name, VDEV_TYPE_SPARE, strlen(VDEV_TYPE_SPARE)) == 0 ||
3276 strncmp(name,
3277 VDEV_TYPE_REPLACING, strlen(VDEV_TYPE_REPLACING)) == 0 ||
3278 strncmp(name, VDEV_TYPE_ROOT, strlen(VDEV_TYPE_ROOT)) == 0 ||
3279 strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0)
3280 return (B_TRUE);
3281
3282 if (strncmp(name, VDEV_TYPE_DRAID, strlen(VDEV_TYPE_DRAID)) == 0 &&
3283 !zpool_is_draid_spare(name))
3284 return (B_TRUE);
3285
3286 return (B_FALSE);
3287 }
3288
3289 /*
3290 * Lookup the nvlist for a given vdev or vdev's parent (depending on
3291 * if 'return_parent' is set).
3292 */
3293 static nvlist_t *
__zpool_find_vdev(zpool_handle_t * zhp,const char * path,boolean_t * avail_spare,boolean_t * l2cache,boolean_t * log,boolean_t return_parent)3294 __zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
3295 boolean_t *l2cache, boolean_t *log, boolean_t return_parent)
3296 {
3297 char *end;
3298 nvlist_t *nvroot, *search, *ret;
3299 uint64_t guid;
3300 boolean_t __avail_spare, __l2cache, __log;
3301
3302 search = fnvlist_alloc();
3303
3304 guid = strtoull(path, &end, 0);
3305 if (guid != 0 && *end == '\0') {
3306 fnvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid);
3307 } else if (zpool_vdev_is_interior(path)) {
3308 fnvlist_add_string(search, ZPOOL_CONFIG_TYPE, path);
3309 } else {
3310 fnvlist_add_string(search, ZPOOL_CONFIG_PATH, path);
3311 }
3312
3313 nvroot = fnvlist_lookup_nvlist(zhp->zpool_config,
3314 ZPOOL_CONFIG_VDEV_TREE);
3315
3316 /*
3317 * User can pass NULL for avail_spare, l2cache, and log, but
3318 * we still need to provide variables to vdev_to_nvlist_iter(), so
3319 * just point them to junk variables here.
3320 */
3321 if (!avail_spare)
3322 avail_spare = &__avail_spare;
3323 if (!l2cache)
3324 l2cache = &__l2cache;
3325 if (!log)
3326 log = &__log;
3327
3328 *avail_spare = B_FALSE;
3329 *l2cache = B_FALSE;
3330 if (log != NULL)
3331 *log = B_FALSE;
3332 ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log,
3333 return_parent);
3334 fnvlist_free(search);
3335
3336 return (ret);
3337 }
3338
3339 nvlist_t *
zpool_find_vdev(zpool_handle_t * zhp,const char * path,boolean_t * avail_spare,boolean_t * l2cache,boolean_t * log)3340 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
3341 boolean_t *l2cache, boolean_t *log)
3342 {
3343 return (__zpool_find_vdev(zhp, path, avail_spare, l2cache, log,
3344 B_FALSE));
3345 }
3346
3347 /* Given a vdev path, return its parent's nvlist */
3348 nvlist_t *
zpool_find_parent_vdev(zpool_handle_t * zhp,const char * path,boolean_t * avail_spare,boolean_t * l2cache,boolean_t * log)3349 zpool_find_parent_vdev(zpool_handle_t *zhp, const char *path,
3350 boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
3351 {
3352 return (__zpool_find_vdev(zhp, path, avail_spare, l2cache, log,
3353 B_TRUE));
3354 }
3355
3356 /*
3357 * Convert a vdev path to a GUID. Returns GUID or 0 on error.
3358 *
3359 * If is_spare, is_l2cache, or is_log is non-NULL, then store within it
3360 * if the VDEV is a spare, l2cache, or log device. If they're NULL then
3361 * ignore them.
3362 */
3363 static uint64_t
zpool_vdev_path_to_guid_impl(zpool_handle_t * zhp,const char * path,boolean_t * is_spare,boolean_t * is_l2cache,boolean_t * is_log)3364 zpool_vdev_path_to_guid_impl(zpool_handle_t *zhp, const char *path,
3365 boolean_t *is_spare, boolean_t *is_l2cache, boolean_t *is_log)
3366 {
3367 boolean_t spare = B_FALSE, l2cache = B_FALSE, log = B_FALSE;
3368 nvlist_t *tgt;
3369
3370 if ((tgt = zpool_find_vdev(zhp, path, &spare, &l2cache,
3371 &log)) == NULL)
3372 return (0);
3373
3374 if (is_spare != NULL)
3375 *is_spare = spare;
3376 if (is_l2cache != NULL)
3377 *is_l2cache = l2cache;
3378 if (is_log != NULL)
3379 *is_log = log;
3380
3381 return (fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID));
3382 }
3383
3384 /* Convert a vdev path to a GUID. Returns GUID or 0 on error. */
3385 uint64_t
zpool_vdev_path_to_guid(zpool_handle_t * zhp,const char * path)3386 zpool_vdev_path_to_guid(zpool_handle_t *zhp, const char *path)
3387 {
3388 return (zpool_vdev_path_to_guid_impl(zhp, path, NULL, NULL, NULL));
3389 }
3390
3391 /*
3392 * Bring the specified vdev online. The 'flags' parameter is a set of the
3393 * ZFS_ONLINE_* flags.
3394 */
3395 int
zpool_vdev_online(zpool_handle_t * zhp,const char * path,int flags,vdev_state_t * newstate)3396 zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
3397 vdev_state_t *newstate)
3398 {
3399 zfs_cmd_t zc = {"\0"};
3400 char errbuf[ERRBUFLEN];
3401 nvlist_t *tgt;
3402 boolean_t avail_spare, l2cache, islog;
3403 libzfs_handle_t *hdl = zhp->zpool_hdl;
3404
3405 if (flags & ZFS_ONLINE_EXPAND) {
3406 (void) snprintf(errbuf, sizeof (errbuf),
3407 dgettext(TEXT_DOMAIN, "cannot expand %s"), path);
3408 } else {
3409 (void) snprintf(errbuf, sizeof (errbuf),
3410 dgettext(TEXT_DOMAIN, "cannot online %s"), path);
3411 }
3412
3413 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3414 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3415 &islog)) == NULL)
3416 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3417
3418 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3419
3420 if (!(flags & ZFS_ONLINE_SPARE) && avail_spare)
3421 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
3422
3423 #ifndef __FreeBSD__
3424 const char *pathname;
3425 if ((flags & ZFS_ONLINE_EXPAND ||
3426 zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) &&
3427 nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &pathname) == 0) {
3428 uint64_t wholedisk = 0;
3429
3430 (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
3431 &wholedisk);
3432
3433 /*
3434 * XXX - L2ARC 1.0 devices can't support expansion.
3435 */
3436 if (l2cache) {
3437 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3438 "cannot expand cache devices"));
3439 return (zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf));
3440 }
3441
3442 if (wholedisk) {
3443 const char *fullpath = path;
3444 char buf[MAXPATHLEN];
3445 int error;
3446
3447 if (path[0] != '/') {
3448 error = zfs_resolve_shortname(path, buf,
3449 sizeof (buf));
3450 if (error != 0)
3451 return (zfs_error(hdl, EZFS_NODEVICE,
3452 errbuf));
3453
3454 fullpath = buf;
3455 }
3456
3457 error = zpool_relabel_disk(hdl, fullpath, errbuf);
3458 if (error != 0)
3459 return (error);
3460 }
3461 }
3462 #endif
3463
3464 zc.zc_cookie = VDEV_STATE_ONLINE;
3465 zc.zc_obj = flags;
3466
3467 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) {
3468 if (errno == EINVAL) {
3469 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "was split "
3470 "from this pool into a new one. Use '%s' "
3471 "instead"), "zpool detach");
3472 return (zfs_error(hdl, EZFS_POSTSPLIT_ONLINE, errbuf));
3473 }
3474 return (zpool_standard_error(hdl, errno, errbuf));
3475 }
3476
3477 *newstate = zc.zc_cookie;
3478 return (0);
3479 }
3480
3481 /*
3482 * Take the specified vdev offline
3483 */
3484 int
zpool_vdev_offline(zpool_handle_t * zhp,const char * path,boolean_t istmp)3485 zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
3486 {
3487 zfs_cmd_t zc = {"\0"};
3488 char errbuf[ERRBUFLEN];
3489 nvlist_t *tgt;
3490 boolean_t avail_spare, l2cache;
3491 libzfs_handle_t *hdl = zhp->zpool_hdl;
3492
3493 (void) snprintf(errbuf, sizeof (errbuf),
3494 dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
3495
3496 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3497 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3498 NULL)) == NULL)
3499 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3500
3501 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3502
3503 if (avail_spare)
3504 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
3505
3506 zc.zc_cookie = VDEV_STATE_OFFLINE;
3507 zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0;
3508
3509 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3510 return (0);
3511
3512 switch (errno) {
3513 case EBUSY:
3514
3515 /*
3516 * There are no other replicas of this device.
3517 */
3518 return (zfs_error(hdl, EZFS_NOREPLICAS, errbuf));
3519
3520 case EEXIST:
3521 /*
3522 * The log device has unplayed logs
3523 */
3524 return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, errbuf));
3525
3526 default:
3527 return (zpool_standard_error(hdl, errno, errbuf));
3528 }
3529 }
3530
3531 /*
3532 * Remove the specified vdev asynchronously from the configuration, so
3533 * that it may come ONLINE if reinserted. This is called from zed on
3534 * Udev remove event.
3535 * Note: We also have a similar function zpool_vdev_remove() that
3536 * removes the vdev from the pool.
3537 */
3538 int
zpool_vdev_remove_wanted(zpool_handle_t * zhp,const char * path)3539 zpool_vdev_remove_wanted(zpool_handle_t *zhp, const char *path)
3540 {
3541 zfs_cmd_t zc = {"\0"};
3542 char errbuf[ERRBUFLEN];
3543 nvlist_t *tgt;
3544 boolean_t avail_spare, l2cache;
3545 libzfs_handle_t *hdl = zhp->zpool_hdl;
3546
3547 (void) snprintf(errbuf, sizeof (errbuf),
3548 dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
3549
3550 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3551 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3552 NULL)) == NULL)
3553 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3554
3555 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3556
3557 zc.zc_cookie = VDEV_STATE_REMOVED;
3558
3559 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3560 return (0);
3561
3562 return (zpool_standard_error(hdl, errno, errbuf));
3563 }
3564
3565 /*
3566 * Mark the given vdev faulted.
3567 */
3568 int
zpool_vdev_fault(zpool_handle_t * zhp,uint64_t guid,vdev_aux_t aux)3569 zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
3570 {
3571 zfs_cmd_t zc = {"\0"};
3572 char errbuf[ERRBUFLEN];
3573 libzfs_handle_t *hdl = zhp->zpool_hdl;
3574
3575 (void) snprintf(errbuf, sizeof (errbuf),
3576 dgettext(TEXT_DOMAIN, "cannot fault %llu"), (u_longlong_t)guid);
3577
3578 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3579 zc.zc_guid = guid;
3580 zc.zc_cookie = VDEV_STATE_FAULTED;
3581 zc.zc_obj = aux;
3582
3583 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3584 return (0);
3585
3586 switch (errno) {
3587 case EBUSY:
3588
3589 /*
3590 * There are no other replicas of this device.
3591 */
3592 return (zfs_error(hdl, EZFS_NOREPLICAS, errbuf));
3593
3594 default:
3595 return (zpool_standard_error(hdl, errno, errbuf));
3596 }
3597
3598 }
3599
3600 /*
3601 * Generic set vdev state function
3602 */
3603 static int
zpool_vdev_set_state(zpool_handle_t * zhp,uint64_t guid,vdev_aux_t aux,vdev_state_t state)3604 zpool_vdev_set_state(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux,
3605 vdev_state_t state)
3606 {
3607 zfs_cmd_t zc = {"\0"};
3608 char errbuf[ERRBUFLEN];
3609 libzfs_handle_t *hdl = zhp->zpool_hdl;
3610
3611 (void) snprintf(errbuf, sizeof (errbuf),
3612 dgettext(TEXT_DOMAIN, "cannot set %s %llu"),
3613 zpool_state_to_name(state, aux), (u_longlong_t)guid);
3614
3615 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3616 zc.zc_guid = guid;
3617 zc.zc_cookie = state;
3618 zc.zc_obj = aux;
3619
3620 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3621 return (0);
3622
3623 return (zpool_standard_error(hdl, errno, errbuf));
3624 }
3625
3626 /*
3627 * Mark the given vdev degraded.
3628 */
3629 int
zpool_vdev_degrade(zpool_handle_t * zhp,uint64_t guid,vdev_aux_t aux)3630 zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
3631 {
3632 return (zpool_vdev_set_state(zhp, guid, aux, VDEV_STATE_DEGRADED));
3633 }
3634
3635 /*
3636 * Mark the given vdev as in a removed state (as if the device does not exist).
3637 *
3638 * This is different than zpool_vdev_remove() which does a removal of a device
3639 * from the pool (but the device does exist).
3640 */
3641 int
zpool_vdev_set_removed_state(zpool_handle_t * zhp,uint64_t guid,vdev_aux_t aux)3642 zpool_vdev_set_removed_state(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
3643 {
3644 return (zpool_vdev_set_state(zhp, guid, aux, VDEV_STATE_REMOVED));
3645 }
3646
3647 /*
3648 * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
3649 * a hot spare.
3650 */
3651 static boolean_t
is_replacing_spare(nvlist_t * search,nvlist_t * tgt,int which)3652 is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
3653 {
3654 nvlist_t **child;
3655 uint_t c, children;
3656
3657 if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
3658 &children) == 0) {
3659 const char *type = fnvlist_lookup_string(search,
3660 ZPOOL_CONFIG_TYPE);
3661 if ((strcmp(type, VDEV_TYPE_SPARE) == 0 ||
3662 strcmp(type, VDEV_TYPE_DRAID_SPARE) == 0) &&
3663 children == 2 && child[which] == tgt)
3664 return (B_TRUE);
3665
3666 for (c = 0; c < children; c++)
3667 if (is_replacing_spare(child[c], tgt, which))
3668 return (B_TRUE);
3669 }
3670
3671 return (B_FALSE);
3672 }
3673
3674 /*
3675 * Attach new_disk (fully described by nvroot) to old_disk.
3676 * If 'replacing' is specified, the new disk will replace the old one.
3677 */
3678 int
zpool_vdev_attach(zpool_handle_t * zhp,const char * old_disk,const char * new_disk,nvlist_t * nvroot,int replacing,boolean_t rebuild)3679 zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk,
3680 const char *new_disk, nvlist_t *nvroot, int replacing, boolean_t rebuild)
3681 {
3682 zfs_cmd_t zc = {"\0"};
3683 char errbuf[ERRBUFLEN];
3684 int ret;
3685 nvlist_t *tgt;
3686 boolean_t avail_spare, l2cache, islog;
3687 uint64_t val;
3688 char *newname;
3689 const char *type;
3690 nvlist_t **child;
3691 uint_t children;
3692 nvlist_t *config_root;
3693 libzfs_handle_t *hdl = zhp->zpool_hdl;
3694
3695 if (replacing)
3696 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3697 "cannot replace %s with %s"), old_disk, new_disk);
3698 else
3699 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3700 "cannot attach %s to %s"), new_disk, old_disk);
3701
3702 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3703 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
3704 &islog)) == NULL)
3705 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3706
3707 if (avail_spare)
3708 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
3709
3710 if (l2cache)
3711 return (zfs_error(hdl, EZFS_ISL2CACHE, errbuf));
3712
3713 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3714 zc.zc_cookie = replacing;
3715 zc.zc_simple = rebuild;
3716
3717 if (rebuild &&
3718 zfeature_lookup_guid("org.openzfs:device_rebuild", NULL) != 0) {
3719 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3720 "the loaded zfs module doesn't support device rebuilds"));
3721 return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
3722 }
3723
3724 type = fnvlist_lookup_string(tgt, ZPOOL_CONFIG_TYPE);
3725 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 &&
3726 zfeature_lookup_guid("org.openzfs:raidz_expansion", NULL) != 0) {
3727 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3728 "the loaded zfs module doesn't support raidz expansion"));
3729 return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
3730 }
3731
3732 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
3733 &child, &children) != 0 || children != 1) {
3734 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3735 "new device must be a single disk"));
3736 return (zfs_error(hdl, EZFS_INVALCONFIG, errbuf));
3737 }
3738
3739 config_root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
3740 ZPOOL_CONFIG_VDEV_TREE);
3741
3742 if ((newname = zpool_vdev_name(NULL, NULL, child[0], 0)) == NULL)
3743 return (-1);
3744
3745 /*
3746 * If the target is a hot spare that has been swapped in, we can only
3747 * replace it with another hot spare.
3748 */
3749 if (replacing &&
3750 nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
3751 (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache,
3752 NULL) == NULL || !avail_spare) &&
3753 is_replacing_spare(config_root, tgt, 1)) {
3754 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3755 "can only be replaced by another hot spare"));
3756 free(newname);
3757 return (zfs_error(hdl, EZFS_BADTARGET, errbuf));
3758 }
3759
3760 free(newname);
3761
3762 zcmd_write_conf_nvlist(hdl, &zc, nvroot);
3763
3764 ret = zfs_ioctl(hdl, ZFS_IOC_VDEV_ATTACH, &zc);
3765
3766 zcmd_free_nvlists(&zc);
3767
3768 if (ret == 0)
3769 return (0);
3770
3771 switch (errno) {
3772 case ENOTSUP:
3773 /*
3774 * Can't attach to or replace this type of vdev.
3775 */
3776 if (replacing) {
3777 uint64_t version = zpool_get_prop_int(zhp,
3778 ZPOOL_PROP_VERSION, NULL);
3779
3780 if (islog) {
3781 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3782 "cannot replace a log with a spare"));
3783 } else if (rebuild) {
3784 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3785 "only mirror and dRAID vdevs support "
3786 "sequential reconstruction"));
3787 } else if (zpool_is_draid_spare(new_disk)) {
3788 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3789 "dRAID spares can only replace child "
3790 "devices in their parent's dRAID vdev"));
3791 } else if (version >= SPA_VERSION_MULTI_REPLACE) {
3792 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3793 "already in replacing/spare config; wait "
3794 "for completion or use 'zpool detach'"));
3795 } else {
3796 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3797 "cannot replace a replacing device"));
3798 }
3799 } else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
3800 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3801 "raidz_expansion feature must be enabled "
3802 "in order to attach a device to raidz"));
3803 } else {
3804 char status[64] = {0};
3805 zpool_prop_get_feature(zhp,
3806 "feature@device_rebuild", status, 63);
3807 if (rebuild &&
3808 strncmp(status, ZFS_FEATURE_DISABLED, 64) == 0) {
3809 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3810 "device_rebuild feature must be enabled "
3811 "in order to use sequential "
3812 "reconstruction"));
3813 } else {
3814 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3815 "can only attach to mirrors and top-level "
3816 "disks"));
3817 }
3818 }
3819 (void) zfs_error(hdl, EZFS_BADTARGET, errbuf);
3820 break;
3821
3822 case EINVAL:
3823 /*
3824 * The new device must be a single disk.
3825 */
3826 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3827 "new device must be a single disk"));
3828 (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
3829 break;
3830
3831 case EBUSY:
3832 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"),
3833 new_disk);
3834 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
3835 break;
3836
3837 case EOVERFLOW:
3838 /*
3839 * The new device is too small.
3840 */
3841 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3842 "device is too small"));
3843 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
3844 break;
3845
3846 case EDOM:
3847 /*
3848 * The new device has a different optimal sector size.
3849 */
3850 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3851 "new device has a different optimal sector size; use the "
3852 "option '-o ashift=N' to override the optimal size"));
3853 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
3854 break;
3855
3856 case ENAMETOOLONG:
3857 /*
3858 * The resulting top-level vdev spec won't fit in the label.
3859 */
3860 (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf);
3861 break;
3862
3863 case ENXIO:
3864 /*
3865 * The existing raidz vdev has offline children
3866 */
3867 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
3868 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3869 "raidz vdev has devices that are are offline or "
3870 "being replaced"));
3871 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
3872 break;
3873 } else {
3874 (void) zpool_standard_error(hdl, errno, errbuf);
3875 }
3876 break;
3877
3878 case EADDRINUSE:
3879 /*
3880 * The boot reserved area is already being used (FreeBSD)
3881 */
3882 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
3883 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3884 "the reserved boot area needed for the expansion "
3885 "is already being used by a boot loader"));
3886 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
3887 } else {
3888 (void) zpool_standard_error(hdl, errno, errbuf);
3889 }
3890 break;
3891
3892 case ZFS_ERR_ASHIFT_MISMATCH:
3893 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3894 "The new device cannot have a higher alignment requirement "
3895 "than the top-level vdev."));
3896 (void) zfs_error(hdl, EZFS_BADTARGET, errbuf);
3897 break;
3898 default:
3899 (void) zpool_standard_error(hdl, errno, errbuf);
3900 }
3901
3902 return (-1);
3903 }
3904
3905 /*
3906 * Detach the specified device.
3907 */
3908 int
zpool_vdev_detach(zpool_handle_t * zhp,const char * path)3909 zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
3910 {
3911 zfs_cmd_t zc = {"\0"};
3912 char errbuf[ERRBUFLEN];
3913 nvlist_t *tgt;
3914 boolean_t avail_spare, l2cache;
3915 libzfs_handle_t *hdl = zhp->zpool_hdl;
3916
3917 (void) snprintf(errbuf, sizeof (errbuf),
3918 dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
3919
3920 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3921 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3922 NULL)) == NULL)
3923 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3924
3925 if (avail_spare)
3926 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
3927
3928 if (l2cache)
3929 return (zfs_error(hdl, EZFS_ISL2CACHE, errbuf));
3930
3931 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3932
3933 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0)
3934 return (0);
3935
3936 switch (errno) {
3937
3938 case ENOTSUP:
3939 /*
3940 * Can't detach from this type of vdev.
3941 */
3942 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
3943 "applicable to mirror and replacing vdevs"));
3944 (void) zfs_error(hdl, EZFS_BADTARGET, errbuf);
3945 break;
3946
3947 case EBUSY:
3948 /*
3949 * There are no other replicas of this device.
3950 */
3951 (void) zfs_error(hdl, EZFS_NOREPLICAS, errbuf);
3952 break;
3953
3954 default:
3955 (void) zpool_standard_error(hdl, errno, errbuf);
3956 }
3957
3958 return (-1);
3959 }
3960
3961 /*
3962 * Find a mirror vdev in the source nvlist.
3963 *
3964 * The mchild array contains a list of disks in one of the top-level mirrors
3965 * of the source pool. The schild array contains a list of disks that the
3966 * user specified on the command line. We loop over the mchild array to
3967 * see if any entry in the schild array matches.
3968 *
3969 * If a disk in the mchild array is found in the schild array, we return
3970 * the index of that entry. Otherwise we return -1.
3971 */
3972 static int
find_vdev_entry(zpool_handle_t * zhp,nvlist_t ** mchild,uint_t mchildren,nvlist_t ** schild,uint_t schildren)3973 find_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren,
3974 nvlist_t **schild, uint_t schildren)
3975 {
3976 uint_t mc;
3977
3978 for (mc = 0; mc < mchildren; mc++) {
3979 uint_t sc;
3980 char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp,
3981 mchild[mc], 0);
3982
3983 for (sc = 0; sc < schildren; sc++) {
3984 char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp,
3985 schild[sc], 0);
3986 boolean_t result = (strcmp(mpath, spath) == 0);
3987
3988 free(spath);
3989 if (result) {
3990 free(mpath);
3991 return (mc);
3992 }
3993 }
3994
3995 free(mpath);
3996 }
3997
3998 return (-1);
3999 }
4000
4001 /*
4002 * Split a mirror pool. If newroot points to null, then a new nvlist
4003 * is generated and it is the responsibility of the caller to free it.
4004 */
4005 int
zpool_vdev_split(zpool_handle_t * zhp,char * newname,nvlist_t ** newroot,nvlist_t * props,splitflags_t flags)4006 zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot,
4007 nvlist_t *props, splitflags_t flags)
4008 {
4009 zfs_cmd_t zc = {"\0"};
4010 char errbuf[ERRBUFLEN];
4011 const char *bias;
4012 nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL;
4013 nvlist_t **varray = NULL, *zc_props = NULL;
4014 uint_t c, children, newchildren, lastlog = 0, vcount, found = 0;
4015 libzfs_handle_t *hdl = zhp->zpool_hdl;
4016 uint64_t vers, readonly = B_FALSE;
4017 boolean_t freelist = B_FALSE, memory_err = B_TRUE;
4018 int retval = 0;
4019
4020 (void) snprintf(errbuf, sizeof (errbuf),
4021 dgettext(TEXT_DOMAIN, "Unable to split %s"), zhp->zpool_name);
4022
4023 if (!zpool_name_valid(hdl, B_FALSE, newname))
4024 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4025
4026 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
4027 (void) fprintf(stderr, gettext("Internal error: unable to "
4028 "retrieve pool configuration\n"));
4029 return (-1);
4030 }
4031
4032 tree = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4033 vers = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
4034
4035 if (props) {
4036 prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
4037 if ((zc_props = zpool_valid_proplist(hdl, zhp->zpool_name,
4038 props, vers, flags, errbuf)) == NULL)
4039 return (-1);
4040 (void) nvlist_lookup_uint64(zc_props,
4041 zpool_prop_to_name(ZPOOL_PROP_READONLY), &readonly);
4042 if (readonly) {
4043 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4044 "property %s can only be set at import time"),
4045 zpool_prop_to_name(ZPOOL_PROP_READONLY));
4046 return (-1);
4047 }
4048 }
4049
4050 if (nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child,
4051 &children) != 0) {
4052 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4053 "Source pool is missing vdev tree"));
4054 nvlist_free(zc_props);
4055 return (-1);
4056 }
4057
4058 varray = zfs_alloc(hdl, children * sizeof (nvlist_t *));
4059 vcount = 0;
4060
4061 if (*newroot == NULL ||
4062 nvlist_lookup_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN,
4063 &newchild, &newchildren) != 0)
4064 newchildren = 0;
4065
4066 for (c = 0; c < children; c++) {
4067 uint64_t is_log = B_FALSE, is_hole = B_FALSE;
4068 boolean_t is_special = B_FALSE, is_dedup = B_FALSE;
4069 const char *type;
4070 nvlist_t **mchild, *vdev;
4071 uint_t mchildren;
4072 int entry;
4073
4074 /*
4075 * Unlike cache & spares, slogs are stored in the
4076 * ZPOOL_CONFIG_CHILDREN array. We filter them out here.
4077 */
4078 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
4079 &is_log);
4080 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
4081 &is_hole);
4082 if (is_log || is_hole) {
4083 /*
4084 * Create a hole vdev and put it in the config.
4085 */
4086 if (nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) != 0)
4087 goto out;
4088 if (nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE,
4089 VDEV_TYPE_HOLE) != 0)
4090 goto out;
4091 if (nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_HOLE,
4092 1) != 0)
4093 goto out;
4094 if (lastlog == 0)
4095 lastlog = vcount;
4096 varray[vcount++] = vdev;
4097 continue;
4098 }
4099 lastlog = 0;
4100 type = fnvlist_lookup_string(child[c], ZPOOL_CONFIG_TYPE);
4101
4102 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) {
4103 vdev = child[c];
4104 if (nvlist_dup(vdev, &varray[vcount++], 0) != 0)
4105 goto out;
4106 continue;
4107 } else if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
4108 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4109 "Source pool must be composed only of mirrors\n"));
4110 retval = zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
4111 goto out;
4112 }
4113
4114 if (nvlist_lookup_string(child[c],
4115 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias) == 0) {
4116 if (strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0)
4117 is_special = B_TRUE;
4118 else if (strcmp(bias, VDEV_ALLOC_BIAS_DEDUP) == 0)
4119 is_dedup = B_TRUE;
4120 }
4121 verify(nvlist_lookup_nvlist_array(child[c],
4122 ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0);
4123
4124 /* find or add an entry for this top-level vdev */
4125 if (newchildren > 0 &&
4126 (entry = find_vdev_entry(zhp, mchild, mchildren,
4127 newchild, newchildren)) >= 0) {
4128 /* We found a disk that the user specified. */
4129 vdev = mchild[entry];
4130 ++found;
4131 } else {
4132 /* User didn't specify a disk for this vdev. */
4133 vdev = mchild[mchildren - 1];
4134 }
4135
4136 if (nvlist_dup(vdev, &varray[vcount++], 0) != 0)
4137 goto out;
4138
4139 if (flags.dryrun != 0) {
4140 if (is_dedup == B_TRUE) {
4141 if (nvlist_add_string(varray[vcount - 1],
4142 ZPOOL_CONFIG_ALLOCATION_BIAS,
4143 VDEV_ALLOC_BIAS_DEDUP) != 0)
4144 goto out;
4145 } else if (is_special == B_TRUE) {
4146 if (nvlist_add_string(varray[vcount - 1],
4147 ZPOOL_CONFIG_ALLOCATION_BIAS,
4148 VDEV_ALLOC_BIAS_SPECIAL) != 0)
4149 goto out;
4150 }
4151 }
4152 }
4153
4154 /* did we find every disk the user specified? */
4155 if (found != newchildren) {
4156 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Device list must "
4157 "include at most one disk from each mirror"));
4158 retval = zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
4159 goto out;
4160 }
4161
4162 /* Prepare the nvlist for populating. */
4163 if (*newroot == NULL) {
4164 if (nvlist_alloc(newroot, NV_UNIQUE_NAME, 0) != 0)
4165 goto out;
4166 freelist = B_TRUE;
4167 if (nvlist_add_string(*newroot, ZPOOL_CONFIG_TYPE,
4168 VDEV_TYPE_ROOT) != 0)
4169 goto out;
4170 } else {
4171 verify(nvlist_remove_all(*newroot, ZPOOL_CONFIG_CHILDREN) == 0);
4172 }
4173
4174 /* Add all the children we found */
4175 if (nvlist_add_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN,
4176 (const nvlist_t **)varray, lastlog == 0 ? vcount : lastlog) != 0)
4177 goto out;
4178
4179 /*
4180 * If we're just doing a dry run, exit now with success.
4181 */
4182 if (flags.dryrun) {
4183 memory_err = B_FALSE;
4184 freelist = B_FALSE;
4185 goto out;
4186 }
4187
4188 /* now build up the config list & call the ioctl */
4189 if (nvlist_alloc(&newconfig, NV_UNIQUE_NAME, 0) != 0)
4190 goto out;
4191
4192 if (nvlist_add_nvlist(newconfig,
4193 ZPOOL_CONFIG_VDEV_TREE, *newroot) != 0 ||
4194 nvlist_add_string(newconfig,
4195 ZPOOL_CONFIG_POOL_NAME, newname) != 0 ||
4196 nvlist_add_uint64(newconfig, ZPOOL_CONFIG_VERSION, vers) != 0)
4197 goto out;
4198
4199 /*
4200 * The new pool is automatically part of the namespace unless we
4201 * explicitly export it.
4202 */
4203 if (!flags.import)
4204 zc.zc_cookie = ZPOOL_EXPORT_AFTER_SPLIT;
4205 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4206 (void) strlcpy(zc.zc_string, newname, sizeof (zc.zc_string));
4207 zcmd_write_conf_nvlist(hdl, &zc, newconfig);
4208 if (zc_props != NULL)
4209 zcmd_write_src_nvlist(hdl, &zc, zc_props);
4210
4211 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SPLIT, &zc) != 0) {
4212 retval = zpool_standard_error(hdl, errno, errbuf);
4213 goto out;
4214 }
4215
4216 freelist = B_FALSE;
4217 memory_err = B_FALSE;
4218
4219 out:
4220 if (varray != NULL) {
4221 int v;
4222
4223 for (v = 0; v < vcount; v++)
4224 nvlist_free(varray[v]);
4225 free(varray);
4226 }
4227 zcmd_free_nvlists(&zc);
4228 nvlist_free(zc_props);
4229 nvlist_free(newconfig);
4230 if (freelist) {
4231 nvlist_free(*newroot);
4232 *newroot = NULL;
4233 }
4234
4235 if (retval != 0)
4236 return (retval);
4237
4238 if (memory_err)
4239 return (no_memory(hdl));
4240
4241 return (0);
4242 }
4243
4244 /*
4245 * Remove the given device.
4246 */
4247 int
zpool_vdev_remove(zpool_handle_t * zhp,const char * path)4248 zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
4249 {
4250 zfs_cmd_t zc = {"\0"};
4251 char errbuf[ERRBUFLEN];
4252 nvlist_t *tgt;
4253 boolean_t avail_spare, l2cache, islog;
4254 libzfs_handle_t *hdl = zhp->zpool_hdl;
4255 uint64_t version;
4256
4257 (void) snprintf(errbuf, sizeof (errbuf),
4258 dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
4259
4260 if (zpool_is_draid_spare(path)) {
4261 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4262 "dRAID spares cannot be removed"));
4263 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
4264 }
4265
4266 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4267 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
4268 &islog)) == NULL)
4269 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
4270
4271 version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
4272 if (islog && version < SPA_VERSION_HOLES) {
4273 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4274 "pool must be upgraded to support log removal"));
4275 return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
4276 }
4277
4278 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
4279
4280 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
4281 return (0);
4282
4283 switch (errno) {
4284
4285 case EALREADY:
4286 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4287 "removal for this vdev is already in progress."));
4288 (void) zfs_error(hdl, EZFS_BUSY, errbuf);
4289 break;
4290
4291 case EINVAL:
4292 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4293 "invalid config; all top-level vdevs must "
4294 "have the same sector size and not be raidz."));
4295 (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
4296 break;
4297
4298 case EBUSY:
4299 if (islog) {
4300 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4301 "Mount encrypted datasets to replay logs."));
4302 } else {
4303 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4304 "Pool busy; removal may already be in progress"));
4305 }
4306 (void) zfs_error(hdl, EZFS_BUSY, errbuf);
4307 break;
4308
4309 case EACCES:
4310 if (islog) {
4311 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4312 "Mount encrypted datasets to replay logs."));
4313 (void) zfs_error(hdl, EZFS_BUSY, errbuf);
4314 } else {
4315 (void) zpool_standard_error(hdl, errno, errbuf);
4316 }
4317 break;
4318
4319 default:
4320 (void) zpool_standard_error(hdl, errno, errbuf);
4321 }
4322 return (-1);
4323 }
4324
4325 int
zpool_vdev_remove_cancel(zpool_handle_t * zhp)4326 zpool_vdev_remove_cancel(zpool_handle_t *zhp)
4327 {
4328 zfs_cmd_t zc = {{0}};
4329 char errbuf[ERRBUFLEN];
4330 libzfs_handle_t *hdl = zhp->zpool_hdl;
4331
4332 (void) snprintf(errbuf, sizeof (errbuf),
4333 dgettext(TEXT_DOMAIN, "cannot cancel removal"));
4334
4335 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4336 zc.zc_cookie = 1;
4337
4338 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
4339 return (0);
4340
4341 return (zpool_standard_error(hdl, errno, errbuf));
4342 }
4343
4344 int
zpool_vdev_indirect_size(zpool_handle_t * zhp,const char * path,uint64_t * sizep)4345 zpool_vdev_indirect_size(zpool_handle_t *zhp, const char *path,
4346 uint64_t *sizep)
4347 {
4348 char errbuf[ERRBUFLEN];
4349 nvlist_t *tgt;
4350 boolean_t avail_spare, l2cache, islog;
4351 libzfs_handle_t *hdl = zhp->zpool_hdl;
4352
4353 (void) snprintf(errbuf, sizeof (errbuf),
4354 dgettext(TEXT_DOMAIN, "cannot determine indirect size of %s"),
4355 path);
4356
4357 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
4358 &islog)) == NULL)
4359 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
4360
4361 if (avail_spare || l2cache || islog) {
4362 *sizep = 0;
4363 return (0);
4364 }
4365
4366 if (nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_INDIRECT_SIZE, sizep) != 0) {
4367 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4368 "indirect size not available"));
4369 return (zfs_error(hdl, EINVAL, errbuf));
4370 }
4371 return (0);
4372 }
4373
4374 /*
4375 * Clear the errors for the pool, or the particular device if specified.
4376 */
4377 int
zpool_clear(zpool_handle_t * zhp,const char * path,nvlist_t * rewindnvl)4378 zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl)
4379 {
4380 zfs_cmd_t zc = {"\0"};
4381 char errbuf[ERRBUFLEN];
4382 nvlist_t *tgt;
4383 zpool_load_policy_t policy;
4384 boolean_t avail_spare, l2cache;
4385 libzfs_handle_t *hdl = zhp->zpool_hdl;
4386 nvlist_t *nvi = NULL;
4387 int error;
4388
4389 if (path)
4390 (void) snprintf(errbuf, sizeof (errbuf),
4391 dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
4392 path);
4393 else
4394 (void) snprintf(errbuf, sizeof (errbuf),
4395 dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
4396 zhp->zpool_name);
4397
4398 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4399 if (path) {
4400 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare,
4401 &l2cache, NULL)) == NULL)
4402 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
4403
4404 /*
4405 * Don't allow error clearing for hot spares. Do allow
4406 * error clearing for l2cache devices.
4407 */
4408 if (avail_spare)
4409 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
4410
4411 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
4412 }
4413
4414 zpool_get_load_policy(rewindnvl, &policy);
4415 zc.zc_cookie = policy.zlp_rewind;
4416
4417 zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size * 2);
4418 if (rewindnvl != NULL)
4419 zcmd_write_src_nvlist(hdl, &zc, rewindnvl);
4420
4421 while ((error = zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc)) != 0 &&
4422 errno == ENOMEM)
4423 zcmd_expand_dst_nvlist(hdl, &zc);
4424
4425 if (!error || ((policy.zlp_rewind & ZPOOL_TRY_REWIND) &&
4426 errno != EPERM && errno != EACCES)) {
4427 if (policy.zlp_rewind &
4428 (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
4429 (void) zcmd_read_dst_nvlist(hdl, &zc, &nvi);
4430 zpool_rewind_exclaim(hdl, zc.zc_name,
4431 ((policy.zlp_rewind & ZPOOL_TRY_REWIND) != 0),
4432 nvi);
4433 nvlist_free(nvi);
4434 }
4435 zcmd_free_nvlists(&zc);
4436 return (0);
4437 }
4438
4439 zcmd_free_nvlists(&zc);
4440 return (zpool_standard_error(hdl, errno, errbuf));
4441 }
4442
4443 /*
4444 * Similar to zpool_clear(), but takes a GUID (used by fmd).
4445 */
4446 int
zpool_vdev_clear(zpool_handle_t * zhp,uint64_t guid)4447 zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
4448 {
4449 zfs_cmd_t zc = {"\0"};
4450 char errbuf[ERRBUFLEN];
4451 libzfs_handle_t *hdl = zhp->zpool_hdl;
4452
4453 (void) snprintf(errbuf, sizeof (errbuf),
4454 dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
4455 (u_longlong_t)guid);
4456
4457 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4458 zc.zc_guid = guid;
4459 zc.zc_cookie = ZPOOL_NO_REWIND;
4460
4461 if (zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc) == 0)
4462 return (0);
4463
4464 return (zpool_standard_error(hdl, errno, errbuf));
4465 }
4466
4467 /*
4468 * Change the GUID for a pool.
4469 *
4470 * Similar to zpool_reguid(), but may take a GUID.
4471 *
4472 * If the guid argument is NULL, then no GUID is passed in the nvlist to the
4473 * ioctl().
4474 */
4475 int
zpool_set_guid(zpool_handle_t * zhp,const uint64_t * guid)4476 zpool_set_guid(zpool_handle_t *zhp, const uint64_t *guid)
4477 {
4478 char errbuf[ERRBUFLEN];
4479 libzfs_handle_t *hdl = zhp->zpool_hdl;
4480 nvlist_t *nvl = NULL;
4481 zfs_cmd_t zc = {"\0"};
4482 int error;
4483
4484 if (guid != NULL) {
4485 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
4486 return (no_memory(hdl));
4487
4488 if (nvlist_add_uint64(nvl, ZPOOL_REGUID_GUID, *guid) != 0) {
4489 nvlist_free(nvl);
4490 return (no_memory(hdl));
4491 }
4492
4493 zcmd_write_src_nvlist(hdl, &zc, nvl);
4494 }
4495
4496 (void) snprintf(errbuf, sizeof (errbuf),
4497 dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name);
4498
4499 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4500 error = zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc);
4501 if (error) {
4502 return (zpool_standard_error(hdl, errno, errbuf));
4503 }
4504 if (guid != NULL) {
4505 zcmd_free_nvlists(&zc);
4506 nvlist_free(nvl);
4507 }
4508 return (0);
4509 }
4510
4511 /*
4512 * Change the GUID for a pool.
4513 */
4514 int
zpool_reguid(zpool_handle_t * zhp)4515 zpool_reguid(zpool_handle_t *zhp)
4516 {
4517 return (zpool_set_guid(zhp, NULL));
4518 }
4519
4520 /*
4521 * Reopen the pool.
4522 */
4523 int
zpool_reopen_one(zpool_handle_t * zhp,void * data)4524 zpool_reopen_one(zpool_handle_t *zhp, void *data)
4525 {
4526 libzfs_handle_t *hdl = zpool_get_handle(zhp);
4527 const char *pool_name = zpool_get_name(zhp);
4528 boolean_t *scrub_restart = data;
4529 int error;
4530
4531 error = lzc_reopen(pool_name, *scrub_restart);
4532 if (error) {
4533 return (zpool_standard_error_fmt(hdl, error,
4534 dgettext(TEXT_DOMAIN, "cannot reopen '%s'"), pool_name));
4535 }
4536
4537 return (0);
4538 }
4539
4540 /* call into libzfs_core to execute the sync IOCTL per pool */
4541 int
zpool_sync_one(zpool_handle_t * zhp,void * data)4542 zpool_sync_one(zpool_handle_t *zhp, void *data)
4543 {
4544 int ret;
4545 libzfs_handle_t *hdl = zpool_get_handle(zhp);
4546 const char *pool_name = zpool_get_name(zhp);
4547 boolean_t *force = data;
4548 nvlist_t *innvl = fnvlist_alloc();
4549
4550 fnvlist_add_boolean_value(innvl, "force", *force);
4551 if ((ret = lzc_sync(pool_name, innvl, NULL)) != 0) {
4552 nvlist_free(innvl);
4553 return (zpool_standard_error_fmt(hdl, ret,
4554 dgettext(TEXT_DOMAIN, "sync '%s' failed"), pool_name));
4555 }
4556 nvlist_free(innvl);
4557
4558 return (0);
4559 }
4560
4561 #define PATH_BUF_LEN 64
4562
4563 /*
4564 * Given a vdev, return the name to display in iostat. If the vdev has a path,
4565 * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
4566 * We also check if this is a whole disk, in which case we strip off the
4567 * trailing 's0' slice name.
4568 *
4569 * This routine is also responsible for identifying when disks have been
4570 * reconfigured in a new location. The kernel will have opened the device by
4571 * devid, but the path will still refer to the old location. To catch this, we
4572 * first do a path -> devid translation (which is fast for the common case). If
4573 * the devid matches, we're done. If not, we do a reverse devid -> path
4574 * translation and issue the appropriate ioctl() to update the path of the vdev.
4575 * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
4576 * of these checks.
4577 */
4578 char *
zpool_vdev_name(libzfs_handle_t * hdl,zpool_handle_t * zhp,nvlist_t * nv,int name_flags)4579 zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
4580 int name_flags)
4581 {
4582 const char *type, *tpath;
4583 const char *path;
4584 uint64_t value;
4585 char buf[PATH_BUF_LEN];
4586 char tmpbuf[PATH_BUF_LEN * 2];
4587
4588 /*
4589 * vdev_name will be "root"/"root-0" for the root vdev, but it is the
4590 * zpool name that will be displayed to the user.
4591 */
4592 type = fnvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE);
4593 if (zhp != NULL && strcmp(type, "root") == 0)
4594 return (zfs_strdup(hdl, zpool_get_name(zhp)));
4595
4596 if (libzfs_envvar_is_set("ZPOOL_VDEV_NAME_PATH"))
4597 name_flags |= VDEV_NAME_PATH;
4598 if (libzfs_envvar_is_set("ZPOOL_VDEV_NAME_GUID"))
4599 name_flags |= VDEV_NAME_GUID;
4600 if (libzfs_envvar_is_set("ZPOOL_VDEV_NAME_FOLLOW_LINKS"))
4601 name_flags |= VDEV_NAME_FOLLOW_LINKS;
4602
4603 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &value) == 0 ||
4604 name_flags & VDEV_NAME_GUID) {
4605 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value);
4606 (void) snprintf(buf, sizeof (buf), "%llu", (u_longlong_t)value);
4607 path = buf;
4608 } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &tpath) == 0) {
4609 path = tpath;
4610
4611 if (name_flags & VDEV_NAME_FOLLOW_LINKS) {
4612 char *rp = realpath(path, NULL);
4613 if (rp) {
4614 strlcpy(buf, rp, sizeof (buf));
4615 path = buf;
4616 free(rp);
4617 }
4618 }
4619
4620 /*
4621 * For a block device only use the name.
4622 */
4623 if ((strcmp(type, VDEV_TYPE_DISK) == 0) &&
4624 !(name_flags & VDEV_NAME_PATH)) {
4625 path = zfs_strip_path(path);
4626 }
4627
4628 /*
4629 * Remove the partition from the path if this is a whole disk.
4630 */
4631 if (strcmp(type, VDEV_TYPE_DRAID_SPARE) != 0 &&
4632 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, &value)
4633 == 0 && value && !(name_flags & VDEV_NAME_PATH)) {
4634 return (zfs_strip_partition(path));
4635 }
4636 } else {
4637 path = type;
4638
4639 /*
4640 * If it's a raidz device, we need to stick in the parity level.
4641 */
4642 if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
4643 value = fnvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY);
4644 (void) snprintf(buf, sizeof (buf), "%s%llu", path,
4645 (u_longlong_t)value);
4646 path = buf;
4647 }
4648
4649 /*
4650 * If it's a dRAID device, we add parity, groups, and spares.
4651 */
4652 if (strcmp(path, VDEV_TYPE_DRAID) == 0) {
4653 uint64_t ndata, nparity, nspares;
4654 nvlist_t **child;
4655 uint_t children;
4656
4657 verify(nvlist_lookup_nvlist_array(nv,
4658 ZPOOL_CONFIG_CHILDREN, &child, &children) == 0);
4659 nparity = fnvlist_lookup_uint64(nv,
4660 ZPOOL_CONFIG_NPARITY);
4661 ndata = fnvlist_lookup_uint64(nv,
4662 ZPOOL_CONFIG_DRAID_NDATA);
4663 nspares = fnvlist_lookup_uint64(nv,
4664 ZPOOL_CONFIG_DRAID_NSPARES);
4665
4666 path = zpool_draid_name(buf, sizeof (buf), ndata,
4667 nparity, nspares, children);
4668 }
4669
4670 /*
4671 * We identify each top-level vdev by using a <type-id>
4672 * naming convention.
4673 */
4674 if (name_flags & VDEV_NAME_TYPE_ID) {
4675 uint64_t id = fnvlist_lookup_uint64(nv,
4676 ZPOOL_CONFIG_ID);
4677 (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s-%llu",
4678 path, (u_longlong_t)id);
4679 path = tmpbuf;
4680 }
4681 }
4682
4683 return (zfs_strdup(hdl, path));
4684 }
4685
4686 static int
zbookmark_mem_compare(const void * a,const void * b)4687 zbookmark_mem_compare(const void *a, const void *b)
4688 {
4689 return (memcmp(a, b, sizeof (zbookmark_phys_t)));
4690 }
4691
4692 void
zpool_add_propname(zpool_handle_t * zhp,const char * propname)4693 zpool_add_propname(zpool_handle_t *zhp, const char *propname)
4694 {
4695 assert(zhp->zpool_n_propnames < ZHP_MAX_PROPNAMES);
4696 zhp->zpool_propnames[zhp->zpool_n_propnames] = propname;
4697 zhp->zpool_n_propnames++;
4698 }
4699
4700 /*
4701 * Retrieve the persistent error log, uniquify the members, and return to the
4702 * caller.
4703 */
4704 int
zpool_get_errlog(zpool_handle_t * zhp,nvlist_t ** nverrlistp)4705 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
4706 {
4707 zfs_cmd_t zc = {"\0"};
4708 libzfs_handle_t *hdl = zhp->zpool_hdl;
4709 zbookmark_phys_t *buf;
4710 uint64_t buflen = 10000; /* approx. 1MB of RAM */
4711
4712 if (fnvlist_lookup_uint64(zhp->zpool_config,
4713 ZPOOL_CONFIG_ERRCOUNT) == 0)
4714 return (0);
4715
4716 /*
4717 * Retrieve the raw error list from the kernel. If it doesn't fit,
4718 * allocate a larger buffer and retry.
4719 */
4720 (void) strcpy(zc.zc_name, zhp->zpool_name);
4721 for (;;) {
4722 buf = zfs_alloc(zhp->zpool_hdl,
4723 buflen * sizeof (zbookmark_phys_t));
4724 zc.zc_nvlist_dst = (uintptr_t)buf;
4725 zc.zc_nvlist_dst_size = buflen;
4726 if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_ERROR_LOG,
4727 &zc) != 0) {
4728 free(buf);
4729 if (errno == ENOMEM) {
4730 buflen *= 2;
4731 } else {
4732 return (zpool_standard_error_fmt(hdl, errno,
4733 dgettext(TEXT_DOMAIN, "errors: List of "
4734 "errors unavailable")));
4735 }
4736 } else {
4737 break;
4738 }
4739 }
4740
4741 /*
4742 * Sort the resulting bookmarks. This is a little confusing due to the
4743 * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last
4744 * to first, and 'zc_nvlist_dst_size' indicates the number of bookmarks
4745 * _not_ copied as part of the process. So we point the start of our
4746 * array appropriate and decrement the total number of elements.
4747 */
4748 zbookmark_phys_t *zb = buf + zc.zc_nvlist_dst_size;
4749 uint64_t zblen = buflen - zc.zc_nvlist_dst_size;
4750
4751 qsort(zb, zblen, sizeof (zbookmark_phys_t), zbookmark_mem_compare);
4752
4753 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
4754
4755 /*
4756 * Fill in the nverrlistp with nvlist's of dataset and object numbers.
4757 */
4758 for (uint64_t i = 0; i < zblen; i++) {
4759 nvlist_t *nv;
4760
4761 /* ignoring zb_blkid and zb_level for now */
4762 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset &&
4763 zb[i-1].zb_object == zb[i].zb_object)
4764 continue;
4765
4766 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0)
4767 goto nomem;
4768 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET,
4769 zb[i].zb_objset) != 0) {
4770 nvlist_free(nv);
4771 goto nomem;
4772 }
4773 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT,
4774 zb[i].zb_object) != 0) {
4775 nvlist_free(nv);
4776 goto nomem;
4777 }
4778 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) {
4779 nvlist_free(nv);
4780 goto nomem;
4781 }
4782 nvlist_free(nv);
4783 }
4784
4785 free(buf);
4786 return (0);
4787
4788 nomem:
4789 free(buf);
4790 return (no_memory(zhp->zpool_hdl));
4791 }
4792
4793 /*
4794 * Upgrade a ZFS pool to the latest on-disk version.
4795 */
4796 int
zpool_upgrade(zpool_handle_t * zhp,uint64_t new_version)4797 zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
4798 {
4799 zfs_cmd_t zc = {"\0"};
4800 libzfs_handle_t *hdl = zhp->zpool_hdl;
4801
4802 (void) strcpy(zc.zc_name, zhp->zpool_name);
4803 zc.zc_cookie = new_version;
4804
4805 if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
4806 return (zpool_standard_error_fmt(hdl, errno,
4807 dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
4808 zhp->zpool_name));
4809 return (0);
4810 }
4811
4812 void
zfs_save_arguments(int argc,char ** argv,char * string,int len)4813 zfs_save_arguments(int argc, char **argv, char *string, int len)
4814 {
4815 int i;
4816
4817 (void) strlcpy(string, zfs_basename(argv[0]), len);
4818 for (i = 1; i < argc; i++) {
4819 (void) strlcat(string, " ", len);
4820 (void) strlcat(string, argv[i], len);
4821 }
4822 }
4823
4824 int
zpool_log_history(libzfs_handle_t * hdl,const char * message)4825 zpool_log_history(libzfs_handle_t *hdl, const char *message)
4826 {
4827 zfs_cmd_t zc = {"\0"};
4828 nvlist_t *args;
4829
4830 args = fnvlist_alloc();
4831 fnvlist_add_string(args, "message", message);
4832 zcmd_write_src_nvlist(hdl, &zc, args);
4833 int err = zfs_ioctl(hdl, ZFS_IOC_LOG_HISTORY, &zc);
4834 nvlist_free(args);
4835 zcmd_free_nvlists(&zc);
4836 return (err);
4837 }
4838
4839 /*
4840 * Perform ioctl to get some command history of a pool.
4841 *
4842 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the
4843 * logical offset of the history buffer to start reading from.
4844 *
4845 * Upon return, 'off' is the next logical offset to read from and
4846 * 'len' is the actual amount of bytes read into 'buf'.
4847 */
4848 static int
get_history(zpool_handle_t * zhp,char * buf,uint64_t * off,uint64_t * len)4849 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
4850 {
4851 zfs_cmd_t zc = {"\0"};
4852 libzfs_handle_t *hdl = zhp->zpool_hdl;
4853
4854 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4855
4856 zc.zc_history = (uint64_t)(uintptr_t)buf;
4857 zc.zc_history_len = *len;
4858 zc.zc_history_offset = *off;
4859
4860 if (zfs_ioctl(hdl, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) {
4861 switch (errno) {
4862 case EPERM:
4863 return (zfs_error_fmt(hdl, EZFS_PERM,
4864 dgettext(TEXT_DOMAIN,
4865 "cannot show history for pool '%s'"),
4866 zhp->zpool_name));
4867 case ENOENT:
4868 return (zfs_error_fmt(hdl, EZFS_NOHISTORY,
4869 dgettext(TEXT_DOMAIN, "cannot get history for pool "
4870 "'%s'"), zhp->zpool_name));
4871 case ENOTSUP:
4872 return (zfs_error_fmt(hdl, EZFS_BADVERSION,
4873 dgettext(TEXT_DOMAIN, "cannot get history for pool "
4874 "'%s', pool must be upgraded"), zhp->zpool_name));
4875 default:
4876 return (zpool_standard_error_fmt(hdl, errno,
4877 dgettext(TEXT_DOMAIN,
4878 "cannot get history for '%s'"), zhp->zpool_name));
4879 }
4880 }
4881
4882 *len = zc.zc_history_len;
4883 *off = zc.zc_history_offset;
4884
4885 return (0);
4886 }
4887
4888 /*
4889 * Retrieve the command history of a pool.
4890 */
4891 int
zpool_get_history(zpool_handle_t * zhp,nvlist_t ** nvhisp,uint64_t * off,boolean_t * eof)4892 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off,
4893 boolean_t *eof)
4894 {
4895 libzfs_handle_t *hdl = zhp->zpool_hdl;
4896 char *buf;
4897 int buflen = 128 * 1024;
4898 nvlist_t **records = NULL;
4899 uint_t numrecords = 0;
4900 int err = 0, i;
4901 uint64_t start = *off;
4902
4903 buf = zfs_alloc(hdl, buflen);
4904
4905 /* process about 1MiB a time */
4906 while (*off - start < 1024 * 1024) {
4907 uint64_t bytes_read = buflen;
4908 uint64_t leftover;
4909
4910 if ((err = get_history(zhp, buf, off, &bytes_read)) != 0)
4911 break;
4912
4913 /* if nothing else was read in, we're at EOF, just return */
4914 if (!bytes_read) {
4915 *eof = B_TRUE;
4916 break;
4917 }
4918
4919 if ((err = zpool_history_unpack(buf, bytes_read,
4920 &leftover, &records, &numrecords)) != 0) {
4921 zpool_standard_error_fmt(hdl, err,
4922 dgettext(TEXT_DOMAIN,
4923 "cannot get history for '%s'"), zhp->zpool_name);
4924 break;
4925 }
4926 *off -= leftover;
4927 if (leftover == bytes_read) {
4928 /*
4929 * no progress made, because buffer is not big enough
4930 * to hold this record; resize and retry.
4931 */
4932 buflen *= 2;
4933 free(buf);
4934 buf = zfs_alloc(hdl, buflen);
4935 }
4936 }
4937
4938 free(buf);
4939
4940 if (!err) {
4941 *nvhisp = fnvlist_alloc();
4942 fnvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
4943 (const nvlist_t **)records, numrecords);
4944 }
4945 for (i = 0; i < numrecords; i++)
4946 nvlist_free(records[i]);
4947 free(records);
4948
4949 return (err);
4950 }
4951
4952 /*
4953 * Retrieve the next event given the passed 'zevent_fd' file descriptor.
4954 * If there is a new event available 'nvp' will contain a newly allocated
4955 * nvlist and 'dropped' will be set to the number of missed events since
4956 * the last call to this function. When 'nvp' is set to NULL it indicates
4957 * no new events are available. In either case the function returns 0 and
4958 * it is up to the caller to free 'nvp'. In the case of a fatal error the
4959 * function will return a non-zero value. When the function is called in
4960 * blocking mode (the default, unless the ZEVENT_NONBLOCK flag is passed),
4961 * it will not return until a new event is available.
4962 */
4963 int
zpool_events_next(libzfs_handle_t * hdl,nvlist_t ** nvp,int * dropped,unsigned flags,int zevent_fd)4964 zpool_events_next(libzfs_handle_t *hdl, nvlist_t **nvp,
4965 int *dropped, unsigned flags, int zevent_fd)
4966 {
4967 zfs_cmd_t zc = {"\0"};
4968 int error = 0;
4969
4970 *nvp = NULL;
4971 *dropped = 0;
4972 zc.zc_cleanup_fd = zevent_fd;
4973
4974 if (flags & ZEVENT_NONBLOCK)
4975 zc.zc_guid = ZEVENT_NONBLOCK;
4976
4977 zcmd_alloc_dst_nvlist(hdl, &zc, ZEVENT_SIZE);
4978
4979 retry:
4980 if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_NEXT, &zc) != 0) {
4981 switch (errno) {
4982 case ESHUTDOWN:
4983 error = zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
4984 dgettext(TEXT_DOMAIN, "zfs shutdown"));
4985 goto out;
4986 case ENOENT:
4987 /* Blocking error case should not occur */
4988 if (!(flags & ZEVENT_NONBLOCK))
4989 error = zpool_standard_error_fmt(hdl, errno,
4990 dgettext(TEXT_DOMAIN, "cannot get event"));
4991
4992 goto out;
4993 case ENOMEM:
4994 zcmd_expand_dst_nvlist(hdl, &zc);
4995 goto retry;
4996 default:
4997 error = zpool_standard_error_fmt(hdl, errno,
4998 dgettext(TEXT_DOMAIN, "cannot get event"));
4999 goto out;
5000 }
5001 }
5002
5003 error = zcmd_read_dst_nvlist(hdl, &zc, nvp);
5004 if (error != 0)
5005 goto out;
5006
5007 *dropped = (int)zc.zc_cookie;
5008 out:
5009 zcmd_free_nvlists(&zc);
5010
5011 return (error);
5012 }
5013
5014 /*
5015 * Clear all events.
5016 */
5017 int
zpool_events_clear(libzfs_handle_t * hdl,int * count)5018 zpool_events_clear(libzfs_handle_t *hdl, int *count)
5019 {
5020 zfs_cmd_t zc = {"\0"};
5021
5022 if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_CLEAR, &zc) != 0)
5023 return (zpool_standard_error(hdl, errno,
5024 dgettext(TEXT_DOMAIN, "cannot clear events")));
5025
5026 if (count != NULL)
5027 *count = (int)zc.zc_cookie; /* # of events cleared */
5028
5029 return (0);
5030 }
5031
5032 /*
5033 * Seek to a specific EID, ZEVENT_SEEK_START, or ZEVENT_SEEK_END for
5034 * the passed zevent_fd file handle. On success zero is returned,
5035 * otherwise -1 is returned and hdl->libzfs_error is set to the errno.
5036 */
5037 int
zpool_events_seek(libzfs_handle_t * hdl,uint64_t eid,int zevent_fd)5038 zpool_events_seek(libzfs_handle_t *hdl, uint64_t eid, int zevent_fd)
5039 {
5040 zfs_cmd_t zc = {"\0"};
5041 int error = 0;
5042
5043 zc.zc_guid = eid;
5044 zc.zc_cleanup_fd = zevent_fd;
5045
5046 if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_SEEK, &zc) != 0) {
5047 switch (errno) {
5048 case ENOENT:
5049 error = zfs_error_fmt(hdl, EZFS_NOENT,
5050 dgettext(TEXT_DOMAIN, "cannot get event"));
5051 break;
5052
5053 case ENOMEM:
5054 error = zfs_error_fmt(hdl, EZFS_NOMEM,
5055 dgettext(TEXT_DOMAIN, "cannot get event"));
5056 break;
5057
5058 default:
5059 error = zpool_standard_error_fmt(hdl, errno,
5060 dgettext(TEXT_DOMAIN, "cannot get event"));
5061 break;
5062 }
5063 }
5064
5065 return (error);
5066 }
5067
5068 static void
zpool_obj_to_path_impl(zpool_handle_t * zhp,uint64_t dsobj,uint64_t obj,char * pathname,size_t len,boolean_t always_unmounted)5069 zpool_obj_to_path_impl(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
5070 char *pathname, size_t len, boolean_t always_unmounted)
5071 {
5072 zfs_cmd_t zc = {"\0"};
5073 boolean_t mounted = B_FALSE;
5074 char *mntpnt = NULL;
5075 char dsname[ZFS_MAX_DATASET_NAME_LEN];
5076
5077 if (dsobj == 0) {
5078 /* special case for the MOS */
5079 (void) snprintf(pathname, len, "<metadata>:<0x%llx>",
5080 (longlong_t)obj);
5081 return;
5082 }
5083
5084 /* get the dataset's name */
5085 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
5086 zc.zc_obj = dsobj;
5087 if (zfs_ioctl(zhp->zpool_hdl,
5088 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) {
5089 /* just write out a path of two object numbers */
5090 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>",
5091 (longlong_t)dsobj, (longlong_t)obj);
5092 return;
5093 }
5094 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
5095
5096 /* find out if the dataset is mounted */
5097 mounted = !always_unmounted && is_mounted(zhp->zpool_hdl, dsname,
5098 &mntpnt);
5099
5100 /* get the corrupted object's path */
5101 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
5102 zc.zc_obj = obj;
5103 if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_OBJ_TO_PATH,
5104 &zc) == 0) {
5105 if (mounted) {
5106 (void) snprintf(pathname, len, "%s%s", mntpnt,
5107 zc.zc_value);
5108 } else {
5109 (void) snprintf(pathname, len, "%s:%s",
5110 dsname, zc.zc_value);
5111 }
5112 } else {
5113 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname,
5114 (longlong_t)obj);
5115 }
5116 free(mntpnt);
5117 }
5118
5119 void
zpool_obj_to_path(zpool_handle_t * zhp,uint64_t dsobj,uint64_t obj,char * pathname,size_t len)5120 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
5121 char *pathname, size_t len)
5122 {
5123 zpool_obj_to_path_impl(zhp, dsobj, obj, pathname, len, B_FALSE);
5124 }
5125
5126 void
zpool_obj_to_path_ds(zpool_handle_t * zhp,uint64_t dsobj,uint64_t obj,char * pathname,size_t len)5127 zpool_obj_to_path_ds(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
5128 char *pathname, size_t len)
5129 {
5130 zpool_obj_to_path_impl(zhp, dsobj, obj, pathname, len, B_TRUE);
5131 }
5132 /*
5133 * Wait while the specified activity is in progress in the pool.
5134 */
5135 int
zpool_wait(zpool_handle_t * zhp,zpool_wait_activity_t activity)5136 zpool_wait(zpool_handle_t *zhp, zpool_wait_activity_t activity)
5137 {
5138 boolean_t missing;
5139
5140 int error = zpool_wait_status(zhp, activity, &missing, NULL);
5141
5142 if (missing) {
5143 (void) zpool_standard_error_fmt(zhp->zpool_hdl, ENOENT,
5144 dgettext(TEXT_DOMAIN, "error waiting in pool '%s'"),
5145 zhp->zpool_name);
5146 return (ENOENT);
5147 } else {
5148 return (error);
5149 }
5150 }
5151
5152 /*
5153 * Wait for the given activity and return the status of the wait (whether or not
5154 * any waiting was done) in the 'waited' parameter. Non-existent pools are
5155 * reported via the 'missing' parameter, rather than by printing an error
5156 * message. This is convenient when this function is called in a loop over a
5157 * long period of time (as it is, for example, by zpool's wait cmd). In that
5158 * scenario, a pool being exported or destroyed should be considered a normal
5159 * event, so we don't want to print an error when we find that the pool doesn't
5160 * exist.
5161 */
5162 int
zpool_wait_status(zpool_handle_t * zhp,zpool_wait_activity_t activity,boolean_t * missing,boolean_t * waited)5163 zpool_wait_status(zpool_handle_t *zhp, zpool_wait_activity_t activity,
5164 boolean_t *missing, boolean_t *waited)
5165 {
5166 int error = lzc_wait(zhp->zpool_name, activity, waited);
5167 *missing = (error == ENOENT);
5168 if (*missing)
5169 return (0);
5170
5171 if (error != 0) {
5172 (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
5173 dgettext(TEXT_DOMAIN, "error waiting in pool '%s'"),
5174 zhp->zpool_name);
5175 }
5176
5177 return (error);
5178 }
5179
5180 int
zpool_set_bootenv(zpool_handle_t * zhp,const nvlist_t * envmap)5181 zpool_set_bootenv(zpool_handle_t *zhp, const nvlist_t *envmap)
5182 {
5183 int error = lzc_set_bootenv(zhp->zpool_name, envmap);
5184 if (error != 0) {
5185 (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
5186 dgettext(TEXT_DOMAIN,
5187 "error setting bootenv in pool '%s'"), zhp->zpool_name);
5188 }
5189
5190 return (error);
5191 }
5192
5193 int
zpool_get_bootenv(zpool_handle_t * zhp,nvlist_t ** nvlp)5194 zpool_get_bootenv(zpool_handle_t *zhp, nvlist_t **nvlp)
5195 {
5196 nvlist_t *nvl;
5197 int error;
5198
5199 nvl = NULL;
5200 error = lzc_get_bootenv(zhp->zpool_name, &nvl);
5201 if (error != 0) {
5202 (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
5203 dgettext(TEXT_DOMAIN,
5204 "error getting bootenv in pool '%s'"), zhp->zpool_name);
5205 } else {
5206 *nvlp = nvl;
5207 }
5208
5209 return (error);
5210 }
5211
5212 /*
5213 * Attempt to read and parse feature file(s) (from "compatibility" property).
5214 * Files contain zpool feature names, comma or whitespace-separated.
5215 * Comments (# character to next newline) are discarded.
5216 *
5217 * Arguments:
5218 * compatibility : string containing feature filenames
5219 * features : either NULL or pointer to array of boolean
5220 * report : either NULL or pointer to string buffer
5221 * rlen : length of "report" buffer
5222 *
5223 * compatibility is NULL (unset), "", "off", "legacy", or list of
5224 * comma-separated filenames. filenames should either be absolute,
5225 * or relative to:
5226 * 1) ZPOOL_SYSCONF_COMPAT_D (eg: /etc/zfs/compatibility.d) or
5227 * 2) ZPOOL_DATA_COMPAT_D (eg: /usr/share/zfs/compatibility.d).
5228 * (Unset), "" or "off" => enable all features
5229 * "legacy" => disable all features
5230 *
5231 * Any feature names read from files which match unames in spa_feature_table
5232 * will have the corresponding boolean set in the features array (if non-NULL).
5233 * If more than one feature set specified, only features present in *all* of
5234 * them will be set.
5235 *
5236 * "report" if not NULL will be populated with a suitable status message.
5237 *
5238 * Return values:
5239 * ZPOOL_COMPATIBILITY_OK : files read and parsed ok
5240 * ZPOOL_COMPATIBILITY_BADFILE : file too big or not a text file
5241 * ZPOOL_COMPATIBILITY_BADTOKEN : SYSCONF file contains invalid feature name
5242 * ZPOOL_COMPATIBILITY_WARNTOKEN : DATA file contains invalid feature name
5243 * ZPOOL_COMPATIBILITY_NOFILES : no feature files found
5244 */
5245 zpool_compat_status_t
zpool_load_compat(const char * compat,boolean_t * features,char * report,size_t rlen)5246 zpool_load_compat(const char *compat, boolean_t *features, char *report,
5247 size_t rlen)
5248 {
5249 int sdirfd, ddirfd, featfd;
5250 struct stat fs;
5251 char *fc;
5252 char *ps, *ls, *ws;
5253 char *file, *line, *word;
5254
5255 char l_compat[ZFS_MAXPROPLEN];
5256
5257 boolean_t ret_nofiles = B_TRUE;
5258 boolean_t ret_badfile = B_FALSE;
5259 boolean_t ret_badtoken = B_FALSE;
5260 boolean_t ret_warntoken = B_FALSE;
5261
5262 /* special cases (unset), "" and "off" => enable all features */
5263 if (compat == NULL || compat[0] == '\0' ||
5264 strcmp(compat, ZPOOL_COMPAT_OFF) == 0) {
5265 if (features != NULL) {
5266 for (uint_t i = 0; i < SPA_FEATURES; i++)
5267 features[i] = B_TRUE;
5268 }
5269 if (report != NULL)
5270 strlcpy(report, gettext("all features enabled"), rlen);
5271 return (ZPOOL_COMPATIBILITY_OK);
5272 }
5273
5274 /* Final special case "legacy" => disable all features */
5275 if (strcmp(compat, ZPOOL_COMPAT_LEGACY) == 0) {
5276 if (features != NULL)
5277 for (uint_t i = 0; i < SPA_FEATURES; i++)
5278 features[i] = B_FALSE;
5279 if (report != NULL)
5280 strlcpy(report, gettext("all features disabled"), rlen);
5281 return (ZPOOL_COMPATIBILITY_OK);
5282 }
5283
5284 /*
5285 * Start with all true; will be ANDed with results from each file
5286 */
5287 if (features != NULL)
5288 for (uint_t i = 0; i < SPA_FEATURES; i++)
5289 features[i] = B_TRUE;
5290
5291 char err_badfile[ZFS_MAXPROPLEN] = "";
5292 char err_badtoken[ZFS_MAXPROPLEN] = "";
5293
5294 /*
5295 * We ignore errors from the directory open()
5296 * as they're only needed if the filename is relative
5297 * which will be checked during the openat().
5298 */
5299
5300 /* O_PATH safer than O_RDONLY if system allows it */
5301 #if defined(O_PATH)
5302 #define ZC_DIR_FLAGS (O_DIRECTORY | O_CLOEXEC | O_PATH)
5303 #else
5304 #define ZC_DIR_FLAGS (O_DIRECTORY | O_CLOEXEC | O_RDONLY)
5305 #endif
5306
5307 sdirfd = open(ZPOOL_SYSCONF_COMPAT_D, ZC_DIR_FLAGS);
5308 ddirfd = open(ZPOOL_DATA_COMPAT_D, ZC_DIR_FLAGS);
5309
5310 (void) strlcpy(l_compat, compat, ZFS_MAXPROPLEN);
5311
5312 for (file = strtok_r(l_compat, ",", &ps);
5313 file != NULL;
5314 file = strtok_r(NULL, ",", &ps)) {
5315
5316 boolean_t l_features[SPA_FEATURES];
5317
5318 enum { Z_SYSCONF, Z_DATA } source;
5319
5320 /* try sysconfdir first, then datadir */
5321 source = Z_SYSCONF;
5322 if ((featfd = openat(sdirfd, file, O_RDONLY | O_CLOEXEC)) < 0) {
5323 featfd = openat(ddirfd, file, O_RDONLY | O_CLOEXEC);
5324 source = Z_DATA;
5325 }
5326
5327 /* File readable and correct size? */
5328 if (featfd < 0 ||
5329 fstat(featfd, &fs) < 0 ||
5330 fs.st_size < 1 ||
5331 fs.st_size > ZPOOL_COMPAT_MAXSIZE) {
5332 (void) close(featfd);
5333 strlcat(err_badfile, file, ZFS_MAXPROPLEN);
5334 strlcat(err_badfile, " ", ZFS_MAXPROPLEN);
5335 ret_badfile = B_TRUE;
5336 continue;
5337 }
5338
5339 /* Prefault the file if system allows */
5340 #if defined(MAP_POPULATE)
5341 #define ZC_MMAP_FLAGS (MAP_PRIVATE | MAP_POPULATE)
5342 #elif defined(MAP_PREFAULT_READ)
5343 #define ZC_MMAP_FLAGS (MAP_PRIVATE | MAP_PREFAULT_READ)
5344 #else
5345 #define ZC_MMAP_FLAGS (MAP_PRIVATE)
5346 #endif
5347
5348 /* private mmap() so we can strtok safely */
5349 fc = (char *)mmap(NULL, fs.st_size, PROT_READ | PROT_WRITE,
5350 ZC_MMAP_FLAGS, featfd, 0);
5351 (void) close(featfd);
5352
5353 /* map ok, and last character == newline? */
5354 if (fc == MAP_FAILED || fc[fs.st_size - 1] != '\n') {
5355 (void) munmap((void *) fc, fs.st_size);
5356 strlcat(err_badfile, file, ZFS_MAXPROPLEN);
5357 strlcat(err_badfile, " ", ZFS_MAXPROPLEN);
5358 ret_badfile = B_TRUE;
5359 continue;
5360 }
5361
5362 ret_nofiles = B_FALSE;
5363
5364 for (uint_t i = 0; i < SPA_FEATURES; i++)
5365 l_features[i] = B_FALSE;
5366
5367 /* replace final newline with NULL to ensure string ends */
5368 fc[fs.st_size - 1] = '\0';
5369
5370 for (line = strtok_r(fc, "\n", &ls);
5371 line != NULL;
5372 line = strtok_r(NULL, "\n", &ls)) {
5373 /* discard comments */
5374 char *r = strchr(line, '#');
5375 if (r != NULL)
5376 *r = '\0';
5377
5378 for (word = strtok_r(line, ", \t", &ws);
5379 word != NULL;
5380 word = strtok_r(NULL, ", \t", &ws)) {
5381 /* Find matching feature name */
5382 uint_t f;
5383 for (f = 0; f < SPA_FEATURES; f++) {
5384 zfeature_info_t *fi =
5385 &spa_feature_table[f];
5386 if (strcmp(word, fi->fi_uname) == 0) {
5387 l_features[f] = B_TRUE;
5388 break;
5389 }
5390 }
5391 if (f < SPA_FEATURES)
5392 continue;
5393
5394 /* found an unrecognized word */
5395 /* lightly sanitize it */
5396 if (strlen(word) > 32)
5397 word[32] = '\0';
5398 for (char *c = word; *c != '\0'; c++)
5399 if (!isprint(*c))
5400 *c = '?';
5401
5402 strlcat(err_badtoken, word, ZFS_MAXPROPLEN);
5403 strlcat(err_badtoken, " ", ZFS_MAXPROPLEN);
5404 if (source == Z_SYSCONF)
5405 ret_badtoken = B_TRUE;
5406 else
5407 ret_warntoken = B_TRUE;
5408 }
5409 }
5410 (void) munmap((void *) fc, fs.st_size);
5411
5412 if (features != NULL)
5413 for (uint_t i = 0; i < SPA_FEATURES; i++)
5414 features[i] &= l_features[i];
5415 }
5416 (void) close(sdirfd);
5417 (void) close(ddirfd);
5418
5419 /* Return the most serious error */
5420 if (ret_badfile) {
5421 if (report != NULL)
5422 snprintf(report, rlen, gettext("could not read/"
5423 "parse feature file(s): %s"), err_badfile);
5424 return (ZPOOL_COMPATIBILITY_BADFILE);
5425 }
5426 if (ret_nofiles) {
5427 if (report != NULL)
5428 strlcpy(report,
5429 gettext("no valid compatibility files specified"),
5430 rlen);
5431 return (ZPOOL_COMPATIBILITY_NOFILES);
5432 }
5433 if (ret_badtoken) {
5434 if (report != NULL)
5435 snprintf(report, rlen, gettext("invalid feature "
5436 "name(s) in local compatibility files: %s"),
5437 err_badtoken);
5438 return (ZPOOL_COMPATIBILITY_BADTOKEN);
5439 }
5440 if (ret_warntoken) {
5441 if (report != NULL)
5442 snprintf(report, rlen, gettext("unrecognized feature "
5443 "name(s) in distribution compatibility files: %s"),
5444 err_badtoken);
5445 return (ZPOOL_COMPATIBILITY_WARNTOKEN);
5446 }
5447 if (report != NULL)
5448 strlcpy(report, gettext("compatibility set ok"), rlen);
5449 return (ZPOOL_COMPATIBILITY_OK);
5450 }
5451
5452 static int
zpool_vdev_guid(zpool_handle_t * zhp,const char * vdevname,uint64_t * vdev_guid)5453 zpool_vdev_guid(zpool_handle_t *zhp, const char *vdevname, uint64_t *vdev_guid)
5454 {
5455 nvlist_t *tgt;
5456 boolean_t avail_spare, l2cache;
5457
5458 verify(zhp != NULL);
5459 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5460 char errbuf[ERRBUFLEN];
5461 (void) snprintf(errbuf, sizeof (errbuf),
5462 dgettext(TEXT_DOMAIN, "pool is in an unavailable state"));
5463 return (zfs_error(zhp->zpool_hdl, EZFS_POOLUNAVAIL, errbuf));
5464 }
5465
5466 if ((tgt = zpool_find_vdev(zhp, vdevname, &avail_spare, &l2cache,
5467 NULL)) == NULL) {
5468 char errbuf[ERRBUFLEN];
5469 (void) snprintf(errbuf, sizeof (errbuf),
5470 dgettext(TEXT_DOMAIN, "can not find %s in %s"),
5471 vdevname, zhp->zpool_name);
5472 return (zfs_error(zhp->zpool_hdl, EZFS_NODEVICE, errbuf));
5473 }
5474
5475 *vdev_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
5476 return (0);
5477 }
5478
5479 /*
5480 * Get a vdev property value for 'prop' and return the value in
5481 * a pre-allocated buffer.
5482 */
5483 int
zpool_get_vdev_prop_value(nvlist_t * nvprop,vdev_prop_t prop,char * prop_name,char * buf,size_t len,zprop_source_t * srctype,boolean_t literal)5484 zpool_get_vdev_prop_value(nvlist_t *nvprop, vdev_prop_t prop, char *prop_name,
5485 char *buf, size_t len, zprop_source_t *srctype, boolean_t literal)
5486 {
5487 nvlist_t *nv;
5488 const char *strval;
5489 uint64_t intval;
5490 zprop_source_t src = ZPROP_SRC_NONE;
5491
5492 if (prop == VDEV_PROP_USERPROP) {
5493 /* user property, prop_name must contain the property name */
5494 assert(prop_name != NULL);
5495 if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
5496 src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
5497 strval = fnvlist_lookup_string(nv, ZPROP_VALUE);
5498 } else {
5499 /* user prop not found */
5500 src = ZPROP_SRC_DEFAULT;
5501 strval = "-";
5502 }
5503 (void) strlcpy(buf, strval, len);
5504 if (srctype)
5505 *srctype = src;
5506 return (0);
5507 }
5508
5509 if (prop_name == NULL)
5510 prop_name = (char *)vdev_prop_to_name(prop);
5511
5512 switch (vdev_prop_get_type(prop)) {
5513 case PROP_TYPE_STRING:
5514 if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
5515 src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
5516 strval = fnvlist_lookup_string(nv, ZPROP_VALUE);
5517 } else {
5518 src = ZPROP_SRC_DEFAULT;
5519 if ((strval = vdev_prop_default_string(prop)) == NULL)
5520 strval = "-";
5521 }
5522 (void) strlcpy(buf, strval, len);
5523 break;
5524
5525 case PROP_TYPE_NUMBER:
5526 if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
5527 src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
5528 intval = fnvlist_lookup_uint64(nv, ZPROP_VALUE);
5529 } else {
5530 src = ZPROP_SRC_DEFAULT;
5531 intval = vdev_prop_default_numeric(prop);
5532 }
5533
5534 switch (prop) {
5535 case VDEV_PROP_ASIZE:
5536 case VDEV_PROP_PSIZE:
5537 case VDEV_PROP_SIZE:
5538 case VDEV_PROP_BOOTSIZE:
5539 case VDEV_PROP_ALLOCATED:
5540 case VDEV_PROP_FREE:
5541 case VDEV_PROP_READ_ERRORS:
5542 case VDEV_PROP_WRITE_ERRORS:
5543 case VDEV_PROP_CHECKSUM_ERRORS:
5544 case VDEV_PROP_INITIALIZE_ERRORS:
5545 case VDEV_PROP_TRIM_ERRORS:
5546 case VDEV_PROP_SLOW_IOS:
5547 case VDEV_PROP_OPS_NULL:
5548 case VDEV_PROP_OPS_READ:
5549 case VDEV_PROP_OPS_WRITE:
5550 case VDEV_PROP_OPS_FREE:
5551 case VDEV_PROP_OPS_CLAIM:
5552 case VDEV_PROP_OPS_TRIM:
5553 case VDEV_PROP_BYTES_NULL:
5554 case VDEV_PROP_BYTES_READ:
5555 case VDEV_PROP_BYTES_WRITE:
5556 case VDEV_PROP_BYTES_FREE:
5557 case VDEV_PROP_BYTES_CLAIM:
5558 case VDEV_PROP_BYTES_TRIM:
5559 if (literal) {
5560 (void) snprintf(buf, len, "%llu",
5561 (u_longlong_t)intval);
5562 } else {
5563 (void) zfs_nicenum(intval, buf, len);
5564 }
5565 break;
5566 case VDEV_PROP_EXPANDSZ:
5567 if (intval == 0) {
5568 (void) strlcpy(buf, "-", len);
5569 } else if (literal) {
5570 (void) snprintf(buf, len, "%llu",
5571 (u_longlong_t)intval);
5572 } else {
5573 (void) zfs_nicenum(intval, buf, len);
5574 }
5575 break;
5576 case VDEV_PROP_CAPACITY:
5577 if (literal) {
5578 (void) snprintf(buf, len, "%llu",
5579 (u_longlong_t)intval);
5580 } else {
5581 (void) snprintf(buf, len, "%llu%%",
5582 (u_longlong_t)intval);
5583 }
5584 break;
5585 case VDEV_PROP_CHECKSUM_N:
5586 case VDEV_PROP_CHECKSUM_T:
5587 case VDEV_PROP_IO_N:
5588 case VDEV_PROP_IO_T:
5589 case VDEV_PROP_SLOW_IO_N:
5590 case VDEV_PROP_SLOW_IO_T:
5591 if (intval == UINT64_MAX) {
5592 (void) strlcpy(buf, "-", len);
5593 } else {
5594 (void) snprintf(buf, len, "%llu",
5595 (u_longlong_t)intval);
5596 }
5597 break;
5598 case VDEV_PROP_FRAGMENTATION:
5599 if (intval == UINT64_MAX) {
5600 (void) strlcpy(buf, "-", len);
5601 } else {
5602 (void) snprintf(buf, len, "%llu%%",
5603 (u_longlong_t)intval);
5604 }
5605 break;
5606 case VDEV_PROP_STATE:
5607 if (literal) {
5608 (void) snprintf(buf, len, "%llu",
5609 (u_longlong_t)intval);
5610 } else {
5611 (void) strlcpy(buf, zpool_state_to_name(intval,
5612 VDEV_AUX_NONE), len);
5613 }
5614 break;
5615 default:
5616 (void) snprintf(buf, len, "%llu",
5617 (u_longlong_t)intval);
5618 }
5619 break;
5620
5621 case PROP_TYPE_INDEX:
5622 if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
5623 src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
5624 intval = fnvlist_lookup_uint64(nv, ZPROP_VALUE);
5625 } else {
5626 /* 'trim_support' only valid for leaf vdevs */
5627 if (prop == VDEV_PROP_TRIM_SUPPORT) {
5628 (void) strlcpy(buf, "-", len);
5629 break;
5630 }
5631 src = ZPROP_SRC_DEFAULT;
5632 intval = vdev_prop_default_numeric(prop);
5633 /* Only use if provided by the RAIDZ VDEV above */
5634 if (prop == VDEV_PROP_RAIDZ_EXPANDING)
5635 return (ENOENT);
5636 if (prop == VDEV_PROP_SIT_OUT)
5637 return (ENOENT);
5638 }
5639 if (vdev_prop_index_to_string(prop, intval,
5640 (const char **)&strval) != 0)
5641 return (-1);
5642 (void) strlcpy(buf, strval, len);
5643 break;
5644
5645 default:
5646 abort();
5647 }
5648
5649 if (srctype)
5650 *srctype = src;
5651
5652 return (0);
5653 }
5654
5655 /*
5656 * Get a vdev property value for 'prop_name' and return the value in
5657 * a pre-allocated buffer.
5658 */
5659 int
zpool_get_vdev_prop(zpool_handle_t * zhp,const char * vdevname,vdev_prop_t prop,char * prop_name,char * buf,size_t len,zprop_source_t * srctype,boolean_t literal)5660 zpool_get_vdev_prop(zpool_handle_t *zhp, const char *vdevname, vdev_prop_t prop,
5661 char *prop_name, char *buf, size_t len, zprop_source_t *srctype,
5662 boolean_t literal)
5663 {
5664 nvlist_t *reqnvl, *reqprops;
5665 nvlist_t *retprops = NULL;
5666 uint64_t vdev_guid = 0;
5667 int ret;
5668
5669 if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0)
5670 return (ret);
5671
5672 if (nvlist_alloc(&reqnvl, NV_UNIQUE_NAME, 0) != 0)
5673 return (no_memory(zhp->zpool_hdl));
5674 if (nvlist_alloc(&reqprops, NV_UNIQUE_NAME, 0) != 0)
5675 return (no_memory(zhp->zpool_hdl));
5676
5677 fnvlist_add_uint64(reqnvl, ZPOOL_VDEV_PROPS_GET_VDEV, vdev_guid);
5678
5679 if (prop != VDEV_PROP_USERPROP) {
5680 /* prop_name overrides prop value */
5681 if (prop_name != NULL)
5682 prop = vdev_name_to_prop(prop_name);
5683 else
5684 prop_name = (char *)vdev_prop_to_name(prop);
5685 assert(prop < VDEV_NUM_PROPS);
5686 }
5687
5688 assert(prop_name != NULL);
5689 if (nvlist_add_uint64(reqprops, prop_name, prop) != 0) {
5690 nvlist_free(reqnvl);
5691 nvlist_free(reqprops);
5692 return (no_memory(zhp->zpool_hdl));
5693 }
5694
5695 fnvlist_add_nvlist(reqnvl, ZPOOL_VDEV_PROPS_GET_PROPS, reqprops);
5696
5697 ret = lzc_get_vdev_prop(zhp->zpool_name, reqnvl, &retprops);
5698
5699 if (ret == 0) {
5700 ret = zpool_get_vdev_prop_value(retprops, prop, prop_name, buf,
5701 len, srctype, literal);
5702 } else {
5703 char errbuf[ERRBUFLEN];
5704 (void) snprintf(errbuf, sizeof (errbuf),
5705 dgettext(TEXT_DOMAIN, "cannot get vdev property %s from"
5706 " %s in %s"), prop_name, vdevname, zhp->zpool_name);
5707 (void) zpool_standard_error(zhp->zpool_hdl, ret, errbuf);
5708 }
5709
5710 nvlist_free(reqnvl);
5711 nvlist_free(reqprops);
5712 nvlist_free(retprops);
5713
5714 return (ret);
5715 }
5716
5717 /*
5718 * Get all vdev properties
5719 */
5720 int
zpool_get_all_vdev_props(zpool_handle_t * zhp,const char * vdevname,nvlist_t ** outnvl)5721 zpool_get_all_vdev_props(zpool_handle_t *zhp, const char *vdevname,
5722 nvlist_t **outnvl)
5723 {
5724 nvlist_t *nvl = NULL;
5725 uint64_t vdev_guid = 0;
5726 int ret;
5727
5728 if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0)
5729 return (ret);
5730
5731 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
5732 return (no_memory(zhp->zpool_hdl));
5733
5734 fnvlist_add_uint64(nvl, ZPOOL_VDEV_PROPS_GET_VDEV, vdev_guid);
5735
5736 ret = lzc_get_vdev_prop(zhp->zpool_name, nvl, outnvl);
5737
5738 nvlist_free(nvl);
5739
5740 if (ret) {
5741 char errbuf[ERRBUFLEN];
5742 (void) snprintf(errbuf, sizeof (errbuf),
5743 dgettext(TEXT_DOMAIN, "cannot get vdev properties for"
5744 " %s in %s"), vdevname, zhp->zpool_name);
5745 (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
5746 }
5747
5748 return (ret);
5749 }
5750
5751 /*
5752 * Set vdev property
5753 */
5754 int
zpool_set_vdev_prop(zpool_handle_t * zhp,const char * vdevname,const char * propname,const char * propval)5755 zpool_set_vdev_prop(zpool_handle_t *zhp, const char *vdevname,
5756 const char *propname, const char *propval)
5757 {
5758 int ret;
5759 nvlist_t *nvl = NULL;
5760 nvlist_t *outnvl = NULL;
5761 nvlist_t *props;
5762 nvlist_t *realprops;
5763 prop_flags_t flags = { 0 };
5764 uint64_t version;
5765 uint64_t vdev_guid;
5766
5767 if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0)
5768 return (ret);
5769
5770 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
5771 return (no_memory(zhp->zpool_hdl));
5772 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
5773 return (no_memory(zhp->zpool_hdl));
5774
5775 fnvlist_add_uint64(nvl, ZPOOL_VDEV_PROPS_SET_VDEV, vdev_guid);
5776
5777 if (nvlist_add_string(props, propname, propval) != 0) {
5778 nvlist_free(props);
5779 return (no_memory(zhp->zpool_hdl));
5780 }
5781
5782 char errbuf[ERRBUFLEN];
5783 (void) snprintf(errbuf, sizeof (errbuf),
5784 dgettext(TEXT_DOMAIN, "cannot set property %s for %s on %s"),
5785 propname, vdevname, zhp->zpool_name);
5786
5787 flags.vdevprop = 1;
5788 version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5789 if ((realprops = zpool_valid_proplist(zhp->zpool_hdl,
5790 zhp->zpool_name, props, version, flags, errbuf)) == NULL) {
5791 nvlist_free(props);
5792 nvlist_free(nvl);
5793 return (-1);
5794 }
5795
5796 nvlist_free(props);
5797 props = realprops;
5798
5799 fnvlist_add_nvlist(nvl, ZPOOL_VDEV_PROPS_SET_PROPS, props);
5800
5801 ret = lzc_set_vdev_prop(zhp->zpool_name, nvl, &outnvl);
5802
5803 nvlist_free(props);
5804 nvlist_free(nvl);
5805 nvlist_free(outnvl);
5806
5807 if (ret) {
5808 if (errno == ENOTSUP) {
5809 zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
5810 "property not supported for this vdev"));
5811 (void) zfs_error(zhp->zpool_hdl, EZFS_PROPTYPE, errbuf);
5812 } else {
5813 (void) zpool_standard_error(zhp->zpool_hdl, errno,
5814 errbuf);
5815 }
5816 }
5817
5818 return (ret);
5819 }
5820
5821 /*
5822 * Prune older entries from the DDT to reclaim space under the quota
5823 */
5824 int
zpool_ddt_prune(zpool_handle_t * zhp,zpool_ddt_prune_unit_t unit,uint64_t amount)5825 zpool_ddt_prune(zpool_handle_t *zhp, zpool_ddt_prune_unit_t unit,
5826 uint64_t amount)
5827 {
5828 int error = lzc_ddt_prune(zhp->zpool_name, unit, amount);
5829 if (error != 0) {
5830 libzfs_handle_t *hdl = zhp->zpool_hdl;
5831 char errbuf[ERRBUFLEN];
5832
5833 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
5834 "cannot prune dedup table on '%s'"), zhp->zpool_name);
5835
5836 if (error == EALREADY) {
5837 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5838 "a prune operation is already in progress"));
5839 (void) zfs_error(hdl, EZFS_BUSY, errbuf);
5840 } else {
5841 (void) zpool_standard_error(hdl, errno, errbuf);
5842 }
5843 return (-1);
5844 }
5845
5846 return (0);
5847 }
5848