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