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,nvlist_t * config)2047 zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, nvlist_t *config)
2048 {
2049 nvlist_t *nv = NULL;
2050 boolean_t dryrun;
2051 uint64_t rewindto, rewindtxg;
2052 int64_t loss = 0;
2053 time_t when;
2054 char timestr[26], whenstr[64];
2055
2056 if (!hdl->libzfs_printerr || config == NULL)
2057 return;
2058
2059 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0)
2060 return;
2061
2062 /*
2063 * The kernel reports the load it did not commit nested, so the
2064 * nesting is what tells a hypothetical rewind from a real one.
2065 */
2066 dryrun = nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) == 0;
2067
2068 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
2069 return;
2070
2071 /*
2072 * The loss is reported only if the load fell back to an older
2073 * uberblock, so an enacted load without it discarded nothing.
2074 */
2075 if (nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss) != 0 &&
2076 !dryrun)
2077 return;
2078
2079 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TXG, &rewindtxg) != 0)
2080 rewindtxg = 0;
2081
2082 when = (time_t)rewindto;
2083 if (ctime_r(&when, timestr) != NULL) {
2084 timestr[24] = '\0';
2085 } else {
2086 (void) snprintf(timestr, sizeof (timestr), "%llu",
2087 (u_longlong_t)rewindto);
2088 }
2089
2090 if (rewindtxg != 0) {
2091 (void) snprintf(whenstr, sizeof (whenstr), "%s (txg %llu)",
2092 timestr, (u_longlong_t)rewindtxg);
2093 } else {
2094 (void) strlcpy(whenstr, timestr, sizeof (whenstr));
2095 }
2096
2097 if (dryrun) {
2098 (void) printf(dgettext(TEXT_DOMAIN,
2099 "Would be able to return %s to its state as of %s.\n"),
2100 name, whenstr);
2101 } else {
2102 (void) printf(dgettext(TEXT_DOMAIN,
2103 "Pool %s returned to its state as of %s.\n"),
2104 name, whenstr);
2105 }
2106 if (loss > 120) {
2107 (void) printf(dgettext(TEXT_DOMAIN,
2108 "%s approximately %lld minutes of transactions.\n"),
2109 dryrun ? "Would discard" : "Discarded",
2110 ((longlong_t)loss + 30) / 60);
2111 } else if (loss > 0) {
2112 (void) printf(dgettext(TEXT_DOMAIN,
2113 "%s approximately %lld seconds of transactions.\n"),
2114 dryrun ? "Would discard" : "Discarded",
2115 (longlong_t)loss);
2116 }
2117 }
2118
2119 void
zpool_explain_recover(libzfs_handle_t * hdl,const char * name,int reason,nvlist_t * config,char * buf,size_t size)2120 zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
2121 nvlist_t *config, char *buf, size_t size)
2122 {
2123 nvlist_t *nv = NULL;
2124 int64_t loss = -1;
2125 uint64_t edata = UINT64_MAX;
2126 uint64_t rewindto;
2127 struct tm t;
2128 char timestr[128], temp[1024];
2129
2130 if (!hdl->libzfs_printerr)
2131 return;
2132
2133 /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */
2134 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
2135 nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 ||
2136 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
2137 goto no_info;
2138
2139 (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
2140 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS,
2141 &edata);
2142
2143 (void) snprintf(buf, size, dgettext(TEXT_DOMAIN,
2144 "Recovery is possible, but will result in some data loss.\n"));
2145
2146 if (localtime_r((time_t *)&rewindto, &t) != NULL &&
2147 ctime_r((time_t *)&rewindto, timestr) != NULL) {
2148 timestr[24] = 0;
2149 (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN,
2150 "\tReturning the pool to its state as of %s\n"
2151 "\tshould correct the problem. "), timestr);
2152 (void) strlcat(buf, temp, size);
2153 } else {
2154 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2155 "\tReverting the pool to an earlier state "
2156 "should correct the problem.\n\t"), size);
2157 }
2158
2159 if (loss > 120) {
2160 (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN,
2161 "Approximately %lld minutes of data\n"
2162 "\tmust be discarded, irreversibly. "),
2163 ((longlong_t)loss + 30) / 60);
2164 (void) strlcat(buf, temp, size);
2165 } else if (loss > 0) {
2166 (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN,
2167 "Approximately %lld seconds of data\n"
2168 "\tmust be discarded, irreversibly. "),
2169 (longlong_t)loss);
2170 (void) strlcat(buf, temp, size);
2171 }
2172 if (edata != 0 && edata != UINT64_MAX) {
2173 if (edata == 1) {
2174 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2175 "After rewind, at least\n"
2176 "\tone persistent user-data error will remain. "),
2177 size);
2178 } else {
2179 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2180 "After rewind, several\n"
2181 "\tpersistent user-data errors will remain. "),
2182 size);
2183 }
2184 }
2185 (void) snprintf(temp, 1024, dgettext(TEXT_DOMAIN,
2186 "Recovery can be attempted\n\tby executing 'zpool %s -F %s'. "),
2187 reason >= 0 ? "clear" : "import", name);
2188 (void) strlcat(buf, temp, size);
2189
2190 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2191 "A scrub of the pool\n"
2192 "\tis strongly recommended after recovery.\n"), size);
2193 return;
2194
2195 no_info:
2196 (void) strlcat(buf, dgettext(TEXT_DOMAIN,
2197 "Ensure all pool devices are present and accessible, then "
2198 "retry the import.\n\tIf the problem persists, destroy and "
2199 "re-create the pool from a backup source.\n"), size);
2200 }
2201
2202 /*
2203 * zpool_import() is a contracted interface. Should be kept the same
2204 * if possible.
2205 *
2206 * Applications should use zpool_import_props() to import a pool with
2207 * new properties value to be set.
2208 */
2209 int
zpool_import(libzfs_handle_t * hdl,nvlist_t * config,const char * newname,char * altroot)2210 zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
2211 char *altroot)
2212 {
2213 nvlist_t *props = NULL;
2214 int ret;
2215
2216 if (altroot != NULL) {
2217 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
2218 return (zfs_error_fmt(hdl, EZFS_NOMEM,
2219 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
2220 newname));
2221 }
2222
2223 if (nvlist_add_string(props,
2224 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 ||
2225 nvlist_add_string(props,
2226 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) {
2227 nvlist_free(props);
2228 return (zfs_error_fmt(hdl, EZFS_NOMEM,
2229 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
2230 newname));
2231 }
2232 }
2233
2234 ret = zpool_import_props(hdl, config, newname, props,
2235 ZFS_IMPORT_NORMAL);
2236 nvlist_free(props);
2237 return (ret);
2238 }
2239
2240 static void
print_vdev_tree(libzfs_handle_t * hdl,const char * name,nvlist_t * nv,int indent)2241 print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv,
2242 int indent)
2243 {
2244 nvlist_t **child;
2245 uint_t c, children;
2246 char *vname;
2247 uint64_t is_log = 0;
2248
2249 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG,
2250 &is_log);
2251
2252 if (name != NULL)
2253 (void) printf("\t%*s%s%s\n", indent, "", name,
2254 is_log ? " [log]" : "");
2255
2256 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2257 &child, &children) != 0)
2258 return;
2259
2260 for (c = 0; c < children; c++) {
2261 vname = zpool_vdev_name(hdl, NULL, child[c], VDEV_NAME_TYPE_ID);
2262 print_vdev_tree(hdl, vname, child[c], indent + 2);
2263 free(vname);
2264 }
2265 }
2266
2267 void
zpool_collect_unsup_feat(nvlist_t * config,char * buf,size_t size)2268 zpool_collect_unsup_feat(nvlist_t *config, char *buf, size_t size)
2269 {
2270 nvlist_t *nvinfo, *unsup_feat;
2271 char temp[512];
2272
2273 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2274 unsup_feat = fnvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT);
2275
2276 for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL);
2277 nvp != NULL; nvp = nvlist_next_nvpair(unsup_feat, nvp)) {
2278 const char *desc = fnvpair_value_string(nvp);
2279 if (strlen(desc) > 0) {
2280 (void) snprintf(temp, 512, "\t%s (%s)\n",
2281 nvpair_name(nvp), desc);
2282 (void) strlcat(buf, temp, size);
2283 } else {
2284 (void) snprintf(temp, 512, "\t%s\n", nvpair_name(nvp));
2285 (void) strlcat(buf, temp, size);
2286 }
2287 }
2288 }
2289
2290 /*
2291 * Import the given pool using the known configuration and a list of
2292 * properties to be set. The configuration should have come from
2293 * zpool_find_import(). The 'newname' parameters control whether the pool
2294 * is imported with a different name.
2295 */
2296 int
zpool_import_props(libzfs_handle_t * hdl,nvlist_t * config,const char * newname,nvlist_t * props,int flags)2297 zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
2298 nvlist_t *props, int flags)
2299 {
2300 zfs_cmd_t zc = {"\0"};
2301 zpool_load_policy_t policy;
2302 nvlist_t *nv = NULL;
2303 nvlist_t *nvinfo = NULL;
2304 nvlist_t *missing = NULL;
2305 const char *thename;
2306 const char *origname;
2307 int ret;
2308 int error = 0;
2309 char buf[2048];
2310 char errbuf[ERRBUFLEN];
2311
2312 origname = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
2313
2314 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2315 "cannot import pool '%s'"), origname);
2316
2317 if (newname != NULL) {
2318 if (!zpool_name_valid(hdl, B_FALSE, newname))
2319 return (zfs_error_fmt(hdl, EZFS_INVALIDNAME,
2320 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
2321 newname));
2322 thename = newname;
2323 } else {
2324 thename = origname;
2325 }
2326
2327 if (props != NULL) {
2328 uint64_t version;
2329 prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
2330
2331 version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
2332
2333 if ((props = zpool_valid_proplist(hdl, origname,
2334 props, version, flags, errbuf)) == NULL)
2335 return (-1);
2336 zcmd_write_src_nvlist(hdl, &zc, props);
2337 nvlist_free(props);
2338 }
2339
2340 (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
2341
2342 zc.zc_guid = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID);
2343
2344 zcmd_write_conf_nvlist(hdl, &zc, config);
2345 zcmd_alloc_dst_nvlist(hdl, &zc, zc.zc_nvlist_conf_size * 2);
2346
2347 zc.zc_cookie = flags;
2348 while ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc)) != 0 &&
2349 errno == ENOMEM)
2350 zcmd_expand_dst_nvlist(hdl, &zc);
2351 if (ret != 0)
2352 error = errno;
2353
2354 (void) zcmd_read_dst_nvlist(hdl, &zc, &nv);
2355
2356 zcmd_free_nvlists(&zc);
2357
2358 zpool_get_load_policy(config, &policy);
2359
2360 if (getenv("ZFS_LOAD_INFO_DEBUG") && nv != NULL &&
2361 nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0) {
2362 dump_nvlist(nvinfo, 4);
2363 }
2364
2365 if (error) {
2366 char desc[1024];
2367 char aux[256];
2368
2369 /*
2370 * Dry-run failed, but we print out what success
2371 * looks like if we found a best txg
2372 */
2373 if (policy.zlp_rewind & ZPOOL_TRY_REWIND) {
2374 zpool_rewind_exclaim(hdl, newname ? origname : thename,
2375 nv);
2376 nvlist_free(nv);
2377 return (-1);
2378 }
2379
2380 if (newname == NULL)
2381 (void) snprintf(desc, sizeof (desc),
2382 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
2383 thename);
2384 else
2385 (void) snprintf(desc, sizeof (desc),
2386 dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
2387 origname, thename);
2388
2389 switch (error) {
2390 case ENOTSUP:
2391 if (nv != NULL && nvlist_lookup_nvlist(nv,
2392 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
2393 nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) {
2394 (void) printf(dgettext(TEXT_DOMAIN, "This "
2395 "pool uses the following feature(s) not "
2396 "supported by this system:\n"));
2397 memset(buf, 0, 2048);
2398 zpool_collect_unsup_feat(nv, buf, 2048);
2399 (void) printf("%s", buf);
2400 if (nvlist_exists(nvinfo,
2401 ZPOOL_CONFIG_CAN_RDONLY)) {
2402 (void) printf(dgettext(TEXT_DOMAIN,
2403 "All unsupported features are only "
2404 "required for writing to the pool."
2405 "\nThe pool can be imported using "
2406 "'-o readonly=on'.\n"));
2407 }
2408 }
2409 /*
2410 * Unsupported version.
2411 */
2412 (void) zfs_error(hdl, EZFS_BADVERSION, desc);
2413 break;
2414
2415 case EREMOTEIO:
2416 if (nv != NULL && nvlist_lookup_nvlist(nv,
2417 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0) {
2418 const char *hostname = "<unknown>";
2419 uint64_t hostid = 0;
2420 mmp_state_t mmp_state;
2421 uint32_t mmp_result = 0;
2422
2423 mmp_state = fnvlist_lookup_uint64(nvinfo,
2424 ZPOOL_CONFIG_MMP_STATE);
2425
2426 /*
2427 * A kernel which does not report a cause
2428 * leaves this zero, which falls through to
2429 * the messages below.
2430 */
2431 if (nvlist_exists(nvinfo,
2432 ZPOOL_CONFIG_MMP_RESULT))
2433 mmp_result = fnvlist_lookup_uint32(
2434 nvinfo, ZPOOL_CONFIG_MMP_RESULT);
2435
2436 if (nvlist_exists(nvinfo,
2437 ZPOOL_CONFIG_MMP_HOSTNAME))
2438 hostname = fnvlist_lookup_string(nvinfo,
2439 ZPOOL_CONFIG_MMP_HOSTNAME);
2440
2441 if (nvlist_exists(nvinfo,
2442 ZPOOL_CONFIG_MMP_HOSTID))
2443 hostid = fnvlist_lookup_uint64(nvinfo,
2444 ZPOOL_CONFIG_MMP_HOSTID);
2445
2446 if (mmp_result == ENODEV) {
2447 (void) snprintf(aux, sizeof (aux),
2448 dgettext(TEXT_DOMAIN, "the multi"
2449 "host claim could not be written "
2450 "to a device\nthe pool "
2451 "configuration expects to be "
2452 "present.\nIf the device is "
2453 "permanently gone, recover with "
2454 "'zhack mmp reclaim'."));
2455 } else if (mmp_result == EIO) {
2456 (void) snprintf(aux, sizeof (aux),
2457 dgettext(TEXT_DOMAIN, "I/O errors "
2458 "occurred while writing the multi"
2459 "host claim.\nClear the device "
2460 "errors, then run 'zpool "
2461 "import'."));
2462 } else if (mmp_state == MMP_STATE_ACTIVE) {
2463 (void) snprintf(aux, sizeof (aux),
2464 dgettext(TEXT_DOMAIN, "pool is imp"
2465 "orted on host '%s' (hostid=%lx).\n"
2466 "Export the pool on the other "
2467 "system, then run 'zpool import'."),
2468 hostname, (unsigned long) hostid);
2469 } else if (mmp_state == MMP_STATE_NO_HOSTID) {
2470 (void) snprintf(aux, sizeof (aux),
2471 dgettext(TEXT_DOMAIN, "pool has "
2472 "the multihost property on and "
2473 "the\nsystem's hostid is not set. "
2474 "Set a unique system hostid with "
2475 "the zgenhostid(8) command.\n"));
2476 }
2477
2478 (void) zfs_error_aux(hdl, "%s", aux);
2479 }
2480 (void) zfs_error(hdl, EZFS_ACTIVE_POOL, desc);
2481 break;
2482
2483 case EINVAL:
2484 (void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
2485 break;
2486
2487 case EROFS:
2488 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2489 "one or more devices is read only"));
2490 (void) zfs_error(hdl, EZFS_BADDEV, desc);
2491 break;
2492
2493 case ENXIO:
2494 if (nv && nvlist_lookup_nvlist(nv,
2495 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
2496 nvlist_lookup_nvlist(nvinfo,
2497 ZPOOL_CONFIG_MISSING_DEVICES, &missing) == 0) {
2498 (void) printf(dgettext(TEXT_DOMAIN,
2499 "The devices below are missing or "
2500 "corrupted, use '-m' to import the pool "
2501 "anyway:\n"));
2502 print_vdev_tree(hdl, NULL, missing, 2);
2503 (void) printf("\n");
2504 }
2505 (void) zpool_standard_error(hdl, error, desc);
2506 break;
2507
2508 case EEXIST:
2509 (void) zpool_standard_error(hdl, error, desc);
2510 break;
2511
2512 case EBUSY:
2513 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2514 "one or more devices are already in use\n"));
2515 (void) zfs_error(hdl, EZFS_BADDEV, desc);
2516 break;
2517 case ENAMETOOLONG:
2518 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2519 "new name of at least one dataset is longer than "
2520 "the maximum allowable length"));
2521 (void) zfs_error(hdl, EZFS_NAMETOOLONG, desc);
2522 break;
2523 default:
2524 (void) zpool_standard_error(hdl, error, desc);
2525 memset(buf, 0, 2048);
2526 zpool_explain_recover(hdl,
2527 newname ? origname : thename, -error, nv,
2528 buf, 2048);
2529 (void) printf("\t%s", buf);
2530 break;
2531 }
2532
2533 nvlist_free(nv);
2534 ret = -1;
2535 } else {
2536 zpool_handle_t *zhp;
2537
2538 /*
2539 * This should never fail, but play it safe anyway.
2540 */
2541 if (zpool_open_silent(hdl, thename, &zhp) != 0)
2542 ret = -1;
2543 else if (zhp != NULL)
2544 zpool_close(zhp);
2545 if (policy.zlp_rewind &
2546 (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
2547 zpool_rewind_exclaim(hdl, newname ? origname : thename,
2548 nv);
2549 }
2550 nvlist_free(nv);
2551 }
2552
2553 return (ret);
2554 }
2555
2556 /*
2557 * Translate vdev names to guids. If a vdev_path is determined to be
2558 * unsuitable then a vd_errlist is allocated and the vdev path and errno
2559 * are added to it.
2560 */
2561 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)2562 zpool_translate_vdev_guids(zpool_handle_t *zhp, nvlist_t *vds,
2563 nvlist_t *vdev_guids, nvlist_t *guids_to_paths, nvlist_t **vd_errlist)
2564 {
2565 nvlist_t *errlist = NULL;
2566 int error = 0;
2567
2568 for (nvpair_t *elem = nvlist_next_nvpair(vds, NULL); elem != NULL;
2569 elem = nvlist_next_nvpair(vds, elem)) {
2570 boolean_t spare, cache;
2571
2572 const char *vd_path = nvpair_name(elem);
2573 nvlist_t *tgt = zpool_find_vdev(zhp, vd_path, &spare, &cache,
2574 NULL);
2575
2576 if ((tgt == NULL) || cache || spare) {
2577 if (errlist == NULL) {
2578 errlist = fnvlist_alloc();
2579 error = EINVAL;
2580 }
2581
2582 uint64_t err = (tgt == NULL) ? EZFS_NODEVICE :
2583 (spare ? EZFS_ISSPARE : EZFS_ISL2CACHE);
2584 fnvlist_add_int64(errlist, vd_path, err);
2585 continue;
2586 }
2587
2588 uint64_t guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
2589 fnvlist_add_uint64(vdev_guids, vd_path, guid);
2590
2591 char msg[MAXNAMELEN];
2592 (void) snprintf(msg, sizeof (msg), "%llu", (u_longlong_t)guid);
2593 fnvlist_add_string(guids_to_paths, msg, vd_path);
2594 }
2595
2596 if (error != 0) {
2597 verify(errlist != NULL);
2598 if (vd_errlist != NULL)
2599 *vd_errlist = errlist;
2600 else
2601 fnvlist_free(errlist);
2602 }
2603
2604 return (error);
2605 }
2606
2607 static int
xlate_init_err(int err)2608 xlate_init_err(int err)
2609 {
2610 switch (err) {
2611 case ENODEV:
2612 return (EZFS_NODEVICE);
2613 case EINVAL:
2614 case EROFS:
2615 return (EZFS_BADDEV);
2616 case EBUSY:
2617 return (EZFS_INITIALIZING);
2618 case ESRCH:
2619 return (EZFS_NO_INITIALIZE);
2620 }
2621 return (err);
2622 }
2623
2624 /*
2625 * Start (or cancel/suspend/uninit) the initialize operation on every
2626 * leaf vdev of the pool.
2627 */
2628 int
zpool_initialize_one(zpool_handle_t * zhp,void * data)2629 zpool_initialize_one(zpool_handle_t *zhp, void *data)
2630 {
2631 int error;
2632 libzfs_handle_t *hdl = zpool_get_handle(zhp);
2633 const char *pool_name = zpool_get_name(zhp);
2634 if (zpool_open_silent(hdl, pool_name, &zhp) != 0)
2635 return (-1);
2636 initialize_cbdata_t *cb = data;
2637 nvlist_t *vdevs = fnvlist_alloc();
2638
2639 nvlist_t *config = zpool_get_config(zhp, NULL);
2640 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
2641 ZPOOL_CONFIG_VDEV_TREE);
2642 zpool_collect_leaves(zhp, nvroot, vdevs);
2643 if (cb->wait)
2644 error = zpool_initialize_wait(zhp, cb->cmd_type, vdevs,
2645 cb->value, cb->value_provided);
2646 else
2647 error = zpool_initialize(zhp, cb->cmd_type, vdevs,
2648 cb->value, cb->value_provided);
2649 fnvlist_free(vdevs);
2650
2651 return (error);
2652 }
2653
2654 /*
2655 * Begin, suspend, cancel, or uninit (clear) the initialization (initializing
2656 * of all free blocks) for the given vdevs in the given pool.
2657 */
2658 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)2659 zpool_initialize_impl(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
2660 nvlist_t *vds, uint64_t value, boolean_t value_provided, boolean_t wait)
2661 {
2662 int err;
2663
2664 nvlist_t *vdev_guids = fnvlist_alloc();
2665 nvlist_t *guids_to_paths = fnvlist_alloc();
2666 nvlist_t *vd_errlist = NULL;
2667 nvlist_t *errlist;
2668 nvpair_t *elem;
2669
2670 err = zpool_translate_vdev_guids(zhp, vds, vdev_guids,
2671 guids_to_paths, &vd_errlist);
2672
2673 if (err != 0) {
2674 verify(vd_errlist != NULL);
2675 goto list_errors;
2676 }
2677
2678 err = lzc_initialize(zhp->zpool_name, cmd_type,
2679 value, value_provided, vdev_guids, &errlist);
2680
2681 if (err != 0) {
2682 if (errlist != NULL && nvlist_lookup_nvlist(errlist,
2683 ZPOOL_INITIALIZE_VDEVS, &vd_errlist) == 0) {
2684 goto list_errors;
2685 }
2686
2687 if (err == EINVAL && cmd_type == POOL_INITIALIZE_UNINIT) {
2688 zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
2689 "uninitialize is not supported by kernel"));
2690 }
2691
2692 (void) zpool_standard_error(zhp->zpool_hdl, err,
2693 dgettext(TEXT_DOMAIN, "operation failed"));
2694 goto out;
2695 }
2696
2697 if (wait) {
2698 for (elem = nvlist_next_nvpair(vdev_guids, NULL); elem != NULL;
2699 elem = nvlist_next_nvpair(vdev_guids, elem)) {
2700
2701 uint64_t guid = fnvpair_value_uint64(elem);
2702
2703 err = lzc_wait_tag(zhp->zpool_name,
2704 ZPOOL_WAIT_INITIALIZE, guid, NULL);
2705 if (err != 0) {
2706 (void) zpool_standard_error_fmt(zhp->zpool_hdl,
2707 err, dgettext(TEXT_DOMAIN, "error "
2708 "waiting for '%s' to initialize"),
2709 nvpair_name(elem));
2710
2711 goto out;
2712 }
2713 }
2714 }
2715 goto out;
2716
2717 list_errors:
2718 for (elem = nvlist_next_nvpair(vd_errlist, NULL); elem != NULL;
2719 elem = nvlist_next_nvpair(vd_errlist, elem)) {
2720 int64_t vd_error = xlate_init_err(fnvpair_value_int64(elem));
2721 const char *path;
2722
2723 if (nvlist_lookup_string(guids_to_paths, nvpair_name(elem),
2724 &path) != 0)
2725 path = nvpair_name(elem);
2726
2727 (void) zfs_error_fmt(zhp->zpool_hdl, vd_error,
2728 "cannot initialize '%s'", path);
2729 }
2730
2731 out:
2732 fnvlist_free(vdev_guids);
2733 fnvlist_free(guids_to_paths);
2734
2735 if (vd_errlist != NULL)
2736 fnvlist_free(vd_errlist);
2737
2738 return (err == 0 ? 0 : -1);
2739 }
2740
2741 /*
2742 * Start (or cancel/suspend/uninit) the initialize operation on the listed
2743 * vdevs. Returns once the new state is committed.
2744 */
2745 int
zpool_initialize(zpool_handle_t * zhp,pool_initialize_func_t cmd_type,nvlist_t * vds,uint64_t value,boolean_t value_provided)2746 zpool_initialize(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
2747 nvlist_t *vds, uint64_t value, boolean_t value_provided)
2748 {
2749 return (zpool_initialize_impl(zhp, cmd_type, vds, value, value_provided,
2750 B_FALSE));
2751 }
2752
2753 /*
2754 * Like zpool_initialize(), but waits for each listed vdev to finish.
2755 */
2756 int
zpool_initialize_wait(zpool_handle_t * zhp,pool_initialize_func_t cmd_type,nvlist_t * vds,uint64_t value,boolean_t value_provided)2757 zpool_initialize_wait(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
2758 nvlist_t *vds, uint64_t value, boolean_t value_provided)
2759 {
2760 return (zpool_initialize_impl(zhp, cmd_type, vds, value, value_provided,
2761 B_TRUE));
2762 }
2763
2764 static int
xlate_trim_err(int err)2765 xlate_trim_err(int err)
2766 {
2767 switch (err) {
2768 case ENODEV:
2769 return (EZFS_NODEVICE);
2770 case EINVAL:
2771 case EROFS:
2772 return (EZFS_BADDEV);
2773 case EBUSY:
2774 return (EZFS_TRIMMING);
2775 case ESRCH:
2776 return (EZFS_NO_TRIM);
2777 case EOPNOTSUPP:
2778 return (EZFS_TRIM_NOTSUP);
2779 }
2780 return (err);
2781 }
2782
2783 void
zpool_collect_leaves(zpool_handle_t * zhp,nvlist_t * nvroot,nvlist_t * res)2784 zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
2785 {
2786 libzfs_handle_t *hdl = zhp->zpool_hdl;
2787 uint_t children = 0;
2788 nvlist_t **child;
2789 uint_t i;
2790
2791 (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
2792 &child, &children);
2793
2794 if (children == 0) {
2795 char *path = zpool_vdev_name(hdl, zhp, nvroot,
2796 VDEV_NAME_PATH);
2797
2798 if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 &&
2799 strcmp(path, VDEV_TYPE_HOLE) != 0)
2800 fnvlist_add_boolean(res, path);
2801
2802 free(path);
2803 return;
2804 }
2805
2806 for (i = 0; i < children; i++) {
2807 zpool_collect_leaves(zhp, child[i], res);
2808 }
2809 }
2810
2811 /*
2812 * Start (or cancel/suspend) the trim operation on every leaf vdev of
2813 * the pool.
2814 */
2815 int
zpool_trim_one(zpool_handle_t * zhp,void * data)2816 zpool_trim_one(zpool_handle_t *zhp, void *data)
2817 {
2818 int error;
2819 libzfs_handle_t *hdl = zpool_get_handle(zhp);
2820 const char *pool_name = zpool_get_name(zhp);
2821 if (zpool_open_silent(hdl, pool_name, &zhp) != 0)
2822 return (-1);
2823
2824 trim_cbdata_t *cb = data;
2825 nvlist_t *vdevs = fnvlist_alloc();
2826
2827 /* no individual leaf vdevs specified, so add them all */
2828 nvlist_t *config = zpool_get_config(zhp, NULL);
2829 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
2830 ZPOOL_CONFIG_VDEV_TREE);
2831
2832 zpool_collect_leaves(zhp, nvroot, vdevs);
2833 error = zpool_trim(zhp, cb->cmd_type, vdevs, &cb->trim_flags);
2834 fnvlist_free(vdevs);
2835
2836 return (error);
2837 }
2838
2839 static int
zpool_trim_wait(zpool_handle_t * zhp,nvlist_t * vdev_guids)2840 zpool_trim_wait(zpool_handle_t *zhp, nvlist_t *vdev_guids)
2841 {
2842 int err;
2843 nvpair_t *elem;
2844
2845 for (elem = nvlist_next_nvpair(vdev_guids, NULL); elem != NULL;
2846 elem = nvlist_next_nvpair(vdev_guids, elem)) {
2847
2848 uint64_t guid = fnvpair_value_uint64(elem);
2849
2850 err = lzc_wait_tag(zhp->zpool_name,
2851 ZPOOL_WAIT_TRIM, guid, NULL);
2852 if (err != 0) {
2853 (void) zpool_standard_error_fmt(zhp->zpool_hdl,
2854 err, dgettext(TEXT_DOMAIN, "error "
2855 "waiting to trim '%s'"), nvpair_name(elem));
2856
2857 return (err);
2858 }
2859 }
2860 return (0);
2861 }
2862
2863 /*
2864 * Check errlist and report any errors, omitting ones which should be
2865 * suppressed. Returns B_TRUE if any errors were reported.
2866 */
2867 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)2868 check_trim_errs(zpool_handle_t *zhp, trimflags_t *trim_flags,
2869 nvlist_t *guids_to_paths, nvlist_t *vds, nvlist_t *errlist)
2870 {
2871 nvpair_t *elem;
2872 boolean_t reported_errs = B_FALSE;
2873 int num_vds = 0;
2874 int num_suppressed_errs = 0;
2875
2876 for (elem = nvlist_next_nvpair(vds, NULL);
2877 elem != NULL; elem = nvlist_next_nvpair(vds, elem)) {
2878 num_vds++;
2879 }
2880
2881 for (elem = nvlist_next_nvpair(errlist, NULL);
2882 elem != NULL; elem = nvlist_next_nvpair(errlist, elem)) {
2883 int64_t vd_error = xlate_trim_err(fnvpair_value_int64(elem));
2884 const char *path;
2885
2886 /*
2887 * If only the pool was specified, and it was not a secure
2888 * trim then suppress warnings for individual vdevs which
2889 * do not support trimming.
2890 */
2891 if (vd_error == EZFS_TRIM_NOTSUP &&
2892 trim_flags->fullpool &&
2893 !trim_flags->secure) {
2894 num_suppressed_errs++;
2895 continue;
2896 }
2897
2898 reported_errs = B_TRUE;
2899 if (nvlist_lookup_string(guids_to_paths, nvpair_name(elem),
2900 &path) != 0)
2901 path = nvpair_name(elem);
2902
2903 (void) zfs_error_fmt(zhp->zpool_hdl, vd_error,
2904 "cannot trim '%s'", path);
2905 }
2906
2907 if (num_suppressed_errs == num_vds) {
2908 (void) zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
2909 "no devices in pool support trim operations"));
2910 (void) (zfs_error(zhp->zpool_hdl, EZFS_TRIM_NOTSUP,
2911 dgettext(TEXT_DOMAIN, "cannot trim")));
2912 reported_errs = B_TRUE;
2913 }
2914
2915 return (reported_errs);
2916 }
2917
2918 /*
2919 * Begin, suspend, or cancel the TRIM (discarding of all free blocks) for
2920 * the given vdevs in the given pool.
2921 */
2922 int
zpool_trim(zpool_handle_t * zhp,pool_trim_func_t cmd_type,nvlist_t * vds,trimflags_t * trim_flags)2923 zpool_trim(zpool_handle_t *zhp, pool_trim_func_t cmd_type, nvlist_t *vds,
2924 trimflags_t *trim_flags)
2925 {
2926 int err;
2927 int retval = 0;
2928
2929 nvlist_t *vdev_guids = fnvlist_alloc();
2930 nvlist_t *guids_to_paths = fnvlist_alloc();
2931 nvlist_t *errlist = NULL;
2932
2933 err = zpool_translate_vdev_guids(zhp, vds, vdev_guids,
2934 guids_to_paths, &errlist);
2935 if (err != 0) {
2936 check_trim_errs(zhp, trim_flags, guids_to_paths, vds, errlist);
2937 retval = -1;
2938 goto out;
2939 }
2940
2941 err = lzc_trim(zhp->zpool_name, cmd_type, trim_flags->rate,
2942 trim_flags->secure, vdev_guids, &errlist);
2943 if (err != 0) {
2944 nvlist_t *vd_errlist;
2945 if (errlist != NULL && nvlist_lookup_nvlist(errlist,
2946 ZPOOL_TRIM_VDEVS, &vd_errlist) == 0) {
2947 if (check_trim_errs(zhp, trim_flags, guids_to_paths,
2948 vds, vd_errlist)) {
2949 retval = -1;
2950 goto out;
2951 }
2952 } else {
2953 char errbuf[ERRBUFLEN];
2954
2955 (void) snprintf(errbuf, sizeof (errbuf),
2956 dgettext(TEXT_DOMAIN, "operation failed"));
2957 zpool_standard_error(zhp->zpool_hdl, err, errbuf);
2958 retval = -1;
2959 goto out;
2960 }
2961 }
2962
2963
2964 if (trim_flags->wait)
2965 retval = zpool_trim_wait(zhp, vdev_guids);
2966
2967 out:
2968 if (errlist != NULL)
2969 fnvlist_free(errlist);
2970 fnvlist_free(vdev_guids);
2971 fnvlist_free(guids_to_paths);
2972 return (retval);
2973 }
2974
2975 /*
2976 * Scan the pool.
2977 */
2978 int
zpool_scan(zpool_handle_t * zhp,pool_scan_func_t func,pool_scrub_cmd_t cmd)2979 zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) {
2980 return (zpool_scan_range(zhp, func, cmd, 0, 0, 0));
2981 }
2982
2983 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)2984 zpool_scan_range(zpool_handle_t *zhp, pool_scan_func_t func,
2985 pool_scrub_cmd_t cmd, pool_scrub_flags_t flags,
2986 time_t date_start, time_t date_end)
2987 {
2988 char errbuf[ERRBUFLEN];
2989 int err;
2990 libzfs_handle_t *hdl = zhp->zpool_hdl;
2991
2992 nvlist_t *args = fnvlist_alloc();
2993 fnvlist_add_uint64(args, "scan_type", (uint64_t)func);
2994 fnvlist_add_uint64(args, "scan_command", (uint64_t)cmd);
2995 if (flags != 0)
2996 fnvlist_add_uint64(args, "scan_flags", (uint64_t)flags);
2997 if (date_start != 0 || date_end != 0) {
2998 fnvlist_add_uint64(args, "scan_date_start",
2999 (uint64_t)date_start);
3000 fnvlist_add_uint64(args, "scan_date_end", (uint64_t)date_end);
3001 }
3002
3003 err = lzc_scrub(ZFS_IOC_POOL_SCRUB, zhp->zpool_name, args, NULL);
3004 fnvlist_free(args);
3005
3006 if (err == 0) {
3007 return (0);
3008 } else if (err == ZFS_ERR_IOC_CMD_UNAVAIL && flags == 0) {
3009 zfs_cmd_t zc = {"\0"};
3010 (void) strlcpy(zc.zc_name, zhp->zpool_name,
3011 sizeof (zc.zc_name));
3012 zc.zc_cookie = func;
3013 zc.zc_flags = cmd;
3014
3015 if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0)
3016 return (0);
3017 }
3018
3019 /*
3020 * An ECANCELED on a scrub means one of the following:
3021 * 1. we resumed a paused scrub.
3022 * 2. we resumed a paused error scrub.
3023 * 3. Error scrub is not run because of no error log.
3024 *
3025 * Note that we no longer return ECANCELED in case 1 or 2. However, in
3026 * order to prevent problems where we have a newer userland than
3027 * kernel, we keep this check in place. That prevents erroneous
3028 * failures when an older kernel returns ECANCELED in those cases.
3029 */
3030 if (err == ECANCELED && (func == POOL_SCAN_SCRUB ||
3031 func == POOL_SCAN_ERRORSCRUB) && cmd == POOL_SCRUB_NORMAL)
3032 return (0);
3033 /*
3034 * The following cases have been handled here:
3035 * 1. Paused a scrub/error scrub if there is none in progress.
3036 */
3037 if (err == ENOENT && func != POOL_SCAN_NONE && cmd ==
3038 POOL_SCRUB_PAUSE) {
3039 return (0);
3040 }
3041
3042 ASSERT3U(func, >=, POOL_SCAN_NONE);
3043 ASSERT3U(func, <, POOL_SCAN_FUNCS);
3044
3045 if (func == POOL_SCAN_SCRUB || func == POOL_SCAN_ERRORSCRUB) {
3046 if (cmd == POOL_SCRUB_PAUSE) {
3047 (void) snprintf(errbuf, sizeof (errbuf),
3048 dgettext(TEXT_DOMAIN, "cannot pause scrubbing %s"),
3049 zhp->zpool_name);
3050 } else {
3051 assert(cmd == POOL_SCRUB_NORMAL);
3052 (void) snprintf(errbuf, sizeof (errbuf),
3053 dgettext(TEXT_DOMAIN, "cannot scrub %s"),
3054 zhp->zpool_name);
3055 }
3056 } else if (func == POOL_SCAN_RESILVER) {
3057 assert(cmd == POOL_SCRUB_NORMAL);
3058 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3059 "cannot restart resilver on %s"), zhp->zpool_name);
3060 } else if (func == POOL_SCAN_NONE) {
3061 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3062 "cannot cancel scrubbing %s"), zhp->zpool_name);
3063 } else {
3064 assert(!"unexpected result");
3065 }
3066
3067 /*
3068 * With EBUSY, six cases are possible:
3069 *
3070 * Current state Requested
3071 * 1. Normal Scrub Running Normal Scrub or Error Scrub
3072 * 2. Normal Scrub Paused Error Scrub
3073 * 3. Normal Scrub Paused Pause Normal Scrub
3074 * 4. Error Scrub Running Normal Scrub or Error Scrub
3075 * 5. Error Scrub Paused Pause Error Scrub
3076 * 6. Resilvering Anything else
3077 */
3078 if (err == EBUSY) {
3079 nvlist_t *nvroot;
3080 pool_scan_stat_t *ps = NULL;
3081 uint_t psc;
3082
3083 nvroot = fnvlist_lookup_nvlist(zhp->zpool_config,
3084 ZPOOL_CONFIG_VDEV_TREE);
3085 (void) nvlist_lookup_uint64_array(nvroot,
3086 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc);
3087 if (ps && ps->pss_func == POOL_SCAN_SCRUB &&
3088 ps->pss_state == DSS_SCANNING) {
3089 if (ps->pss_pass_scrub_pause == 0) {
3090 /* handles case 1 */
3091 assert(cmd == POOL_SCRUB_NORMAL);
3092 return (zfs_error(hdl, EZFS_SCRUBBING,
3093 errbuf));
3094 } else {
3095 if (func == POOL_SCAN_ERRORSCRUB) {
3096 /* handles case 2 */
3097 ASSERT3U(cmd, ==, POOL_SCRUB_NORMAL);
3098 return (zfs_error(hdl,
3099 EZFS_SCRUB_PAUSED_TO_CANCEL,
3100 errbuf));
3101 } else {
3102 /* handles case 3 */
3103 ASSERT3U(func, ==, POOL_SCAN_SCRUB);
3104 ASSERT3U(cmd, ==, POOL_SCRUB_PAUSE);
3105 return (zfs_error(hdl,
3106 EZFS_SCRUB_PAUSED, errbuf));
3107 }
3108 }
3109 } else if (ps &&
3110 ps->pss_error_scrub_func == POOL_SCAN_ERRORSCRUB &&
3111 ps->pss_error_scrub_state == DSS_ERRORSCRUBBING) {
3112 if (ps->pss_pass_error_scrub_pause == 0) {
3113 /* handles case 4 */
3114 ASSERT3U(cmd, ==, POOL_SCRUB_NORMAL);
3115 return (zfs_error(hdl, EZFS_ERRORSCRUBBING,
3116 errbuf));
3117 } else {
3118 /* handles case 5 */
3119 ASSERT3U(func, ==, POOL_SCAN_ERRORSCRUB);
3120 ASSERT3U(cmd, ==, POOL_SCRUB_PAUSE);
3121 return (zfs_error(hdl, EZFS_ERRORSCRUB_PAUSED,
3122 errbuf));
3123 }
3124 } else {
3125 /* handles case 6 */
3126 return (zfs_error(hdl, EZFS_RESILVERING, errbuf));
3127 }
3128 } else if (err == ENOENT) {
3129 return (zfs_error(hdl, EZFS_NO_SCRUB, errbuf));
3130 } else if (err == ENOTSUP && func == POOL_SCAN_RESILVER) {
3131 return (zfs_error(hdl, EZFS_NO_RESILVER_DEFER, errbuf));
3132 } else {
3133 return (zpool_standard_error(hdl, err, errbuf));
3134 }
3135 }
3136
3137 /*
3138 * Find a vdev that matches the search criteria specified. We use the
3139 * the nvpair name to determine how we should look for the device.
3140 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
3141 * spare; but FALSE if its an INUSE spare.
3142 *
3143 * If 'return_parent' is set, then return the *parent* of the vdev you're
3144 * searching for rather than the vdev itself.
3145 */
3146 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)3147 vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
3148 boolean_t *l2cache, boolean_t *log, boolean_t return_parent)
3149 {
3150 uint_t c, children;
3151 nvlist_t **child;
3152 nvlist_t *ret;
3153 uint64_t is_log;
3154 const char *srchkey;
3155 nvpair_t *pair = nvlist_next_nvpair(search, NULL);
3156 const char *tmp = NULL;
3157 boolean_t is_root;
3158
3159 /* Nothing to look for */
3160 if (search == NULL || pair == NULL)
3161 return (NULL);
3162
3163 /* Obtain the key we will use to search */
3164 srchkey = nvpair_name(pair);
3165
3166 nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &tmp);
3167 if (strcmp(tmp, "root") == 0)
3168 is_root = B_TRUE;
3169 else
3170 is_root = B_FALSE;
3171
3172 switch (nvpair_type(pair)) {
3173 case DATA_TYPE_UINT64:
3174 if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
3175 uint64_t srchval = fnvpair_value_uint64(pair);
3176 uint64_t theguid = fnvlist_lookup_uint64(nv,
3177 ZPOOL_CONFIG_GUID);
3178 if (theguid == srchval)
3179 return (nv);
3180 }
3181 break;
3182
3183 case DATA_TYPE_STRING: {
3184 const char *srchval, *val;
3185
3186 srchval = fnvpair_value_string(pair);
3187 if (nvlist_lookup_string(nv, srchkey, &val) != 0)
3188 break;
3189
3190 /*
3191 * Search for the requested value. Special cases:
3192 *
3193 * - ZPOOL_CONFIG_PATH for whole disk entries. These end in
3194 * "-part1", or "p1". The suffix is hidden from the user,
3195 * but included in the string, so this matches around it.
3196 * - ZPOOL_CONFIG_PATH for short names zfs_strcmp_shortname()
3197 * is used to check all possible expanded paths.
3198 * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE).
3199 *
3200 * Otherwise, all other searches are simple string compares.
3201 */
3202 if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0) {
3203 uint64_t wholedisk = 0;
3204
3205 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
3206 &wholedisk);
3207 if (zfs_strcmp_pathname(srchval, val, wholedisk) == 0)
3208 return (nv);
3209
3210 } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0) {
3211 char *type, *idx, *end, *p;
3212 uint64_t id, vdev_id;
3213
3214 /*
3215 * Determine our vdev type, keeping in mind
3216 * that the srchval is composed of a type and
3217 * vdev id pair (i.e. mirror-4).
3218 */
3219 if ((type = strdup(srchval)) == NULL)
3220 return (NULL);
3221
3222 if ((p = strrchr(type, '-')) == NULL) {
3223 free(type);
3224 break;
3225 }
3226 idx = p + 1;
3227 *p = '\0';
3228
3229 /*
3230 * draid names are presented like: draid2:4d:6c:0s
3231 * We match them up to the first ':' so we can still
3232 * do the parity check below, but the other params
3233 * are ignored.
3234 */
3235 if ((p = strchr(type, ':')) != NULL) {
3236 if (strncmp(type, VDEV_TYPE_DRAID,
3237 strlen(VDEV_TYPE_DRAID)) == 0)
3238 *p = '\0';
3239 }
3240
3241 /*
3242 * If the types don't match then keep looking.
3243 */
3244 if (strncmp(val, type, strlen(val)) != 0) {
3245 free(type);
3246 break;
3247 }
3248
3249 verify(zpool_vdev_is_interior(type));
3250
3251 id = fnvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID);
3252 errno = 0;
3253 vdev_id = strtoull(idx, &end, 10);
3254
3255 /*
3256 * If we are looking for a raidz and a parity is
3257 * specified, make sure it matches.
3258 */
3259 int rzlen = strlen(VDEV_TYPE_RAIDZ);
3260 assert(rzlen == strlen(VDEV_TYPE_DRAID));
3261 int typlen = strlen(type);
3262 if ((strncmp(type, VDEV_TYPE_RAIDZ, rzlen) == 0 ||
3263 strncmp(type, VDEV_TYPE_DRAID, rzlen) == 0) &&
3264 typlen != rzlen) {
3265 uint64_t vdev_parity;
3266 int parity = *(type + rzlen) - '0';
3267
3268 if (parity <= 0 || parity > 3 ||
3269 (typlen - rzlen) != 1) {
3270 /*
3271 * Nonsense parity specified, can
3272 * never match
3273 */
3274 free(type);
3275 return (NULL);
3276 }
3277 vdev_parity = fnvlist_lookup_uint64(nv,
3278 ZPOOL_CONFIG_NPARITY);
3279 if ((int)vdev_parity != parity) {
3280 free(type);
3281 break;
3282 }
3283 }
3284
3285 free(type);
3286 if (errno != 0)
3287 return (NULL);
3288
3289 /*
3290 * Now verify that we have the correct vdev id.
3291 */
3292 if (vdev_id == id)
3293 return (nv);
3294 }
3295
3296 /*
3297 * Common case
3298 */
3299 if (strcmp(srchval, val) == 0)
3300 return (nv);
3301 break;
3302 }
3303
3304 default:
3305 break;
3306 }
3307
3308 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3309 &child, &children) != 0)
3310 return (NULL);
3311
3312 for (c = 0; c < children; c++) {
3313 if ((ret = vdev_to_nvlist_iter(child[c], search,
3314 avail_spare, l2cache, NULL, return_parent)) != NULL) {
3315 /*
3316 * The 'is_log' value is only set for the toplevel
3317 * vdev, not the leaf vdevs. So we always lookup the
3318 * log device from the root of the vdev tree (where
3319 * 'log' is non-NULL).
3320 */
3321 if (log != NULL &&
3322 nvlist_lookup_uint64(child[c],
3323 ZPOOL_CONFIG_IS_LOG, &is_log) == 0 &&
3324 is_log) {
3325 *log = B_TRUE;
3326 }
3327 return (ret && return_parent && !is_root ? nv : ret);
3328 }
3329 }
3330
3331 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
3332 &child, &children) == 0) {
3333 for (c = 0; c < children; c++) {
3334 if ((ret = vdev_to_nvlist_iter(child[c], search,
3335 avail_spare, l2cache, NULL, return_parent))
3336 != NULL) {
3337 *avail_spare = B_TRUE;
3338 return (ret && return_parent &&
3339 !is_root ? nv : ret);
3340 }
3341 }
3342 }
3343
3344 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3345 &child, &children) == 0) {
3346 for (c = 0; c < children; c++) {
3347 if ((ret = vdev_to_nvlist_iter(child[c], search,
3348 avail_spare, l2cache, NULL, return_parent))
3349 != NULL) {
3350 *l2cache = B_TRUE;
3351 return (ret && return_parent &&
3352 !is_root ? nv : ret);
3353 }
3354 }
3355 }
3356
3357 return (NULL);
3358 }
3359
3360 /*
3361 * Given a physical path or guid, find the associated vdev.
3362 */
3363 nvlist_t *
zpool_find_vdev_by_physpath(zpool_handle_t * zhp,const char * ppath,boolean_t * avail_spare,boolean_t * l2cache,boolean_t * log)3364 zpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath,
3365 boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
3366 {
3367 nvlist_t *search, *nvroot, *ret;
3368 uint64_t guid;
3369 char *end;
3370
3371 search = fnvlist_alloc();
3372
3373 guid = strtoull(ppath, &end, 0);
3374 if (guid != 0 && *end == '\0') {
3375 fnvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid);
3376 } else {
3377 fnvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath);
3378 }
3379
3380 nvroot = fnvlist_lookup_nvlist(zhp->zpool_config,
3381 ZPOOL_CONFIG_VDEV_TREE);
3382
3383 *avail_spare = B_FALSE;
3384 *l2cache = B_FALSE;
3385 if (log != NULL)
3386 *log = B_FALSE;
3387 ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log,
3388 B_FALSE);
3389 fnvlist_free(search);
3390
3391 return (ret);
3392 }
3393
3394 /*
3395 * Determine if we have an "interior" top-level vdev (i.e mirror/raidz).
3396 */
3397 static boolean_t
zpool_vdev_is_interior(const char * name)3398 zpool_vdev_is_interior(const char *name)
3399 {
3400 if (strncmp(name, VDEV_TYPE_RAIDZ, strlen(VDEV_TYPE_RAIDZ)) == 0 ||
3401 strncmp(name, VDEV_TYPE_SPARE, strlen(VDEV_TYPE_SPARE)) == 0 ||
3402 strncmp(name,
3403 VDEV_TYPE_REPLACING, strlen(VDEV_TYPE_REPLACING)) == 0 ||
3404 strncmp(name, VDEV_TYPE_ROOT, strlen(VDEV_TYPE_ROOT)) == 0 ||
3405 strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0)
3406 return (B_TRUE);
3407
3408 if (strncmp(name, VDEV_TYPE_DRAID, strlen(VDEV_TYPE_DRAID)) == 0 &&
3409 !zpool_is_draid_spare(name))
3410 return (B_TRUE);
3411
3412 return (B_FALSE);
3413 }
3414
3415 /*
3416 * Lookup the nvlist for a given vdev or vdev's parent (depending on
3417 * if 'return_parent' is set).
3418 */
3419 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)3420 __zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
3421 boolean_t *l2cache, boolean_t *log, boolean_t return_parent)
3422 {
3423 char *end;
3424 nvlist_t *nvroot, *search, *ret;
3425 uint64_t guid;
3426 boolean_t __avail_spare, __l2cache, __log;
3427
3428 search = fnvlist_alloc();
3429
3430 guid = strtoull(path, &end, 0);
3431 if (guid != 0 && *end == '\0') {
3432 fnvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid);
3433 } else if (zpool_vdev_is_interior(path)) {
3434 fnvlist_add_string(search, ZPOOL_CONFIG_TYPE, path);
3435 } else {
3436 fnvlist_add_string(search, ZPOOL_CONFIG_PATH, path);
3437 }
3438
3439 nvroot = fnvlist_lookup_nvlist(zhp->zpool_config,
3440 ZPOOL_CONFIG_VDEV_TREE);
3441
3442 /*
3443 * User can pass NULL for avail_spare, l2cache, and log, but
3444 * we still need to provide variables to vdev_to_nvlist_iter(), so
3445 * just point them to junk variables here.
3446 */
3447 if (!avail_spare)
3448 avail_spare = &__avail_spare;
3449 if (!l2cache)
3450 l2cache = &__l2cache;
3451 if (!log)
3452 log = &__log;
3453
3454 *avail_spare = B_FALSE;
3455 *l2cache = B_FALSE;
3456 if (log != NULL)
3457 *log = B_FALSE;
3458 ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log,
3459 return_parent);
3460 fnvlist_free(search);
3461
3462 return (ret);
3463 }
3464
3465 /*
3466 * Look up a vdev in the pool by path, name, or guid. Returns the
3467 * vdev's configuration nvlist, or NULL on no match. Also, fills
3468 * in avail_spare, l2cache, and log if they are non-NULL.
3469 */
3470 nvlist_t *
zpool_find_vdev(zpool_handle_t * zhp,const char * path,boolean_t * avail_spare,boolean_t * l2cache,boolean_t * log)3471 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
3472 boolean_t *l2cache, boolean_t *log)
3473 {
3474 return (__zpool_find_vdev(zhp, path, avail_spare, l2cache, log,
3475 B_FALSE));
3476 }
3477
3478 /* Given a vdev path, return its parent's nvlist */
3479 nvlist_t *
zpool_find_parent_vdev(zpool_handle_t * zhp,const char * path,boolean_t * avail_spare,boolean_t * l2cache,boolean_t * log)3480 zpool_find_parent_vdev(zpool_handle_t *zhp, const char *path,
3481 boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
3482 {
3483 return (__zpool_find_vdev(zhp, path, avail_spare, l2cache, log,
3484 B_TRUE));
3485 }
3486
3487 /*
3488 * Convert a vdev path to a GUID. Returns GUID or 0 on error.
3489 *
3490 * If is_spare, is_l2cache, or is_log is non-NULL, then store within it
3491 * if the VDEV is a spare, l2cache, or log device. If they're NULL then
3492 * ignore them.
3493 */
3494 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)3495 zpool_vdev_path_to_guid_impl(zpool_handle_t *zhp, const char *path,
3496 boolean_t *is_spare, boolean_t *is_l2cache, boolean_t *is_log)
3497 {
3498 boolean_t spare = B_FALSE, l2cache = B_FALSE, log = B_FALSE;
3499 nvlist_t *tgt;
3500
3501 if ((tgt = zpool_find_vdev(zhp, path, &spare, &l2cache,
3502 &log)) == NULL)
3503 return (0);
3504
3505 if (is_spare != NULL)
3506 *is_spare = spare;
3507 if (is_l2cache != NULL)
3508 *is_l2cache = l2cache;
3509 if (is_log != NULL)
3510 *is_log = log;
3511
3512 return (fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID));
3513 }
3514
3515 /* Convert a vdev path to a GUID. Returns GUID or 0 on error. */
3516 uint64_t
zpool_vdev_path_to_guid(zpool_handle_t * zhp,const char * path)3517 zpool_vdev_path_to_guid(zpool_handle_t *zhp, const char *path)
3518 {
3519 return (zpool_vdev_path_to_guid_impl(zhp, path, NULL, NULL, NULL));
3520 }
3521
3522 /*
3523 * Bring the specified vdev online. The 'flags' parameter is a set of the
3524 * ZFS_ONLINE_* flags.
3525 */
3526 int
zpool_vdev_online(zpool_handle_t * zhp,const char * path,int flags,vdev_state_t * newstate)3527 zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
3528 vdev_state_t *newstate)
3529 {
3530 zfs_cmd_t zc = {"\0"};
3531 char errbuf[ERRBUFLEN];
3532 nvlist_t *tgt;
3533 boolean_t avail_spare, l2cache, islog;
3534 libzfs_handle_t *hdl = zhp->zpool_hdl;
3535
3536 if (flags & ZFS_ONLINE_EXPAND) {
3537 (void) snprintf(errbuf, sizeof (errbuf),
3538 dgettext(TEXT_DOMAIN, "cannot expand %s"), path);
3539 } else {
3540 (void) snprintf(errbuf, sizeof (errbuf),
3541 dgettext(TEXT_DOMAIN, "cannot online %s"), path);
3542 }
3543
3544 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3545 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3546 &islog)) == NULL)
3547 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3548
3549 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3550
3551 if (!(flags & ZFS_ONLINE_SPARE) && avail_spare)
3552 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
3553
3554 #ifndef __FreeBSD__
3555 const char *pathname;
3556 if ((flags & ZFS_ONLINE_EXPAND ||
3557 zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) &&
3558 nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &pathname) == 0) {
3559 uint64_t wholedisk = 0;
3560
3561 (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
3562 &wholedisk);
3563
3564 /*
3565 * XXX - L2ARC 1.0 devices can't support expansion.
3566 */
3567 if (l2cache) {
3568 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3569 "cannot expand cache devices"));
3570 return (zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf));
3571 }
3572
3573 if (wholedisk) {
3574 const char *fullpath = path;
3575 char buf[MAXPATHLEN];
3576 int error;
3577
3578 if (path[0] != '/') {
3579 error = zfs_resolve_shortname(path, buf,
3580 sizeof (buf));
3581 if (error != 0)
3582 return (zfs_error(hdl, EZFS_NODEVICE,
3583 errbuf));
3584
3585 fullpath = buf;
3586 }
3587
3588 error = zpool_relabel_disk(hdl, fullpath, errbuf);
3589 if (error != 0)
3590 return (error);
3591 }
3592 }
3593 #endif
3594
3595 zc.zc_cookie = VDEV_STATE_ONLINE;
3596 zc.zc_obj = flags;
3597
3598 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) {
3599 if (errno == EINVAL) {
3600 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "was split "
3601 "from this pool into a new one. Use '%s' "
3602 "instead"), "zpool detach");
3603 return (zfs_error(hdl, EZFS_POSTSPLIT_ONLINE, errbuf));
3604 }
3605 return (zpool_standard_error(hdl, errno, errbuf));
3606 }
3607
3608 *newstate = zc.zc_cookie;
3609 return (0);
3610 }
3611
3612 /*
3613 * Take the specified vdev offline
3614 */
3615 int
zpool_vdev_offline(zpool_handle_t * zhp,const char * path,boolean_t istmp)3616 zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
3617 {
3618 zfs_cmd_t zc = {"\0"};
3619 char errbuf[ERRBUFLEN];
3620 nvlist_t *tgt;
3621 boolean_t avail_spare, l2cache;
3622 libzfs_handle_t *hdl = zhp->zpool_hdl;
3623
3624 (void) snprintf(errbuf, sizeof (errbuf),
3625 dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
3626
3627 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3628 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3629 NULL)) == NULL)
3630 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3631
3632 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3633
3634 if (avail_spare)
3635 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
3636
3637 zc.zc_cookie = VDEV_STATE_OFFLINE;
3638 zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0;
3639
3640 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3641 return (0);
3642
3643 switch (errno) {
3644 case EBUSY:
3645
3646 /*
3647 * There are no other replicas of this device.
3648 */
3649 return (zfs_error(hdl, EZFS_NOREPLICAS, errbuf));
3650
3651 case EEXIST:
3652 /*
3653 * The log device has unplayed logs
3654 */
3655 return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, errbuf));
3656
3657 default:
3658 return (zpool_standard_error(hdl, errno, errbuf));
3659 }
3660 }
3661
3662 /*
3663 * Remove the specified vdev asynchronously from the configuration, so
3664 * that it may come ONLINE if reinserted. This is called from zed on
3665 * Udev remove event.
3666 * Note: We also have a similar function zpool_vdev_remove() that
3667 * removes the vdev from the pool.
3668 */
3669 int
zpool_vdev_remove_wanted(zpool_handle_t * zhp,const char * path)3670 zpool_vdev_remove_wanted(zpool_handle_t *zhp, const char *path)
3671 {
3672 zfs_cmd_t zc = {"\0"};
3673 char errbuf[ERRBUFLEN];
3674 nvlist_t *tgt;
3675 boolean_t avail_spare, l2cache;
3676 libzfs_handle_t *hdl = zhp->zpool_hdl;
3677
3678 (void) snprintf(errbuf, sizeof (errbuf),
3679 dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
3680
3681 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3682 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3683 NULL)) == NULL)
3684 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3685
3686 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3687
3688 zc.zc_cookie = VDEV_STATE_REMOVED;
3689
3690 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3691 return (0);
3692
3693 return (zpool_standard_error(hdl, errno, errbuf));
3694 }
3695
3696 /*
3697 * Mark the given vdev faulted.
3698 */
3699 int
zpool_vdev_fault(zpool_handle_t * zhp,uint64_t guid,vdev_aux_t aux)3700 zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
3701 {
3702 zfs_cmd_t zc = {"\0"};
3703 char errbuf[ERRBUFLEN];
3704 libzfs_handle_t *hdl = zhp->zpool_hdl;
3705 nvlist_t *vdev_nv;
3706 boolean_t avail_spare, l2cache;
3707 char *vdev_name;
3708 char guid_str[21]; /* 64-bit num + '\0' */
3709 boolean_t is_draid_spare = B_FALSE;
3710 const char *vdev_type;
3711
3712 (void) snprintf(errbuf, sizeof (errbuf),
3713 dgettext(TEXT_DOMAIN, "cannot fault %llu"), (u_longlong_t)guid);
3714
3715 snprintf(guid_str, sizeof (guid_str), "%llu", (u_longlong_t)guid);
3716 if ((vdev_nv = zpool_find_vdev(zhp, guid_str, &avail_spare,
3717 &l2cache, NULL)) == NULL)
3718 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3719
3720 vdev_name = zpool_vdev_name(hdl, zhp, vdev_nv, 0);
3721 if (vdev_name != NULL) {
3722 /*
3723 * We have the actual vdev name, so use that instead of the GUID
3724 * in any error messages.
3725 */
3726 (void) snprintf(errbuf, sizeof (errbuf),
3727 dgettext(TEXT_DOMAIN, "cannot fault %s"), vdev_name);
3728 free(vdev_name);
3729 }
3730
3731 /*
3732 * Spares (traditional or draid) cannot be faulted by libzfs, except:
3733 *
3734 * - Any spare type that exceeds it's errors can be faulted (aux =
3735 * VDEV_AUX_ERR_EXCEEDED). This is only used by zed.
3736 *
3737 * - Traditional spares that are active can be force faulted.
3738 */
3739 if (nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_TYPE, &vdev_type) == 0)
3740 if (strcmp(vdev_type, VDEV_TYPE_DRAID_SPARE) == 0)
3741 is_draid_spare = B_TRUE;
3742
3743 /*
3744 * If vdev is a spare that is not being used, or is a dRAID spare (in
3745 * use or not), then don't allow it to be force-faulted. However, an
3746 * in-use dRAID spare can be faulted by ZED if see too many errors
3747 * (aux = VDEV_AUX_ERR_EXCEEDED).
3748 */
3749 if (avail_spare || (is_draid_spare && aux != VDEV_AUX_ERR_EXCEEDED))
3750 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
3751
3752 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3753 zc.zc_guid = guid;
3754 zc.zc_cookie = VDEV_STATE_FAULTED;
3755 zc.zc_obj = aux;
3756
3757 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3758 return (0);
3759
3760 switch (errno) {
3761 case EBUSY:
3762
3763 /*
3764 * There are no other replicas of this device.
3765 */
3766 return (zfs_error(hdl, EZFS_NOREPLICAS, errbuf));
3767
3768 default:
3769 return (zpool_standard_error(hdl, errno, errbuf));
3770 }
3771
3772 }
3773
3774 /*
3775 * Generic set vdev state function
3776 */
3777 static int
zpool_vdev_set_state(zpool_handle_t * zhp,uint64_t guid,vdev_aux_t aux,vdev_state_t state)3778 zpool_vdev_set_state(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux,
3779 vdev_state_t state)
3780 {
3781 zfs_cmd_t zc = {"\0"};
3782 char errbuf[ERRBUFLEN];
3783 libzfs_handle_t *hdl = zhp->zpool_hdl;
3784
3785 (void) snprintf(errbuf, sizeof (errbuf),
3786 dgettext(TEXT_DOMAIN, "cannot set %s %llu"),
3787 zpool_state_to_name(state, aux), (u_longlong_t)guid);
3788
3789 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3790 zc.zc_guid = guid;
3791 zc.zc_cookie = state;
3792 zc.zc_obj = aux;
3793
3794 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3795 return (0);
3796
3797 return (zpool_standard_error(hdl, errno, errbuf));
3798 }
3799
3800 /*
3801 * Mark the given vdev degraded.
3802 */
3803 int
zpool_vdev_degrade(zpool_handle_t * zhp,uint64_t guid,vdev_aux_t aux)3804 zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
3805 {
3806 return (zpool_vdev_set_state(zhp, guid, aux, VDEV_STATE_DEGRADED));
3807 }
3808
3809 /*
3810 * Mark the given vdev as in a removed state (as if the device does not exist).
3811 *
3812 * This is different than zpool_vdev_remove() which does a removal of a device
3813 * from the pool (but the device does exist).
3814 */
3815 int
zpool_vdev_set_removed_state(zpool_handle_t * zhp,uint64_t guid,vdev_aux_t aux)3816 zpool_vdev_set_removed_state(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
3817 {
3818 return (zpool_vdev_set_state(zhp, guid, aux, VDEV_STATE_REMOVED));
3819 }
3820
3821 /*
3822 * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
3823 * a hot spare.
3824 */
3825 static boolean_t
is_replacing_spare(nvlist_t * search,nvlist_t * tgt,int which)3826 is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
3827 {
3828 nvlist_t **child;
3829 uint_t c, children;
3830
3831 if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
3832 &children) == 0) {
3833 const char *type = fnvlist_lookup_string(search,
3834 ZPOOL_CONFIG_TYPE);
3835 if ((strcmp(type, VDEV_TYPE_SPARE) == 0 ||
3836 strcmp(type, VDEV_TYPE_DRAID_SPARE) == 0) &&
3837 children == 2 && child[which] == tgt)
3838 return (B_TRUE);
3839
3840 for (c = 0; c < children; c++)
3841 if (is_replacing_spare(child[c], tgt, which))
3842 return (B_TRUE);
3843 }
3844
3845 return (B_FALSE);
3846 }
3847
3848 /*
3849 * Attach new_disk (fully described by nvroot) to old_disk.
3850 * If 'replacing' is specified, the new disk will replace the old one.
3851 */
3852 int
zpool_vdev_attach(zpool_handle_t * zhp,const char * old_disk,const char * new_disk,nvlist_t * nvroot,int replacing,boolean_t rebuild)3853 zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk,
3854 const char *new_disk, nvlist_t *nvroot, int replacing, boolean_t rebuild)
3855 {
3856 zfs_cmd_t zc = {"\0"};
3857 char errbuf[ERRBUFLEN];
3858 int ret;
3859 nvlist_t *tgt;
3860 boolean_t avail_spare, l2cache, islog;
3861 uint64_t val;
3862 char *newname;
3863 const char *type;
3864 nvlist_t **child;
3865 uint_t children;
3866 nvlist_t *config_root;
3867 libzfs_handle_t *hdl = zhp->zpool_hdl;
3868
3869 if (replacing)
3870 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3871 "cannot replace %s with %s"), old_disk, new_disk);
3872 else
3873 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3874 "cannot attach %s to %s"), new_disk, old_disk);
3875
3876 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3877 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
3878 &islog)) == NULL)
3879 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
3880
3881 if (avail_spare)
3882 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
3883
3884 if (l2cache)
3885 return (zfs_error(hdl, EZFS_ISL2CACHE, errbuf));
3886
3887 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3888 zc.zc_cookie = replacing;
3889 zc.zc_simple = rebuild;
3890
3891 if (rebuild &&
3892 zfeature_lookup_guid("org.openzfs:device_rebuild", NULL) != 0) {
3893 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3894 "the loaded zfs module doesn't support device rebuilds"));
3895 return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
3896 }
3897
3898 type = fnvlist_lookup_string(tgt, ZPOOL_CONFIG_TYPE);
3899 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 &&
3900 zfeature_lookup_guid("org.openzfs:raidz_expansion", NULL) != 0) {
3901 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3902 "the loaded zfs module doesn't support raidz expansion"));
3903 return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
3904 }
3905
3906 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
3907 &child, &children) != 0 || children != 1) {
3908 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3909 "new device must be a single disk"));
3910 return (zfs_error(hdl, EZFS_INVALCONFIG, errbuf));
3911 }
3912
3913 config_root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
3914 ZPOOL_CONFIG_VDEV_TREE);
3915
3916 if ((newname = zpool_vdev_name(NULL, NULL, child[0], 0)) == NULL)
3917 return (-1);
3918
3919 /*
3920 * If the target is a hot spare that has been swapped in, we can only
3921 * replace it with another hot spare.
3922 */
3923 if (replacing &&
3924 nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
3925 (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache,
3926 NULL) == NULL || !avail_spare) &&
3927 is_replacing_spare(config_root, tgt, 1)) {
3928 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3929 "can only be replaced by another hot spare"));
3930 free(newname);
3931 return (zfs_error(hdl, EZFS_BADTARGET, errbuf));
3932 }
3933
3934 free(newname);
3935
3936 zcmd_write_conf_nvlist(hdl, &zc, nvroot);
3937
3938 ret = zfs_ioctl(hdl, ZFS_IOC_VDEV_ATTACH, &zc);
3939
3940 zcmd_free_nvlists(&zc);
3941
3942 if (ret == 0)
3943 return (0);
3944
3945 switch (errno) {
3946 case ENOTSUP:
3947 /*
3948 * Can't attach to or replace this type of vdev.
3949 */
3950 if (replacing) {
3951 uint64_t version = zpool_get_prop_int(zhp,
3952 ZPOOL_PROP_VERSION, NULL);
3953
3954 if (islog) {
3955 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3956 "cannot replace a log with a spare"));
3957 } else if (rebuild) {
3958 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3959 "only mirror and dRAID vdevs support "
3960 "sequential reconstruction"));
3961 } else if (zpool_is_draid_spare(new_disk)) {
3962 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3963 "dRAID spares can only replace child "
3964 "devices in their parent's dRAID vdev"));
3965 } else if (version >= SPA_VERSION_MULTI_REPLACE) {
3966 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3967 "already in replacing/spare config; wait "
3968 "for completion or use 'zpool detach'"));
3969 } else {
3970 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3971 "cannot replace a replacing device"));
3972 }
3973 } else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
3974 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3975 "raidz_expansion feature must be enabled "
3976 "in order to attach a device to raidz"));
3977 } else {
3978 char status[64] = {0};
3979 zpool_prop_get_feature(zhp,
3980 "feature@device_rebuild", status, 63);
3981 if (rebuild &&
3982 strncmp(status, ZFS_FEATURE_DISABLED, 64) == 0) {
3983 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3984 "device_rebuild feature must be enabled "
3985 "in order to use sequential "
3986 "reconstruction"));
3987 } else {
3988 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3989 "can only attach to mirrors and top-level "
3990 "disks"));
3991 }
3992 }
3993 (void) zfs_error(hdl, EZFS_BADTARGET, errbuf);
3994 break;
3995
3996 case EINVAL:
3997 /*
3998 * The new device must be a single disk.
3999 */
4000 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4001 "new device must be a single disk"));
4002 (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
4003 break;
4004
4005 case EBUSY:
4006 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"),
4007 new_disk);
4008 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
4009 break;
4010
4011 case EOVERFLOW:
4012 /*
4013 * The new device is too small.
4014 */
4015 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4016 "device is too small"));
4017 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
4018 break;
4019
4020 case EDOM:
4021 /*
4022 * The new device has a different optimal sector size.
4023 */
4024 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4025 "new device has a different optimal sector size; use the "
4026 "option '-o ashift=N' to override the optimal size"));
4027 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
4028 break;
4029
4030 case ENAMETOOLONG:
4031 /*
4032 * The resulting top-level vdev spec won't fit in the label.
4033 */
4034 (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf);
4035 break;
4036
4037 case ENXIO:
4038 /*
4039 * The existing raidz vdev has offline children
4040 */
4041 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
4042 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4043 "raidz vdev has devices that are are offline or "
4044 "being replaced"));
4045 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
4046 break;
4047 } else {
4048 (void) zpool_standard_error(hdl, errno, errbuf);
4049 }
4050 break;
4051
4052 case EADDRINUSE:
4053 /*
4054 * The boot reserved area is already being used (FreeBSD)
4055 */
4056 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
4057 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4058 "the reserved boot area needed for the expansion "
4059 "is already being used by a boot loader"));
4060 (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
4061 } else {
4062 (void) zpool_standard_error(hdl, errno, errbuf);
4063 }
4064 break;
4065
4066 case ZFS_ERR_ASHIFT_MISMATCH:
4067 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4068 "The new device cannot have a higher alignment requirement "
4069 "than the top-level vdev."));
4070 (void) zfs_error(hdl, EZFS_BADTARGET, errbuf);
4071 break;
4072 default:
4073 (void) zpool_standard_error(hdl, errno, errbuf);
4074 }
4075
4076 return (-1);
4077 }
4078
4079 /*
4080 * Detach the specified device.
4081 */
4082 int
zpool_vdev_detach(zpool_handle_t * zhp,const char * path)4083 zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
4084 {
4085 zfs_cmd_t zc = {"\0"};
4086 char errbuf[ERRBUFLEN];
4087 nvlist_t *tgt;
4088 boolean_t avail_spare, l2cache;
4089 libzfs_handle_t *hdl = zhp->zpool_hdl;
4090
4091 (void) snprintf(errbuf, sizeof (errbuf),
4092 dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
4093
4094 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4095 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
4096 NULL)) == NULL)
4097 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
4098
4099 if (avail_spare)
4100 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
4101
4102 if (l2cache)
4103 return (zfs_error(hdl, EZFS_ISL2CACHE, errbuf));
4104
4105 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
4106
4107 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0)
4108 return (0);
4109
4110 switch (errno) {
4111
4112 case ENOTSUP:
4113 /*
4114 * Can't detach from this type of vdev.
4115 */
4116 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
4117 "applicable to mirror and replacing vdevs"));
4118 (void) zfs_error(hdl, EZFS_BADTARGET, errbuf);
4119 break;
4120
4121 case EBUSY:
4122 /*
4123 * There are no other replicas of this device.
4124 */
4125 (void) zfs_error(hdl, EZFS_NOREPLICAS, errbuf);
4126 break;
4127
4128 default:
4129 (void) zpool_standard_error(hdl, errno, errbuf);
4130 }
4131
4132 return (-1);
4133 }
4134
4135 /*
4136 * Find a mirror vdev in the source nvlist.
4137 *
4138 * The mchild array contains a list of disks in one of the top-level mirrors
4139 * of the source pool. The schild array contains a list of disks that the
4140 * user specified on the command line. We loop over the mchild array to
4141 * see if any entry in the schild array matches.
4142 *
4143 * If a disk in the mchild array is found in the schild array, we return
4144 * the index of that entry. Otherwise we return -1.
4145 */
4146 static int
find_vdev_entry(zpool_handle_t * zhp,nvlist_t ** mchild,uint_t mchildren,nvlist_t ** schild,uint_t schildren)4147 find_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren,
4148 nvlist_t **schild, uint_t schildren)
4149 {
4150 uint_t mc;
4151
4152 for (mc = 0; mc < mchildren; mc++) {
4153 uint_t sc;
4154 char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp,
4155 mchild[mc], 0);
4156
4157 for (sc = 0; sc < schildren; sc++) {
4158 char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp,
4159 schild[sc], 0);
4160 boolean_t result = (strcmp(mpath, spath) == 0);
4161
4162 free(spath);
4163 if (result) {
4164 free(mpath);
4165 return (mc);
4166 }
4167 }
4168
4169 free(mpath);
4170 }
4171
4172 return (-1);
4173 }
4174
4175 /*
4176 * Split a mirror pool. If newroot points to null, then a new nvlist
4177 * is generated and it is the responsibility of the caller to free it.
4178 */
4179 int
zpool_vdev_split(zpool_handle_t * zhp,char * newname,nvlist_t ** newroot,nvlist_t * props,splitflags_t flags)4180 zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot,
4181 nvlist_t *props, splitflags_t flags)
4182 {
4183 zfs_cmd_t zc = {"\0"};
4184 char errbuf[ERRBUFLEN];
4185 const char *bias;
4186 nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL;
4187 nvlist_t **varray = NULL, *zc_props = NULL;
4188 uint_t c, children, newchildren, lastlog = 0, vcount, found = 0;
4189 libzfs_handle_t *hdl = zhp->zpool_hdl;
4190 uint64_t vers, readonly = B_FALSE;
4191 boolean_t freelist = B_FALSE, memory_err = B_TRUE;
4192 int retval = 0;
4193
4194 (void) snprintf(errbuf, sizeof (errbuf),
4195 dgettext(TEXT_DOMAIN, "Unable to split %s"), zhp->zpool_name);
4196
4197 if (!zpool_name_valid(hdl, B_FALSE, newname))
4198 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4199
4200 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
4201 (void) fprintf(stderr, gettext("Internal error: unable to "
4202 "retrieve pool configuration\n"));
4203 return (-1);
4204 }
4205
4206 tree = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4207 vers = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
4208
4209 if (props) {
4210 prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
4211 if ((zc_props = zpool_valid_proplist(hdl, zhp->zpool_name,
4212 props, vers, flags, errbuf)) == NULL)
4213 return (-1);
4214 (void) nvlist_lookup_uint64(zc_props,
4215 zpool_prop_to_name(ZPOOL_PROP_READONLY), &readonly);
4216 if (readonly) {
4217 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4218 "property %s can only be set at import time"),
4219 zpool_prop_to_name(ZPOOL_PROP_READONLY));
4220 return (-1);
4221 }
4222 }
4223
4224 if (nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child,
4225 &children) != 0) {
4226 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4227 "Source pool is missing vdev tree"));
4228 nvlist_free(zc_props);
4229 return (-1);
4230 }
4231
4232 varray = zfs_alloc(hdl, children * sizeof (nvlist_t *));
4233 vcount = 0;
4234
4235 if (*newroot == NULL ||
4236 nvlist_lookup_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN,
4237 &newchild, &newchildren) != 0)
4238 newchildren = 0;
4239
4240 for (c = 0; c < children; c++) {
4241 uint64_t is_log = B_FALSE, is_hole = B_FALSE;
4242 boolean_t is_special = B_FALSE, is_dedup = B_FALSE;
4243 const char *type;
4244 nvlist_t **mchild, *vdev;
4245 uint_t mchildren;
4246 int entry;
4247
4248 /*
4249 * Unlike cache & spares, slogs are stored in the
4250 * ZPOOL_CONFIG_CHILDREN array. We filter them out here.
4251 */
4252 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
4253 &is_log);
4254 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
4255 &is_hole);
4256 if (is_log || is_hole) {
4257 /*
4258 * Create a hole vdev and put it in the config.
4259 */
4260 if (nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) != 0)
4261 goto out;
4262 if (nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE,
4263 VDEV_TYPE_HOLE) != 0)
4264 goto out;
4265 if (nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_HOLE,
4266 1) != 0)
4267 goto out;
4268 if (lastlog == 0)
4269 lastlog = vcount;
4270 varray[vcount++] = vdev;
4271 continue;
4272 }
4273 lastlog = 0;
4274 type = fnvlist_lookup_string(child[c], ZPOOL_CONFIG_TYPE);
4275
4276 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) {
4277 vdev = child[c];
4278 if (nvlist_dup(vdev, &varray[vcount++], 0) != 0)
4279 goto out;
4280 continue;
4281 } else if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
4282 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4283 "Source pool must be composed only of mirrors\n"));
4284 retval = zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
4285 goto out;
4286 }
4287
4288 if (nvlist_lookup_string(child[c],
4289 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias) == 0) {
4290 if (strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0)
4291 is_special = B_TRUE;
4292 else if (strcmp(bias, VDEV_ALLOC_BIAS_DEDUP) == 0)
4293 is_dedup = B_TRUE;
4294 }
4295 verify(nvlist_lookup_nvlist_array(child[c],
4296 ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0);
4297
4298 /* find or add an entry for this top-level vdev */
4299 if (newchildren > 0 &&
4300 (entry = find_vdev_entry(zhp, mchild, mchildren,
4301 newchild, newchildren)) >= 0) {
4302 /* We found a disk that the user specified. */
4303 vdev = mchild[entry];
4304 ++found;
4305 } else {
4306 /* User didn't specify a disk for this vdev. */
4307 vdev = mchild[mchildren - 1];
4308 }
4309
4310 if (nvlist_dup(vdev, &varray[vcount++], 0) != 0)
4311 goto out;
4312
4313 if (flags.dryrun != 0) {
4314 if (is_dedup == B_TRUE) {
4315 if (nvlist_add_string(varray[vcount - 1],
4316 ZPOOL_CONFIG_ALLOCATION_BIAS,
4317 VDEV_ALLOC_BIAS_DEDUP) != 0)
4318 goto out;
4319 } else if (is_special == B_TRUE) {
4320 if (nvlist_add_string(varray[vcount - 1],
4321 ZPOOL_CONFIG_ALLOCATION_BIAS,
4322 VDEV_ALLOC_BIAS_SPECIAL) != 0)
4323 goto out;
4324 }
4325 }
4326 }
4327
4328 /* did we find every disk the user specified? */
4329 if (found != newchildren) {
4330 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Device list must "
4331 "include at most one disk from each mirror"));
4332 retval = zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
4333 goto out;
4334 }
4335
4336 /* Prepare the nvlist for populating. */
4337 if (*newroot == NULL) {
4338 if (nvlist_alloc(newroot, NV_UNIQUE_NAME, 0) != 0)
4339 goto out;
4340 freelist = B_TRUE;
4341 if (nvlist_add_string(*newroot, ZPOOL_CONFIG_TYPE,
4342 VDEV_TYPE_ROOT) != 0)
4343 goto out;
4344 } else {
4345 verify(nvlist_remove_all(*newroot, ZPOOL_CONFIG_CHILDREN) == 0);
4346 }
4347
4348 /* Add all the children we found */
4349 if (nvlist_add_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN,
4350 (const nvlist_t **)varray, lastlog == 0 ? vcount : lastlog) != 0)
4351 goto out;
4352
4353 /*
4354 * If we're just doing a dry run, exit now with success.
4355 */
4356 if (flags.dryrun) {
4357 memory_err = B_FALSE;
4358 freelist = B_FALSE;
4359 goto out;
4360 }
4361
4362 /* now build up the config list & call the ioctl */
4363 if (nvlist_alloc(&newconfig, NV_UNIQUE_NAME, 0) != 0)
4364 goto out;
4365
4366 if (nvlist_add_nvlist(newconfig,
4367 ZPOOL_CONFIG_VDEV_TREE, *newroot) != 0 ||
4368 nvlist_add_string(newconfig,
4369 ZPOOL_CONFIG_POOL_NAME, newname) != 0 ||
4370 nvlist_add_uint64(newconfig, ZPOOL_CONFIG_VERSION, vers) != 0)
4371 goto out;
4372
4373 /*
4374 * The new pool is automatically part of the namespace unless we
4375 * explicitly export it.
4376 */
4377 if (!flags.import)
4378 zc.zc_cookie = ZPOOL_EXPORT_AFTER_SPLIT;
4379 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4380 (void) strlcpy(zc.zc_string, newname, sizeof (zc.zc_string));
4381 zcmd_write_conf_nvlist(hdl, &zc, newconfig);
4382 if (zc_props != NULL)
4383 zcmd_write_src_nvlist(hdl, &zc, zc_props);
4384
4385 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SPLIT, &zc) != 0) {
4386 retval = zpool_standard_error(hdl, errno, errbuf);
4387 goto out;
4388 }
4389
4390 freelist = B_FALSE;
4391 memory_err = B_FALSE;
4392
4393 out:
4394 if (varray != NULL) {
4395 int v;
4396
4397 for (v = 0; v < vcount; v++)
4398 nvlist_free(varray[v]);
4399 free(varray);
4400 }
4401 zcmd_free_nvlists(&zc);
4402 nvlist_free(zc_props);
4403 nvlist_free(newconfig);
4404 if (freelist) {
4405 nvlist_free(*newroot);
4406 *newroot = NULL;
4407 }
4408
4409 if (retval != 0)
4410 return (retval);
4411
4412 if (memory_err)
4413 return (no_memory(hdl));
4414
4415 return (0);
4416 }
4417
4418 /*
4419 * Remove the given device.
4420 */
4421 int
zpool_vdev_remove(zpool_handle_t * zhp,const char * path)4422 zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
4423 {
4424 zfs_cmd_t zc = {"\0"};
4425 char errbuf[ERRBUFLEN];
4426 nvlist_t *tgt;
4427 boolean_t avail_spare, l2cache, islog;
4428 libzfs_handle_t *hdl = zhp->zpool_hdl;
4429 uint64_t version;
4430
4431 (void) snprintf(errbuf, sizeof (errbuf),
4432 dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
4433
4434 if (zpool_is_draid_spare(path)) {
4435 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4436 "dRAID spares cannot be removed"));
4437 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
4438 }
4439
4440 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4441 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
4442 &islog)) == NULL)
4443 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
4444
4445 version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
4446 if (islog && version < SPA_VERSION_HOLES) {
4447 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4448 "pool must be upgraded to support log removal"));
4449 return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
4450 }
4451
4452 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
4453
4454 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
4455 return (0);
4456
4457 switch (errno) {
4458
4459 case EALREADY:
4460 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4461 "removal for this vdev is already in progress."));
4462 (void) zfs_error(hdl, EZFS_BUSY, errbuf);
4463 break;
4464
4465 case EINVAL:
4466 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4467 "invalid config; all top-level vdevs must "
4468 "have the same sector size and not be raidz."));
4469 (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
4470 break;
4471
4472 case EBUSY:
4473 if (islog) {
4474 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4475 "Mount encrypted datasets to replay logs."));
4476 } else {
4477 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4478 "Pool busy; removal may already be in progress"));
4479 }
4480 (void) zfs_error(hdl, EZFS_BUSY, errbuf);
4481 break;
4482
4483 case EACCES:
4484 if (islog) {
4485 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4486 "Mount encrypted datasets to replay logs."));
4487 (void) zfs_error(hdl, EZFS_BUSY, errbuf);
4488 } else {
4489 (void) zpool_standard_error(hdl, errno, errbuf);
4490 }
4491 break;
4492
4493 default:
4494 (void) zpool_standard_error(hdl, errno, errbuf);
4495 }
4496 return (-1);
4497 }
4498
4499 int
zpool_vdev_remove_cancel(zpool_handle_t * zhp)4500 zpool_vdev_remove_cancel(zpool_handle_t *zhp)
4501 {
4502 zfs_cmd_t zc = {{0}};
4503 char errbuf[ERRBUFLEN];
4504 libzfs_handle_t *hdl = zhp->zpool_hdl;
4505
4506 (void) snprintf(errbuf, sizeof (errbuf),
4507 dgettext(TEXT_DOMAIN, "cannot cancel removal"));
4508
4509 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4510 zc.zc_cookie = 1;
4511
4512 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
4513 return (0);
4514
4515 return (zpool_standard_error(hdl, errno, errbuf));
4516 }
4517
4518 int
zpool_vdev_indirect_size(zpool_handle_t * zhp,const char * path,uint64_t * sizep)4519 zpool_vdev_indirect_size(zpool_handle_t *zhp, const char *path,
4520 uint64_t *sizep)
4521 {
4522 char errbuf[ERRBUFLEN];
4523 nvlist_t *tgt;
4524 boolean_t avail_spare, l2cache, islog;
4525 libzfs_handle_t *hdl = zhp->zpool_hdl;
4526
4527 (void) snprintf(errbuf, sizeof (errbuf),
4528 dgettext(TEXT_DOMAIN, "cannot determine indirect size of %s"),
4529 path);
4530
4531 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
4532 &islog)) == NULL)
4533 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
4534
4535 if (avail_spare || l2cache || islog) {
4536 *sizep = 0;
4537 return (0);
4538 }
4539
4540 if (nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_INDIRECT_SIZE, sizep) != 0) {
4541 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4542 "indirect size not available"));
4543 return (zfs_error(hdl, EINVAL, errbuf));
4544 }
4545 return (0);
4546 }
4547
4548 /*
4549 * Clear the errors for the pool, or the particular device if specified.
4550 */
4551 int
zpool_clear(zpool_handle_t * zhp,const char * path,nvlist_t * rewindnvl)4552 zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl)
4553 {
4554 zfs_cmd_t zc = {"\0"};
4555 char errbuf[ERRBUFLEN];
4556 nvlist_t *tgt;
4557 zpool_load_policy_t policy;
4558 boolean_t avail_spare, l2cache;
4559 libzfs_handle_t *hdl = zhp->zpool_hdl;
4560 nvlist_t *nvi = NULL;
4561 int error;
4562
4563 if (path)
4564 (void) snprintf(errbuf, sizeof (errbuf),
4565 dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
4566 path);
4567 else
4568 (void) snprintf(errbuf, sizeof (errbuf),
4569 dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
4570 zhp->zpool_name);
4571
4572 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4573 if (path) {
4574 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare,
4575 &l2cache, NULL)) == NULL)
4576 return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
4577
4578 /*
4579 * Don't allow error clearing for hot spares. Do allow
4580 * error clearing for l2cache devices.
4581 */
4582 if (avail_spare)
4583 return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
4584
4585 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
4586 }
4587
4588 zpool_get_load_policy(rewindnvl, &policy);
4589 zc.zc_cookie = policy.zlp_rewind;
4590
4591 zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size * 2);
4592 if (rewindnvl != NULL)
4593 zcmd_write_src_nvlist(hdl, &zc, rewindnvl);
4594
4595 while ((error = zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc)) != 0 &&
4596 errno == ENOMEM)
4597 zcmd_expand_dst_nvlist(hdl, &zc);
4598
4599 if (!error || ((policy.zlp_rewind & ZPOOL_TRY_REWIND) &&
4600 errno != EPERM && errno != EACCES)) {
4601 if (policy.zlp_rewind &
4602 (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
4603 (void) zcmd_read_dst_nvlist(hdl, &zc, &nvi);
4604 zpool_rewind_exclaim(hdl, zc.zc_name, nvi);
4605 nvlist_free(nvi);
4606 }
4607 zcmd_free_nvlists(&zc);
4608 return (0);
4609 }
4610
4611 zcmd_free_nvlists(&zc);
4612 return (zpool_standard_error(hdl, errno, errbuf));
4613 }
4614
4615 /*
4616 * Similar to zpool_clear(), but takes a GUID (used by fmd).
4617 */
4618 int
zpool_vdev_clear(zpool_handle_t * zhp,uint64_t guid)4619 zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
4620 {
4621 zfs_cmd_t zc = {"\0"};
4622 char errbuf[ERRBUFLEN];
4623 libzfs_handle_t *hdl = zhp->zpool_hdl;
4624
4625 (void) snprintf(errbuf, sizeof (errbuf),
4626 dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
4627 (u_longlong_t)guid);
4628
4629 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4630 zc.zc_guid = guid;
4631 zc.zc_cookie = ZPOOL_NO_REWIND;
4632
4633 if (zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc) == 0)
4634 return (0);
4635
4636 return (zpool_standard_error(hdl, errno, errbuf));
4637 }
4638
4639 /*
4640 * Change the GUID for a pool.
4641 *
4642 * Similar to zpool_reguid(), but may take a GUID.
4643 *
4644 * If the guid argument is NULL, then no GUID is passed in the nvlist to the
4645 * ioctl().
4646 */
4647 int
zpool_set_guid(zpool_handle_t * zhp,const uint64_t * guid)4648 zpool_set_guid(zpool_handle_t *zhp, const uint64_t *guid)
4649 {
4650 char errbuf[ERRBUFLEN];
4651 libzfs_handle_t *hdl = zhp->zpool_hdl;
4652 nvlist_t *nvl = NULL;
4653 zfs_cmd_t zc = {"\0"};
4654 int error;
4655
4656 if (guid != NULL) {
4657 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
4658 return (no_memory(hdl));
4659
4660 if (nvlist_add_uint64(nvl, ZPOOL_REGUID_GUID, *guid) != 0) {
4661 nvlist_free(nvl);
4662 return (no_memory(hdl));
4663 }
4664
4665 zcmd_write_src_nvlist(hdl, &zc, nvl);
4666 }
4667
4668 (void) snprintf(errbuf, sizeof (errbuf),
4669 dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name);
4670
4671 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4672 error = zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc);
4673 if (error) {
4674 return (zpool_standard_error(hdl, errno, errbuf));
4675 }
4676 if (guid != NULL) {
4677 zcmd_free_nvlists(&zc);
4678 nvlist_free(nvl);
4679 }
4680 return (0);
4681 }
4682
4683 /*
4684 * Change the GUID for a pool.
4685 */
4686 int
zpool_reguid(zpool_handle_t * zhp)4687 zpool_reguid(zpool_handle_t *zhp)
4688 {
4689 return (zpool_set_guid(zhp, NULL));
4690 }
4691
4692 /*
4693 * Reopen the pool.
4694 */
4695 int
zpool_reopen_one(zpool_handle_t * zhp,void * data)4696 zpool_reopen_one(zpool_handle_t *zhp, void *data)
4697 {
4698 libzfs_handle_t *hdl = zpool_get_handle(zhp);
4699 const char *pool_name = zpool_get_name(zhp);
4700 boolean_t *scrub_restart = data;
4701 int error;
4702
4703 error = lzc_reopen(pool_name, *scrub_restart);
4704 if (error) {
4705 return (zpool_standard_error_fmt(hdl, error,
4706 dgettext(TEXT_DOMAIN, "cannot reopen '%s'"), pool_name));
4707 }
4708
4709 return (0);
4710 }
4711
4712 /*
4713 * Block until every buffered write for the pool has reached the
4714 * underlying disks.
4715 */
4716 int
zpool_sync_one(zpool_handle_t * zhp,void * data)4717 zpool_sync_one(zpool_handle_t *zhp, void *data)
4718 {
4719 int ret;
4720 libzfs_handle_t *hdl = zpool_get_handle(zhp);
4721 const char *pool_name = zpool_get_name(zhp);
4722 boolean_t *force = data;
4723 nvlist_t *innvl = fnvlist_alloc();
4724
4725 fnvlist_add_boolean_value(innvl, "force", *force);
4726 if ((ret = lzc_sync(pool_name, innvl, NULL)) != 0) {
4727 nvlist_free(innvl);
4728 return (zpool_standard_error_fmt(hdl, ret,
4729 dgettext(TEXT_DOMAIN, "sync '%s' failed"), pool_name));
4730 }
4731 nvlist_free(innvl);
4732
4733 return (0);
4734 }
4735
4736 int
zpool_condense(zpool_handle_t * zhp,const char * cmd,const char * type)4737 zpool_condense(zpool_handle_t *zhp, const char *cmd, const char *type)
4738 {
4739 int ret;
4740
4741 libzfs_handle_t *hdl = zpool_get_handle(zhp);
4742 const char *pool_name = zpool_get_name(zhp);
4743
4744 if ((ret = lzc_condense(pool_name, cmd, type)) != 0) {
4745 return (zpool_standard_error_fmt(hdl, ret,
4746 dgettext(TEXT_DOMAIN, "condense '%s' failed"), pool_name));
4747 }
4748
4749 return (0);
4750 }
4751
4752 #define PATH_BUF_LEN 64
4753
4754 /*
4755 * Given a vdev, return the name to display in iostat. If the vdev has a path,
4756 * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
4757 * We also check if this is a whole disk, in which case we strip off the
4758 * trailing 's0' slice name.
4759 *
4760 * This routine is also responsible for identifying when disks have been
4761 * reconfigured in a new location. The kernel will have opened the device by
4762 * devid, but the path will still refer to the old location. To catch this, we
4763 * first do a path -> devid translation (which is fast for the common case). If
4764 * the devid matches, we're done. If not, we do a reverse devid -> path
4765 * translation and issue the appropriate ioctl() to update the path of the vdev.
4766 * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
4767 * of these checks.
4768 */
4769 char *
zpool_vdev_name(libzfs_handle_t * hdl,zpool_handle_t * zhp,nvlist_t * nv,int name_flags)4770 zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
4771 int name_flags)
4772 {
4773 const char *type, *tpath;
4774 const char *path;
4775 uint64_t value;
4776 char buf[PATH_BUF_LEN];
4777 char tmpbuf[PATH_BUF_LEN * 2];
4778 char rpath[MAXPATHLEN];
4779
4780 /*
4781 * vdev_name will be "root"/"root-0" for the root vdev, but it is the
4782 * zpool name that will be displayed to the user.
4783 */
4784 type = fnvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE);
4785 if (zhp != NULL && strcmp(type, "root") == 0)
4786 return (zfs_strdup(hdl, zpool_get_name(zhp)));
4787
4788 if (libzfs_envvar_is_set("ZPOOL_VDEV_NAME_PATH"))
4789 name_flags |= VDEV_NAME_PATH;
4790 if (libzfs_envvar_is_set("ZPOOL_VDEV_NAME_GUID"))
4791 name_flags |= VDEV_NAME_GUID;
4792 if (libzfs_envvar_is_set("ZPOOL_VDEV_NAME_FOLLOW_LINKS"))
4793 name_flags |= VDEV_NAME_FOLLOW_LINKS;
4794
4795 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &value) == 0 ||
4796 name_flags & VDEV_NAME_GUID) {
4797 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value);
4798 (void) snprintf(buf, sizeof (buf), "%llu", (u_longlong_t)value);
4799 path = buf;
4800 } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &tpath) == 0) {
4801 path = tpath;
4802
4803 if (name_flags & VDEV_NAME_FOLLOW_LINKS) {
4804 if (realpath(path, rpath) != NULL)
4805 path = rpath;
4806 }
4807
4808 /*
4809 * For a block device only use the name.
4810 */
4811 if ((strcmp(type, VDEV_TYPE_DISK) == 0) &&
4812 !(name_flags & VDEV_NAME_PATH)) {
4813 path = zfs_strip_path(path);
4814 }
4815
4816 /*
4817 * Remove the partition from the path if this is a whole disk.
4818 */
4819 if (strcmp(type, VDEV_TYPE_DRAID_SPARE) != 0 &&
4820 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, &value)
4821 == 0 && value && !(name_flags & VDEV_NAME_PATH)) {
4822 return (zfs_strip_partition(path));
4823 }
4824 } else {
4825 path = type;
4826
4827 /*
4828 * If it's a raidz device, we need to stick in the parity level.
4829 */
4830 if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
4831 value = fnvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY);
4832 (void) snprintf(buf, sizeof (buf), "%s%llu", path,
4833 (u_longlong_t)value);
4834 path = buf;
4835 }
4836
4837 /*
4838 * If it's a dRAID device, we add parity, groups, and spares.
4839 */
4840 if (strcmp(path, VDEV_TYPE_DRAID) == 0) {
4841 uint64_t ndata, nparity, nspares, children;
4842 nvlist_t **child;
4843 uint_t width;
4844
4845 verify(nvlist_lookup_nvlist_array(nv,
4846 ZPOOL_CONFIG_CHILDREN, &child, &width) == 0);
4847 nparity = fnvlist_lookup_uint64(nv,
4848 ZPOOL_CONFIG_NPARITY);
4849 ndata = fnvlist_lookup_uint64(nv,
4850 ZPOOL_CONFIG_DRAID_NDATA);
4851 nspares = fnvlist_lookup_uint64(nv,
4852 ZPOOL_CONFIG_DRAID_NSPARES);
4853
4854 if (nvlist_lookup_uint64(nv,
4855 ZPOOL_CONFIG_DRAID_NCHILDREN, &children) != 0)
4856 children = width;
4857
4858 path = zpool_draid_name(buf, sizeof (buf), ndata,
4859 nparity, nspares, children, width);
4860 }
4861
4862 /*
4863 * We identify each top-level vdev by using a <type-id>
4864 * naming convention.
4865 */
4866 if (name_flags & VDEV_NAME_TYPE_ID) {
4867 uint64_t id = fnvlist_lookup_uint64(nv,
4868 ZPOOL_CONFIG_ID);
4869 (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s-%llu",
4870 path, (u_longlong_t)id);
4871 path = tmpbuf;
4872 }
4873 }
4874
4875 return (zfs_strdup(hdl, path));
4876 }
4877
4878 static int
zbookmark_mem_compare(const void * a,const void * b)4879 zbookmark_mem_compare(const void *a, const void *b)
4880 {
4881 return (memcmp(a, b, sizeof (zbookmark_phys_t)));
4882 }
4883
4884 void
zpool_add_propname(zpool_handle_t * zhp,const char * propname)4885 zpool_add_propname(zpool_handle_t *zhp, const char *propname)
4886 {
4887 assert(zhp->zpool_n_propnames < ZHP_MAX_PROPNAMES);
4888 zhp->zpool_propnames[zhp->zpool_n_propnames] = propname;
4889 zhp->zpool_n_propnames++;
4890 }
4891
4892 /*
4893 * Retrieve the persistent error log, uniquify the members, and return to the
4894 * caller.
4895 */
4896 int
zpool_get_errlog(zpool_handle_t * zhp,nvlist_t ** nverrlistp)4897 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
4898 {
4899 zfs_cmd_t zc = {"\0"};
4900 libzfs_handle_t *hdl = zhp->zpool_hdl;
4901 zbookmark_phys_t *buf;
4902 uint64_t buflen = 10000; /* approx. 1MB of RAM */
4903
4904 if (fnvlist_lookup_uint64(zhp->zpool_config,
4905 ZPOOL_CONFIG_ERRCOUNT) == 0)
4906 return (0);
4907
4908 /*
4909 * Retrieve the raw error list from the kernel. If it doesn't fit,
4910 * allocate a larger buffer and retry.
4911 */
4912 (void) strcpy(zc.zc_name, zhp->zpool_name);
4913 for (;;) {
4914 buf = zfs_alloc(zhp->zpool_hdl,
4915 buflen * sizeof (zbookmark_phys_t));
4916 zc.zc_nvlist_dst = (uintptr_t)buf;
4917 zc.zc_nvlist_dst_size = buflen;
4918 if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_ERROR_LOG,
4919 &zc) != 0) {
4920 free(buf);
4921 if (errno == ENOMEM) {
4922 buflen *= 2;
4923 } else {
4924 return (zpool_standard_error_fmt(hdl, errno,
4925 dgettext(TEXT_DOMAIN, "errors: List of "
4926 "errors unavailable")));
4927 }
4928 } else {
4929 break;
4930 }
4931 }
4932
4933 /*
4934 * Sort the resulting bookmarks. This is a little confusing due to the
4935 * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last
4936 * to first, and 'zc_nvlist_dst_size' indicates the number of bookmarks
4937 * _not_ copied as part of the process. So we point the start of our
4938 * array appropriate and decrement the total number of elements.
4939 */
4940 zbookmark_phys_t *zb = buf + zc.zc_nvlist_dst_size;
4941 uint64_t zblen = buflen - zc.zc_nvlist_dst_size;
4942
4943 qsort(zb, zblen, sizeof (zbookmark_phys_t), zbookmark_mem_compare);
4944
4945 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
4946
4947 /*
4948 * Fill in the nverrlistp with nvlist's of dataset and object numbers.
4949 */
4950 for (uint64_t i = 0; i < zblen; i++) {
4951 nvlist_t *nv;
4952
4953 /* ignoring zb_blkid and zb_level for now */
4954 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset &&
4955 zb[i-1].zb_object == zb[i].zb_object)
4956 continue;
4957
4958 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0)
4959 goto nomem;
4960 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET,
4961 zb[i].zb_objset) != 0) {
4962 nvlist_free(nv);
4963 goto nomem;
4964 }
4965 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT,
4966 zb[i].zb_object) != 0) {
4967 nvlist_free(nv);
4968 goto nomem;
4969 }
4970 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) {
4971 nvlist_free(nv);
4972 goto nomem;
4973 }
4974 nvlist_free(nv);
4975 }
4976
4977 free(buf);
4978 return (0);
4979
4980 nomem:
4981 free(buf);
4982 return (no_memory(zhp->zpool_hdl));
4983 }
4984
4985 /*
4986 * Upgrade a ZFS pool to the latest on-disk version.
4987 */
4988 int
zpool_upgrade(zpool_handle_t * zhp,uint64_t new_version)4989 zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
4990 {
4991 zfs_cmd_t zc = {"\0"};
4992 libzfs_handle_t *hdl = zhp->zpool_hdl;
4993
4994 (void) strcpy(zc.zc_name, zhp->zpool_name);
4995 zc.zc_cookie = new_version;
4996
4997 if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
4998 return (zpool_standard_error_fmt(hdl, errno,
4999 dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
5000 zhp->zpool_name));
5001 return (0);
5002 }
5003
5004 /*
5005 * Format the program name and its command-line arguments into a single
5006 * space-separated string.
5007 */
5008 void
zfs_save_arguments(int argc,char ** argv,char * string,int len)5009 zfs_save_arguments(int argc, char **argv, char *string, int len)
5010 {
5011 int i;
5012
5013 (void) strlcpy(string, zfs_basename(argv[0]), len);
5014 for (i = 1; i < argc; i++) {
5015 (void) strlcat(string, " ", len);
5016 (void) strlcat(string, argv[i], len);
5017 }
5018 }
5019
5020 /*
5021 * Append a message to the pool's command-history log, retrievable via
5022 * "zpool history".
5023 */
5024 int
zpool_log_history(libzfs_handle_t * hdl,const char * message)5025 zpool_log_history(libzfs_handle_t *hdl, const char *message)
5026 {
5027 zfs_cmd_t zc = {"\0"};
5028 nvlist_t *args;
5029
5030 args = fnvlist_alloc();
5031 fnvlist_add_string(args, "message", message);
5032 zcmd_write_src_nvlist(hdl, &zc, args);
5033 int err = zfs_ioctl(hdl, ZFS_IOC_LOG_HISTORY, &zc);
5034 nvlist_free(args);
5035 zcmd_free_nvlists(&zc);
5036 return (err);
5037 }
5038
5039 /*
5040 * Perform ioctl to get some command history of a pool.
5041 *
5042 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the
5043 * logical offset of the history buffer to start reading from.
5044 *
5045 * Upon return, 'off' is the next logical offset to read from and
5046 * 'len' is the actual amount of bytes read into 'buf'.
5047 */
5048 static int
get_history(zpool_handle_t * zhp,char * buf,uint64_t * off,uint64_t * len)5049 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
5050 {
5051 zfs_cmd_t zc = {"\0"};
5052 libzfs_handle_t *hdl = zhp->zpool_hdl;
5053
5054 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
5055
5056 zc.zc_history = (uint64_t)(uintptr_t)buf;
5057 zc.zc_history_len = *len;
5058 zc.zc_history_offset = *off;
5059
5060 if (zfs_ioctl(hdl, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) {
5061 switch (errno) {
5062 case EPERM:
5063 return (zfs_error_fmt(hdl, EZFS_PERM,
5064 dgettext(TEXT_DOMAIN,
5065 "cannot show history for pool '%s'"),
5066 zhp->zpool_name));
5067 case ENOENT:
5068 return (zfs_error_fmt(hdl, EZFS_NOHISTORY,
5069 dgettext(TEXT_DOMAIN, "cannot get history for pool "
5070 "'%s'"), zhp->zpool_name));
5071 case ENOTSUP:
5072 return (zfs_error_fmt(hdl, EZFS_BADVERSION,
5073 dgettext(TEXT_DOMAIN, "cannot get history for pool "
5074 "'%s', pool must be upgraded"), zhp->zpool_name));
5075 default:
5076 return (zpool_standard_error_fmt(hdl, errno,
5077 dgettext(TEXT_DOMAIN,
5078 "cannot get history for '%s'"), zhp->zpool_name));
5079 }
5080 }
5081
5082 *len = zc.zc_history_len;
5083 *off = zc.zc_history_offset;
5084
5085 return (0);
5086 }
5087
5088 /*
5089 * Retrieve the command history of a pool.
5090 */
5091 int
zpool_get_history(zpool_handle_t * zhp,nvlist_t ** nvhisp,uint64_t * off,boolean_t * eof)5092 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off,
5093 boolean_t *eof)
5094 {
5095 libzfs_handle_t *hdl = zhp->zpool_hdl;
5096 char *buf;
5097 int buflen = 128 * 1024;
5098 nvlist_t **records = NULL;
5099 uint_t numrecords = 0;
5100 int err = 0, i;
5101 uint64_t start = *off;
5102
5103 buf = zfs_alloc(hdl, buflen);
5104
5105 /* process about 1MiB a time */
5106 while (*off - start < 1024 * 1024) {
5107 uint64_t bytes_read = buflen;
5108 uint64_t leftover;
5109
5110 if ((err = get_history(zhp, buf, off, &bytes_read)) != 0)
5111 break;
5112
5113 /* if nothing else was read in, we're at EOF, just return */
5114 if (!bytes_read) {
5115 *eof = B_TRUE;
5116 break;
5117 }
5118
5119 if ((err = zpool_history_unpack(buf, bytes_read,
5120 &leftover, &records, &numrecords)) != 0) {
5121 zpool_standard_error_fmt(hdl, err,
5122 dgettext(TEXT_DOMAIN,
5123 "cannot get history for '%s'"), zhp->zpool_name);
5124 break;
5125 }
5126 *off -= leftover;
5127 if (leftover == bytes_read) {
5128 /*
5129 * no progress made, because buffer is not big enough
5130 * to hold this record; resize and retry.
5131 */
5132 buflen *= 2;
5133 free(buf);
5134 buf = zfs_alloc(hdl, buflen);
5135 }
5136 }
5137
5138 free(buf);
5139
5140 if (!err) {
5141 *nvhisp = fnvlist_alloc();
5142 fnvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
5143 (const nvlist_t **)records, numrecords);
5144 }
5145 for (i = 0; i < numrecords; i++)
5146 nvlist_free(records[i]);
5147 free(records);
5148
5149 return (err);
5150 }
5151
5152 /*
5153 * Retrieve the next event given the passed 'zevent_fd' file descriptor.
5154 * If there is a new event available 'nvp' will contain a newly allocated
5155 * nvlist and 'dropped' will be set to the number of missed events since
5156 * the last call to this function. When 'nvp' is set to NULL it indicates
5157 * no new events are available. In either case the function returns 0 and
5158 * it is up to the caller to free 'nvp'. In the case of a fatal error the
5159 * function will return a non-zero value. When the function is called in
5160 * blocking mode (the default, unless the ZEVENT_NONBLOCK flag is passed),
5161 * it will not return until a new event is available.
5162 */
5163 int
zpool_events_next(libzfs_handle_t * hdl,nvlist_t ** nvp,int * dropped,unsigned flags,int zevent_fd)5164 zpool_events_next(libzfs_handle_t *hdl, nvlist_t **nvp,
5165 int *dropped, unsigned flags, int zevent_fd)
5166 {
5167 zfs_cmd_t zc = {"\0"};
5168 int error = 0;
5169
5170 *nvp = NULL;
5171 *dropped = 0;
5172 zc.zc_cleanup_fd = zevent_fd;
5173
5174 if (flags & ZEVENT_NONBLOCK)
5175 zc.zc_guid = ZEVENT_NONBLOCK;
5176
5177 zcmd_alloc_dst_nvlist(hdl, &zc, ZEVENT_SIZE);
5178
5179 retry:
5180 if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_NEXT, &zc) != 0) {
5181 switch (errno) {
5182 case ESHUTDOWN:
5183 error = zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
5184 dgettext(TEXT_DOMAIN, "zfs shutdown"));
5185 goto out;
5186 case ENOENT:
5187 /* Blocking error case should not occur */
5188 if (!(flags & ZEVENT_NONBLOCK))
5189 error = zpool_standard_error_fmt(hdl, errno,
5190 dgettext(TEXT_DOMAIN, "cannot get event"));
5191
5192 goto out;
5193 case ENOMEM:
5194 zcmd_expand_dst_nvlist(hdl, &zc);
5195 goto retry;
5196 default:
5197 error = zpool_standard_error_fmt(hdl, errno,
5198 dgettext(TEXT_DOMAIN, "cannot get event"));
5199 goto out;
5200 }
5201 }
5202
5203 error = zcmd_read_dst_nvlist(hdl, &zc, nvp);
5204 if (error != 0)
5205 goto out;
5206
5207 *dropped = (int)zc.zc_cookie;
5208 out:
5209 zcmd_free_nvlists(&zc);
5210
5211 return (error);
5212 }
5213
5214 /*
5215 * Clear all events.
5216 */
5217 int
zpool_events_clear(libzfs_handle_t * hdl,int * count)5218 zpool_events_clear(libzfs_handle_t *hdl, int *count)
5219 {
5220 zfs_cmd_t zc = {"\0"};
5221
5222 if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_CLEAR, &zc) != 0)
5223 return (zpool_standard_error(hdl, errno,
5224 dgettext(TEXT_DOMAIN, "cannot clear events")));
5225
5226 if (count != NULL)
5227 *count = (int)zc.zc_cookie; /* # of events cleared */
5228
5229 return (0);
5230 }
5231
5232 /*
5233 * Seek to a specific EID, ZEVENT_SEEK_START, or ZEVENT_SEEK_END for
5234 * the passed zevent_fd file handle. On success zero is returned,
5235 * otherwise -1 is returned and hdl->libzfs_error is set to the errno.
5236 */
5237 int
zpool_events_seek(libzfs_handle_t * hdl,uint64_t eid,int zevent_fd)5238 zpool_events_seek(libzfs_handle_t *hdl, uint64_t eid, int zevent_fd)
5239 {
5240 zfs_cmd_t zc = {"\0"};
5241 int error = 0;
5242
5243 zc.zc_guid = eid;
5244 zc.zc_cleanup_fd = zevent_fd;
5245
5246 if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_SEEK, &zc) != 0) {
5247 switch (errno) {
5248 case ENOENT:
5249 error = zfs_error_fmt(hdl, EZFS_NOENT,
5250 dgettext(TEXT_DOMAIN, "cannot get event"));
5251 break;
5252
5253 case ENOMEM:
5254 error = zfs_error_fmt(hdl, EZFS_NOMEM,
5255 dgettext(TEXT_DOMAIN, "cannot get event"));
5256 break;
5257
5258 default:
5259 error = zpool_standard_error_fmt(hdl, errno,
5260 dgettext(TEXT_DOMAIN, "cannot get event"));
5261 break;
5262 }
5263 }
5264
5265 return (error);
5266 }
5267
5268 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)5269 zpool_obj_to_path_impl(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
5270 char *pathname, size_t len, boolean_t always_unmounted)
5271 {
5272 zfs_cmd_t zc = {"\0"};
5273 boolean_t mounted = B_FALSE;
5274 char *mntpnt = NULL;
5275 char dsname[ZFS_MAX_DATASET_NAME_LEN];
5276
5277 if (dsobj == 0) {
5278 /* special case for the MOS */
5279 (void) snprintf(pathname, len, "<metadata>:<0x%llx>",
5280 (longlong_t)obj);
5281 return;
5282 }
5283
5284 /* get the dataset's name */
5285 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
5286 zc.zc_obj = dsobj;
5287 if (zfs_ioctl(zhp->zpool_hdl,
5288 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) {
5289 /* just write out a path of two object numbers */
5290 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>",
5291 (longlong_t)dsobj, (longlong_t)obj);
5292 return;
5293 }
5294 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
5295
5296 /* find out if the dataset is mounted */
5297 mounted = !always_unmounted && is_mounted(zhp->zpool_hdl, dsname,
5298 &mntpnt);
5299
5300 /* get the corrupted object's path */
5301 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
5302 zc.zc_obj = obj;
5303 if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_OBJ_TO_PATH,
5304 &zc) == 0) {
5305 if (mounted) {
5306 (void) snprintf(pathname, len, "%s%s", mntpnt,
5307 zc.zc_value);
5308 } else {
5309 (void) snprintf(pathname, len, "%s:%s",
5310 dsname, zc.zc_value);
5311 }
5312 } else {
5313 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname,
5314 (longlong_t)obj);
5315 }
5316 free(mntpnt);
5317 }
5318
5319 /*
5320 * Translate a (dataset object id, file object id) pair into a readable
5321 * path. If the dataset is mounted the result is an absolute filesystem
5322 * path; otherwise it is `dataset:path`.
5323 */
5324 void
zpool_obj_to_path(zpool_handle_t * zhp,uint64_t dsobj,uint64_t obj,char * pathname,size_t len)5325 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
5326 char *pathname, size_t len)
5327 {
5328 zpool_obj_to_path_impl(zhp, dsobj, obj, pathname, len, B_FALSE);
5329 }
5330
5331 /*
5332 * Translate a (dataset object id, file object id) pair into a
5333 * `dataset:path` string.
5334 */
5335 void
zpool_obj_to_path_ds(zpool_handle_t * zhp,uint64_t dsobj,uint64_t obj,char * pathname,size_t len)5336 zpool_obj_to_path_ds(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
5337 char *pathname, size_t len)
5338 {
5339 zpool_obj_to_path_impl(zhp, dsobj, obj, pathname, len, B_TRUE);
5340 }
5341 /*
5342 * Wait while the specified activity is in progress in the pool.
5343 */
5344 int
zpool_wait(zpool_handle_t * zhp,zpool_wait_activity_t activity)5345 zpool_wait(zpool_handle_t *zhp, zpool_wait_activity_t activity)
5346 {
5347 boolean_t missing;
5348
5349 int error = zpool_wait_status(zhp, activity, &missing, NULL);
5350
5351 if (missing) {
5352 (void) zpool_standard_error_fmt(zhp->zpool_hdl, ENOENT,
5353 dgettext(TEXT_DOMAIN, "error waiting in pool '%s'"),
5354 zhp->zpool_name);
5355 return (ENOENT);
5356 } else {
5357 return (error);
5358 }
5359 }
5360
5361 /*
5362 * Wait for the given activity and return the status of the wait (whether or not
5363 * any waiting was done) in the 'waited' parameter. Non-existent pools are
5364 * reported via the 'missing' parameter, rather than by printing an error
5365 * message. This is convenient when this function is called in a loop over a
5366 * long period of time (as it is, for example, by zpool's wait cmd). In that
5367 * scenario, a pool being exported or destroyed should be considered a normal
5368 * event, so we don't want to print an error when we find that the pool doesn't
5369 * exist.
5370 */
5371 int
zpool_wait_status(zpool_handle_t * zhp,zpool_wait_activity_t activity,boolean_t * missing,boolean_t * waited)5372 zpool_wait_status(zpool_handle_t *zhp, zpool_wait_activity_t activity,
5373 boolean_t *missing, boolean_t *waited)
5374 {
5375 int error = lzc_wait(zhp->zpool_name, activity, waited);
5376 *missing = (error == ENOENT);
5377 if (*missing)
5378 return (0);
5379
5380 if (error != 0) {
5381 (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
5382 dgettext(TEXT_DOMAIN, "error waiting in pool '%s'"),
5383 zhp->zpool_name);
5384 }
5385
5386 return (error);
5387 }
5388
5389 /*
5390 * Store a boot configuration map in the bootenv area of each leaf
5391 * vdev's labels.
5392 */
5393 int
zpool_set_bootenv(zpool_handle_t * zhp,const nvlist_t * envmap)5394 zpool_set_bootenv(zpool_handle_t *zhp, const nvlist_t *envmap)
5395 {
5396 int error = lzc_set_bootenv(zhp->zpool_name, envmap);
5397 if (error != 0) {
5398 (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
5399 dgettext(TEXT_DOMAIN,
5400 "error setting bootenv in pool '%s'"), zhp->zpool_name);
5401 }
5402
5403 return (error);
5404 }
5405
5406 /*
5407 * Read the boot configuration map from each leaf vdev's bootenv area.
5408 */
5409 int
zpool_get_bootenv(zpool_handle_t * zhp,nvlist_t ** nvlp)5410 zpool_get_bootenv(zpool_handle_t *zhp, nvlist_t **nvlp)
5411 {
5412 nvlist_t *nvl;
5413 int error;
5414
5415 nvl = NULL;
5416 error = lzc_get_bootenv(zhp->zpool_name, &nvl);
5417 if (error != 0) {
5418 (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
5419 dgettext(TEXT_DOMAIN,
5420 "error getting bootenv in pool '%s'"), zhp->zpool_name);
5421 } else {
5422 *nvlp = nvl;
5423 }
5424
5425 return (error);
5426 }
5427
5428 /*
5429 * Attempt to read and parse feature file(s) (from "compatibility" property).
5430 * Files contain zpool feature names, comma or whitespace-separated.
5431 * Comments (# character to next newline) are discarded.
5432 *
5433 * Arguments:
5434 * compatibility : string containing feature filenames
5435 * features : either NULL or pointer to array of boolean
5436 * report : either NULL or pointer to string buffer
5437 * rlen : length of "report" buffer
5438 *
5439 * compatibility is NULL (unset), "", "off", "legacy", or list of
5440 * comma-separated filenames. filenames should either be absolute,
5441 * or relative to:
5442 * 1) ZPOOL_SYSCONF_COMPAT_D (eg: /etc/zfs/compatibility.d) or
5443 * 2) ZPOOL_DATA_COMPAT_D (eg: /usr/share/zfs/compatibility.d).
5444 * (Unset), "" or "off" => enable all features
5445 * "legacy" => disable all features
5446 *
5447 * Any feature names read from files which match unames in spa_feature_table
5448 * will have the corresponding boolean set in the features array (if non-NULL).
5449 * If more than one feature set specified, only features present in *all* of
5450 * them will be set.
5451 *
5452 * "report" if not NULL will be populated with a suitable status message.
5453 *
5454 * Return values:
5455 * ZPOOL_COMPATIBILITY_OK : files read and parsed ok
5456 * ZPOOL_COMPATIBILITY_BADFILE : file too big or not a text file
5457 * ZPOOL_COMPATIBILITY_BADTOKEN : SYSCONF file contains invalid feature name
5458 * ZPOOL_COMPATIBILITY_WARNTOKEN : DATA file contains invalid feature name
5459 * ZPOOL_COMPATIBILITY_NOFILES : no feature files found
5460 */
5461 zpool_compat_status_t
zpool_load_compat(const char * compat,boolean_t * features,char * report,size_t rlen)5462 zpool_load_compat(const char *compat, boolean_t *features, char *report,
5463 size_t rlen)
5464 {
5465 int sdirfd, ddirfd, featfd;
5466 struct stat fs;
5467 char *fc;
5468 char *ps, *ls, *ws;
5469 char *file, *line, *word;
5470
5471 char l_compat[ZFS_MAXPROPLEN];
5472
5473 boolean_t ret_nofiles = B_TRUE;
5474 boolean_t ret_badfile = B_FALSE;
5475 boolean_t ret_badtoken = B_FALSE;
5476 boolean_t ret_warntoken = B_FALSE;
5477
5478 /* special cases (unset), "" and "off" => enable all features */
5479 if (compat == NULL || compat[0] == '\0' ||
5480 strcmp(compat, ZPOOL_COMPAT_OFF) == 0) {
5481 if (features != NULL) {
5482 for (uint_t i = 0; i < SPA_FEATURES; i++)
5483 features[i] = B_TRUE;
5484 }
5485 if (report != NULL)
5486 strlcpy(report, gettext("all features enabled"), rlen);
5487 return (ZPOOL_COMPATIBILITY_OK);
5488 }
5489
5490 /* Final special case "legacy" => disable all features */
5491 if (strcmp(compat, ZPOOL_COMPAT_LEGACY) == 0) {
5492 if (features != NULL)
5493 for (uint_t i = 0; i < SPA_FEATURES; i++)
5494 features[i] = B_FALSE;
5495 if (report != NULL)
5496 strlcpy(report, gettext("all features disabled"), rlen);
5497 return (ZPOOL_COMPATIBILITY_OK);
5498 }
5499
5500 /*
5501 * Start with all true; will be ANDed with results from each file
5502 */
5503 if (features != NULL)
5504 for (uint_t i = 0; i < SPA_FEATURES; i++)
5505 features[i] = B_TRUE;
5506
5507 char err_badfile[ZFS_MAXPROPLEN] = "";
5508 char err_badtoken[ZFS_MAXPROPLEN] = "";
5509
5510 /*
5511 * We ignore errors from the directory open()
5512 * as they're only needed if the filename is relative
5513 * which will be checked during the openat().
5514 */
5515
5516 /* O_PATH safer than O_RDONLY if system allows it */
5517 #if defined(O_PATH)
5518 #define ZC_DIR_FLAGS (O_DIRECTORY | O_CLOEXEC | O_PATH)
5519 #else
5520 #define ZC_DIR_FLAGS (O_DIRECTORY | O_CLOEXEC | O_RDONLY)
5521 #endif
5522
5523 sdirfd = open(ZPOOL_SYSCONF_COMPAT_D, ZC_DIR_FLAGS);
5524 ddirfd = open(ZPOOL_DATA_COMPAT_D, ZC_DIR_FLAGS);
5525
5526 (void) strlcpy(l_compat, compat, ZFS_MAXPROPLEN);
5527
5528 for (file = strtok_r(l_compat, ",", &ps);
5529 file != NULL;
5530 file = strtok_r(NULL, ",", &ps)) {
5531
5532 boolean_t l_features[SPA_FEATURES];
5533
5534 enum { Z_SYSCONF, Z_DATA } source;
5535
5536 /* try sysconfdir first, then datadir */
5537 source = Z_SYSCONF;
5538 if ((featfd = openat(sdirfd, file, O_RDONLY | O_CLOEXEC)) < 0) {
5539 featfd = openat(ddirfd, file, O_RDONLY | O_CLOEXEC);
5540 source = Z_DATA;
5541 }
5542
5543 /* File readable and correct size? */
5544 if (featfd < 0 ||
5545 fstat(featfd, &fs) < 0 ||
5546 fs.st_size < 1 ||
5547 fs.st_size > ZPOOL_COMPAT_MAXSIZE) {
5548 (void) close(featfd);
5549 strlcat(err_badfile, file, ZFS_MAXPROPLEN);
5550 strlcat(err_badfile, " ", ZFS_MAXPROPLEN);
5551 ret_badfile = B_TRUE;
5552 continue;
5553 }
5554
5555 /* Prefault the file if system allows */
5556 #if defined(MAP_POPULATE)
5557 #define ZC_MMAP_FLAGS (MAP_PRIVATE | MAP_POPULATE)
5558 #elif defined(MAP_PREFAULT_READ)
5559 #define ZC_MMAP_FLAGS (MAP_PRIVATE | MAP_PREFAULT_READ)
5560 #else
5561 #define ZC_MMAP_FLAGS (MAP_PRIVATE)
5562 #endif
5563
5564 /* private mmap() so we can strtok safely */
5565 fc = (char *)mmap(NULL, fs.st_size, PROT_READ | PROT_WRITE,
5566 ZC_MMAP_FLAGS, featfd, 0);
5567 (void) close(featfd);
5568
5569 /* need map ok, and last character == newline */
5570 if (fc == MAP_FAILED || fc[fs.st_size - 1] != '\n') {
5571 if (fc != MAP_FAILED)
5572 (void) munmap((void *) fc, fs.st_size);
5573 strlcat(err_badfile, file, ZFS_MAXPROPLEN);
5574 strlcat(err_badfile, " ", ZFS_MAXPROPLEN);
5575 ret_badfile = B_TRUE;
5576 continue;
5577 }
5578
5579 ret_nofiles = B_FALSE;
5580
5581 for (uint_t i = 0; i < SPA_FEATURES; i++)
5582 l_features[i] = B_FALSE;
5583
5584 /* replace final newline with NULL to ensure string ends */
5585 fc[fs.st_size - 1] = '\0';
5586
5587 for (line = strtok_r(fc, "\n", &ls);
5588 line != NULL;
5589 line = strtok_r(NULL, "\n", &ls)) {
5590 /* discard comments */
5591 char *r = strchr(line, '#');
5592 if (r != NULL)
5593 *r = '\0';
5594
5595 for (word = strtok_r(line, ", \t", &ws);
5596 word != NULL;
5597 word = strtok_r(NULL, ", \t", &ws)) {
5598 /* Find matching feature name */
5599 uint_t f;
5600 for (f = 0; f < SPA_FEATURES; f++) {
5601 zfeature_info_t *fi =
5602 &spa_feature_table[f];
5603 if (strcmp(word, fi->fi_uname) == 0) {
5604 l_features[f] = B_TRUE;
5605 break;
5606 }
5607 }
5608 if (f < SPA_FEATURES)
5609 continue;
5610
5611 /* found an unrecognized word */
5612 /* lightly sanitize it */
5613 if (strlen(word) > 32)
5614 word[32] = '\0';
5615 for (char *c = word; *c != '\0'; c++)
5616 if (!isprint(*c))
5617 *c = '?';
5618
5619 strlcat(err_badtoken, word, ZFS_MAXPROPLEN);
5620 strlcat(err_badtoken, " ", ZFS_MAXPROPLEN);
5621 if (source == Z_SYSCONF)
5622 ret_badtoken = B_TRUE;
5623 else
5624 ret_warntoken = B_TRUE;
5625 }
5626 }
5627 (void) munmap((void *) fc, fs.st_size);
5628
5629 if (features != NULL)
5630 for (uint_t i = 0; i < SPA_FEATURES; i++)
5631 features[i] &= l_features[i];
5632 }
5633 (void) close(sdirfd);
5634 (void) close(ddirfd);
5635
5636 /* Return the most serious error */
5637 if (ret_badfile) {
5638 if (report != NULL)
5639 snprintf(report, rlen, gettext("could not read/"
5640 "parse feature file(s): %s"), err_badfile);
5641 return (ZPOOL_COMPATIBILITY_BADFILE);
5642 }
5643 if (ret_nofiles) {
5644 if (report != NULL)
5645 strlcpy(report,
5646 gettext("no valid compatibility files specified"),
5647 rlen);
5648 return (ZPOOL_COMPATIBILITY_NOFILES);
5649 }
5650 if (ret_badtoken) {
5651 if (report != NULL)
5652 snprintf(report, rlen, gettext("invalid feature "
5653 "name(s) in local compatibility files: %s"),
5654 err_badtoken);
5655 return (ZPOOL_COMPATIBILITY_BADTOKEN);
5656 }
5657 if (ret_warntoken) {
5658 if (report != NULL)
5659 snprintf(report, rlen, gettext("unrecognized feature "
5660 "name(s) in distribution compatibility files: %s"),
5661 err_badtoken);
5662 return (ZPOOL_COMPATIBILITY_WARNTOKEN);
5663 }
5664 if (report != NULL)
5665 strlcpy(report, gettext("compatibility set ok"), rlen);
5666 return (ZPOOL_COMPATIBILITY_OK);
5667 }
5668
5669 static int
zpool_vdev_guid(zpool_handle_t * zhp,const char * vdevname,uint64_t * vdev_guid)5670 zpool_vdev_guid(zpool_handle_t *zhp, const char *vdevname, uint64_t *vdev_guid)
5671 {
5672 nvlist_t *tgt;
5673 boolean_t avail_spare, l2cache;
5674
5675 verify(zhp != NULL);
5676 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5677 char errbuf[ERRBUFLEN];
5678 (void) snprintf(errbuf, sizeof (errbuf),
5679 dgettext(TEXT_DOMAIN, "pool is in an unavailable state"));
5680 return (zfs_error(zhp->zpool_hdl, EZFS_POOLUNAVAIL, errbuf));
5681 }
5682
5683 if ((tgt = zpool_find_vdev(zhp, vdevname, &avail_spare, &l2cache,
5684 NULL)) == NULL) {
5685 char errbuf[ERRBUFLEN];
5686 (void) snprintf(errbuf, sizeof (errbuf),
5687 dgettext(TEXT_DOMAIN, "can not find %s in %s"),
5688 vdevname, zhp->zpool_name);
5689 return (zfs_error(zhp->zpool_hdl, EZFS_NODEVICE, errbuf));
5690 }
5691
5692 *vdev_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
5693 return (0);
5694 }
5695
5696 /*
5697 * Get a vdev property value for 'prop' and return the value in
5698 * a pre-allocated buffer.
5699 */
5700 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)5701 zpool_get_vdev_prop_value(nvlist_t *nvprop, vdev_prop_t prop, char *prop_name,
5702 char *buf, size_t len, zprop_source_t *srctype, boolean_t literal)
5703 {
5704 nvlist_t *nv;
5705 const char *strval;
5706 uint64_t intval;
5707 zprop_source_t src = ZPROP_SRC_NONE;
5708
5709 if (prop == VDEV_PROP_USERPROP) {
5710 /* user property, prop_name must contain the property name */
5711 assert(prop_name != NULL);
5712 if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
5713 src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
5714 strval = fnvlist_lookup_string(nv, ZPROP_VALUE);
5715 } else {
5716 /* user prop not found */
5717 src = ZPROP_SRC_DEFAULT;
5718 strval = "-";
5719 }
5720 (void) strlcpy(buf, strval, len);
5721 if (srctype)
5722 *srctype = src;
5723 return (0);
5724 }
5725
5726 if (prop_name == NULL)
5727 prop_name = (char *)vdev_prop_to_name(prop);
5728
5729 switch (vdev_prop_get_type(prop)) {
5730 case PROP_TYPE_STRING:
5731 if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
5732 src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
5733 strval = fnvlist_lookup_string(nv, ZPROP_VALUE);
5734 } else {
5735 src = ZPROP_SRC_DEFAULT;
5736 if ((strval = vdev_prop_default_string(prop)) == NULL)
5737 strval = "-";
5738 }
5739 (void) strlcpy(buf, strval, len);
5740 break;
5741
5742 case PROP_TYPE_NUMBER:
5743 if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
5744 src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
5745 intval = fnvlist_lookup_uint64(nv, ZPROP_VALUE);
5746 } else {
5747 src = ZPROP_SRC_DEFAULT;
5748 intval = vdev_prop_default_numeric(prop);
5749 }
5750
5751 switch (prop) {
5752 case VDEV_PROP_ASIZE:
5753 case VDEV_PROP_PSIZE:
5754 case VDEV_PROP_SIZE:
5755 case VDEV_PROP_BOOTSIZE:
5756 case VDEV_PROP_ALLOCATED:
5757 case VDEV_PROP_FREE:
5758 case VDEV_PROP_READ_ERRORS:
5759 case VDEV_PROP_WRITE_ERRORS:
5760 case VDEV_PROP_CHECKSUM_ERRORS:
5761 case VDEV_PROP_INITIALIZE_ERRORS:
5762 case VDEV_PROP_TRIM_ERRORS:
5763 case VDEV_PROP_SLOW_IOS:
5764 case VDEV_PROP_OPS_NULL:
5765 case VDEV_PROP_OPS_READ:
5766 case VDEV_PROP_OPS_WRITE:
5767 case VDEV_PROP_OPS_FREE:
5768 case VDEV_PROP_OPS_CLAIM:
5769 case VDEV_PROP_OPS_TRIM:
5770 case VDEV_PROP_BYTES_NULL:
5771 case VDEV_PROP_BYTES_READ:
5772 case VDEV_PROP_BYTES_WRITE:
5773 case VDEV_PROP_BYTES_FREE:
5774 case VDEV_PROP_BYTES_CLAIM:
5775 case VDEV_PROP_BYTES_TRIM:
5776 if (literal) {
5777 (void) snprintf(buf, len, "%llu",
5778 (u_longlong_t)intval);
5779 } else {
5780 (void) zfs_nicenum(intval, buf, len);
5781 }
5782 break;
5783 case VDEV_PROP_EXPANDSZ:
5784 if (intval == 0) {
5785 (void) strlcpy(buf, "-", len);
5786 } else if (literal) {
5787 (void) snprintf(buf, len, "%llu",
5788 (u_longlong_t)intval);
5789 } else {
5790 (void) zfs_nicenum(intval, buf, len);
5791 }
5792 break;
5793 case VDEV_PROP_CAPACITY:
5794 if (literal) {
5795 (void) snprintf(buf, len, "%llu",
5796 (u_longlong_t)intval);
5797 } else {
5798 (void) snprintf(buf, len, "%llu%%",
5799 (u_longlong_t)intval);
5800 }
5801 break;
5802 case VDEV_PROP_CHECKSUM_N:
5803 case VDEV_PROP_CHECKSUM_T:
5804 case VDEV_PROP_IO_N:
5805 case VDEV_PROP_IO_T:
5806 case VDEV_PROP_SLOW_IO_N:
5807 case VDEV_PROP_SLOW_IO_T:
5808 case VDEV_PROP_FDOMAIN:
5809 case VDEV_PROP_FGROUP:
5810 if (intval == UINT64_MAX) {
5811 (void) strlcpy(buf, "-", len);
5812 } else {
5813 (void) snprintf(buf, len, "%llu",
5814 (u_longlong_t)intval);
5815 }
5816 break;
5817 case VDEV_PROP_FRAGMENTATION:
5818 if (intval == UINT64_MAX) {
5819 (void) strlcpy(buf, "-", len);
5820 } else {
5821 (void) snprintf(buf, len, "%llu%%",
5822 (u_longlong_t)intval);
5823 }
5824 break;
5825 case VDEV_PROP_STATE:
5826 if (literal) {
5827 (void) snprintf(buf, len, "%llu",
5828 (u_longlong_t)intval);
5829 } else {
5830 (void) strlcpy(buf, zpool_state_to_name(intval,
5831 VDEV_AUX_NONE), len);
5832 }
5833 break;
5834 default:
5835 (void) snprintf(buf, len, "%llu",
5836 (u_longlong_t)intval);
5837 }
5838 break;
5839
5840 case PROP_TYPE_INDEX:
5841 if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
5842 src = fnvlist_lookup_uint64(nv, ZPROP_SOURCE);
5843 intval = fnvlist_lookup_uint64(nv, ZPROP_VALUE);
5844 } else {
5845 /* 'trim_support' only valid for leaf vdevs */
5846 if (prop == VDEV_PROP_TRIM_SUPPORT) {
5847 (void) strlcpy(buf, "-", len);
5848 break;
5849 }
5850 src = ZPROP_SRC_DEFAULT;
5851 intval = vdev_prop_default_numeric(prop);
5852 /* Only use if provided by the RAIDZ VDEV above */
5853 if (prop == VDEV_PROP_RAIDZ_EXPANDING)
5854 return (ENOENT);
5855 if (prop == VDEV_PROP_SIT_OUT)
5856 return (ENOENT);
5857 /* Only valid for top-level vdevs */
5858 if (prop == VDEV_PROP_ALLOC_BIAS)
5859 return (ENOENT);
5860 }
5861 if (vdev_prop_index_to_string(prop, intval,
5862 (const char **)&strval) != 0)
5863 return (-1);
5864 (void) strlcpy(buf, strval, len);
5865 break;
5866
5867 default:
5868 abort();
5869 }
5870
5871 if (srctype)
5872 *srctype = src;
5873
5874 return (0);
5875 }
5876
5877 /*
5878 * Get a vdev property value for 'prop_name' and return the value in
5879 * a pre-allocated buffer.
5880 */
5881 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)5882 zpool_get_vdev_prop(zpool_handle_t *zhp, const char *vdevname, vdev_prop_t prop,
5883 char *prop_name, char *buf, size_t len, zprop_source_t *srctype,
5884 boolean_t literal)
5885 {
5886 nvlist_t *reqnvl, *reqprops;
5887 nvlist_t *retprops = NULL;
5888 uint64_t vdev_guid = 0;
5889 int ret;
5890
5891 if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0)
5892 return (ret);
5893
5894 if (nvlist_alloc(&reqnvl, NV_UNIQUE_NAME, 0) != 0)
5895 return (no_memory(zhp->zpool_hdl));
5896 if (nvlist_alloc(&reqprops, NV_UNIQUE_NAME, 0) != 0)
5897 return (no_memory(zhp->zpool_hdl));
5898
5899 fnvlist_add_uint64(reqnvl, ZPOOL_VDEV_PROPS_GET_VDEV, vdev_guid);
5900
5901 if (prop != VDEV_PROP_USERPROP) {
5902 /* prop_name overrides prop value */
5903 if (prop_name != NULL)
5904 prop = vdev_name_to_prop(prop_name);
5905 else
5906 prop_name = (char *)vdev_prop_to_name(prop);
5907 assert(prop < VDEV_NUM_PROPS);
5908 }
5909
5910 assert(prop_name != NULL);
5911 if (nvlist_add_uint64(reqprops, prop_name, prop) != 0) {
5912 nvlist_free(reqnvl);
5913 nvlist_free(reqprops);
5914 return (no_memory(zhp->zpool_hdl));
5915 }
5916
5917 fnvlist_add_nvlist(reqnvl, ZPOOL_VDEV_PROPS_GET_PROPS, reqprops);
5918
5919 ret = lzc_get_vdev_prop(zhp->zpool_name, reqnvl, &retprops);
5920
5921 if (ret == 0) {
5922 ret = zpool_get_vdev_prop_value(retprops, prop, prop_name, buf,
5923 len, srctype, literal);
5924 } else {
5925 char errbuf[ERRBUFLEN];
5926 (void) snprintf(errbuf, sizeof (errbuf),
5927 dgettext(TEXT_DOMAIN, "cannot get vdev property %s from"
5928 " %s in %s"), prop_name, vdevname, zhp->zpool_name);
5929 (void) zpool_standard_error(zhp->zpool_hdl, ret, errbuf);
5930 }
5931
5932 nvlist_free(reqnvl);
5933 nvlist_free(reqprops);
5934 nvlist_free(retprops);
5935
5936 return (ret);
5937 }
5938
5939 /*
5940 * Get all vdev properties
5941 */
5942 int
zpool_get_all_vdev_props(zpool_handle_t * zhp,const char * vdevname,nvlist_t ** outnvl)5943 zpool_get_all_vdev_props(zpool_handle_t *zhp, const char *vdevname,
5944 nvlist_t **outnvl)
5945 {
5946 nvlist_t *nvl = NULL;
5947 uint64_t vdev_guid = 0;
5948 int ret;
5949
5950 if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0)
5951 return (ret);
5952
5953 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
5954 return (no_memory(zhp->zpool_hdl));
5955
5956 fnvlist_add_uint64(nvl, ZPOOL_VDEV_PROPS_GET_VDEV, vdev_guid);
5957
5958 ret = lzc_get_vdev_prop(zhp->zpool_name, nvl, outnvl);
5959
5960 nvlist_free(nvl);
5961
5962 if (ret) {
5963 char errbuf[ERRBUFLEN];
5964 (void) snprintf(errbuf, sizeof (errbuf),
5965 dgettext(TEXT_DOMAIN, "cannot get vdev properties for"
5966 " %s in %s"), vdevname, zhp->zpool_name);
5967 (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
5968 }
5969
5970 return (ret);
5971 }
5972
5973 /*
5974 * Set vdev property
5975 */
5976 int
zpool_set_vdev_prop(zpool_handle_t * zhp,const char * vdevname,const char * propname,const char * propval)5977 zpool_set_vdev_prop(zpool_handle_t *zhp, const char *vdevname,
5978 const char *propname, const char *propval)
5979 {
5980 int ret;
5981 nvlist_t *nvl = NULL;
5982 nvlist_t *outnvl = NULL;
5983 nvlist_t *props;
5984 nvlist_t *realprops;
5985 prop_flags_t flags = { 0 };
5986 uint64_t version;
5987 uint64_t vdev_guid;
5988
5989 if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0)
5990 return (ret);
5991
5992 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
5993 return (no_memory(zhp->zpool_hdl));
5994 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
5995 return (no_memory(zhp->zpool_hdl));
5996
5997 fnvlist_add_uint64(nvl, ZPOOL_VDEV_PROPS_SET_VDEV, vdev_guid);
5998
5999 if (nvlist_add_string(props, propname, propval) != 0) {
6000 nvlist_free(props);
6001 return (no_memory(zhp->zpool_hdl));
6002 }
6003
6004 char errbuf[ERRBUFLEN];
6005 (void) snprintf(errbuf, sizeof (errbuf),
6006 dgettext(TEXT_DOMAIN, "cannot set property %s for %s on %s"),
6007 propname, vdevname, zhp->zpool_name);
6008
6009 flags.vdevprop = 1;
6010 version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
6011 if ((realprops = zpool_valid_proplist(zhp->zpool_hdl,
6012 zhp->zpool_name, props, version, flags, errbuf)) == NULL) {
6013 nvlist_free(props);
6014 nvlist_free(nvl);
6015 return (-1);
6016 }
6017
6018 nvlist_free(props);
6019 props = realprops;
6020
6021 fnvlist_add_nvlist(nvl, ZPOOL_VDEV_PROPS_SET_PROPS, props);
6022
6023 ret = lzc_set_vdev_prop(zhp->zpool_name, nvl, &outnvl);
6024
6025 nvlist_free(props);
6026 nvlist_free(nvl);
6027 nvlist_free(outnvl);
6028
6029 if (ret) {
6030 if (errno == ENOTSUP) {
6031 zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
6032 "property not supported for this vdev"));
6033 (void) zfs_error(zhp->zpool_hdl, EZFS_PROPTYPE, errbuf);
6034 } else {
6035 (void) zpool_standard_error(zhp->zpool_hdl, errno,
6036 errbuf);
6037 }
6038 }
6039
6040 return (ret);
6041 }
6042
6043 /*
6044 * Prune older entries from the DDT to reclaim space under the quota
6045 */
6046 int
zpool_ddt_prune(zpool_handle_t * zhp,zpool_ddt_prune_unit_t unit,uint64_t amount)6047 zpool_ddt_prune(zpool_handle_t *zhp, zpool_ddt_prune_unit_t unit,
6048 uint64_t amount)
6049 {
6050 int error = lzc_ddt_prune(zhp->zpool_name, unit, amount);
6051 if (error != 0) {
6052 libzfs_handle_t *hdl = zhp->zpool_hdl;
6053 char errbuf[ERRBUFLEN];
6054
6055 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
6056 "cannot prune dedup table on '%s'"), zhp->zpool_name);
6057
6058 if (error == EALREADY) {
6059 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
6060 "a prune operation is already in progress"));
6061 (void) zfs_error(hdl, EZFS_BUSY, errbuf);
6062 } else {
6063 (void) zpool_standard_error(hdl, errno, errbuf);
6064 }
6065 return (-1);
6066 }
6067
6068 return (0);
6069 }
6070