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