1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd 22168404Spjd/* 23219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24229578Smm * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 25263391Sdelphij * Copyright (c) 2013 by Delphix. All rights reserved. 26262089Savg * Copyright (c) 2013, Joyent, Inc. All rights reserved. 27168404Spjd */ 28168404Spjd 29168404Spjd#include <sys/types.h> 30168404Spjd#include <sys/stat.h> 31168404Spjd#include <ctype.h> 32168404Spjd#include <errno.h> 33168404Spjd#include <devid.h> 34168404Spjd#include <fcntl.h> 35168404Spjd#include <libintl.h> 36168404Spjd#include <stdio.h> 37168404Spjd#include <stdlib.h> 38168404Spjd#include <strings.h> 39168404Spjd#include <unistd.h> 40249643Smm#include <libgen.h> 41168404Spjd#include <sys/zfs_ioctl.h> 42219089Spjd#include <dlfcn.h> 43168404Spjd 44168404Spjd#include "zfs_namecheck.h" 45168404Spjd#include "zfs_prop.h" 46168404Spjd#include "libzfs_impl.h" 47219089Spjd#include "zfs_comutil.h" 48243674Smm#include "zfeature_common.h" 49168404Spjd 50185029Spjdstatic int read_efi_label(nvlist_t *config, diskaddr_t *sb); 51185029Spjd 52219089Spjd#define DISK_ROOT "/dev/dsk" 53219089Spjd#define RDISK_ROOT "/dev/rdsk" 54219089Spjd#define BACKUP_SLICE "s2" 55209962Smm 56219089Spjdtypedef struct prop_flags { 57219089Spjd int create:1; /* Validate property on creation */ 58219089Spjd int import:1; /* Validate property on import */ 59219089Spjd} prop_flags_t; 60219089Spjd 61168404Spjd/* 62185029Spjd * ==================================================================== 63185029Spjd * zpool property functions 64185029Spjd * ==================================================================== 65185029Spjd */ 66185029Spjd 67185029Spjdstatic int 68185029Spjdzpool_get_all_props(zpool_handle_t *zhp) 69185029Spjd{ 70185029Spjd zfs_cmd_t zc = { 0 }; 71185029Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 72185029Spjd 73185029Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 74185029Spjd 75185029Spjd if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 76185029Spjd return (-1); 77185029Spjd 78185029Spjd while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) { 79185029Spjd if (errno == ENOMEM) { 80185029Spjd if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 81185029Spjd zcmd_free_nvlists(&zc); 82185029Spjd return (-1); 83185029Spjd } 84185029Spjd } else { 85185029Spjd zcmd_free_nvlists(&zc); 86185029Spjd return (-1); 87185029Spjd } 88185029Spjd } 89185029Spjd 90185029Spjd if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) { 91185029Spjd zcmd_free_nvlists(&zc); 92185029Spjd return (-1); 93185029Spjd } 94185029Spjd 95185029Spjd zcmd_free_nvlists(&zc); 96185029Spjd 97185029Spjd return (0); 98185029Spjd} 99185029Spjd 100185029Spjdstatic int 101185029Spjdzpool_props_refresh(zpool_handle_t *zhp) 102185029Spjd{ 103185029Spjd nvlist_t *old_props; 104185029Spjd 105185029Spjd old_props = zhp->zpool_props; 106185029Spjd 107185029Spjd if (zpool_get_all_props(zhp) != 0) 108185029Spjd return (-1); 109185029Spjd 110185029Spjd nvlist_free(old_props); 111185029Spjd return (0); 112185029Spjd} 113185029Spjd 114185029Spjdstatic char * 115185029Spjdzpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop, 116185029Spjd zprop_source_t *src) 117185029Spjd{ 118185029Spjd nvlist_t *nv, *nvl; 119185029Spjd uint64_t ival; 120185029Spjd char *value; 121185029Spjd zprop_source_t source; 122185029Spjd 123185029Spjd nvl = zhp->zpool_props; 124185029Spjd if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) { 125185029Spjd verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0); 126185029Spjd source = ival; 127185029Spjd verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0); 128185029Spjd } else { 129185029Spjd source = ZPROP_SRC_DEFAULT; 130185029Spjd if ((value = (char *)zpool_prop_default_string(prop)) == NULL) 131185029Spjd value = "-"; 132185029Spjd } 133185029Spjd 134185029Spjd if (src) 135185029Spjd *src = source; 136185029Spjd 137185029Spjd return (value); 138185029Spjd} 139185029Spjd 140185029Spjduint64_t 141185029Spjdzpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src) 142185029Spjd{ 143185029Spjd nvlist_t *nv, *nvl; 144185029Spjd uint64_t value; 145185029Spjd zprop_source_t source; 146185029Spjd 147185029Spjd if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) { 148185029Spjd /* 149185029Spjd * zpool_get_all_props() has most likely failed because 150185029Spjd * the pool is faulted, but if all we need is the top level 151185029Spjd * vdev's guid then get it from the zhp config nvlist. 152185029Spjd */ 153185029Spjd if ((prop == ZPOOL_PROP_GUID) && 154185029Spjd (nvlist_lookup_nvlist(zhp->zpool_config, 155185029Spjd ZPOOL_CONFIG_VDEV_TREE, &nv) == 0) && 156185029Spjd (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value) 157185029Spjd == 0)) { 158185029Spjd return (value); 159185029Spjd } 160185029Spjd return (zpool_prop_default_numeric(prop)); 161185029Spjd } 162185029Spjd 163185029Spjd nvl = zhp->zpool_props; 164185029Spjd if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) { 165185029Spjd verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &value) == 0); 166185029Spjd source = value; 167185029Spjd verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0); 168185029Spjd } else { 169185029Spjd source = ZPROP_SRC_DEFAULT; 170185029Spjd value = zpool_prop_default_numeric(prop); 171185029Spjd } 172185029Spjd 173185029Spjd if (src) 174185029Spjd *src = source; 175185029Spjd 176185029Spjd return (value); 177185029Spjd} 178185029Spjd 179185029Spjd/* 180185029Spjd * Map VDEV STATE to printed strings. 181185029Spjd */ 182224169Sgibbsconst char * 183185029Spjdzpool_state_to_name(vdev_state_t state, vdev_aux_t aux) 184185029Spjd{ 185185029Spjd switch (state) { 186185029Spjd case VDEV_STATE_CLOSED: 187185029Spjd case VDEV_STATE_OFFLINE: 188185029Spjd return (gettext("OFFLINE")); 189185029Spjd case VDEV_STATE_REMOVED: 190185029Spjd return (gettext("REMOVED")); 191185029Spjd case VDEV_STATE_CANT_OPEN: 192185029Spjd if (aux == VDEV_AUX_CORRUPT_DATA || aux == VDEV_AUX_BAD_LOG) 193185029Spjd return (gettext("FAULTED")); 194219089Spjd else if (aux == VDEV_AUX_SPLIT_POOL) 195219089Spjd return (gettext("SPLIT")); 196185029Spjd else 197185029Spjd return (gettext("UNAVAIL")); 198185029Spjd case VDEV_STATE_FAULTED: 199185029Spjd return (gettext("FAULTED")); 200185029Spjd case VDEV_STATE_DEGRADED: 201185029Spjd return (gettext("DEGRADED")); 202185029Spjd case VDEV_STATE_HEALTHY: 203185029Spjd return (gettext("ONLINE")); 204185029Spjd } 205185029Spjd 206185029Spjd return (gettext("UNKNOWN")); 207185029Spjd} 208185029Spjd 209185029Spjd/* 210224169Sgibbs * Map POOL STATE to printed strings. 211224169Sgibbs */ 212224169Sgibbsconst char * 213224169Sgibbszpool_pool_state_to_name(pool_state_t state) 214224169Sgibbs{ 215224169Sgibbs switch (state) { 216224169Sgibbs case POOL_STATE_ACTIVE: 217224169Sgibbs return (gettext("ACTIVE")); 218224169Sgibbs case POOL_STATE_EXPORTED: 219224169Sgibbs return (gettext("EXPORTED")); 220224169Sgibbs case POOL_STATE_DESTROYED: 221224169Sgibbs return (gettext("DESTROYED")); 222224169Sgibbs case POOL_STATE_SPARE: 223224169Sgibbs return (gettext("SPARE")); 224224169Sgibbs case POOL_STATE_L2CACHE: 225224169Sgibbs return (gettext("L2CACHE")); 226224169Sgibbs case POOL_STATE_UNINITIALIZED: 227224169Sgibbs return (gettext("UNINITIALIZED")); 228224169Sgibbs case POOL_STATE_UNAVAIL: 229224169Sgibbs return (gettext("UNAVAIL")); 230224169Sgibbs case POOL_STATE_POTENTIALLY_ACTIVE: 231224169Sgibbs return (gettext("POTENTIALLY_ACTIVE")); 232224169Sgibbs } 233224169Sgibbs 234224169Sgibbs return (gettext("UNKNOWN")); 235224169Sgibbs} 236224169Sgibbs 237224169Sgibbs/* 238185029Spjd * Get a zpool property value for 'prop' and return the value in 239185029Spjd * a pre-allocated buffer. 240185029Spjd */ 241185029Spjdint 242185029Spjdzpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, 243265749Sdelphij zprop_source_t *srctype, boolean_t literal) 244185029Spjd{ 245185029Spjd uint64_t intval; 246185029Spjd const char *strval; 247185029Spjd zprop_source_t src = ZPROP_SRC_NONE; 248185029Spjd nvlist_t *nvroot; 249185029Spjd vdev_stat_t *vs; 250185029Spjd uint_t vsc; 251185029Spjd 252185029Spjd if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 253209962Smm switch (prop) { 254209962Smm case ZPOOL_PROP_NAME: 255185029Spjd (void) strlcpy(buf, zpool_get_name(zhp), len); 256209962Smm break; 257209962Smm 258209962Smm case ZPOOL_PROP_HEALTH: 259185029Spjd (void) strlcpy(buf, "FAULTED", len); 260209962Smm break; 261209962Smm 262209962Smm case ZPOOL_PROP_GUID: 263209962Smm intval = zpool_get_prop_int(zhp, prop, &src); 264209962Smm (void) snprintf(buf, len, "%llu", intval); 265209962Smm break; 266209962Smm 267209962Smm case ZPOOL_PROP_ALTROOT: 268209962Smm case ZPOOL_PROP_CACHEFILE: 269229578Smm case ZPOOL_PROP_COMMENT: 270209962Smm if (zhp->zpool_props != NULL || 271209962Smm zpool_get_all_props(zhp) == 0) { 272209962Smm (void) strlcpy(buf, 273209962Smm zpool_get_prop_string(zhp, prop, &src), 274209962Smm len); 275265749Sdelphij break; 276209962Smm } 277209962Smm /* FALLTHROUGH */ 278209962Smm default: 279185029Spjd (void) strlcpy(buf, "-", len); 280209962Smm break; 281209962Smm } 282209962Smm 283209962Smm if (srctype != NULL) 284209962Smm *srctype = src; 285185029Spjd return (0); 286185029Spjd } 287185029Spjd 288185029Spjd if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) && 289185029Spjd prop != ZPOOL_PROP_NAME) 290185029Spjd return (-1); 291185029Spjd 292185029Spjd switch (zpool_prop_get_type(prop)) { 293185029Spjd case PROP_TYPE_STRING: 294185029Spjd (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src), 295185029Spjd len); 296185029Spjd break; 297185029Spjd 298185029Spjd case PROP_TYPE_NUMBER: 299185029Spjd intval = zpool_get_prop_int(zhp, prop, &src); 300185029Spjd 301185029Spjd switch (prop) { 302185029Spjd case ZPOOL_PROP_SIZE: 303219089Spjd case ZPOOL_PROP_ALLOCATED: 304219089Spjd case ZPOOL_PROP_FREE: 305243674Smm case ZPOOL_PROP_FREEING: 306236839Smm case ZPOOL_PROP_EXPANDSZ: 307265749Sdelphij if (literal) { 308265749Sdelphij (void) snprintf(buf, len, "%llu", 309265749Sdelphij (u_longlong_t)intval); 310265749Sdelphij } else { 311265749Sdelphij (void) zfs_nicenum(intval, buf, len); 312265749Sdelphij } 313185029Spjd break; 314185029Spjd 315185029Spjd case ZPOOL_PROP_CAPACITY: 316265749Sdelphij if (literal) { 317265749Sdelphij (void) snprintf(buf, len, "%llu", 318265749Sdelphij (u_longlong_t)intval); 319265749Sdelphij } else { 320265749Sdelphij (void) snprintf(buf, len, "%llu%%", 321265749Sdelphij (u_longlong_t)intval); 322265749Sdelphij } 323185029Spjd break; 324185029Spjd 325219089Spjd case ZPOOL_PROP_DEDUPRATIO: 326219089Spjd (void) snprintf(buf, len, "%llu.%02llux", 327219089Spjd (u_longlong_t)(intval / 100), 328219089Spjd (u_longlong_t)(intval % 100)); 329219089Spjd break; 330219089Spjd 331185029Spjd case ZPOOL_PROP_HEALTH: 332185029Spjd verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 333185029Spjd ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 334185029Spjd verify(nvlist_lookup_uint64_array(nvroot, 335219089Spjd ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &vsc) 336219089Spjd == 0); 337185029Spjd 338185029Spjd (void) strlcpy(buf, zpool_state_to_name(intval, 339185029Spjd vs->vs_aux), len); 340185029Spjd break; 341243674Smm case ZPOOL_PROP_VERSION: 342243674Smm if (intval >= SPA_VERSION_FEATURES) { 343243674Smm (void) snprintf(buf, len, "-"); 344243674Smm break; 345243674Smm } 346243674Smm /* FALLTHROUGH */ 347185029Spjd default: 348185029Spjd (void) snprintf(buf, len, "%llu", intval); 349185029Spjd } 350185029Spjd break; 351185029Spjd 352185029Spjd case PROP_TYPE_INDEX: 353185029Spjd intval = zpool_get_prop_int(zhp, prop, &src); 354185029Spjd if (zpool_prop_index_to_string(prop, intval, &strval) 355185029Spjd != 0) 356185029Spjd return (-1); 357185029Spjd (void) strlcpy(buf, strval, len); 358185029Spjd break; 359185029Spjd 360185029Spjd default: 361185029Spjd abort(); 362185029Spjd } 363185029Spjd 364185029Spjd if (srctype) 365185029Spjd *srctype = src; 366185029Spjd 367185029Spjd return (0); 368185029Spjd} 369185029Spjd 370185029Spjd/* 371185029Spjd * Check if the bootfs name has the same pool name as it is set to. 372185029Spjd * Assuming bootfs is a valid dataset name. 373185029Spjd */ 374185029Spjdstatic boolean_t 375185029Spjdbootfs_name_valid(const char *pool, char *bootfs) 376185029Spjd{ 377185029Spjd int len = strlen(pool); 378185029Spjd 379185029Spjd if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM|ZFS_TYPE_SNAPSHOT)) 380185029Spjd return (B_FALSE); 381185029Spjd 382185029Spjd if (strncmp(pool, bootfs, len) == 0 && 383185029Spjd (bootfs[len] == '/' || bootfs[len] == '\0')) 384185029Spjd return (B_TRUE); 385185029Spjd 386185029Spjd return (B_FALSE); 387185029Spjd} 388185029Spjd 389185029Spjd/* 390185029Spjd * Inspect the configuration to determine if any of the devices contain 391185029Spjd * an EFI label. 392185029Spjd */ 393185029Spjdstatic boolean_t 394185029Spjdpool_uses_efi(nvlist_t *config) 395185029Spjd{ 396209962Smm#ifdef sun 397185029Spjd nvlist_t **child; 398185029Spjd uint_t c, children; 399185029Spjd 400185029Spjd if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN, 401185029Spjd &child, &children) != 0) 402185029Spjd return (read_efi_label(config, NULL) >= 0); 403185029Spjd 404185029Spjd for (c = 0; c < children; c++) { 405185029Spjd if (pool_uses_efi(child[c])) 406185029Spjd return (B_TRUE); 407185029Spjd } 408209962Smm#endif /* sun */ 409185029Spjd return (B_FALSE); 410185029Spjd} 411185029Spjd 412236839Smmboolean_t 413236839Smmzpool_is_bootable(zpool_handle_t *zhp) 414219089Spjd{ 415219089Spjd char bootfs[ZPOOL_MAXNAMELEN]; 416219089Spjd 417219089Spjd return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs, 418265749Sdelphij sizeof (bootfs), NULL, B_FALSE) == 0 && strncmp(bootfs, "-", 419219089Spjd sizeof (bootfs)) != 0); 420219089Spjd} 421219089Spjd 422219089Spjd 423185029Spjd/* 424185029Spjd * Given an nvlist of zpool properties to be set, validate that they are 425185029Spjd * correct, and parse any numeric properties (index, boolean, etc) if they are 426185029Spjd * specified as strings. 427185029Spjd */ 428185029Spjdstatic nvlist_t * 429185029Spjdzpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname, 430219089Spjd nvlist_t *props, uint64_t version, prop_flags_t flags, char *errbuf) 431185029Spjd{ 432185029Spjd nvpair_t *elem; 433185029Spjd nvlist_t *retprops; 434185029Spjd zpool_prop_t prop; 435185029Spjd char *strval; 436185029Spjd uint64_t intval; 437229578Smm char *slash, *check; 438185029Spjd struct stat64 statbuf; 439185029Spjd zpool_handle_t *zhp; 440185029Spjd nvlist_t *nvroot; 441185029Spjd 442185029Spjd if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) { 443185029Spjd (void) no_memory(hdl); 444185029Spjd return (NULL); 445185029Spjd } 446185029Spjd 447185029Spjd elem = NULL; 448185029Spjd while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 449185029Spjd const char *propname = nvpair_name(elem); 450185029Spjd 451243674Smm prop = zpool_name_to_prop(propname); 452243674Smm if (prop == ZPROP_INVAL && zpool_prop_feature(propname)) { 453243674Smm int err; 454243674Smm char *fname = strchr(propname, '@') + 1; 455243674Smm 456263391Sdelphij err = zfeature_lookup_name(fname, NULL); 457243674Smm if (err != 0) { 458243674Smm ASSERT3U(err, ==, ENOENT); 459243674Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 460243674Smm "invalid feature '%s'"), fname); 461243674Smm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 462243674Smm goto error; 463243674Smm } 464243674Smm 465243674Smm if (nvpair_type(elem) != DATA_TYPE_STRING) { 466243674Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 467243674Smm "'%s' must be a string"), propname); 468243674Smm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 469243674Smm goto error; 470243674Smm } 471243674Smm 472243674Smm (void) nvpair_value_string(elem, &strval); 473243674Smm if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0) { 474243674Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 475243674Smm "property '%s' can only be set to " 476243674Smm "'enabled'"), propname); 477243674Smm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 478243674Smm goto error; 479243674Smm } 480243674Smm 481243674Smm if (nvlist_add_uint64(retprops, propname, 0) != 0) { 482243674Smm (void) no_memory(hdl); 483243674Smm goto error; 484243674Smm } 485243674Smm continue; 486243674Smm } 487243674Smm 488185029Spjd /* 489185029Spjd * Make sure this property is valid and applies to this type. 490185029Spjd */ 491243674Smm if (prop == ZPROP_INVAL) { 492185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 493185029Spjd "invalid property '%s'"), propname); 494185029Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 495185029Spjd goto error; 496185029Spjd } 497185029Spjd 498185029Spjd if (zpool_prop_readonly(prop)) { 499185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 500185029Spjd "is readonly"), propname); 501185029Spjd (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); 502185029Spjd goto error; 503185029Spjd } 504185029Spjd 505185029Spjd if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops, 506185029Spjd &strval, &intval, errbuf) != 0) 507185029Spjd goto error; 508185029Spjd 509185029Spjd /* 510185029Spjd * Perform additional checking for specific properties. 511185029Spjd */ 512185029Spjd switch (prop) { 513185029Spjd case ZPOOL_PROP_VERSION: 514243674Smm if (intval < version || 515243674Smm !SPA_VERSION_IS_SUPPORTED(intval)) { 516185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 517185029Spjd "property '%s' number %d is invalid."), 518185029Spjd propname, intval); 519185029Spjd (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 520185029Spjd goto error; 521185029Spjd } 522185029Spjd break; 523185029Spjd 524185029Spjd case ZPOOL_PROP_BOOTFS: 525219089Spjd if (flags.create || flags.import) { 526185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 527185029Spjd "property '%s' cannot be set at creation " 528185029Spjd "or import time"), propname); 529185029Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 530185029Spjd goto error; 531185029Spjd } 532185029Spjd 533185029Spjd if (version < SPA_VERSION_BOOTFS) { 534185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 535185029Spjd "pool must be upgraded to support " 536185029Spjd "'%s' property"), propname); 537185029Spjd (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 538185029Spjd goto error; 539185029Spjd } 540185029Spjd 541185029Spjd /* 542185029Spjd * bootfs property value has to be a dataset name and 543185029Spjd * the dataset has to be in the same pool as it sets to. 544185029Spjd */ 545185029Spjd if (strval[0] != '\0' && !bootfs_name_valid(poolname, 546185029Spjd strval)) { 547185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 548185029Spjd "is an invalid name"), strval); 549185029Spjd (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 550185029Spjd goto error; 551185029Spjd } 552185029Spjd 553185029Spjd if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) { 554185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 555185029Spjd "could not open pool '%s'"), poolname); 556185029Spjd (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf); 557185029Spjd goto error; 558185029Spjd } 559185029Spjd verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 560185029Spjd ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 561185029Spjd 562219089Spjd#ifdef sun 563185029Spjd /* 564185029Spjd * bootfs property cannot be set on a disk which has 565185029Spjd * been EFI labeled. 566185029Spjd */ 567185029Spjd if (pool_uses_efi(nvroot)) { 568185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 569185029Spjd "property '%s' not supported on " 570185029Spjd "EFI labeled devices"), propname); 571185029Spjd (void) zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf); 572185029Spjd zpool_close(zhp); 573185029Spjd goto error; 574185029Spjd } 575219089Spjd#endif /* sun */ 576185029Spjd zpool_close(zhp); 577185029Spjd break; 578185029Spjd 579185029Spjd case ZPOOL_PROP_ALTROOT: 580219089Spjd if (!flags.create && !flags.import) { 581185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 582185029Spjd "property '%s' can only be set during pool " 583185029Spjd "creation or import"), propname); 584185029Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 585185029Spjd goto error; 586185029Spjd } 587185029Spjd 588185029Spjd if (strval[0] != '/') { 589185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 590185029Spjd "bad alternate root '%s'"), strval); 591185029Spjd (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 592185029Spjd goto error; 593185029Spjd } 594185029Spjd break; 595185029Spjd 596185029Spjd case ZPOOL_PROP_CACHEFILE: 597185029Spjd if (strval[0] == '\0') 598185029Spjd break; 599185029Spjd 600185029Spjd if (strcmp(strval, "none") == 0) 601185029Spjd break; 602185029Spjd 603185029Spjd if (strval[0] != '/') { 604185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 605185029Spjd "property '%s' must be empty, an " 606185029Spjd "absolute path, or 'none'"), propname); 607185029Spjd (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 608185029Spjd goto error; 609185029Spjd } 610185029Spjd 611185029Spjd slash = strrchr(strval, '/'); 612185029Spjd 613185029Spjd if (slash[1] == '\0' || strcmp(slash, "/.") == 0 || 614185029Spjd strcmp(slash, "/..") == 0) { 615185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 616185029Spjd "'%s' is not a valid file"), strval); 617185029Spjd (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 618185029Spjd goto error; 619185029Spjd } 620185029Spjd 621185029Spjd *slash = '\0'; 622185029Spjd 623185029Spjd if (strval[0] != '\0' && 624185029Spjd (stat64(strval, &statbuf) != 0 || 625185029Spjd !S_ISDIR(statbuf.st_mode))) { 626185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 627185029Spjd "'%s' is not a valid directory"), 628185029Spjd strval); 629185029Spjd (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 630185029Spjd goto error; 631185029Spjd } 632185029Spjd 633185029Spjd *slash = '/'; 634185029Spjd break; 635219089Spjd 636229578Smm case ZPOOL_PROP_COMMENT: 637229578Smm for (check = strval; *check != '\0'; check++) { 638229578Smm if (!isprint(*check)) { 639229578Smm zfs_error_aux(hdl, 640229578Smm dgettext(TEXT_DOMAIN, 641229578Smm "comment may only have printable " 642229578Smm "characters")); 643229578Smm (void) zfs_error(hdl, EZFS_BADPROP, 644229578Smm errbuf); 645229578Smm goto error; 646229578Smm } 647229578Smm } 648229578Smm if (strlen(strval) > ZPROP_MAX_COMMENT) { 649229578Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 650229578Smm "comment must not exceed %d characters"), 651229578Smm ZPROP_MAX_COMMENT); 652229578Smm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 653229578Smm goto error; 654229578Smm } 655229578Smm break; 656219089Spjd case ZPOOL_PROP_READONLY: 657219089Spjd if (!flags.import) { 658219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 659219089Spjd "property '%s' can only be set at " 660219089Spjd "import time"), propname); 661219089Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 662219089Spjd goto error; 663219089Spjd } 664219089Spjd break; 665185029Spjd } 666185029Spjd } 667185029Spjd 668185029Spjd return (retprops); 669185029Spjderror: 670185029Spjd nvlist_free(retprops); 671185029Spjd return (NULL); 672185029Spjd} 673185029Spjd 674185029Spjd/* 675185029Spjd * Set zpool property : propname=propval. 676185029Spjd */ 677185029Spjdint 678185029Spjdzpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) 679185029Spjd{ 680185029Spjd zfs_cmd_t zc = { 0 }; 681185029Spjd int ret = -1; 682185029Spjd char errbuf[1024]; 683185029Spjd nvlist_t *nvl = NULL; 684185029Spjd nvlist_t *realprops; 685185029Spjd uint64_t version; 686219089Spjd prop_flags_t flags = { 0 }; 687185029Spjd 688185029Spjd (void) snprintf(errbuf, sizeof (errbuf), 689185029Spjd dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 690185029Spjd zhp->zpool_name); 691185029Spjd 692185029Spjd if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 693185029Spjd return (no_memory(zhp->zpool_hdl)); 694185029Spjd 695185029Spjd if (nvlist_add_string(nvl, propname, propval) != 0) { 696185029Spjd nvlist_free(nvl); 697185029Spjd return (no_memory(zhp->zpool_hdl)); 698185029Spjd } 699185029Spjd 700185029Spjd version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 701185029Spjd if ((realprops = zpool_valid_proplist(zhp->zpool_hdl, 702219089Spjd zhp->zpool_name, nvl, version, flags, errbuf)) == NULL) { 703185029Spjd nvlist_free(nvl); 704185029Spjd return (-1); 705185029Spjd } 706185029Spjd 707185029Spjd nvlist_free(nvl); 708185029Spjd nvl = realprops; 709185029Spjd 710185029Spjd /* 711185029Spjd * Execute the corresponding ioctl() to set this property. 712185029Spjd */ 713185029Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 714185029Spjd 715185029Spjd if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) { 716185029Spjd nvlist_free(nvl); 717185029Spjd return (-1); 718185029Spjd } 719185029Spjd 720185029Spjd ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc); 721185029Spjd 722185029Spjd zcmd_free_nvlists(&zc); 723185029Spjd nvlist_free(nvl); 724185029Spjd 725185029Spjd if (ret) 726185029Spjd (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); 727185029Spjd else 728185029Spjd (void) zpool_props_refresh(zhp); 729185029Spjd 730185029Spjd return (ret); 731185029Spjd} 732185029Spjd 733185029Spjdint 734185029Spjdzpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp) 735185029Spjd{ 736185029Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 737185029Spjd zprop_list_t *entry; 738185029Spjd char buf[ZFS_MAXPROPLEN]; 739243674Smm nvlist_t *features = NULL; 740243674Smm zprop_list_t **last; 741243674Smm boolean_t firstexpand = (NULL == *plp); 742185029Spjd 743185029Spjd if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0) 744185029Spjd return (-1); 745185029Spjd 746243674Smm last = plp; 747243674Smm while (*last != NULL) 748243674Smm last = &(*last)->pl_next; 749243674Smm 750243674Smm if ((*plp)->pl_all) 751243674Smm features = zpool_get_features(zhp); 752243674Smm 753243674Smm if ((*plp)->pl_all && firstexpand) { 754243674Smm for (int i = 0; i < SPA_FEATURES; i++) { 755243674Smm zprop_list_t *entry = zfs_alloc(hdl, 756243674Smm sizeof (zprop_list_t)); 757243674Smm entry->pl_prop = ZPROP_INVAL; 758243674Smm entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s", 759243674Smm spa_feature_table[i].fi_uname); 760243674Smm entry->pl_width = strlen(entry->pl_user_prop); 761243674Smm entry->pl_all = B_TRUE; 762243674Smm 763243674Smm *last = entry; 764243674Smm last = &entry->pl_next; 765243674Smm } 766243674Smm } 767243674Smm 768243674Smm /* add any unsupported features */ 769243674Smm for (nvpair_t *nvp = nvlist_next_nvpair(features, NULL); 770243674Smm nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) { 771243674Smm char *propname; 772243674Smm boolean_t found; 773243674Smm zprop_list_t *entry; 774243674Smm 775243674Smm if (zfeature_is_supported(nvpair_name(nvp))) 776243674Smm continue; 777243674Smm 778243674Smm propname = zfs_asprintf(hdl, "unsupported@%s", 779243674Smm nvpair_name(nvp)); 780243674Smm 781243674Smm /* 782243674Smm * Before adding the property to the list make sure that no 783243674Smm * other pool already added the same property. 784243674Smm */ 785243674Smm found = B_FALSE; 786243674Smm entry = *plp; 787243674Smm while (entry != NULL) { 788243674Smm if (entry->pl_user_prop != NULL && 789243674Smm strcmp(propname, entry->pl_user_prop) == 0) { 790243674Smm found = B_TRUE; 791243674Smm break; 792243674Smm } 793243674Smm entry = entry->pl_next; 794243674Smm } 795243674Smm if (found) { 796243674Smm free(propname); 797243674Smm continue; 798243674Smm } 799243674Smm 800243674Smm entry = zfs_alloc(hdl, sizeof (zprop_list_t)); 801243674Smm entry->pl_prop = ZPROP_INVAL; 802243674Smm entry->pl_user_prop = propname; 803243674Smm entry->pl_width = strlen(entry->pl_user_prop); 804243674Smm entry->pl_all = B_TRUE; 805243674Smm 806243674Smm *last = entry; 807243674Smm last = &entry->pl_next; 808243674Smm } 809243674Smm 810185029Spjd for (entry = *plp; entry != NULL; entry = entry->pl_next) { 811185029Spjd 812185029Spjd if (entry->pl_fixed) 813185029Spjd continue; 814185029Spjd 815185029Spjd if (entry->pl_prop != ZPROP_INVAL && 816185029Spjd zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), 817265749Sdelphij NULL, B_FALSE) == 0) { 818185029Spjd if (strlen(buf) > entry->pl_width) 819185029Spjd entry->pl_width = strlen(buf); 820185029Spjd } 821185029Spjd } 822185029Spjd 823185029Spjd return (0); 824185029Spjd} 825185029Spjd 826243674Smm/* 827243674Smm * Get the state for the given feature on the given ZFS pool. 828243674Smm */ 829243674Smmint 830243674Smmzpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf, 831243674Smm size_t len) 832243674Smm{ 833243674Smm uint64_t refcount; 834243674Smm boolean_t found = B_FALSE; 835243674Smm nvlist_t *features = zpool_get_features(zhp); 836243674Smm boolean_t supported; 837243674Smm const char *feature = strchr(propname, '@') + 1; 838185029Spjd 839243674Smm supported = zpool_prop_feature(propname); 840243674Smm ASSERT(supported || zpool_prop_unsupported(propname)); 841243674Smm 842243674Smm /* 843243674Smm * Convert from feature name to feature guid. This conversion is 844243674Smm * unecessary for unsupported@... properties because they already 845243674Smm * use guids. 846243674Smm */ 847243674Smm if (supported) { 848243674Smm int ret; 849263391Sdelphij spa_feature_t fid; 850243674Smm 851263391Sdelphij ret = zfeature_lookup_name(feature, &fid); 852243674Smm if (ret != 0) { 853243674Smm (void) strlcpy(buf, "-", len); 854243674Smm return (ENOTSUP); 855243674Smm } 856263391Sdelphij feature = spa_feature_table[fid].fi_guid; 857243674Smm } 858243674Smm 859243674Smm if (nvlist_lookup_uint64(features, feature, &refcount) == 0) 860243674Smm found = B_TRUE; 861243674Smm 862243674Smm if (supported) { 863243674Smm if (!found) { 864243674Smm (void) strlcpy(buf, ZFS_FEATURE_DISABLED, len); 865243674Smm } else { 866243674Smm if (refcount == 0) 867243674Smm (void) strlcpy(buf, ZFS_FEATURE_ENABLED, len); 868243674Smm else 869243674Smm (void) strlcpy(buf, ZFS_FEATURE_ACTIVE, len); 870243674Smm } 871243674Smm } else { 872243674Smm if (found) { 873243674Smm if (refcount == 0) { 874243674Smm (void) strcpy(buf, ZFS_UNSUPPORTED_INACTIVE); 875243674Smm } else { 876243674Smm (void) strcpy(buf, ZFS_UNSUPPORTED_READONLY); 877243674Smm } 878243674Smm } else { 879243674Smm (void) strlcpy(buf, "-", len); 880243674Smm return (ENOTSUP); 881243674Smm } 882243674Smm } 883243674Smm 884243674Smm return (0); 885243674Smm} 886243674Smm 887185029Spjd/* 888219089Spjd * Don't start the slice at the default block of 34; many storage 889219089Spjd * devices will use a stripe width of 128k, so start there instead. 890219089Spjd */ 891219089Spjd#define NEW_START_BLOCK 256 892219089Spjd 893219089Spjd/* 894168404Spjd * Validate the given pool name, optionally putting an extended error message in 895168404Spjd * 'buf'. 896168404Spjd */ 897185029Spjdboolean_t 898168404Spjdzpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) 899168404Spjd{ 900168404Spjd namecheck_err_t why; 901168404Spjd char what; 902168404Spjd int ret; 903168404Spjd 904168404Spjd ret = pool_namecheck(pool, &why, &what); 905168404Spjd 906168404Spjd /* 907168404Spjd * The rules for reserved pool names were extended at a later point. 908168404Spjd * But we need to support users with existing pools that may now be 909168404Spjd * invalid. So we only check for this expanded set of names during a 910168404Spjd * create (or import), and only in userland. 911168404Spjd */ 912168404Spjd if (ret == 0 && !isopen && 913168404Spjd (strncmp(pool, "mirror", 6) == 0 || 914168404Spjd strncmp(pool, "raidz", 5) == 0 || 915185029Spjd strncmp(pool, "spare", 5) == 0 || 916185029Spjd strcmp(pool, "log") == 0)) { 917185029Spjd if (hdl != NULL) 918185029Spjd zfs_error_aux(hdl, 919185029Spjd dgettext(TEXT_DOMAIN, "name is reserved")); 920168404Spjd return (B_FALSE); 921168404Spjd } 922168404Spjd 923168404Spjd 924168404Spjd if (ret != 0) { 925168404Spjd if (hdl != NULL) { 926168404Spjd switch (why) { 927168404Spjd case NAME_ERR_TOOLONG: 928168404Spjd zfs_error_aux(hdl, 929168404Spjd dgettext(TEXT_DOMAIN, "name is too long")); 930168404Spjd break; 931168404Spjd 932168404Spjd case NAME_ERR_INVALCHAR: 933168404Spjd zfs_error_aux(hdl, 934168404Spjd dgettext(TEXT_DOMAIN, "invalid character " 935168404Spjd "'%c' in pool name"), what); 936168404Spjd break; 937168404Spjd 938168404Spjd case NAME_ERR_NOLETTER: 939168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 940168404Spjd "name must begin with a letter")); 941168404Spjd break; 942168404Spjd 943168404Spjd case NAME_ERR_RESERVED: 944168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 945168404Spjd "name is reserved")); 946168404Spjd break; 947168404Spjd 948168404Spjd case NAME_ERR_DISKLIKE: 949168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 950168404Spjd "pool name is reserved")); 951168404Spjd break; 952168404Spjd 953168404Spjd case NAME_ERR_LEADING_SLASH: 954168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 955168404Spjd "leading slash in name")); 956168404Spjd break; 957168404Spjd 958168404Spjd case NAME_ERR_EMPTY_COMPONENT: 959168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 960168404Spjd "empty component in name")); 961168404Spjd break; 962168404Spjd 963168404Spjd case NAME_ERR_TRAILING_SLASH: 964168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 965168404Spjd "trailing slash in name")); 966168404Spjd break; 967168404Spjd 968168404Spjd case NAME_ERR_MULTIPLE_AT: 969168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 970168404Spjd "multiple '@' delimiters in name")); 971168404Spjd break; 972168404Spjd 973168404Spjd } 974168404Spjd } 975168404Spjd return (B_FALSE); 976168404Spjd } 977168404Spjd 978168404Spjd return (B_TRUE); 979168404Spjd} 980168404Spjd 981168404Spjd/* 982168404Spjd * Open a handle to the given pool, even if the pool is currently in the FAULTED 983168404Spjd * state. 984168404Spjd */ 985168404Spjdzpool_handle_t * 986168404Spjdzpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 987168404Spjd{ 988168404Spjd zpool_handle_t *zhp; 989168404Spjd boolean_t missing; 990168404Spjd 991168404Spjd /* 992168404Spjd * Make sure the pool name is valid. 993168404Spjd */ 994168404Spjd if (!zpool_name_valid(hdl, B_TRUE, pool)) { 995168404Spjd (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, 996168404Spjd dgettext(TEXT_DOMAIN, "cannot open '%s'"), 997168404Spjd pool); 998168404Spjd return (NULL); 999168404Spjd } 1000168404Spjd 1001168404Spjd if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1002168404Spjd return (NULL); 1003168404Spjd 1004168404Spjd zhp->zpool_hdl = hdl; 1005168404Spjd (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 1006168404Spjd 1007168404Spjd if (zpool_refresh_stats(zhp, &missing) != 0) { 1008168404Spjd zpool_close(zhp); 1009168404Spjd return (NULL); 1010168404Spjd } 1011168404Spjd 1012168404Spjd if (missing) { 1013185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool")); 1014168404Spjd (void) zfs_error_fmt(hdl, EZFS_NOENT, 1015185029Spjd dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool); 1016168404Spjd zpool_close(zhp); 1017168404Spjd return (NULL); 1018168404Spjd } 1019168404Spjd 1020168404Spjd return (zhp); 1021168404Spjd} 1022168404Spjd 1023168404Spjd/* 1024168404Spjd * Like the above, but silent on error. Used when iterating over pools (because 1025168404Spjd * the configuration cache may be out of date). 1026168404Spjd */ 1027168404Spjdint 1028168404Spjdzpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 1029168404Spjd{ 1030168404Spjd zpool_handle_t *zhp; 1031168404Spjd boolean_t missing; 1032168404Spjd 1033168404Spjd if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1034168404Spjd return (-1); 1035168404Spjd 1036168404Spjd zhp->zpool_hdl = hdl; 1037168404Spjd (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 1038168404Spjd 1039168404Spjd if (zpool_refresh_stats(zhp, &missing) != 0) { 1040168404Spjd zpool_close(zhp); 1041168404Spjd return (-1); 1042168404Spjd } 1043168404Spjd 1044168404Spjd if (missing) { 1045168404Spjd zpool_close(zhp); 1046168404Spjd *ret = NULL; 1047168404Spjd return (0); 1048168404Spjd } 1049168404Spjd 1050168404Spjd *ret = zhp; 1051168404Spjd return (0); 1052168404Spjd} 1053168404Spjd 1054168404Spjd/* 1055168404Spjd * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 1056168404Spjd * state. 1057168404Spjd */ 1058168404Spjdzpool_handle_t * 1059168404Spjdzpool_open(libzfs_handle_t *hdl, const char *pool) 1060168404Spjd{ 1061168404Spjd zpool_handle_t *zhp; 1062168404Spjd 1063168404Spjd if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 1064168404Spjd return (NULL); 1065168404Spjd 1066168404Spjd if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 1067168404Spjd (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, 1068168404Spjd dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 1069168404Spjd zpool_close(zhp); 1070168404Spjd return (NULL); 1071168404Spjd } 1072168404Spjd 1073168404Spjd return (zhp); 1074168404Spjd} 1075168404Spjd 1076168404Spjd/* 1077168404Spjd * Close the handle. Simply frees the memory associated with the handle. 1078168404Spjd */ 1079168404Spjdvoid 1080168404Spjdzpool_close(zpool_handle_t *zhp) 1081168404Spjd{ 1082168404Spjd if (zhp->zpool_config) 1083168404Spjd nvlist_free(zhp->zpool_config); 1084168404Spjd if (zhp->zpool_old_config) 1085168404Spjd nvlist_free(zhp->zpool_old_config); 1086168404Spjd if (zhp->zpool_props) 1087168404Spjd nvlist_free(zhp->zpool_props); 1088168404Spjd free(zhp); 1089168404Spjd} 1090168404Spjd 1091168404Spjd/* 1092168404Spjd * Return the name of the pool. 1093168404Spjd */ 1094168404Spjdconst char * 1095168404Spjdzpool_get_name(zpool_handle_t *zhp) 1096168404Spjd{ 1097168404Spjd return (zhp->zpool_name); 1098168404Spjd} 1099168404Spjd 1100168404Spjd 1101168404Spjd/* 1102168404Spjd * Return the state of the pool (ACTIVE or UNAVAILABLE) 1103168404Spjd */ 1104168404Spjdint 1105168404Spjdzpool_get_state(zpool_handle_t *zhp) 1106168404Spjd{ 1107168404Spjd return (zhp->zpool_state); 1108168404Spjd} 1109168404Spjd 1110168404Spjd/* 1111168404Spjd * Create the named pool, using the provided vdev list. It is assumed 1112168404Spjd * that the consumer has already validated the contents of the nvlist, so we 1113168404Spjd * don't have to worry about error semantics. 1114168404Spjd */ 1115168404Spjdint 1116168404Spjdzpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 1117185029Spjd nvlist_t *props, nvlist_t *fsprops) 1118168404Spjd{ 1119168404Spjd zfs_cmd_t zc = { 0 }; 1120185029Spjd nvlist_t *zc_fsprops = NULL; 1121185029Spjd nvlist_t *zc_props = NULL; 1122168404Spjd char msg[1024]; 1123185029Spjd int ret = -1; 1124168404Spjd 1125168404Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 1126168404Spjd "cannot create '%s'"), pool); 1127168404Spjd 1128168404Spjd if (!zpool_name_valid(hdl, B_FALSE, pool)) 1129168404Spjd return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 1130168404Spjd 1131185029Spjd if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 1132168404Spjd return (-1); 1133168404Spjd 1134185029Spjd if (props) { 1135219089Spjd prop_flags_t flags = { .create = B_TRUE, .import = B_FALSE }; 1136219089Spjd 1137185029Spjd if ((zc_props = zpool_valid_proplist(hdl, pool, props, 1138219089Spjd SPA_VERSION_1, flags, msg)) == NULL) { 1139185029Spjd goto create_failed; 1140185029Spjd } 1141185029Spjd } 1142185029Spjd 1143185029Spjd if (fsprops) { 1144185029Spjd uint64_t zoned; 1145185029Spjd char *zonestr; 1146185029Spjd 1147185029Spjd zoned = ((nvlist_lookup_string(fsprops, 1148185029Spjd zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) && 1149185029Spjd strcmp(zonestr, "on") == 0); 1150185029Spjd 1151185029Spjd if ((zc_fsprops = zfs_valid_proplist(hdl, 1152185029Spjd ZFS_TYPE_FILESYSTEM, fsprops, zoned, NULL, msg)) == NULL) { 1153185029Spjd goto create_failed; 1154185029Spjd } 1155185029Spjd if (!zc_props && 1156185029Spjd (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) { 1157185029Spjd goto create_failed; 1158185029Spjd } 1159185029Spjd if (nvlist_add_nvlist(zc_props, 1160185029Spjd ZPOOL_ROOTFS_PROPS, zc_fsprops) != 0) { 1161185029Spjd goto create_failed; 1162185029Spjd } 1163185029Spjd } 1164185029Spjd 1165185029Spjd if (zc_props && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0) 1166185029Spjd goto create_failed; 1167185029Spjd 1168168404Spjd (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 1169168404Spjd 1170185029Spjd if ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc)) != 0) { 1171168404Spjd 1172168404Spjd zcmd_free_nvlists(&zc); 1173185029Spjd nvlist_free(zc_props); 1174185029Spjd nvlist_free(zc_fsprops); 1175168404Spjd 1176168404Spjd switch (errno) { 1177168404Spjd case EBUSY: 1178168404Spjd /* 1179168404Spjd * This can happen if the user has specified the same 1180168404Spjd * device multiple times. We can't reliably detect this 1181168404Spjd * until we try to add it and see we already have a 1182168404Spjd * label. 1183168404Spjd */ 1184168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1185168404Spjd "one or more vdevs refer to the same device")); 1186168404Spjd return (zfs_error(hdl, EZFS_BADDEV, msg)); 1187168404Spjd 1188168404Spjd case EOVERFLOW: 1189168404Spjd /* 1190168404Spjd * This occurs when one of the devices is below 1191168404Spjd * SPA_MINDEVSIZE. Unfortunately, we can't detect which 1192168404Spjd * device was the problem device since there's no 1193168404Spjd * reliable way to determine device size from userland. 1194168404Spjd */ 1195168404Spjd { 1196168404Spjd char buf[64]; 1197168404Spjd 1198168404Spjd zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 1199168404Spjd 1200168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1201168404Spjd "one or more devices is less than the " 1202168404Spjd "minimum size (%s)"), buf); 1203168404Spjd } 1204168404Spjd return (zfs_error(hdl, EZFS_BADDEV, msg)); 1205168404Spjd 1206168404Spjd case ENOSPC: 1207168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1208168404Spjd "one or more devices is out of space")); 1209168404Spjd return (zfs_error(hdl, EZFS_BADDEV, msg)); 1210168404Spjd 1211185029Spjd case ENOTBLK: 1212185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1213185029Spjd "cache device must be a disk or disk slice")); 1214185029Spjd return (zfs_error(hdl, EZFS_BADDEV, msg)); 1215185029Spjd 1216168404Spjd default: 1217168404Spjd return (zpool_standard_error(hdl, errno, msg)); 1218168404Spjd } 1219168404Spjd } 1220168404Spjd 1221185029Spjdcreate_failed: 1222185029Spjd zcmd_free_nvlists(&zc); 1223185029Spjd nvlist_free(zc_props); 1224185029Spjd nvlist_free(zc_fsprops); 1225185029Spjd return (ret); 1226168404Spjd} 1227168404Spjd 1228168404Spjd/* 1229168404Spjd * Destroy the given pool. It is up to the caller to ensure that there are no 1230168404Spjd * datasets left in the pool. 1231168404Spjd */ 1232168404Spjdint 1233249643Smmzpool_destroy(zpool_handle_t *zhp, const char *log_str) 1234168404Spjd{ 1235168404Spjd zfs_cmd_t zc = { 0 }; 1236168404Spjd zfs_handle_t *zfp = NULL; 1237168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 1238168404Spjd char msg[1024]; 1239168404Spjd 1240168404Spjd if (zhp->zpool_state == POOL_STATE_ACTIVE && 1241219089Spjd (zfp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL) 1242168404Spjd return (-1); 1243168404Spjd 1244168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1245249643Smm zc.zc_history = (uint64_t)(uintptr_t)log_str; 1246168404Spjd 1247219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 1248168404Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 1249168404Spjd "cannot destroy '%s'"), zhp->zpool_name); 1250168404Spjd 1251168404Spjd if (errno == EROFS) { 1252168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1253168404Spjd "one or more devices is read only")); 1254168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 1255168404Spjd } else { 1256168404Spjd (void) zpool_standard_error(hdl, errno, msg); 1257168404Spjd } 1258168404Spjd 1259168404Spjd if (zfp) 1260168404Spjd zfs_close(zfp); 1261168404Spjd return (-1); 1262168404Spjd } 1263168404Spjd 1264168404Spjd if (zfp) { 1265168404Spjd remove_mountpoint(zfp); 1266168404Spjd zfs_close(zfp); 1267168404Spjd } 1268168404Spjd 1269168404Spjd return (0); 1270168404Spjd} 1271168404Spjd 1272168404Spjd/* 1273168404Spjd * Add the given vdevs to the pool. The caller must have already performed the 1274168404Spjd * necessary verification to ensure that the vdev specification is well-formed. 1275168404Spjd */ 1276168404Spjdint 1277168404Spjdzpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 1278168404Spjd{ 1279168404Spjd zfs_cmd_t zc = { 0 }; 1280168404Spjd int ret; 1281168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 1282168404Spjd char msg[1024]; 1283185029Spjd nvlist_t **spares, **l2cache; 1284185029Spjd uint_t nspares, nl2cache; 1285168404Spjd 1286168404Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 1287168404Spjd "cannot add to '%s'"), zhp->zpool_name); 1288168404Spjd 1289185029Spjd if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) < 1290185029Spjd SPA_VERSION_SPARES && 1291168404Spjd nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 1292168404Spjd &spares, &nspares) == 0) { 1293168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 1294168404Spjd "upgraded to add hot spares")); 1295168404Spjd return (zfs_error(hdl, EZFS_BADVERSION, msg)); 1296168404Spjd } 1297168404Spjd 1298236839Smm if (zpool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot, 1299209962Smm ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) { 1300209962Smm uint64_t s; 1301209962Smm 1302209962Smm for (s = 0; s < nspares; s++) { 1303209962Smm char *path; 1304209962Smm 1305209962Smm if (nvlist_lookup_string(spares[s], ZPOOL_CONFIG_PATH, 1306209962Smm &path) == 0 && pool_uses_efi(spares[s])) { 1307209962Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1308209962Smm "device '%s' contains an EFI label and " 1309209962Smm "cannot be used on root pools."), 1310219089Spjd zpool_vdev_name(hdl, NULL, spares[s], 1311219089Spjd B_FALSE)); 1312209962Smm return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg)); 1313209962Smm } 1314209962Smm } 1315209962Smm } 1316209962Smm 1317185029Spjd if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) < 1318185029Spjd SPA_VERSION_L2CACHE && 1319185029Spjd nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 1320185029Spjd &l2cache, &nl2cache) == 0) { 1321185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 1322185029Spjd "upgraded to add cache devices")); 1323185029Spjd return (zfs_error(hdl, EZFS_BADVERSION, msg)); 1324185029Spjd } 1325185029Spjd 1326185029Spjd if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 1327168404Spjd return (-1); 1328168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1329168404Spjd 1330219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) { 1331168404Spjd switch (errno) { 1332168404Spjd case EBUSY: 1333168404Spjd /* 1334168404Spjd * This can happen if the user has specified the same 1335168404Spjd * device multiple times. We can't reliably detect this 1336168404Spjd * until we try to add it and see we already have a 1337168404Spjd * label. 1338168404Spjd */ 1339168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1340168404Spjd "one or more vdevs refer to the same device")); 1341168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 1342168404Spjd break; 1343168404Spjd 1344168404Spjd case EOVERFLOW: 1345168404Spjd /* 1346168404Spjd * This occurrs when one of the devices is below 1347168404Spjd * SPA_MINDEVSIZE. Unfortunately, we can't detect which 1348168404Spjd * device was the problem device since there's no 1349168404Spjd * reliable way to determine device size from userland. 1350168404Spjd */ 1351168404Spjd { 1352168404Spjd char buf[64]; 1353168404Spjd 1354168404Spjd zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 1355168404Spjd 1356168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1357168404Spjd "device is less than the minimum " 1358168404Spjd "size (%s)"), buf); 1359168404Spjd } 1360168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 1361168404Spjd break; 1362168404Spjd 1363168404Spjd case ENOTSUP: 1364168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1365185029Spjd "pool must be upgraded to add these vdevs")); 1366168404Spjd (void) zfs_error(hdl, EZFS_BADVERSION, msg); 1367168404Spjd break; 1368168404Spjd 1369168404Spjd case EDOM: 1370168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1371185029Spjd "root pool can not have multiple vdevs" 1372185029Spjd " or separate logs")); 1373168404Spjd (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg); 1374168404Spjd break; 1375168404Spjd 1376185029Spjd case ENOTBLK: 1377185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1378185029Spjd "cache device must be a disk or disk slice")); 1379185029Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 1380185029Spjd break; 1381185029Spjd 1382168404Spjd default: 1383168404Spjd (void) zpool_standard_error(hdl, errno, msg); 1384168404Spjd } 1385168404Spjd 1386168404Spjd ret = -1; 1387168404Spjd } else { 1388168404Spjd ret = 0; 1389168404Spjd } 1390168404Spjd 1391168404Spjd zcmd_free_nvlists(&zc); 1392168404Spjd 1393168404Spjd return (ret); 1394168404Spjd} 1395168404Spjd 1396168404Spjd/* 1397168404Spjd * Exports the pool from the system. The caller must ensure that there are no 1398168404Spjd * mounted datasets in the pool. 1399168404Spjd */ 1400249643Smmstatic int 1401249643Smmzpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce, 1402249643Smm const char *log_str) 1403168404Spjd{ 1404168404Spjd zfs_cmd_t zc = { 0 }; 1405185029Spjd char msg[1024]; 1406168404Spjd 1407185029Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 1408185029Spjd "cannot export '%s'"), zhp->zpool_name); 1409185029Spjd 1410168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1411185029Spjd zc.zc_cookie = force; 1412207670Smm zc.zc_guid = hardforce; 1413249643Smm zc.zc_history = (uint64_t)(uintptr_t)log_str; 1414168404Spjd 1415185029Spjd if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) { 1416185029Spjd switch (errno) { 1417185029Spjd case EXDEV: 1418185029Spjd zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, 1419185029Spjd "use '-f' to override the following errors:\n" 1420185029Spjd "'%s' has an active shared spare which could be" 1421185029Spjd " used by other pools once '%s' is exported."), 1422185029Spjd zhp->zpool_name, zhp->zpool_name); 1423185029Spjd return (zfs_error(zhp->zpool_hdl, EZFS_ACTIVE_SPARE, 1424185029Spjd msg)); 1425185029Spjd default: 1426185029Spjd return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 1427185029Spjd msg)); 1428185029Spjd } 1429185029Spjd } 1430185029Spjd 1431168404Spjd return (0); 1432168404Spjd} 1433168404Spjd 1434207670Smmint 1435249643Smmzpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str) 1436207670Smm{ 1437249643Smm return (zpool_export_common(zhp, force, B_FALSE, log_str)); 1438207670Smm} 1439207670Smm 1440207670Smmint 1441249643Smmzpool_export_force(zpool_handle_t *zhp, const char *log_str) 1442207670Smm{ 1443249643Smm return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str)); 1444207670Smm} 1445207670Smm 1446219089Spjdstatic void 1447219089Spjdzpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun, 1448219089Spjd nvlist_t *config) 1449219089Spjd{ 1450219089Spjd nvlist_t *nv = NULL; 1451219089Spjd uint64_t rewindto; 1452219089Spjd int64_t loss = -1; 1453219089Spjd struct tm t; 1454219089Spjd char timestr[128]; 1455219089Spjd 1456219089Spjd if (!hdl->libzfs_printerr || config == NULL) 1457219089Spjd return; 1458219089Spjd 1459243674Smm if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 || 1460243674Smm nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0) { 1461219089Spjd return; 1462243674Smm } 1463219089Spjd 1464219089Spjd if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0) 1465219089Spjd return; 1466219089Spjd (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss); 1467219089Spjd 1468219089Spjd if (localtime_r((time_t *)&rewindto, &t) != NULL && 1469219089Spjd strftime(timestr, 128, 0, &t) != 0) { 1470219089Spjd if (dryrun) { 1471219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1472219089Spjd "Would be able to return %s " 1473219089Spjd "to its state as of %s.\n"), 1474219089Spjd name, timestr); 1475219089Spjd } else { 1476219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1477219089Spjd "Pool %s returned to its state as of %s.\n"), 1478219089Spjd name, timestr); 1479219089Spjd } 1480219089Spjd if (loss > 120) { 1481219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1482219089Spjd "%s approximately %lld "), 1483219089Spjd dryrun ? "Would discard" : "Discarded", 1484219089Spjd (loss + 30) / 60); 1485219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1486219089Spjd "minutes of transactions.\n")); 1487219089Spjd } else if (loss > 0) { 1488219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1489219089Spjd "%s approximately %lld "), 1490219089Spjd dryrun ? "Would discard" : "Discarded", loss); 1491219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1492219089Spjd "seconds of transactions.\n")); 1493219089Spjd } 1494219089Spjd } 1495219089Spjd} 1496219089Spjd 1497219089Spjdvoid 1498219089Spjdzpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason, 1499219089Spjd nvlist_t *config) 1500219089Spjd{ 1501219089Spjd nvlist_t *nv = NULL; 1502219089Spjd int64_t loss = -1; 1503219089Spjd uint64_t edata = UINT64_MAX; 1504219089Spjd uint64_t rewindto; 1505219089Spjd struct tm t; 1506219089Spjd char timestr[128]; 1507219089Spjd 1508219089Spjd if (!hdl->libzfs_printerr) 1509219089Spjd return; 1510219089Spjd 1511219089Spjd if (reason >= 0) 1512219089Spjd (void) printf(dgettext(TEXT_DOMAIN, "action: ")); 1513219089Spjd else 1514219089Spjd (void) printf(dgettext(TEXT_DOMAIN, "\t")); 1515219089Spjd 1516219089Spjd /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */ 1517219089Spjd if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 || 1518243674Smm nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 || 1519219089Spjd nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0) 1520219089Spjd goto no_info; 1521219089Spjd 1522219089Spjd (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss); 1523219089Spjd (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS, 1524219089Spjd &edata); 1525219089Spjd 1526219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1527219089Spjd "Recovery is possible, but will result in some data loss.\n")); 1528219089Spjd 1529219089Spjd if (localtime_r((time_t *)&rewindto, &t) != NULL && 1530219089Spjd strftime(timestr, 128, 0, &t) != 0) { 1531219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1532219089Spjd "\tReturning the pool to its state as of %s\n" 1533219089Spjd "\tshould correct the problem. "), 1534219089Spjd timestr); 1535219089Spjd } else { 1536219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1537219089Spjd "\tReverting the pool to an earlier state " 1538219089Spjd "should correct the problem.\n\t")); 1539219089Spjd } 1540219089Spjd 1541219089Spjd if (loss > 120) { 1542219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1543219089Spjd "Approximately %lld minutes of data\n" 1544219089Spjd "\tmust be discarded, irreversibly. "), (loss + 30) / 60); 1545219089Spjd } else if (loss > 0) { 1546219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1547219089Spjd "Approximately %lld seconds of data\n" 1548219089Spjd "\tmust be discarded, irreversibly. "), loss); 1549219089Spjd } 1550219089Spjd if (edata != 0 && edata != UINT64_MAX) { 1551219089Spjd if (edata == 1) { 1552219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1553219089Spjd "After rewind, at least\n" 1554219089Spjd "\tone persistent user-data error will remain. ")); 1555219089Spjd } else { 1556219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1557219089Spjd "After rewind, several\n" 1558219089Spjd "\tpersistent user-data errors will remain. ")); 1559219089Spjd } 1560219089Spjd } 1561219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1562219089Spjd "Recovery can be attempted\n\tby executing 'zpool %s -F %s'. "), 1563219089Spjd reason >= 0 ? "clear" : "import", name); 1564219089Spjd 1565219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1566219089Spjd "A scrub of the pool\n" 1567219089Spjd "\tis strongly recommended after recovery.\n")); 1568219089Spjd return; 1569219089Spjd 1570219089Spjdno_info: 1571219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1572219089Spjd "Destroy and re-create the pool from\n\ta backup source.\n")); 1573219089Spjd} 1574219089Spjd 1575168404Spjd/* 1576185029Spjd * zpool_import() is a contracted interface. Should be kept the same 1577185029Spjd * if possible. 1578185029Spjd * 1579185029Spjd * Applications should use zpool_import_props() to import a pool with 1580185029Spjd * new properties value to be set. 1581168404Spjd */ 1582168404Spjdint 1583168404Spjdzpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 1584185029Spjd char *altroot) 1585168404Spjd{ 1586185029Spjd nvlist_t *props = NULL; 1587185029Spjd int ret; 1588185029Spjd 1589185029Spjd if (altroot != NULL) { 1590185029Spjd if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 1591185029Spjd return (zfs_error_fmt(hdl, EZFS_NOMEM, 1592185029Spjd dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1593185029Spjd newname)); 1594185029Spjd } 1595185029Spjd 1596185029Spjd if (nvlist_add_string(props, 1597209962Smm zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 || 1598209962Smm nvlist_add_string(props, 1599209962Smm zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) { 1600185029Spjd nvlist_free(props); 1601185029Spjd return (zfs_error_fmt(hdl, EZFS_NOMEM, 1602185029Spjd dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1603185029Spjd newname)); 1604185029Spjd } 1605185029Spjd } 1606185029Spjd 1607219089Spjd ret = zpool_import_props(hdl, config, newname, props, 1608219089Spjd ZFS_IMPORT_NORMAL); 1609185029Spjd if (props) 1610185029Spjd nvlist_free(props); 1611185029Spjd return (ret); 1612185029Spjd} 1613185029Spjd 1614219089Spjdstatic void 1615219089Spjdprint_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv, 1616219089Spjd int indent) 1617219089Spjd{ 1618219089Spjd nvlist_t **child; 1619219089Spjd uint_t c, children; 1620219089Spjd char *vname; 1621219089Spjd uint64_t is_log = 0; 1622219089Spjd 1623219089Spjd (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, 1624219089Spjd &is_log); 1625219089Spjd 1626219089Spjd if (name != NULL) 1627219089Spjd (void) printf("\t%*s%s%s\n", indent, "", name, 1628219089Spjd is_log ? " [log]" : ""); 1629219089Spjd 1630219089Spjd if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1631219089Spjd &child, &children) != 0) 1632219089Spjd return; 1633219089Spjd 1634219089Spjd for (c = 0; c < children; c++) { 1635219089Spjd vname = zpool_vdev_name(hdl, NULL, child[c], B_TRUE); 1636219089Spjd print_vdev_tree(hdl, vname, child[c], indent + 2); 1637219089Spjd free(vname); 1638219089Spjd } 1639219089Spjd} 1640219089Spjd 1641243674Smmvoid 1642243674Smmzpool_print_unsup_feat(nvlist_t *config) 1643243674Smm{ 1644243674Smm nvlist_t *nvinfo, *unsup_feat; 1645243674Smm 1646243674Smm verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 1647243674Smm 0); 1648243674Smm verify(nvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT, 1649243674Smm &unsup_feat) == 0); 1650243674Smm 1651243674Smm for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL); nvp != NULL; 1652243674Smm nvp = nvlist_next_nvpair(unsup_feat, nvp)) { 1653243674Smm char *desc; 1654243674Smm 1655243674Smm verify(nvpair_type(nvp) == DATA_TYPE_STRING); 1656243674Smm verify(nvpair_value_string(nvp, &desc) == 0); 1657243674Smm 1658243674Smm if (strlen(desc) > 0) 1659243674Smm (void) printf("\t%s (%s)\n", nvpair_name(nvp), desc); 1660243674Smm else 1661243674Smm (void) printf("\t%s\n", nvpair_name(nvp)); 1662243674Smm } 1663243674Smm} 1664243674Smm 1665185029Spjd/* 1666185029Spjd * Import the given pool using the known configuration and a list of 1667185029Spjd * properties to be set. The configuration should have come from 1668185029Spjd * zpool_find_import(). The 'newname' parameters control whether the pool 1669185029Spjd * is imported with a different name. 1670185029Spjd */ 1671185029Spjdint 1672185029Spjdzpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 1673219089Spjd nvlist_t *props, int flags) 1674185029Spjd{ 1675168404Spjd zfs_cmd_t zc = { 0 }; 1676219089Spjd zpool_rewind_policy_t policy; 1677219089Spjd nvlist_t *nv = NULL; 1678219089Spjd nvlist_t *nvinfo = NULL; 1679219089Spjd nvlist_t *missing = NULL; 1680168404Spjd char *thename; 1681168404Spjd char *origname; 1682168404Spjd int ret; 1683219089Spjd int error = 0; 1684185029Spjd char errbuf[1024]; 1685168404Spjd 1686168404Spjd verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1687168404Spjd &origname) == 0); 1688168404Spjd 1689185029Spjd (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 1690185029Spjd "cannot import pool '%s'"), origname); 1691185029Spjd 1692168404Spjd if (newname != NULL) { 1693168404Spjd if (!zpool_name_valid(hdl, B_FALSE, newname)) 1694168404Spjd return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 1695168404Spjd dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1696168404Spjd newname)); 1697168404Spjd thename = (char *)newname; 1698168404Spjd } else { 1699168404Spjd thename = origname; 1700168404Spjd } 1701168404Spjd 1702185029Spjd if (props) { 1703185029Spjd uint64_t version; 1704219089Spjd prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE }; 1705168404Spjd 1706185029Spjd verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 1707185029Spjd &version) == 0); 1708185029Spjd 1709185029Spjd if ((props = zpool_valid_proplist(hdl, origname, 1710219089Spjd props, version, flags, errbuf)) == NULL) { 1711185029Spjd return (-1); 1712185029Spjd } else if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) { 1713185029Spjd nvlist_free(props); 1714185029Spjd return (-1); 1715185029Spjd } 1716185029Spjd } 1717185029Spjd 1718168404Spjd (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 1719168404Spjd 1720168404Spjd verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1721168404Spjd &zc.zc_guid) == 0); 1722168404Spjd 1723185029Spjd if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) { 1724185029Spjd nvlist_free(props); 1725168404Spjd return (-1); 1726185029Spjd } 1727219089Spjd if (zcmd_alloc_dst_nvlist(hdl, &zc, zc.zc_nvlist_conf_size * 2) != 0) { 1728219089Spjd nvlist_free(props); 1729219089Spjd return (-1); 1730219089Spjd } 1731168404Spjd 1732219089Spjd zc.zc_cookie = flags; 1733219089Spjd while ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc)) != 0 && 1734219089Spjd errno == ENOMEM) { 1735219089Spjd if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 1736219089Spjd zcmd_free_nvlists(&zc); 1737219089Spjd return (-1); 1738219089Spjd } 1739219089Spjd } 1740219089Spjd if (ret != 0) 1741219089Spjd error = errno; 1742219089Spjd 1743219089Spjd (void) zcmd_read_dst_nvlist(hdl, &zc, &nv); 1744219089Spjd zpool_get_rewind_policy(config, &policy); 1745219089Spjd 1746219089Spjd if (error) { 1747168404Spjd char desc[1024]; 1748219089Spjd 1749219089Spjd /* 1750219089Spjd * Dry-run failed, but we print out what success 1751219089Spjd * looks like if we found a best txg 1752219089Spjd */ 1753219089Spjd if (policy.zrp_request & ZPOOL_TRY_REWIND) { 1754219089Spjd zpool_rewind_exclaim(hdl, newname ? origname : thename, 1755219089Spjd B_TRUE, nv); 1756219089Spjd nvlist_free(nv); 1757219089Spjd return (-1); 1758219089Spjd } 1759219089Spjd 1760168404Spjd if (newname == NULL) 1761168404Spjd (void) snprintf(desc, sizeof (desc), 1762168404Spjd dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1763168404Spjd thename); 1764168404Spjd else 1765168404Spjd (void) snprintf(desc, sizeof (desc), 1766168404Spjd dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 1767168404Spjd origname, thename); 1768168404Spjd 1769219089Spjd switch (error) { 1770168404Spjd case ENOTSUP: 1771243674Smm if (nv != NULL && nvlist_lookup_nvlist(nv, 1772243674Smm ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 && 1773243674Smm nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) { 1774243674Smm (void) printf(dgettext(TEXT_DOMAIN, "This " 1775243674Smm "pool uses the following feature(s) not " 1776243674Smm "supported by this system:\n")); 1777243674Smm zpool_print_unsup_feat(nv); 1778243674Smm if (nvlist_exists(nvinfo, 1779243674Smm ZPOOL_CONFIG_CAN_RDONLY)) { 1780243674Smm (void) printf(dgettext(TEXT_DOMAIN, 1781243674Smm "All unsupported features are only " 1782243674Smm "required for writing to the pool." 1783243674Smm "\nThe pool can be imported using " 1784243674Smm "'-o readonly=on'.\n")); 1785243674Smm } 1786243674Smm } 1787168404Spjd /* 1788168404Spjd * Unsupported version. 1789168404Spjd */ 1790168404Spjd (void) zfs_error(hdl, EZFS_BADVERSION, desc); 1791168404Spjd break; 1792168404Spjd 1793168404Spjd case EINVAL: 1794168404Spjd (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 1795168404Spjd break; 1796168404Spjd 1797219089Spjd case EROFS: 1798219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1799219089Spjd "one or more devices is read only")); 1800219089Spjd (void) zfs_error(hdl, EZFS_BADDEV, desc); 1801219089Spjd break; 1802219089Spjd 1803219089Spjd case ENXIO: 1804219089Spjd if (nv && nvlist_lookup_nvlist(nv, 1805219089Spjd ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 && 1806219089Spjd nvlist_lookup_nvlist(nvinfo, 1807219089Spjd ZPOOL_CONFIG_MISSING_DEVICES, &missing) == 0) { 1808219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1809219089Spjd "The devices below are missing, use " 1810219089Spjd "'-m' to import the pool anyway:\n")); 1811219089Spjd print_vdev_tree(hdl, NULL, missing, 2); 1812219089Spjd (void) printf("\n"); 1813219089Spjd } 1814219089Spjd (void) zpool_standard_error(hdl, error, desc); 1815219089Spjd break; 1816219089Spjd 1817219089Spjd case EEXIST: 1818219089Spjd (void) zpool_standard_error(hdl, error, desc); 1819219089Spjd break; 1820219089Spjd 1821168404Spjd default: 1822219089Spjd (void) zpool_standard_error(hdl, error, desc); 1823219089Spjd zpool_explain_recover(hdl, 1824219089Spjd newname ? origname : thename, -error, nv); 1825219089Spjd break; 1826168404Spjd } 1827168404Spjd 1828219089Spjd nvlist_free(nv); 1829168404Spjd ret = -1; 1830168404Spjd } else { 1831168404Spjd zpool_handle_t *zhp; 1832185029Spjd 1833168404Spjd /* 1834168404Spjd * This should never fail, but play it safe anyway. 1835168404Spjd */ 1836219089Spjd if (zpool_open_silent(hdl, thename, &zhp) != 0) 1837168404Spjd ret = -1; 1838219089Spjd else if (zhp != NULL) 1839168404Spjd zpool_close(zhp); 1840219089Spjd if (policy.zrp_request & 1841219089Spjd (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) { 1842219089Spjd zpool_rewind_exclaim(hdl, newname ? origname : thename, 1843219089Spjd ((policy.zrp_request & ZPOOL_TRY_REWIND) != 0), nv); 1844168404Spjd } 1845219089Spjd nvlist_free(nv); 1846219089Spjd return (0); 1847168404Spjd } 1848168404Spjd 1849168404Spjd zcmd_free_nvlists(&zc); 1850185029Spjd nvlist_free(props); 1851185029Spjd 1852168404Spjd return (ret); 1853168404Spjd} 1854168404Spjd 1855168404Spjd/* 1856219089Spjd * Scan the pool. 1857168404Spjd */ 1858168404Spjdint 1859219089Spjdzpool_scan(zpool_handle_t *zhp, pool_scan_func_t func) 1860168404Spjd{ 1861168404Spjd zfs_cmd_t zc = { 0 }; 1862168404Spjd char msg[1024]; 1863168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 1864168404Spjd 1865168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1866219089Spjd zc.zc_cookie = func; 1867168404Spjd 1868219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0 || 1869219089Spjd (errno == ENOENT && func != POOL_SCAN_NONE)) 1870168404Spjd return (0); 1871168404Spjd 1872219089Spjd if (func == POOL_SCAN_SCRUB) { 1873219089Spjd (void) snprintf(msg, sizeof (msg), 1874219089Spjd dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 1875219089Spjd } else if (func == POOL_SCAN_NONE) { 1876219089Spjd (void) snprintf(msg, sizeof (msg), 1877219089Spjd dgettext(TEXT_DOMAIN, "cannot cancel scrubbing %s"), 1878219089Spjd zc.zc_name); 1879219089Spjd } else { 1880219089Spjd assert(!"unexpected result"); 1881219089Spjd } 1882168404Spjd 1883219089Spjd if (errno == EBUSY) { 1884219089Spjd nvlist_t *nvroot; 1885219089Spjd pool_scan_stat_t *ps = NULL; 1886219089Spjd uint_t psc; 1887219089Spjd 1888219089Spjd verify(nvlist_lookup_nvlist(zhp->zpool_config, 1889219089Spjd ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 1890219089Spjd (void) nvlist_lookup_uint64_array(nvroot, 1891219089Spjd ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc); 1892219089Spjd if (ps && ps->pss_func == POOL_SCAN_SCRUB) 1893219089Spjd return (zfs_error(hdl, EZFS_SCRUBBING, msg)); 1894219089Spjd else 1895219089Spjd return (zfs_error(hdl, EZFS_RESILVERING, msg)); 1896219089Spjd } else if (errno == ENOENT) { 1897219089Spjd return (zfs_error(hdl, EZFS_NO_SCRUB, msg)); 1898219089Spjd } else { 1899168404Spjd return (zpool_standard_error(hdl, errno, msg)); 1900219089Spjd } 1901168404Spjd} 1902168404Spjd 1903168404Spjd/* 1904219089Spjd * This provides a very minimal check whether a given string is likely a 1905219089Spjd * c#t#d# style string. Users of this are expected to do their own 1906219089Spjd * verification of the s# part. 1907219089Spjd */ 1908219089Spjd#define CTD_CHECK(str) (str && str[0] == 'c' && isdigit(str[1])) 1909219089Spjd 1910219089Spjd/* 1911219089Spjd * More elaborate version for ones which may start with "/dev/dsk/" 1912219089Spjd * and the like. 1913219089Spjd */ 1914219089Spjdstatic int 1915219089Spjdctd_check_path(char *str) { 1916219089Spjd /* 1917219089Spjd * If it starts with a slash, check the last component. 1918219089Spjd */ 1919219089Spjd if (str && str[0] == '/') { 1920219089Spjd char *tmp = strrchr(str, '/'); 1921219089Spjd 1922219089Spjd /* 1923219089Spjd * If it ends in "/old", check the second-to-last 1924219089Spjd * component of the string instead. 1925219089Spjd */ 1926219089Spjd if (tmp != str && strcmp(tmp, "/old") == 0) { 1927219089Spjd for (tmp--; *tmp != '/'; tmp--) 1928219089Spjd ; 1929219089Spjd } 1930219089Spjd str = tmp + 1; 1931219089Spjd } 1932219089Spjd return (CTD_CHECK(str)); 1933219089Spjd} 1934219089Spjd 1935219089Spjd/* 1936219089Spjd * Find a vdev that matches the search criteria specified. We use the 1937219089Spjd * the nvpair name to determine how we should look for the device. 1938168404Spjd * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 1939168404Spjd * spare; but FALSE if its an INUSE spare. 1940168404Spjd */ 1941168404Spjdstatic nvlist_t * 1942219089Spjdvdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare, 1943219089Spjd boolean_t *l2cache, boolean_t *log) 1944168404Spjd{ 1945168404Spjd uint_t c, children; 1946168404Spjd nvlist_t **child; 1947168404Spjd nvlist_t *ret; 1948185029Spjd uint64_t is_log; 1949219089Spjd char *srchkey; 1950219089Spjd nvpair_t *pair = nvlist_next_nvpair(search, NULL); 1951168404Spjd 1952219089Spjd /* Nothing to look for */ 1953219089Spjd if (search == NULL || pair == NULL) 1954219089Spjd return (NULL); 1955168404Spjd 1956219089Spjd /* Obtain the key we will use to search */ 1957219089Spjd srchkey = nvpair_name(pair); 1958219089Spjd 1959219089Spjd switch (nvpair_type(pair)) { 1960219089Spjd case DATA_TYPE_UINT64: 1961219089Spjd if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) { 1962219089Spjd uint64_t srchval, theguid; 1963219089Spjd 1964219089Spjd verify(nvpair_value_uint64(pair, &srchval) == 0); 1965219089Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1966219089Spjd &theguid) == 0); 1967219089Spjd if (theguid == srchval) 1968219089Spjd return (nv); 1969219089Spjd } 1970219089Spjd break; 1971219089Spjd 1972219089Spjd case DATA_TYPE_STRING: { 1973219089Spjd char *srchval, *val; 1974219089Spjd 1975219089Spjd verify(nvpair_value_string(pair, &srchval) == 0); 1976219089Spjd if (nvlist_lookup_string(nv, srchkey, &val) != 0) 1977219089Spjd break; 1978219089Spjd 1979168404Spjd /* 1980219089Spjd * Search for the requested value. Special cases: 1981219089Spjd * 1982219089Spjd * - ZPOOL_CONFIG_PATH for whole disk entries. These end in 1983219089Spjd * "s0" or "s0/old". The "s0" part is hidden from the user, 1984219089Spjd * but included in the string, so this matches around it. 1985219089Spjd * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE). 1986219089Spjd * 1987219089Spjd * Otherwise, all other searches are simple string compares. 1988168404Spjd */ 1989219089Spjd if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0 && 1990219089Spjd ctd_check_path(val)) { 1991219089Spjd uint64_t wholedisk = 0; 1992219089Spjd 1993219089Spjd (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 1994219089Spjd &wholedisk); 1995219089Spjd if (wholedisk) { 1996219089Spjd int slen = strlen(srchval); 1997219089Spjd int vlen = strlen(val); 1998219089Spjd 1999219089Spjd if (slen != vlen - 2) 2000219089Spjd break; 2001219089Spjd 2002219089Spjd /* 2003219089Spjd * make_leaf_vdev() should only set 2004219089Spjd * wholedisk for ZPOOL_CONFIG_PATHs which 2005219089Spjd * will include "/dev/dsk/", giving plenty of 2006219089Spjd * room for the indices used next. 2007219089Spjd */ 2008219089Spjd ASSERT(vlen >= 6); 2009219089Spjd 2010219089Spjd /* 2011219089Spjd * strings identical except trailing "s0" 2012219089Spjd */ 2013219089Spjd if (strcmp(&val[vlen - 2], "s0") == 0 && 2014219089Spjd strncmp(srchval, val, slen) == 0) 2015219089Spjd return (nv); 2016219089Spjd 2017219089Spjd /* 2018219089Spjd * strings identical except trailing "s0/old" 2019219089Spjd */ 2020219089Spjd if (strcmp(&val[vlen - 6], "s0/old") == 0 && 2021219089Spjd strcmp(&srchval[slen - 4], "/old") == 0 && 2022219089Spjd strncmp(srchval, val, slen - 4) == 0) 2023219089Spjd return (nv); 2024219089Spjd 2025219089Spjd break; 2026219089Spjd } 2027219089Spjd } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) { 2028219089Spjd char *type, *idx, *end, *p; 2029219089Spjd uint64_t id, vdev_id; 2030219089Spjd 2031168404Spjd /* 2032219089Spjd * Determine our vdev type, keeping in mind 2033219089Spjd * that the srchval is composed of a type and 2034219089Spjd * vdev id pair (i.e. mirror-4). 2035168404Spjd */ 2036219089Spjd if ((type = strdup(srchval)) == NULL) 2037219089Spjd return (NULL); 2038219089Spjd 2039219089Spjd if ((p = strrchr(type, '-')) == NULL) { 2040219089Spjd free(type); 2041219089Spjd break; 2042219089Spjd } 2043219089Spjd idx = p + 1; 2044219089Spjd *p = '\0'; 2045219089Spjd 2046219089Spjd /* 2047219089Spjd * If the types don't match then keep looking. 2048219089Spjd */ 2049219089Spjd if (strncmp(val, type, strlen(val)) != 0) { 2050219089Spjd free(type); 2051219089Spjd break; 2052219089Spjd } 2053219089Spjd 2054219089Spjd verify(strncmp(type, VDEV_TYPE_RAIDZ, 2055219089Spjd strlen(VDEV_TYPE_RAIDZ)) == 0 || 2056219089Spjd strncmp(type, VDEV_TYPE_MIRROR, 2057219089Spjd strlen(VDEV_TYPE_MIRROR)) == 0); 2058219089Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID, 2059219089Spjd &id) == 0); 2060219089Spjd 2061219089Spjd errno = 0; 2062219089Spjd vdev_id = strtoull(idx, &end, 10); 2063219089Spjd 2064219089Spjd free(type); 2065219089Spjd if (errno != 0) 2066219089Spjd return (NULL); 2067219089Spjd 2068219089Spjd /* 2069219089Spjd * Now verify that we have the correct vdev id. 2070219089Spjd */ 2071219089Spjd if (vdev_id == id) 2072168404Spjd return (nv); 2073219089Spjd } 2074219089Spjd 2075219089Spjd /* 2076219089Spjd * Common case 2077219089Spjd */ 2078219089Spjd if (strcmp(srchval, val) == 0) 2079168404Spjd return (nv); 2080219089Spjd break; 2081168404Spjd } 2082168404Spjd 2083219089Spjd default: 2084219089Spjd break; 2085219089Spjd } 2086219089Spjd 2087168404Spjd if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2088168404Spjd &child, &children) != 0) 2089168404Spjd return (NULL); 2090168404Spjd 2091185029Spjd for (c = 0; c < children; c++) { 2092219089Spjd if ((ret = vdev_to_nvlist_iter(child[c], search, 2093185029Spjd avail_spare, l2cache, NULL)) != NULL) { 2094185029Spjd /* 2095185029Spjd * The 'is_log' value is only set for the toplevel 2096185029Spjd * vdev, not the leaf vdevs. So we always lookup the 2097185029Spjd * log device from the root of the vdev tree (where 2098185029Spjd * 'log' is non-NULL). 2099185029Spjd */ 2100185029Spjd if (log != NULL && 2101185029Spjd nvlist_lookup_uint64(child[c], 2102185029Spjd ZPOOL_CONFIG_IS_LOG, &is_log) == 0 && 2103185029Spjd is_log) { 2104185029Spjd *log = B_TRUE; 2105185029Spjd } 2106168404Spjd return (ret); 2107185029Spjd } 2108185029Spjd } 2109168404Spjd 2110168404Spjd if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 2111168404Spjd &child, &children) == 0) { 2112168404Spjd for (c = 0; c < children; c++) { 2113219089Spjd if ((ret = vdev_to_nvlist_iter(child[c], search, 2114185029Spjd avail_spare, l2cache, NULL)) != NULL) { 2115168404Spjd *avail_spare = B_TRUE; 2116168404Spjd return (ret); 2117168404Spjd } 2118168404Spjd } 2119168404Spjd } 2120168404Spjd 2121185029Spjd if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 2122185029Spjd &child, &children) == 0) { 2123185029Spjd for (c = 0; c < children; c++) { 2124219089Spjd if ((ret = vdev_to_nvlist_iter(child[c], search, 2125185029Spjd avail_spare, l2cache, NULL)) != NULL) { 2126185029Spjd *l2cache = B_TRUE; 2127185029Spjd return (ret); 2128185029Spjd } 2129185029Spjd } 2130185029Spjd } 2131185029Spjd 2132168404Spjd return (NULL); 2133168404Spjd} 2134168404Spjd 2135219089Spjd/* 2136219089Spjd * Given a physical path (minus the "/devices" prefix), find the 2137219089Spjd * associated vdev. 2138219089Spjd */ 2139168404Spjdnvlist_t * 2140219089Spjdzpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath, 2141219089Spjd boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log) 2142219089Spjd{ 2143219089Spjd nvlist_t *search, *nvroot, *ret; 2144219089Spjd 2145219089Spjd verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0); 2146219089Spjd verify(nvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath) == 0); 2147219089Spjd 2148219089Spjd verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 2149219089Spjd &nvroot) == 0); 2150219089Spjd 2151219089Spjd *avail_spare = B_FALSE; 2152219089Spjd *l2cache = B_FALSE; 2153219089Spjd if (log != NULL) 2154219089Spjd *log = B_FALSE; 2155219089Spjd ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log); 2156219089Spjd nvlist_free(search); 2157219089Spjd 2158219089Spjd return (ret); 2159219089Spjd} 2160219089Spjd 2161219089Spjd/* 2162219089Spjd * Determine if we have an "interior" top-level vdev (i.e mirror/raidz). 2163219089Spjd */ 2164219089Spjdboolean_t 2165219089Spjdzpool_vdev_is_interior(const char *name) 2166219089Spjd{ 2167219089Spjd if (strncmp(name, VDEV_TYPE_RAIDZ, strlen(VDEV_TYPE_RAIDZ)) == 0 || 2168219089Spjd strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0) 2169219089Spjd return (B_TRUE); 2170219089Spjd return (B_FALSE); 2171219089Spjd} 2172219089Spjd 2173219089Spjdnvlist_t * 2174185029Spjdzpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare, 2175185029Spjd boolean_t *l2cache, boolean_t *log) 2176168404Spjd{ 2177168404Spjd char buf[MAXPATHLEN]; 2178168404Spjd char *end; 2179219089Spjd nvlist_t *nvroot, *search, *ret; 2180168404Spjd uint64_t guid; 2181168404Spjd 2182219089Spjd verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0); 2183219089Spjd 2184168404Spjd guid = strtoull(path, &end, 10); 2185168404Spjd if (guid != 0 && *end == '\0') { 2186219089Spjd verify(nvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid) == 0); 2187219089Spjd } else if (zpool_vdev_is_interior(path)) { 2188219089Spjd verify(nvlist_add_string(search, ZPOOL_CONFIG_TYPE, path) == 0); 2189168404Spjd } else if (path[0] != '/') { 2190168404Spjd (void) snprintf(buf, sizeof (buf), "%s%s", _PATH_DEV, path); 2191219089Spjd verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, buf) == 0); 2192168404Spjd } else { 2193219089Spjd verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, path) == 0); 2194168404Spjd } 2195168404Spjd 2196168404Spjd verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 2197168404Spjd &nvroot) == 0); 2198168404Spjd 2199168404Spjd *avail_spare = B_FALSE; 2200185029Spjd *l2cache = B_FALSE; 2201185029Spjd if (log != NULL) 2202185029Spjd *log = B_FALSE; 2203219089Spjd ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log); 2204219089Spjd nvlist_free(search); 2205219089Spjd 2206219089Spjd return (ret); 2207168404Spjd} 2208168404Spjd 2209185029Spjdstatic int 2210185029Spjdvdev_online(nvlist_t *nv) 2211185029Spjd{ 2212185029Spjd uint64_t ival; 2213185029Spjd 2214185029Spjd if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE, &ival) == 0 || 2215185029Spjd nvlist_lookup_uint64(nv, ZPOOL_CONFIG_FAULTED, &ival) == 0 || 2216185029Spjd nvlist_lookup_uint64(nv, ZPOOL_CONFIG_REMOVED, &ival) == 0) 2217185029Spjd return (0); 2218185029Spjd 2219185029Spjd return (1); 2220185029Spjd} 2221185029Spjd 2222168404Spjd/* 2223219089Spjd * Helper function for zpool_get_physpaths(). 2224168404Spjd */ 2225219089Spjdstatic int 2226219089Spjdvdev_get_one_physpath(nvlist_t *config, char *physpath, size_t physpath_size, 2227219089Spjd size_t *bytes_written) 2228185029Spjd{ 2229219089Spjd size_t bytes_left, pos, rsz; 2230219089Spjd char *tmppath; 2231219089Spjd const char *format; 2232185029Spjd 2233219089Spjd if (nvlist_lookup_string(config, ZPOOL_CONFIG_PHYS_PATH, 2234219089Spjd &tmppath) != 0) 2235219089Spjd return (EZFS_NODEVICE); 2236185029Spjd 2237219089Spjd pos = *bytes_written; 2238219089Spjd bytes_left = physpath_size - pos; 2239219089Spjd format = (pos == 0) ? "%s" : " %s"; 2240185029Spjd 2241219089Spjd rsz = snprintf(physpath + pos, bytes_left, format, tmppath); 2242219089Spjd *bytes_written += rsz; 2243185029Spjd 2244219089Spjd if (rsz >= bytes_left) { 2245219089Spjd /* if physpath was not copied properly, clear it */ 2246219089Spjd if (bytes_left != 0) { 2247219089Spjd physpath[pos] = 0; 2248219089Spjd } 2249219089Spjd return (EZFS_NOSPC); 2250219089Spjd } 2251219089Spjd return (0); 2252219089Spjd} 2253185029Spjd 2254219089Spjdstatic int 2255219089Spjdvdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size, 2256219089Spjd size_t *rsz, boolean_t is_spare) 2257219089Spjd{ 2258219089Spjd char *type; 2259219089Spjd int ret; 2260185029Spjd 2261219089Spjd if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0) 2262219089Spjd return (EZFS_INVALCONFIG); 2263185029Spjd 2264219089Spjd if (strcmp(type, VDEV_TYPE_DISK) == 0) { 2265219089Spjd /* 2266219089Spjd * An active spare device has ZPOOL_CONFIG_IS_SPARE set. 2267219089Spjd * For a spare vdev, we only want to boot from the active 2268219089Spjd * spare device. 2269219089Spjd */ 2270219089Spjd if (is_spare) { 2271219089Spjd uint64_t spare = 0; 2272219089Spjd (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_SPARE, 2273219089Spjd &spare); 2274219089Spjd if (!spare) 2275219089Spjd return (EZFS_INVALCONFIG); 2276219089Spjd } 2277185029Spjd 2278219089Spjd if (vdev_online(nv)) { 2279219089Spjd if ((ret = vdev_get_one_physpath(nv, physpath, 2280219089Spjd phypath_size, rsz)) != 0) 2281219089Spjd return (ret); 2282219089Spjd } 2283219089Spjd } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 || 2284219089Spjd strcmp(type, VDEV_TYPE_REPLACING) == 0 || 2285219089Spjd (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) { 2286219089Spjd nvlist_t **child; 2287219089Spjd uint_t count; 2288219089Spjd int i, ret; 2289185029Spjd 2290219089Spjd if (nvlist_lookup_nvlist_array(nv, 2291219089Spjd ZPOOL_CONFIG_CHILDREN, &child, &count) != 0) 2292219089Spjd return (EZFS_INVALCONFIG); 2293219089Spjd 2294219089Spjd for (i = 0; i < count; i++) { 2295219089Spjd ret = vdev_get_physpaths(child[i], physpath, 2296219089Spjd phypath_size, rsz, is_spare); 2297219089Spjd if (ret == EZFS_NOSPC) 2298219089Spjd return (ret); 2299185029Spjd } 2300185029Spjd } 2301185029Spjd 2302219089Spjd return (EZFS_POOL_INVALARG); 2303185029Spjd} 2304185029Spjd 2305185029Spjd/* 2306219089Spjd * Get phys_path for a root pool config. 2307219089Spjd * Return 0 on success; non-zero on failure. 2308185029Spjd */ 2309219089Spjdstatic int 2310219089Spjdzpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size) 2311168404Spjd{ 2312219089Spjd size_t rsz; 2313219089Spjd nvlist_t *vdev_root; 2314219089Spjd nvlist_t **child; 2315185029Spjd uint_t count; 2316219089Spjd char *type; 2317168404Spjd 2318219089Spjd rsz = 0; 2319219089Spjd 2320219089Spjd if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2321219089Spjd &vdev_root) != 0) 2322219089Spjd return (EZFS_INVALCONFIG); 2323219089Spjd 2324219089Spjd if (nvlist_lookup_string(vdev_root, ZPOOL_CONFIG_TYPE, &type) != 0 || 2325219089Spjd nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN, 2326219089Spjd &child, &count) != 0) 2327219089Spjd return (EZFS_INVALCONFIG); 2328219089Spjd 2329219089Spjd /* 2330219089Spjd * root pool can not have EFI labeled disks and can only have 2331219089Spjd * a single top-level vdev. 2332219089Spjd */ 2333219089Spjd if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1 || 2334219089Spjd pool_uses_efi(vdev_root)) 2335219089Spjd return (EZFS_POOL_INVALARG); 2336219089Spjd 2337219089Spjd (void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz, 2338219089Spjd B_FALSE); 2339219089Spjd 2340219089Spjd /* No online devices */ 2341219089Spjd if (rsz == 0) 2342219089Spjd return (EZFS_NODEVICE); 2343219089Spjd 2344219089Spjd return (0); 2345219089Spjd} 2346219089Spjd 2347219089Spjd/* 2348219089Spjd * Get phys_path for a root pool 2349219089Spjd * Return 0 on success; non-zero on failure. 2350219089Spjd */ 2351219089Spjdint 2352219089Spjdzpool_get_physpath(zpool_handle_t *zhp, char *physpath, size_t phypath_size) 2353219089Spjd{ 2354219089Spjd return (zpool_get_config_physpath(zhp->zpool_config, physpath, 2355219089Spjd phypath_size)); 2356219089Spjd} 2357219089Spjd 2358219089Spjd/* 2359219089Spjd * If the device has being dynamically expanded then we need to relabel 2360219089Spjd * the disk to use the new unallocated space. 2361219089Spjd */ 2362219089Spjdstatic int 2363219089Spjdzpool_relabel_disk(libzfs_handle_t *hdl, const char *name) 2364219089Spjd{ 2365219089Spjd#ifdef sun 2366219089Spjd char path[MAXPATHLEN]; 2367219089Spjd char errbuf[1024]; 2368219089Spjd int fd, error; 2369219089Spjd int (*_efi_use_whole_disk)(int); 2370219089Spjd 2371219089Spjd if ((_efi_use_whole_disk = (int (*)(int))dlsym(RTLD_DEFAULT, 2372219089Spjd "efi_use_whole_disk")) == NULL) 2373219089Spjd return (-1); 2374219089Spjd 2375219089Spjd (void) snprintf(path, sizeof (path), "%s/%s", RDISK_ROOT, name); 2376219089Spjd 2377219089Spjd if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) { 2378219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 2379219089Spjd "relabel '%s': unable to open device"), name); 2380219089Spjd return (zfs_error(hdl, EZFS_OPENFAILED, errbuf)); 2381168404Spjd } 2382168404Spjd 2383219089Spjd /* 2384219089Spjd * It's possible that we might encounter an error if the device 2385219089Spjd * does not have any unallocated space left. If so, we simply 2386219089Spjd * ignore that error and continue on. 2387219089Spjd */ 2388219089Spjd error = _efi_use_whole_disk(fd); 2389219089Spjd (void) close(fd); 2390219089Spjd if (error && error != VT_ENOSPC) { 2391219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 2392219089Spjd "relabel '%s': unable to read disk capacity"), name); 2393219089Spjd return (zfs_error(hdl, EZFS_NOCAP, errbuf)); 2394219089Spjd } 2395219089Spjd#endif /* sun */ 2396219089Spjd return (0); 2397168404Spjd} 2398168404Spjd 2399168404Spjd/* 2400185029Spjd * Bring the specified vdev online. The 'flags' parameter is a set of the 2401185029Spjd * ZFS_ONLINE_* flags. 2402168404Spjd */ 2403168404Spjdint 2404185029Spjdzpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags, 2405185029Spjd vdev_state_t *newstate) 2406168404Spjd{ 2407168404Spjd zfs_cmd_t zc = { 0 }; 2408168404Spjd char msg[1024]; 2409168404Spjd nvlist_t *tgt; 2410219089Spjd boolean_t avail_spare, l2cache, islog; 2411168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2412168404Spjd 2413219089Spjd if (flags & ZFS_ONLINE_EXPAND) { 2414219089Spjd (void) snprintf(msg, sizeof (msg), 2415219089Spjd dgettext(TEXT_DOMAIN, "cannot expand %s"), path); 2416219089Spjd } else { 2417219089Spjd (void) snprintf(msg, sizeof (msg), 2418219089Spjd dgettext(TEXT_DOMAIN, "cannot online %s"), path); 2419219089Spjd } 2420168404Spjd 2421168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2422185029Spjd if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, 2423219089Spjd &islog)) == NULL) 2424168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 2425168404Spjd 2426168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 2427168404Spjd 2428219089Spjd if (avail_spare) 2429168404Spjd return (zfs_error(hdl, EZFS_ISSPARE, msg)); 2430168404Spjd 2431219089Spjd if (flags & ZFS_ONLINE_EXPAND || 2432219089Spjd zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) { 2433219089Spjd char *pathname = NULL; 2434219089Spjd uint64_t wholedisk = 0; 2435219089Spjd 2436219089Spjd (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK, 2437219089Spjd &wholedisk); 2438219089Spjd verify(nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, 2439219089Spjd &pathname) == 0); 2440219089Spjd 2441219089Spjd /* 2442219089Spjd * XXX - L2ARC 1.0 devices can't support expansion. 2443219089Spjd */ 2444219089Spjd if (l2cache) { 2445219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2446219089Spjd "cannot expand cache devices")); 2447219089Spjd return (zfs_error(hdl, EZFS_VDEVNOTSUP, msg)); 2448219089Spjd } 2449219089Spjd 2450219089Spjd if (wholedisk) { 2451219089Spjd pathname += strlen(DISK_ROOT) + 1; 2452219089Spjd (void) zpool_relabel_disk(hdl, pathname); 2453219089Spjd } 2454219089Spjd } 2455219089Spjd 2456185029Spjd zc.zc_cookie = VDEV_STATE_ONLINE; 2457185029Spjd zc.zc_obj = flags; 2458168404Spjd 2459219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) { 2460219089Spjd if (errno == EINVAL) { 2461219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "was split " 2462219089Spjd "from this pool into a new one. Use '%s' " 2463219089Spjd "instead"), "zpool detach"); 2464219089Spjd return (zfs_error(hdl, EZFS_POSTSPLIT_ONLINE, msg)); 2465219089Spjd } 2466185029Spjd return (zpool_standard_error(hdl, errno, msg)); 2467219089Spjd } 2468185029Spjd 2469185029Spjd *newstate = zc.zc_cookie; 2470185029Spjd return (0); 2471168404Spjd} 2472168404Spjd 2473168404Spjd/* 2474168404Spjd * Take the specified vdev offline 2475168404Spjd */ 2476168404Spjdint 2477185029Spjdzpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp) 2478168404Spjd{ 2479168404Spjd zfs_cmd_t zc = { 0 }; 2480168404Spjd char msg[1024]; 2481168404Spjd nvlist_t *tgt; 2482185029Spjd boolean_t avail_spare, l2cache; 2483168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2484168404Spjd 2485168404Spjd (void) snprintf(msg, sizeof (msg), 2486168404Spjd dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 2487168404Spjd 2488168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2489185029Spjd if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, 2490185029Spjd NULL)) == NULL) 2491168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 2492168404Spjd 2493168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 2494168404Spjd 2495219089Spjd if (avail_spare) 2496168404Spjd return (zfs_error(hdl, EZFS_ISSPARE, msg)); 2497168404Spjd 2498185029Spjd zc.zc_cookie = VDEV_STATE_OFFLINE; 2499185029Spjd zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0; 2500168404Spjd 2501219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 2502168404Spjd return (0); 2503168404Spjd 2504168404Spjd switch (errno) { 2505168404Spjd case EBUSY: 2506168404Spjd 2507168404Spjd /* 2508168404Spjd * There are no other replicas of this device. 2509168404Spjd */ 2510168404Spjd return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 2511168404Spjd 2512219089Spjd case EEXIST: 2513219089Spjd /* 2514219089Spjd * The log device has unplayed logs 2515219089Spjd */ 2516219089Spjd return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, msg)); 2517219089Spjd 2518168404Spjd default: 2519168404Spjd return (zpool_standard_error(hdl, errno, msg)); 2520168404Spjd } 2521168404Spjd} 2522168404Spjd 2523168404Spjd/* 2524185029Spjd * Mark the given vdev faulted. 2525185029Spjd */ 2526185029Spjdint 2527219089Spjdzpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux) 2528185029Spjd{ 2529185029Spjd zfs_cmd_t zc = { 0 }; 2530185029Spjd char msg[1024]; 2531185029Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2532185029Spjd 2533185029Spjd (void) snprintf(msg, sizeof (msg), 2534185029Spjd dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid); 2535185029Spjd 2536185029Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2537185029Spjd zc.zc_guid = guid; 2538185029Spjd zc.zc_cookie = VDEV_STATE_FAULTED; 2539219089Spjd zc.zc_obj = aux; 2540185029Spjd 2541219089Spjd if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 2542185029Spjd return (0); 2543185029Spjd 2544185029Spjd switch (errno) { 2545185029Spjd case EBUSY: 2546185029Spjd 2547185029Spjd /* 2548185029Spjd * There are no other replicas of this device. 2549185029Spjd */ 2550185029Spjd return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 2551185029Spjd 2552185029Spjd default: 2553185029Spjd return (zpool_standard_error(hdl, errno, msg)); 2554185029Spjd } 2555185029Spjd 2556185029Spjd} 2557185029Spjd 2558185029Spjd/* 2559185029Spjd * Mark the given vdev degraded. 2560185029Spjd */ 2561185029Spjdint 2562219089Spjdzpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux) 2563185029Spjd{ 2564185029Spjd zfs_cmd_t zc = { 0 }; 2565185029Spjd char msg[1024]; 2566185029Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2567185029Spjd 2568185029Spjd (void) snprintf(msg, sizeof (msg), 2569185029Spjd dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid); 2570185029Spjd 2571185029Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2572185029Spjd zc.zc_guid = guid; 2573185029Spjd zc.zc_cookie = VDEV_STATE_DEGRADED; 2574219089Spjd zc.zc_obj = aux; 2575185029Spjd 2576219089Spjd if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 2577185029Spjd return (0); 2578185029Spjd 2579185029Spjd return (zpool_standard_error(hdl, errno, msg)); 2580185029Spjd} 2581185029Spjd 2582185029Spjd/* 2583168404Spjd * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 2584168404Spjd * a hot spare. 2585168404Spjd */ 2586168404Spjdstatic boolean_t 2587168404Spjdis_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 2588168404Spjd{ 2589168404Spjd nvlist_t **child; 2590168404Spjd uint_t c, children; 2591168404Spjd char *type; 2592168404Spjd 2593168404Spjd if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 2594168404Spjd &children) == 0) { 2595168404Spjd verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 2596168404Spjd &type) == 0); 2597168404Spjd 2598168404Spjd if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 2599168404Spjd children == 2 && child[which] == tgt) 2600168404Spjd return (B_TRUE); 2601168404Spjd 2602168404Spjd for (c = 0; c < children; c++) 2603168404Spjd if (is_replacing_spare(child[c], tgt, which)) 2604168404Spjd return (B_TRUE); 2605168404Spjd } 2606168404Spjd 2607168404Spjd return (B_FALSE); 2608168404Spjd} 2609168404Spjd 2610168404Spjd/* 2611168404Spjd * Attach new_disk (fully described by nvroot) to old_disk. 2612185029Spjd * If 'replacing' is specified, the new disk will replace the old one. 2613168404Spjd */ 2614168404Spjdint 2615168404Spjdzpool_vdev_attach(zpool_handle_t *zhp, 2616168404Spjd const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 2617168404Spjd{ 2618168404Spjd zfs_cmd_t zc = { 0 }; 2619168404Spjd char msg[1024]; 2620168404Spjd int ret; 2621168404Spjd nvlist_t *tgt; 2622185029Spjd boolean_t avail_spare, l2cache, islog; 2623168404Spjd uint64_t val; 2624219089Spjd char *newname; 2625168404Spjd nvlist_t **child; 2626168404Spjd uint_t children; 2627168404Spjd nvlist_t *config_root; 2628168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2629236839Smm boolean_t rootpool = zpool_is_bootable(zhp); 2630168404Spjd 2631168404Spjd if (replacing) 2632168404Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 2633168404Spjd "cannot replace %s with %s"), old_disk, new_disk); 2634168404Spjd else 2635168404Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 2636168404Spjd "cannot attach %s to %s"), new_disk, old_disk); 2637168404Spjd 2638209962Smm /* 2639209962Smm * If this is a root pool, make sure that we're not attaching an 2640209962Smm * EFI labeled device. 2641209962Smm */ 2642209962Smm if (rootpool && pool_uses_efi(nvroot)) { 2643209962Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2644209962Smm "EFI labeled devices are not supported on root pools.")); 2645209962Smm return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg)); 2646209962Smm } 2647209962Smm 2648168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2649185029Spjd if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache, 2650185029Spjd &islog)) == 0) 2651168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 2652168404Spjd 2653168404Spjd if (avail_spare) 2654168404Spjd return (zfs_error(hdl, EZFS_ISSPARE, msg)); 2655168404Spjd 2656185029Spjd if (l2cache) 2657185029Spjd return (zfs_error(hdl, EZFS_ISL2CACHE, msg)); 2658185029Spjd 2659168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 2660168404Spjd zc.zc_cookie = replacing; 2661168404Spjd 2662168404Spjd if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 2663168404Spjd &child, &children) != 0 || children != 1) { 2664168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2665168404Spjd "new device must be a single disk")); 2666168404Spjd return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 2667168404Spjd } 2668168404Spjd 2669168404Spjd verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 2670168404Spjd ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 2671168404Spjd 2672219089Spjd if ((newname = zpool_vdev_name(NULL, NULL, child[0], B_FALSE)) == NULL) 2673185029Spjd return (-1); 2674185029Spjd 2675168404Spjd /* 2676168404Spjd * If the target is a hot spare that has been swapped in, we can only 2677168404Spjd * replace it with another hot spare. 2678168404Spjd */ 2679168404Spjd if (replacing && 2680168404Spjd nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 2681185029Spjd (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache, 2682185029Spjd NULL) == NULL || !avail_spare) && 2683185029Spjd is_replacing_spare(config_root, tgt, 1)) { 2684168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2685168404Spjd "can only be replaced by another hot spare")); 2686185029Spjd free(newname); 2687168404Spjd return (zfs_error(hdl, EZFS_BADTARGET, msg)); 2688168404Spjd } 2689168404Spjd 2690185029Spjd free(newname); 2691185029Spjd 2692185029Spjd if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 2693168404Spjd return (-1); 2694168404Spjd 2695219089Spjd ret = zfs_ioctl(hdl, ZFS_IOC_VDEV_ATTACH, &zc); 2696168404Spjd 2697168404Spjd zcmd_free_nvlists(&zc); 2698168404Spjd 2699209962Smm if (ret == 0) { 2700209962Smm if (rootpool) { 2701219089Spjd /* 2702219089Spjd * XXX need a better way to prevent user from 2703219089Spjd * booting up a half-baked vdev. 2704219089Spjd */ 2705219089Spjd (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Make " 2706219089Spjd "sure to wait until resilver is done " 2707219089Spjd "before rebooting.\n")); 2708219089Spjd (void) fprintf(stderr, "\n"); 2709216293Smm (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "If " 2710216293Smm "you boot from pool '%s', you may need to update\n" 2711216293Smm "boot code on newly attached disk '%s'.\n\n" 2712216293Smm "Assuming you use GPT partitioning and 'da0' is " 2713216293Smm "your new boot disk\n" 2714216293Smm "you may use the following command:\n\n" 2715216293Smm "\tgpart bootcode -b /boot/pmbr -p " 2716216293Smm "/boot/gptzfsboot -i 1 da0\n\n"), 2717216293Smm zhp->zpool_name, new_disk); 2718209962Smm } 2719168404Spjd return (0); 2720209962Smm } 2721168404Spjd 2722168404Spjd switch (errno) { 2723168404Spjd case ENOTSUP: 2724168404Spjd /* 2725168404Spjd * Can't attach to or replace this type of vdev. 2726168404Spjd */ 2727185029Spjd if (replacing) { 2728219089Spjd uint64_t version = zpool_get_prop_int(zhp, 2729219089Spjd ZPOOL_PROP_VERSION, NULL); 2730219089Spjd 2731185029Spjd if (islog) 2732185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2733185029Spjd "cannot replace a log with a spare")); 2734219089Spjd else if (version >= SPA_VERSION_MULTI_REPLACE) 2735219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2736219089Spjd "already in replacing/spare config; wait " 2737219089Spjd "for completion or use 'zpool detach'")); 2738185029Spjd else 2739185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2740185029Spjd "cannot replace a replacing device")); 2741185029Spjd } else { 2742168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2743168404Spjd "can only attach to mirrors and top-level " 2744168404Spjd "disks")); 2745185029Spjd } 2746168404Spjd (void) zfs_error(hdl, EZFS_BADTARGET, msg); 2747168404Spjd break; 2748168404Spjd 2749168404Spjd case EINVAL: 2750168404Spjd /* 2751168404Spjd * The new device must be a single disk. 2752168404Spjd */ 2753168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2754168404Spjd "new device must be a single disk")); 2755168404Spjd (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 2756168404Spjd break; 2757168404Spjd 2758168404Spjd case EBUSY: 2759168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 2760168404Spjd new_disk); 2761168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 2762168404Spjd break; 2763168404Spjd 2764168404Spjd case EOVERFLOW: 2765168404Spjd /* 2766168404Spjd * The new device is too small. 2767168404Spjd */ 2768168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2769168404Spjd "device is too small")); 2770168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 2771168404Spjd break; 2772168404Spjd 2773168404Spjd case EDOM: 2774168404Spjd /* 2775168404Spjd * The new device has a different alignment requirement. 2776168404Spjd */ 2777168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2778168404Spjd "devices have different sector alignment")); 2779168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 2780168404Spjd break; 2781168404Spjd 2782168404Spjd case ENAMETOOLONG: 2783168404Spjd /* 2784168404Spjd * The resulting top-level vdev spec won't fit in the label. 2785168404Spjd */ 2786168404Spjd (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 2787168404Spjd break; 2788168404Spjd 2789168404Spjd default: 2790168404Spjd (void) zpool_standard_error(hdl, errno, msg); 2791168404Spjd } 2792168404Spjd 2793168404Spjd return (-1); 2794168404Spjd} 2795168404Spjd 2796168404Spjd/* 2797168404Spjd * Detach the specified device. 2798168404Spjd */ 2799168404Spjdint 2800168404Spjdzpool_vdev_detach(zpool_handle_t *zhp, const char *path) 2801168404Spjd{ 2802168404Spjd zfs_cmd_t zc = { 0 }; 2803168404Spjd char msg[1024]; 2804168404Spjd nvlist_t *tgt; 2805185029Spjd boolean_t avail_spare, l2cache; 2806168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2807168404Spjd 2808168404Spjd (void) snprintf(msg, sizeof (msg), 2809168404Spjd dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 2810168404Spjd 2811168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2812185029Spjd if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, 2813185029Spjd NULL)) == 0) 2814168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 2815168404Spjd 2816168404Spjd if (avail_spare) 2817168404Spjd return (zfs_error(hdl, EZFS_ISSPARE, msg)); 2818168404Spjd 2819185029Spjd if (l2cache) 2820185029Spjd return (zfs_error(hdl, EZFS_ISL2CACHE, msg)); 2821185029Spjd 2822168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 2823168404Spjd 2824185029Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0) 2825168404Spjd return (0); 2826168404Spjd 2827168404Spjd switch (errno) { 2828168404Spjd 2829168404Spjd case ENOTSUP: 2830168404Spjd /* 2831168404Spjd * Can't detach from this type of vdev. 2832168404Spjd */ 2833168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 2834168404Spjd "applicable to mirror and replacing vdevs")); 2835219089Spjd (void) zfs_error(hdl, EZFS_BADTARGET, msg); 2836168404Spjd break; 2837168404Spjd 2838168404Spjd case EBUSY: 2839168404Spjd /* 2840168404Spjd * There are no other replicas of this device. 2841168404Spjd */ 2842168404Spjd (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 2843168404Spjd break; 2844168404Spjd 2845168404Spjd default: 2846168404Spjd (void) zpool_standard_error(hdl, errno, msg); 2847168404Spjd } 2848168404Spjd 2849168404Spjd return (-1); 2850168404Spjd} 2851168404Spjd 2852168404Spjd/* 2853219089Spjd * Find a mirror vdev in the source nvlist. 2854219089Spjd * 2855219089Spjd * The mchild array contains a list of disks in one of the top-level mirrors 2856219089Spjd * of the source pool. The schild array contains a list of disks that the 2857219089Spjd * user specified on the command line. We loop over the mchild array to 2858219089Spjd * see if any entry in the schild array matches. 2859219089Spjd * 2860219089Spjd * If a disk in the mchild array is found in the schild array, we return 2861219089Spjd * the index of that entry. Otherwise we return -1. 2862219089Spjd */ 2863219089Spjdstatic int 2864219089Spjdfind_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren, 2865219089Spjd nvlist_t **schild, uint_t schildren) 2866219089Spjd{ 2867219089Spjd uint_t mc; 2868219089Spjd 2869219089Spjd for (mc = 0; mc < mchildren; mc++) { 2870219089Spjd uint_t sc; 2871219089Spjd char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp, 2872219089Spjd mchild[mc], B_FALSE); 2873219089Spjd 2874219089Spjd for (sc = 0; sc < schildren; sc++) { 2875219089Spjd char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp, 2876219089Spjd schild[sc], B_FALSE); 2877219089Spjd boolean_t result = (strcmp(mpath, spath) == 0); 2878219089Spjd 2879219089Spjd free(spath); 2880219089Spjd if (result) { 2881219089Spjd free(mpath); 2882219089Spjd return (mc); 2883219089Spjd } 2884219089Spjd } 2885219089Spjd 2886219089Spjd free(mpath); 2887219089Spjd } 2888219089Spjd 2889219089Spjd return (-1); 2890219089Spjd} 2891219089Spjd 2892219089Spjd/* 2893219089Spjd * Split a mirror pool. If newroot points to null, then a new nvlist 2894219089Spjd * is generated and it is the responsibility of the caller to free it. 2895219089Spjd */ 2896219089Spjdint 2897219089Spjdzpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot, 2898219089Spjd nvlist_t *props, splitflags_t flags) 2899219089Spjd{ 2900219089Spjd zfs_cmd_t zc = { 0 }; 2901219089Spjd char msg[1024]; 2902219089Spjd nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL; 2903219089Spjd nvlist_t **varray = NULL, *zc_props = NULL; 2904219089Spjd uint_t c, children, newchildren, lastlog = 0, vcount, found = 0; 2905219089Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2906219089Spjd uint64_t vers; 2907219089Spjd boolean_t freelist = B_FALSE, memory_err = B_TRUE; 2908219089Spjd int retval = 0; 2909219089Spjd 2910219089Spjd (void) snprintf(msg, sizeof (msg), 2911219089Spjd dgettext(TEXT_DOMAIN, "Unable to split %s"), zhp->zpool_name); 2912219089Spjd 2913219089Spjd if (!zpool_name_valid(hdl, B_FALSE, newname)) 2914219089Spjd return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 2915219089Spjd 2916219089Spjd if ((config = zpool_get_config(zhp, NULL)) == NULL) { 2917219089Spjd (void) fprintf(stderr, gettext("Internal error: unable to " 2918219089Spjd "retrieve pool configuration\n")); 2919219089Spjd return (-1); 2920219089Spjd } 2921219089Spjd 2922219089Spjd verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &tree) 2923219089Spjd == 0); 2924219089Spjd verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &vers) == 0); 2925219089Spjd 2926219089Spjd if (props) { 2927219089Spjd prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE }; 2928219089Spjd if ((zc_props = zpool_valid_proplist(hdl, zhp->zpool_name, 2929219089Spjd props, vers, flags, msg)) == NULL) 2930219089Spjd return (-1); 2931219089Spjd } 2932219089Spjd 2933219089Spjd if (nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child, 2934219089Spjd &children) != 0) { 2935219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2936219089Spjd "Source pool is missing vdev tree")); 2937219089Spjd if (zc_props) 2938219089Spjd nvlist_free(zc_props); 2939219089Spjd return (-1); 2940219089Spjd } 2941219089Spjd 2942219089Spjd varray = zfs_alloc(hdl, children * sizeof (nvlist_t *)); 2943219089Spjd vcount = 0; 2944219089Spjd 2945219089Spjd if (*newroot == NULL || 2946219089Spjd nvlist_lookup_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN, 2947219089Spjd &newchild, &newchildren) != 0) 2948219089Spjd newchildren = 0; 2949219089Spjd 2950219089Spjd for (c = 0; c < children; c++) { 2951219089Spjd uint64_t is_log = B_FALSE, is_hole = B_FALSE; 2952219089Spjd char *type; 2953219089Spjd nvlist_t **mchild, *vdev; 2954219089Spjd uint_t mchildren; 2955219089Spjd int entry; 2956219089Spjd 2957219089Spjd /* 2958219089Spjd * Unlike cache & spares, slogs are stored in the 2959219089Spjd * ZPOOL_CONFIG_CHILDREN array. We filter them out here. 2960219089Spjd */ 2961219089Spjd (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 2962219089Spjd &is_log); 2963219089Spjd (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 2964219089Spjd &is_hole); 2965219089Spjd if (is_log || is_hole) { 2966219089Spjd /* 2967219089Spjd * Create a hole vdev and put it in the config. 2968219089Spjd */ 2969219089Spjd if (nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) != 0) 2970219089Spjd goto out; 2971219089Spjd if (nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, 2972219089Spjd VDEV_TYPE_HOLE) != 0) 2973219089Spjd goto out; 2974219089Spjd if (nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_HOLE, 2975219089Spjd 1) != 0) 2976219089Spjd goto out; 2977219089Spjd if (lastlog == 0) 2978219089Spjd lastlog = vcount; 2979219089Spjd varray[vcount++] = vdev; 2980219089Spjd continue; 2981219089Spjd } 2982219089Spjd lastlog = 0; 2983219089Spjd verify(nvlist_lookup_string(child[c], ZPOOL_CONFIG_TYPE, &type) 2984219089Spjd == 0); 2985219089Spjd if (strcmp(type, VDEV_TYPE_MIRROR) != 0) { 2986219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2987219089Spjd "Source pool must be composed only of mirrors\n")); 2988219089Spjd retval = zfs_error(hdl, EZFS_INVALCONFIG, msg); 2989219089Spjd goto out; 2990219089Spjd } 2991219089Spjd 2992219089Spjd verify(nvlist_lookup_nvlist_array(child[c], 2993219089Spjd ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0); 2994219089Spjd 2995219089Spjd /* find or add an entry for this top-level vdev */ 2996219089Spjd if (newchildren > 0 && 2997219089Spjd (entry = find_vdev_entry(zhp, mchild, mchildren, 2998219089Spjd newchild, newchildren)) >= 0) { 2999219089Spjd /* We found a disk that the user specified. */ 3000219089Spjd vdev = mchild[entry]; 3001219089Spjd ++found; 3002219089Spjd } else { 3003219089Spjd /* User didn't specify a disk for this vdev. */ 3004219089Spjd vdev = mchild[mchildren - 1]; 3005219089Spjd } 3006219089Spjd 3007219089Spjd if (nvlist_dup(vdev, &varray[vcount++], 0) != 0) 3008219089Spjd goto out; 3009219089Spjd } 3010219089Spjd 3011219089Spjd /* did we find every disk the user specified? */ 3012219089Spjd if (found != newchildren) { 3013219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Device list must " 3014219089Spjd "include at most one disk from each mirror")); 3015219089Spjd retval = zfs_error(hdl, EZFS_INVALCONFIG, msg); 3016219089Spjd goto out; 3017219089Spjd } 3018219089Spjd 3019219089Spjd /* Prepare the nvlist for populating. */ 3020219089Spjd if (*newroot == NULL) { 3021219089Spjd if (nvlist_alloc(newroot, NV_UNIQUE_NAME, 0) != 0) 3022219089Spjd goto out; 3023219089Spjd freelist = B_TRUE; 3024219089Spjd if (nvlist_add_string(*newroot, ZPOOL_CONFIG_TYPE, 3025219089Spjd VDEV_TYPE_ROOT) != 0) 3026219089Spjd goto out; 3027219089Spjd } else { 3028219089Spjd verify(nvlist_remove_all(*newroot, ZPOOL_CONFIG_CHILDREN) == 0); 3029219089Spjd } 3030219089Spjd 3031219089Spjd /* Add all the children we found */ 3032219089Spjd if (nvlist_add_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN, varray, 3033219089Spjd lastlog == 0 ? vcount : lastlog) != 0) 3034219089Spjd goto out; 3035219089Spjd 3036219089Spjd /* 3037219089Spjd * If we're just doing a dry run, exit now with success. 3038219089Spjd */ 3039219089Spjd if (flags.dryrun) { 3040219089Spjd memory_err = B_FALSE; 3041219089Spjd freelist = B_FALSE; 3042219089Spjd goto out; 3043219089Spjd } 3044219089Spjd 3045219089Spjd /* now build up the config list & call the ioctl */ 3046219089Spjd if (nvlist_alloc(&newconfig, NV_UNIQUE_NAME, 0) != 0) 3047219089Spjd goto out; 3048219089Spjd 3049219089Spjd if (nvlist_add_nvlist(newconfig, 3050219089Spjd ZPOOL_CONFIG_VDEV_TREE, *newroot) != 0 || 3051219089Spjd nvlist_add_string(newconfig, 3052219089Spjd ZPOOL_CONFIG_POOL_NAME, newname) != 0 || 3053219089Spjd nvlist_add_uint64(newconfig, ZPOOL_CONFIG_VERSION, vers) != 0) 3054219089Spjd goto out; 3055219089Spjd 3056219089Spjd /* 3057219089Spjd * The new pool is automatically part of the namespace unless we 3058219089Spjd * explicitly export it. 3059219089Spjd */ 3060219089Spjd if (!flags.import) 3061219089Spjd zc.zc_cookie = ZPOOL_EXPORT_AFTER_SPLIT; 3062219089Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3063219089Spjd (void) strlcpy(zc.zc_string, newname, sizeof (zc.zc_string)); 3064219089Spjd if (zcmd_write_conf_nvlist(hdl, &zc, newconfig) != 0) 3065219089Spjd goto out; 3066219089Spjd if (zc_props != NULL && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0) 3067219089Spjd goto out; 3068219089Spjd 3069219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SPLIT, &zc) != 0) { 3070219089Spjd retval = zpool_standard_error(hdl, errno, msg); 3071219089Spjd goto out; 3072219089Spjd } 3073219089Spjd 3074219089Spjd freelist = B_FALSE; 3075219089Spjd memory_err = B_FALSE; 3076219089Spjd 3077219089Spjdout: 3078219089Spjd if (varray != NULL) { 3079219089Spjd int v; 3080219089Spjd 3081219089Spjd for (v = 0; v < vcount; v++) 3082219089Spjd nvlist_free(varray[v]); 3083219089Spjd free(varray); 3084219089Spjd } 3085219089Spjd zcmd_free_nvlists(&zc); 3086219089Spjd if (zc_props) 3087219089Spjd nvlist_free(zc_props); 3088219089Spjd if (newconfig) 3089219089Spjd nvlist_free(newconfig); 3090219089Spjd if (freelist) { 3091219089Spjd nvlist_free(*newroot); 3092219089Spjd *newroot = NULL; 3093219089Spjd } 3094219089Spjd 3095219089Spjd if (retval != 0) 3096219089Spjd return (retval); 3097219089Spjd 3098219089Spjd if (memory_err) 3099219089Spjd return (no_memory(hdl)); 3100219089Spjd 3101219089Spjd return (0); 3102219089Spjd} 3103219089Spjd 3104219089Spjd/* 3105185029Spjd * Remove the given device. Currently, this is supported only for hot spares 3106185029Spjd * and level 2 cache devices. 3107168404Spjd */ 3108168404Spjdint 3109168404Spjdzpool_vdev_remove(zpool_handle_t *zhp, const char *path) 3110168404Spjd{ 3111168404Spjd zfs_cmd_t zc = { 0 }; 3112168404Spjd char msg[1024]; 3113168404Spjd nvlist_t *tgt; 3114219089Spjd boolean_t avail_spare, l2cache, islog; 3115168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 3116219089Spjd uint64_t version; 3117168404Spjd 3118168404Spjd (void) snprintf(msg, sizeof (msg), 3119168404Spjd dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 3120168404Spjd 3121168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3122185029Spjd if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, 3123219089Spjd &islog)) == 0) 3124168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 3125219089Spjd /* 3126219089Spjd * XXX - this should just go away. 3127219089Spjd */ 3128219089Spjd if (!avail_spare && !l2cache && !islog) { 3129168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3130219089Spjd "only inactive hot spares, cache, top-level, " 3131219089Spjd "or log devices can be removed")); 3132168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 3133168404Spjd } 3134168404Spjd 3135219089Spjd version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 3136219089Spjd if (islog && version < SPA_VERSION_HOLES) { 3137219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3138219089Spjd "pool must be upgrade to support log removal")); 3139219089Spjd return (zfs_error(hdl, EZFS_BADVERSION, msg)); 3140219089Spjd } 3141219089Spjd 3142168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 3143168404Spjd 3144185029Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 3145168404Spjd return (0); 3146168404Spjd 3147168404Spjd return (zpool_standard_error(hdl, errno, msg)); 3148168404Spjd} 3149168404Spjd 3150168404Spjd/* 3151168404Spjd * Clear the errors for the pool, or the particular device if specified. 3152168404Spjd */ 3153168404Spjdint 3154219089Spjdzpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl) 3155168404Spjd{ 3156168404Spjd zfs_cmd_t zc = { 0 }; 3157168404Spjd char msg[1024]; 3158168404Spjd nvlist_t *tgt; 3159219089Spjd zpool_rewind_policy_t policy; 3160185029Spjd boolean_t avail_spare, l2cache; 3161168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 3162219089Spjd nvlist_t *nvi = NULL; 3163219089Spjd int error; 3164168404Spjd 3165168404Spjd if (path) 3166168404Spjd (void) snprintf(msg, sizeof (msg), 3167168404Spjd dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 3168168404Spjd path); 3169168404Spjd else 3170168404Spjd (void) snprintf(msg, sizeof (msg), 3171168404Spjd dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 3172168404Spjd zhp->zpool_name); 3173168404Spjd 3174168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3175168404Spjd if (path) { 3176185029Spjd if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, 3177185029Spjd &l2cache, NULL)) == 0) 3178168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 3179168404Spjd 3180185029Spjd /* 3181185029Spjd * Don't allow error clearing for hot spares. Do allow 3182185029Spjd * error clearing for l2cache devices. 3183185029Spjd */ 3184168404Spjd if (avail_spare) 3185168404Spjd return (zfs_error(hdl, EZFS_ISSPARE, msg)); 3186168404Spjd 3187168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 3188168404Spjd &zc.zc_guid) == 0); 3189168404Spjd } 3190168404Spjd 3191219089Spjd zpool_get_rewind_policy(rewindnvl, &policy); 3192219089Spjd zc.zc_cookie = policy.zrp_request; 3193219089Spjd 3194219089Spjd if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size * 2) != 0) 3195219089Spjd return (-1); 3196219089Spjd 3197219089Spjd if (zcmd_write_src_nvlist(hdl, &zc, rewindnvl) != 0) 3198219089Spjd return (-1); 3199219089Spjd 3200219089Spjd while ((error = zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc)) != 0 && 3201219089Spjd errno == ENOMEM) { 3202219089Spjd if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 3203219089Spjd zcmd_free_nvlists(&zc); 3204219089Spjd return (-1); 3205219089Spjd } 3206219089Spjd } 3207219089Spjd 3208219089Spjd if (!error || ((policy.zrp_request & ZPOOL_TRY_REWIND) && 3209219089Spjd errno != EPERM && errno != EACCES)) { 3210219089Spjd if (policy.zrp_request & 3211219089Spjd (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) { 3212219089Spjd (void) zcmd_read_dst_nvlist(hdl, &zc, &nvi); 3213219089Spjd zpool_rewind_exclaim(hdl, zc.zc_name, 3214219089Spjd ((policy.zrp_request & ZPOOL_TRY_REWIND) != 0), 3215219089Spjd nvi); 3216219089Spjd nvlist_free(nvi); 3217219089Spjd } 3218219089Spjd zcmd_free_nvlists(&zc); 3219185029Spjd return (0); 3220219089Spjd } 3221185029Spjd 3222219089Spjd zcmd_free_nvlists(&zc); 3223185029Spjd return (zpool_standard_error(hdl, errno, msg)); 3224185029Spjd} 3225185029Spjd 3226185029Spjd/* 3227185029Spjd * Similar to zpool_clear(), but takes a GUID (used by fmd). 3228185029Spjd */ 3229185029Spjdint 3230185029Spjdzpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid) 3231185029Spjd{ 3232185029Spjd zfs_cmd_t zc = { 0 }; 3233185029Spjd char msg[1024]; 3234185029Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 3235185029Spjd 3236185029Spjd (void) snprintf(msg, sizeof (msg), 3237185029Spjd dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"), 3238185029Spjd guid); 3239185029Spjd 3240185029Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3241185029Spjd zc.zc_guid = guid; 3242219089Spjd zc.zc_cookie = ZPOOL_NO_REWIND; 3243185029Spjd 3244168404Spjd if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 3245168404Spjd return (0); 3246168404Spjd 3247168404Spjd return (zpool_standard_error(hdl, errno, msg)); 3248168404Spjd} 3249168404Spjd 3250168404Spjd/* 3251229578Smm * Change the GUID for a pool. 3252229578Smm */ 3253229578Smmint 3254229578Smmzpool_reguid(zpool_handle_t *zhp) 3255229578Smm{ 3256229578Smm char msg[1024]; 3257229578Smm libzfs_handle_t *hdl = zhp->zpool_hdl; 3258229578Smm zfs_cmd_t zc = { 0 }; 3259229578Smm 3260229578Smm (void) snprintf(msg, sizeof (msg), 3261229578Smm dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name); 3262229578Smm 3263229578Smm (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3264229578Smm if (zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc) == 0) 3265229578Smm return (0); 3266229578Smm 3267229578Smm return (zpool_standard_error(hdl, errno, msg)); 3268229578Smm} 3269229578Smm 3270229578Smm/* 3271236839Smm * Reopen the pool. 3272236839Smm */ 3273236839Smmint 3274236839Smmzpool_reopen(zpool_handle_t *zhp) 3275236839Smm{ 3276236839Smm zfs_cmd_t zc = { 0 }; 3277236839Smm char msg[1024]; 3278236839Smm libzfs_handle_t *hdl = zhp->zpool_hdl; 3279236839Smm 3280236839Smm (void) snprintf(msg, sizeof (msg), 3281236839Smm dgettext(TEXT_DOMAIN, "cannot reopen '%s'"), 3282236839Smm zhp->zpool_name); 3283236839Smm 3284236839Smm (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3285236839Smm if (zfs_ioctl(hdl, ZFS_IOC_POOL_REOPEN, &zc) == 0) 3286236839Smm return (0); 3287236839Smm return (zpool_standard_error(hdl, errno, msg)); 3288236839Smm} 3289236839Smm 3290236839Smm/* 3291168404Spjd * Convert from a devid string to a path. 3292168404Spjd */ 3293168404Spjdstatic char * 3294168404Spjddevid_to_path(char *devid_str) 3295168404Spjd{ 3296168404Spjd ddi_devid_t devid; 3297168404Spjd char *minor; 3298168404Spjd char *path; 3299168404Spjd devid_nmlist_t *list = NULL; 3300168404Spjd int ret; 3301168404Spjd 3302168404Spjd if (devid_str_decode(devid_str, &devid, &minor) != 0) 3303168404Spjd return (NULL); 3304168404Spjd 3305168404Spjd ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 3306168404Spjd 3307168404Spjd devid_str_free(minor); 3308168404Spjd devid_free(devid); 3309168404Spjd 3310168404Spjd if (ret != 0) 3311168404Spjd return (NULL); 3312168404Spjd 3313168404Spjd if ((path = strdup(list[0].devname)) == NULL) 3314168404Spjd return (NULL); 3315168404Spjd 3316168404Spjd devid_free_nmlist(list); 3317168404Spjd 3318168404Spjd return (path); 3319168404Spjd} 3320168404Spjd 3321168404Spjd/* 3322168404Spjd * Convert from a path to a devid string. 3323168404Spjd */ 3324168404Spjdstatic char * 3325168404Spjdpath_to_devid(const char *path) 3326168404Spjd{ 3327168404Spjd int fd; 3328168404Spjd ddi_devid_t devid; 3329168404Spjd char *minor, *ret; 3330168404Spjd 3331168404Spjd if ((fd = open(path, O_RDONLY)) < 0) 3332168404Spjd return (NULL); 3333168404Spjd 3334168404Spjd minor = NULL; 3335168404Spjd ret = NULL; 3336168404Spjd if (devid_get(fd, &devid) == 0) { 3337168404Spjd if (devid_get_minor_name(fd, &minor) == 0) 3338168404Spjd ret = devid_str_encode(devid, minor); 3339168404Spjd if (minor != NULL) 3340168404Spjd devid_str_free(minor); 3341168404Spjd devid_free(devid); 3342168404Spjd } 3343168404Spjd (void) close(fd); 3344168404Spjd 3345168404Spjd return (ret); 3346168404Spjd} 3347168404Spjd 3348168404Spjd/* 3349168404Spjd * Issue the necessary ioctl() to update the stored path value for the vdev. We 3350168404Spjd * ignore any failure here, since a common case is for an unprivileged user to 3351168404Spjd * type 'zpool status', and we'll display the correct information anyway. 3352168404Spjd */ 3353168404Spjdstatic void 3354168404Spjdset_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 3355168404Spjd{ 3356168404Spjd zfs_cmd_t zc = { 0 }; 3357168404Spjd 3358168404Spjd (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3359168404Spjd (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 3360168404Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 3361168404Spjd &zc.zc_guid) == 0); 3362168404Spjd 3363168404Spjd (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 3364168404Spjd} 3365168404Spjd 3366168404Spjd/* 3367168404Spjd * Given a vdev, return the name to display in iostat. If the vdev has a path, 3368168404Spjd * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 3369168404Spjd * We also check if this is a whole disk, in which case we strip off the 3370168404Spjd * trailing 's0' slice name. 3371168404Spjd * 3372168404Spjd * This routine is also responsible for identifying when disks have been 3373168404Spjd * reconfigured in a new location. The kernel will have opened the device by 3374168404Spjd * devid, but the path will still refer to the old location. To catch this, we 3375168404Spjd * first do a path -> devid translation (which is fast for the common case). If 3376168404Spjd * the devid matches, we're done. If not, we do a reverse devid -> path 3377168404Spjd * translation and issue the appropriate ioctl() to update the path of the vdev. 3378168404Spjd * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 3379168404Spjd * of these checks. 3380168404Spjd */ 3381168404Spjdchar * 3382219089Spjdzpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv, 3383219089Spjd boolean_t verbose) 3384168404Spjd{ 3385168404Spjd char *path, *devid; 3386168404Spjd uint64_t value; 3387168404Spjd char buf[64]; 3388185029Spjd vdev_stat_t *vs; 3389185029Spjd uint_t vsc; 3390224170Sgibbs int have_stats; 3391224170Sgibbs int have_path; 3392168404Spjd 3393224170Sgibbs have_stats = nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 3394224170Sgibbs (uint64_t **)&vs, &vsc) == 0; 3395224170Sgibbs have_path = nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0; 3396224170Sgibbs 3397224170Sgibbs /* 3398224170Sgibbs * If the device is not currently present, assume it will not 3399224170Sgibbs * come back at the same device path. Display the device by GUID. 3400224170Sgibbs */ 3401224170Sgibbs if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &value) == 0 || 3402224170Sgibbs have_path && have_stats && vs->vs_state <= VDEV_STATE_CANT_OPEN) { 3403168404Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 3404168404Spjd &value) == 0); 3405168404Spjd (void) snprintf(buf, sizeof (buf), "%llu", 3406168404Spjd (u_longlong_t)value); 3407168404Spjd path = buf; 3408224170Sgibbs } else if (have_path) { 3409168404Spjd 3410185029Spjd /* 3411185029Spjd * If the device is dead (faulted, offline, etc) then don't 3412185029Spjd * bother opening it. Otherwise we may be forcing the user to 3413185029Spjd * open a misbehaving device, which can have undesirable 3414185029Spjd * effects. 3415185029Spjd */ 3416224170Sgibbs if ((have_stats == 0 || 3417185029Spjd vs->vs_state >= VDEV_STATE_DEGRADED) && 3418185029Spjd zhp != NULL && 3419168404Spjd nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 3420168404Spjd /* 3421168404Spjd * Determine if the current path is correct. 3422168404Spjd */ 3423168404Spjd char *newdevid = path_to_devid(path); 3424168404Spjd 3425168404Spjd if (newdevid == NULL || 3426168404Spjd strcmp(devid, newdevid) != 0) { 3427168404Spjd char *newpath; 3428168404Spjd 3429168404Spjd if ((newpath = devid_to_path(devid)) != NULL) { 3430168404Spjd /* 3431168404Spjd * Update the path appropriately. 3432168404Spjd */ 3433168404Spjd set_path(zhp, nv, newpath); 3434168404Spjd if (nvlist_add_string(nv, 3435168404Spjd ZPOOL_CONFIG_PATH, newpath) == 0) 3436168404Spjd verify(nvlist_lookup_string(nv, 3437168404Spjd ZPOOL_CONFIG_PATH, 3438168404Spjd &path) == 0); 3439168404Spjd free(newpath); 3440168404Spjd } 3441168404Spjd } 3442168404Spjd 3443168404Spjd if (newdevid) 3444168404Spjd devid_str_free(newdevid); 3445168404Spjd } 3446168404Spjd 3447219089Spjd#ifdef sun 3448219089Spjd if (strncmp(path, "/dev/dsk/", 9) == 0) 3449219089Spjd path += 9; 3450168404Spjd 3451168404Spjd if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 3452168404Spjd &value) == 0 && value) { 3453219089Spjd int pathlen = strlen(path); 3454168404Spjd char *tmp = zfs_strdup(hdl, path); 3455219089Spjd 3456219089Spjd /* 3457219089Spjd * If it starts with c#, and ends with "s0", chop 3458219089Spjd * the "s0" off, or if it ends with "s0/old", remove 3459219089Spjd * the "s0" from the middle. 3460219089Spjd */ 3461219089Spjd if (CTD_CHECK(tmp)) { 3462219089Spjd if (strcmp(&tmp[pathlen - 2], "s0") == 0) { 3463219089Spjd tmp[pathlen - 2] = '\0'; 3464219089Spjd } else if (pathlen > 6 && 3465219089Spjd strcmp(&tmp[pathlen - 6], "s0/old") == 0) { 3466219089Spjd (void) strcpy(&tmp[pathlen - 6], 3467219089Spjd "/old"); 3468219089Spjd } 3469219089Spjd } 3470168404Spjd return (tmp); 3471168404Spjd } 3472219089Spjd#else /* !sun */ 3473219089Spjd if (strncmp(path, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 3474219089Spjd path += sizeof(_PATH_DEV) - 1; 3475219089Spjd#endif /* !sun */ 3476168404Spjd } else { 3477168404Spjd verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 3478168404Spjd 3479168404Spjd /* 3480168404Spjd * If it's a raidz device, we need to stick in the parity level. 3481168404Spjd */ 3482168404Spjd if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 3483168404Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 3484168404Spjd &value) == 0); 3485168404Spjd (void) snprintf(buf, sizeof (buf), "%s%llu", path, 3486168404Spjd (u_longlong_t)value); 3487168404Spjd path = buf; 3488168404Spjd } 3489219089Spjd 3490219089Spjd /* 3491219089Spjd * We identify each top-level vdev by using a <type-id> 3492219089Spjd * naming convention. 3493219089Spjd */ 3494219089Spjd if (verbose) { 3495219089Spjd uint64_t id; 3496219089Spjd 3497219089Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID, 3498219089Spjd &id) == 0); 3499219089Spjd (void) snprintf(buf, sizeof (buf), "%s-%llu", path, 3500219089Spjd (u_longlong_t)id); 3501219089Spjd path = buf; 3502219089Spjd } 3503168404Spjd } 3504168404Spjd 3505168404Spjd return (zfs_strdup(hdl, path)); 3506168404Spjd} 3507168404Spjd 3508168404Spjdstatic int 3509168404Spjdzbookmark_compare(const void *a, const void *b) 3510168404Spjd{ 3511168404Spjd return (memcmp(a, b, sizeof (zbookmark_t))); 3512168404Spjd} 3513168404Spjd 3514168404Spjd/* 3515168404Spjd * Retrieve the persistent error log, uniquify the members, and return to the 3516168404Spjd * caller. 3517168404Spjd */ 3518168404Spjdint 3519168404Spjdzpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) 3520168404Spjd{ 3521168404Spjd zfs_cmd_t zc = { 0 }; 3522168404Spjd uint64_t count; 3523168404Spjd zbookmark_t *zb = NULL; 3524168404Spjd int i; 3525168404Spjd 3526168404Spjd /* 3527168404Spjd * Retrieve the raw error list from the kernel. If the number of errors 3528168404Spjd * has increased, allocate more space and continue until we get the 3529168404Spjd * entire list. 3530168404Spjd */ 3531168404Spjd verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 3532168404Spjd &count) == 0); 3533185029Spjd if (count == 0) 3534185029Spjd return (0); 3535168404Spjd if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 3536168404Spjd count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 3537168404Spjd return (-1); 3538168404Spjd zc.zc_nvlist_dst_size = count; 3539168404Spjd (void) strcpy(zc.zc_name, zhp->zpool_name); 3540168404Spjd for (;;) { 3541168404Spjd if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 3542168404Spjd &zc) != 0) { 3543168404Spjd free((void *)(uintptr_t)zc.zc_nvlist_dst); 3544168404Spjd if (errno == ENOMEM) { 3545168404Spjd count = zc.zc_nvlist_dst_size; 3546168404Spjd if ((zc.zc_nvlist_dst = (uintptr_t) 3547168404Spjd zfs_alloc(zhp->zpool_hdl, count * 3548168404Spjd sizeof (zbookmark_t))) == (uintptr_t)NULL) 3549168404Spjd return (-1); 3550168404Spjd } else { 3551168404Spjd return (-1); 3552168404Spjd } 3553168404Spjd } else { 3554168404Spjd break; 3555168404Spjd } 3556168404Spjd } 3557168404Spjd 3558168404Spjd /* 3559168404Spjd * Sort the resulting bookmarks. This is a little confusing due to the 3560168404Spjd * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 3561168404Spjd * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 3562168404Spjd * _not_ copied as part of the process. So we point the start of our 3563168404Spjd * array appropriate and decrement the total number of elements. 3564168404Spjd */ 3565168404Spjd zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 3566168404Spjd zc.zc_nvlist_dst_size; 3567168404Spjd count -= zc.zc_nvlist_dst_size; 3568168404Spjd 3569168404Spjd qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 3570168404Spjd 3571168404Spjd verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); 3572168404Spjd 3573168404Spjd /* 3574168404Spjd * Fill in the nverrlistp with nvlist's of dataset and object numbers. 3575168404Spjd */ 3576168404Spjd for (i = 0; i < count; i++) { 3577168404Spjd nvlist_t *nv; 3578168404Spjd 3579168404Spjd /* ignoring zb_blkid and zb_level for now */ 3580168404Spjd if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && 3581168404Spjd zb[i-1].zb_object == zb[i].zb_object) 3582168404Spjd continue; 3583168404Spjd 3584168404Spjd if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) 3585168404Spjd goto nomem; 3586168404Spjd if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, 3587168404Spjd zb[i].zb_objset) != 0) { 3588168404Spjd nvlist_free(nv); 3589168404Spjd goto nomem; 3590168404Spjd } 3591168404Spjd if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, 3592168404Spjd zb[i].zb_object) != 0) { 3593168404Spjd nvlist_free(nv); 3594168404Spjd goto nomem; 3595168404Spjd } 3596168404Spjd if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { 3597168404Spjd nvlist_free(nv); 3598168404Spjd goto nomem; 3599168404Spjd } 3600168404Spjd nvlist_free(nv); 3601168404Spjd } 3602168404Spjd 3603168404Spjd free((void *)(uintptr_t)zc.zc_nvlist_dst); 3604168404Spjd return (0); 3605168404Spjd 3606168404Spjdnomem: 3607168404Spjd free((void *)(uintptr_t)zc.zc_nvlist_dst); 3608168404Spjd return (no_memory(zhp->zpool_hdl)); 3609168404Spjd} 3610168404Spjd 3611168404Spjd/* 3612168404Spjd * Upgrade a ZFS pool to the latest on-disk version. 3613168404Spjd */ 3614168404Spjdint 3615185029Spjdzpool_upgrade(zpool_handle_t *zhp, uint64_t new_version) 3616168404Spjd{ 3617168404Spjd zfs_cmd_t zc = { 0 }; 3618168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 3619168404Spjd 3620168404Spjd (void) strcpy(zc.zc_name, zhp->zpool_name); 3621185029Spjd zc.zc_cookie = new_version; 3622185029Spjd 3623185029Spjd if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 3624168404Spjd return (zpool_standard_error_fmt(hdl, errno, 3625168404Spjd dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 3626168404Spjd zhp->zpool_name)); 3627168404Spjd return (0); 3628168404Spjd} 3629168404Spjd 3630168404Spjdvoid 3631249643Smmzfs_save_arguments(int argc, char **argv, char *string, int len) 3632168404Spjd{ 3633249643Smm (void) strlcpy(string, basename(argv[0]), len); 3634249643Smm for (int i = 1; i < argc; i++) { 3635249643Smm (void) strlcat(string, " ", len); 3636249643Smm (void) strlcat(string, argv[i], len); 3637168404Spjd } 3638185029Spjd} 3639168404Spjd 3640185029Spjdint 3641249643Smmzpool_log_history(libzfs_handle_t *hdl, const char *message) 3642185029Spjd{ 3643249643Smm zfs_cmd_t zc = { 0 }; 3644249643Smm nvlist_t *args; 3645249643Smm int err; 3646168404Spjd 3647249643Smm args = fnvlist_alloc(); 3648249643Smm fnvlist_add_string(args, "message", message); 3649249643Smm err = zcmd_write_src_nvlist(hdl, &zc, args); 3650249643Smm if (err == 0) 3651249643Smm err = ioctl(hdl->libzfs_fd, ZFS_IOC_LOG_HISTORY, &zc); 3652249643Smm nvlist_free(args); 3653249643Smm zcmd_free_nvlists(&zc); 3654249643Smm return (err); 3655168404Spjd} 3656168404Spjd 3657168404Spjd/* 3658168404Spjd * Perform ioctl to get some command history of a pool. 3659168404Spjd * 3660168404Spjd * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 3661168404Spjd * logical offset of the history buffer to start reading from. 3662168404Spjd * 3663168404Spjd * Upon return, 'off' is the next logical offset to read from and 3664168404Spjd * 'len' is the actual amount of bytes read into 'buf'. 3665168404Spjd */ 3666168404Spjdstatic int 3667168404Spjdget_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 3668168404Spjd{ 3669168404Spjd zfs_cmd_t zc = { 0 }; 3670168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 3671168404Spjd 3672168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3673168404Spjd 3674168404Spjd zc.zc_history = (uint64_t)(uintptr_t)buf; 3675168404Spjd zc.zc_history_len = *len; 3676168404Spjd zc.zc_history_offset = *off; 3677168404Spjd 3678168404Spjd if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 3679168404Spjd switch (errno) { 3680168404Spjd case EPERM: 3681168404Spjd return (zfs_error_fmt(hdl, EZFS_PERM, 3682168404Spjd dgettext(TEXT_DOMAIN, 3683168404Spjd "cannot show history for pool '%s'"), 3684168404Spjd zhp->zpool_name)); 3685168404Spjd case ENOENT: 3686168404Spjd return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 3687168404Spjd dgettext(TEXT_DOMAIN, "cannot get history for pool " 3688168404Spjd "'%s'"), zhp->zpool_name)); 3689168404Spjd case ENOTSUP: 3690168404Spjd return (zfs_error_fmt(hdl, EZFS_BADVERSION, 3691168404Spjd dgettext(TEXT_DOMAIN, "cannot get history for pool " 3692168404Spjd "'%s', pool must be upgraded"), zhp->zpool_name)); 3693168404Spjd default: 3694168404Spjd return (zpool_standard_error_fmt(hdl, errno, 3695168404Spjd dgettext(TEXT_DOMAIN, 3696168404Spjd "cannot get history for '%s'"), zhp->zpool_name)); 3697168404Spjd } 3698168404Spjd } 3699168404Spjd 3700168404Spjd *len = zc.zc_history_len; 3701168404Spjd *off = zc.zc_history_offset; 3702168404Spjd 3703168404Spjd return (0); 3704168404Spjd} 3705168404Spjd 3706168404Spjd/* 3707168404Spjd * Process the buffer of nvlists, unpacking and storing each nvlist record 3708168404Spjd * into 'records'. 'leftover' is set to the number of bytes that weren't 3709168404Spjd * processed as there wasn't a complete record. 3710168404Spjd */ 3711219089Spjdint 3712168404Spjdzpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 3713168404Spjd nvlist_t ***records, uint_t *numrecords) 3714168404Spjd{ 3715168404Spjd uint64_t reclen; 3716168404Spjd nvlist_t *nv; 3717168404Spjd int i; 3718168404Spjd 3719168404Spjd while (bytes_read > sizeof (reclen)) { 3720168404Spjd 3721168404Spjd /* get length of packed record (stored as little endian) */ 3722168404Spjd for (i = 0, reclen = 0; i < sizeof (reclen); i++) 3723168404Spjd reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 3724168404Spjd 3725168404Spjd if (bytes_read < sizeof (reclen) + reclen) 3726168404Spjd break; 3727168404Spjd 3728168404Spjd /* unpack record */ 3729168404Spjd if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 3730168404Spjd return (ENOMEM); 3731168404Spjd bytes_read -= sizeof (reclen) + reclen; 3732168404Spjd buf += sizeof (reclen) + reclen; 3733168404Spjd 3734168404Spjd /* add record to nvlist array */ 3735168404Spjd (*numrecords)++; 3736168404Spjd if (ISP2(*numrecords + 1)) { 3737168404Spjd *records = realloc(*records, 3738168404Spjd *numrecords * 2 * sizeof (nvlist_t *)); 3739168404Spjd } 3740168404Spjd (*records)[*numrecords - 1] = nv; 3741168404Spjd } 3742168404Spjd 3743168404Spjd *leftover = bytes_read; 3744168404Spjd return (0); 3745168404Spjd} 3746168404Spjd 3747265040Sdelphij/* from spa_history.c: spa_history_create_obj() */ 3748265040Sdelphij#define HIS_BUF_LEN_DEF (128 << 10) 3749265040Sdelphij#define HIS_BUF_LEN_MAX (1 << 30) 3750168404Spjd 3751168404Spjd/* 3752168404Spjd * Retrieve the command history of a pool. 3753168404Spjd */ 3754168404Spjdint 3755168404Spjdzpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 3756168404Spjd{ 3757265040Sdelphij char *buf = NULL; 3758265040Sdelphij uint64_t bufsize = HIS_BUF_LEN_DEF; 3759168404Spjd uint64_t off = 0; 3760168404Spjd nvlist_t **records = NULL; 3761168404Spjd uint_t numrecords = 0; 3762168404Spjd int err, i; 3763168404Spjd 3764265040Sdelphij if ((buf = malloc(bufsize)) == NULL) 3765265040Sdelphij return (ENOMEM); 3766168404Spjd do { 3767265040Sdelphij uint64_t bytes_read = bufsize; 3768168404Spjd uint64_t leftover; 3769168404Spjd 3770168404Spjd if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 3771168404Spjd break; 3772168404Spjd 3773168404Spjd /* if nothing else was read in, we're at EOF, just return */ 3774265040Sdelphij if (bytes_read == 0) 3775168404Spjd break; 3776168404Spjd 3777168404Spjd if ((err = zpool_history_unpack(buf, bytes_read, 3778168404Spjd &leftover, &records, &numrecords)) != 0) 3779168404Spjd break; 3780168404Spjd off -= leftover; 3781168404Spjd 3782265040Sdelphij /* 3783265040Sdelphij * If the history block is too big, double the buffer 3784265040Sdelphij * size and try again. 3785265040Sdelphij */ 3786265040Sdelphij if (leftover == bytes_read) { 3787265040Sdelphij free(buf); 3788265040Sdelphij buf = NULL; 3789265040Sdelphij 3790265040Sdelphij bufsize <<= 1; 3791265040Sdelphij if ((bufsize >= HIS_BUF_LEN_MAX) || 3792265040Sdelphij ((buf = malloc(bufsize)) == NULL)) { 3793265040Sdelphij err = ENOMEM; 3794265040Sdelphij break; 3795265040Sdelphij } 3796265040Sdelphij } 3797265040Sdelphij 3798168404Spjd /* CONSTCOND */ 3799168404Spjd } while (1); 3800265040Sdelphij free(buf); 3801168404Spjd 3802168404Spjd if (!err) { 3803168404Spjd verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 3804168404Spjd verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 3805168404Spjd records, numrecords) == 0); 3806168404Spjd } 3807168404Spjd for (i = 0; i < numrecords; i++) 3808168404Spjd nvlist_free(records[i]); 3809168404Spjd free(records); 3810168404Spjd 3811168404Spjd return (err); 3812168404Spjd} 3813168404Spjd 3814168404Spjdvoid 3815168404Spjdzpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, 3816168404Spjd char *pathname, size_t len) 3817168404Spjd{ 3818168404Spjd zfs_cmd_t zc = { 0 }; 3819168404Spjd boolean_t mounted = B_FALSE; 3820168404Spjd char *mntpnt = NULL; 3821168404Spjd char dsname[MAXNAMELEN]; 3822168404Spjd 3823168404Spjd if (dsobj == 0) { 3824168404Spjd /* special case for the MOS */ 3825168404Spjd (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj); 3826168404Spjd return; 3827168404Spjd } 3828168404Spjd 3829168404Spjd /* get the dataset's name */ 3830168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3831168404Spjd zc.zc_obj = dsobj; 3832168404Spjd if (ioctl(zhp->zpool_hdl->libzfs_fd, 3833168404Spjd ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { 3834168404Spjd /* just write out a path of two object numbers */ 3835168404Spjd (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", 3836168404Spjd dsobj, obj); 3837168404Spjd return; 3838168404Spjd } 3839168404Spjd (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); 3840168404Spjd 3841168404Spjd /* find out if the dataset is mounted */ 3842168404Spjd mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt); 3843168404Spjd 3844168404Spjd /* get the corrupted object's path */ 3845168404Spjd (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); 3846168404Spjd zc.zc_obj = obj; 3847168404Spjd if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH, 3848168404Spjd &zc) == 0) { 3849168404Spjd if (mounted) { 3850168404Spjd (void) snprintf(pathname, len, "%s%s", mntpnt, 3851168404Spjd zc.zc_value); 3852168404Spjd } else { 3853168404Spjd (void) snprintf(pathname, len, "%s:%s", 3854168404Spjd dsname, zc.zc_value); 3855168404Spjd } 3856168404Spjd } else { 3857168404Spjd (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj); 3858168404Spjd } 3859168404Spjd free(mntpnt); 3860168404Spjd} 3861168404Spjd 3862219089Spjd#ifdef sun 3863185029Spjd/* 3864185029Spjd * Read the EFI label from the config, if a label does not exist then 3865185029Spjd * pass back the error to the caller. If the caller has passed a non-NULL 3866185029Spjd * diskaddr argument then we set it to the starting address of the EFI 3867185029Spjd * partition. 3868185029Spjd */ 3869185029Spjdstatic int 3870185029Spjdread_efi_label(nvlist_t *config, diskaddr_t *sb) 3871168404Spjd{ 3872185029Spjd char *path; 3873185029Spjd int fd; 3874185029Spjd char diskname[MAXPATHLEN]; 3875185029Spjd int err = -1; 3876168404Spjd 3877185029Spjd if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0) 3878185029Spjd return (err); 3879168404Spjd 3880185029Spjd (void) snprintf(diskname, sizeof (diskname), "%s%s", RDISK_ROOT, 3881185029Spjd strrchr(path, '/')); 3882185029Spjd if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) { 3883185029Spjd struct dk_gpt *vtoc; 3884185029Spjd 3885185029Spjd if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) { 3886185029Spjd if (sb != NULL) 3887185029Spjd *sb = vtoc->efi_parts[0].p_start; 3888185029Spjd efi_free(vtoc); 3889185029Spjd } 3890185029Spjd (void) close(fd); 3891168404Spjd } 3892185029Spjd return (err); 3893185029Spjd} 3894168404Spjd 3895185029Spjd/* 3896185029Spjd * determine where a partition starts on a disk in the current 3897185029Spjd * configuration 3898185029Spjd */ 3899185029Spjdstatic diskaddr_t 3900185029Spjdfind_start_block(nvlist_t *config) 3901185029Spjd{ 3902185029Spjd nvlist_t **child; 3903185029Spjd uint_t c, children; 3904185029Spjd diskaddr_t sb = MAXOFFSET_T; 3905185029Spjd uint64_t wholedisk; 3906168404Spjd 3907185029Spjd if (nvlist_lookup_nvlist_array(config, 3908185029Spjd ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) { 3909185029Spjd if (nvlist_lookup_uint64(config, 3910185029Spjd ZPOOL_CONFIG_WHOLE_DISK, 3911185029Spjd &wholedisk) != 0 || !wholedisk) { 3912185029Spjd return (MAXOFFSET_T); 3913185029Spjd } 3914185029Spjd if (read_efi_label(config, &sb) < 0) 3915185029Spjd sb = MAXOFFSET_T; 3916185029Spjd return (sb); 3917168404Spjd } 3918168404Spjd 3919185029Spjd for (c = 0; c < children; c++) { 3920185029Spjd sb = find_start_block(child[c]); 3921185029Spjd if (sb != MAXOFFSET_T) { 3922185029Spjd return (sb); 3923185029Spjd } 3924168404Spjd } 3925185029Spjd return (MAXOFFSET_T); 3926185029Spjd} 3927185029Spjd#endif /* sun */ 3928168404Spjd 3929185029Spjd/* 3930185029Spjd * Label an individual disk. The name provided is the short name, 3931185029Spjd * stripped of any leading /dev path. 3932185029Spjd */ 3933185029Spjdint 3934224169Sgibbszpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name) 3935185029Spjd{ 3936219089Spjd#ifdef sun 3937185029Spjd char path[MAXPATHLEN]; 3938185029Spjd struct dk_gpt *vtoc; 3939185029Spjd int fd; 3940185029Spjd size_t resv = EFI_MIN_RESV_SIZE; 3941185029Spjd uint64_t slice_size; 3942185029Spjd diskaddr_t start_block; 3943185029Spjd char errbuf[1024]; 3944168404Spjd 3945185029Spjd /* prepare an error message just in case */ 3946185029Spjd (void) snprintf(errbuf, sizeof (errbuf), 3947185029Spjd dgettext(TEXT_DOMAIN, "cannot label '%s'"), name); 3948168404Spjd 3949185029Spjd if (zhp) { 3950185029Spjd nvlist_t *nvroot; 3951168404Spjd 3952236839Smm if (zpool_is_bootable(zhp)) { 3953209962Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3954209962Smm "EFI labeled devices are not supported on root " 3955209962Smm "pools.")); 3956209962Smm return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf)); 3957209962Smm } 3958209962Smm 3959185029Spjd verify(nvlist_lookup_nvlist(zhp->zpool_config, 3960185029Spjd ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 3961168404Spjd 3962185029Spjd if (zhp->zpool_start_block == 0) 3963185029Spjd start_block = find_start_block(nvroot); 3964185029Spjd else 3965185029Spjd start_block = zhp->zpool_start_block; 3966185029Spjd zhp->zpool_start_block = start_block; 3967185029Spjd } else { 3968185029Spjd /* new pool */ 3969185029Spjd start_block = NEW_START_BLOCK; 3970185029Spjd } 3971168404Spjd 3972185029Spjd (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name, 3973185029Spjd BACKUP_SLICE); 3974168404Spjd 3975185029Spjd if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) { 3976185029Spjd /* 3977185029Spjd * This shouldn't happen. We've long since verified that this 3978185029Spjd * is a valid device. 3979185029Spjd */ 3980185029Spjd zfs_error_aux(hdl, 3981185029Spjd dgettext(TEXT_DOMAIN, "unable to open device")); 3982185029Spjd return (zfs_error(hdl, EZFS_OPENFAILED, errbuf)); 3983185029Spjd } 3984168404Spjd 3985185029Spjd if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) { 3986185029Spjd /* 3987185029Spjd * The only way this can fail is if we run out of memory, or we 3988185029Spjd * were unable to read the disk's capacity 3989185029Spjd */ 3990185029Spjd if (errno == ENOMEM) 3991185029Spjd (void) no_memory(hdl); 3992168404Spjd 3993185029Spjd (void) close(fd); 3994185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3995185029Spjd "unable to read disk capacity"), name); 3996185029Spjd 3997185029Spjd return (zfs_error(hdl, EZFS_NOCAP, errbuf)); 3998168404Spjd } 3999168404Spjd 4000185029Spjd slice_size = vtoc->efi_last_u_lba + 1; 4001185029Spjd slice_size -= EFI_MIN_RESV_SIZE; 4002185029Spjd if (start_block == MAXOFFSET_T) 4003185029Spjd start_block = NEW_START_BLOCK; 4004185029Spjd slice_size -= start_block; 4005168404Spjd 4006185029Spjd vtoc->efi_parts[0].p_start = start_block; 4007185029Spjd vtoc->efi_parts[0].p_size = slice_size; 4008185029Spjd 4009168404Spjd /* 4010185029Spjd * Why we use V_USR: V_BACKUP confuses users, and is considered 4011185029Spjd * disposable by some EFI utilities (since EFI doesn't have a backup 4012185029Spjd * slice). V_UNASSIGNED is supposed to be used only for zero size 4013185029Spjd * partitions, and efi_write() will fail if we use it. V_ROOT, V_BOOT, 4014185029Spjd * etc. were all pretty specific. V_USR is as close to reality as we 4015185029Spjd * can get, in the absence of V_OTHER. 4016168404Spjd */ 4017185029Spjd vtoc->efi_parts[0].p_tag = V_USR; 4018185029Spjd (void) strcpy(vtoc->efi_parts[0].p_name, "zfs"); 4019168404Spjd 4020185029Spjd vtoc->efi_parts[8].p_start = slice_size + start_block; 4021185029Spjd vtoc->efi_parts[8].p_size = resv; 4022185029Spjd vtoc->efi_parts[8].p_tag = V_RESERVED; 4023168404Spjd 4024185029Spjd if (efi_write(fd, vtoc) != 0) { 4025185029Spjd /* 4026185029Spjd * Some block drivers (like pcata) may not support EFI 4027185029Spjd * GPT labels. Print out a helpful error message dir- 4028185029Spjd * ecting the user to manually label the disk and give 4029185029Spjd * a specific slice. 4030185029Spjd */ 4031185029Spjd (void) close(fd); 4032185029Spjd efi_free(vtoc); 4033168404Spjd 4034185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4035185029Spjd "try using fdisk(1M) and then provide a specific slice")); 4036185029Spjd return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); 4037168404Spjd } 4038185029Spjd 4039185029Spjd (void) close(fd); 4040185029Spjd efi_free(vtoc); 4041185029Spjd#endif /* sun */ 4042168404Spjd return (0); 4043168404Spjd} 4044168404Spjd 4045185029Spjdstatic boolean_t 4046185029Spjdsupported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf) 4047168404Spjd{ 4048185029Spjd char *type; 4049185029Spjd nvlist_t **child; 4050185029Spjd uint_t children, c; 4051185029Spjd 4052185029Spjd verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0); 4053262089Savg if (strcmp(type, VDEV_TYPE_FILE) == 0 || 4054219089Spjd strcmp(type, VDEV_TYPE_HOLE) == 0 || 4055185029Spjd strcmp(type, VDEV_TYPE_MISSING) == 0) { 4056185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4057185029Spjd "vdev type '%s' is not supported"), type); 4058185029Spjd (void) zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf); 4059185029Spjd return (B_FALSE); 4060185029Spjd } 4061185029Spjd if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN, 4062185029Spjd &child, &children) == 0) { 4063185029Spjd for (c = 0; c < children; c++) { 4064185029Spjd if (!supported_dump_vdev_type(hdl, child[c], errbuf)) 4065185029Spjd return (B_FALSE); 4066185029Spjd } 4067185029Spjd } 4068185029Spjd return (B_TRUE); 4069168404Spjd} 4070168404Spjd 4071185029Spjd/* 4072262089Savg * Check if this zvol is allowable for use as a dump device; zero if 4073262089Savg * it is, > 0 if it isn't, < 0 if it isn't a zvol. 4074262089Savg * 4075262089Savg * Allowable storage configurations include mirrors, all raidz variants, and 4076262089Savg * pools with log, cache, and spare devices. Pools which are backed by files or 4077262089Savg * have missing/hole vdevs are not suitable. 4078185029Spjd */ 4079168404Spjdint 4080185029Spjdzvol_check_dump_config(char *arg) 4081168404Spjd{ 4082185029Spjd zpool_handle_t *zhp = NULL; 4083185029Spjd nvlist_t *config, *nvroot; 4084185029Spjd char *p, *volname; 4085185029Spjd nvlist_t **top; 4086185029Spjd uint_t toplevels; 4087185029Spjd libzfs_handle_t *hdl; 4088185029Spjd char errbuf[1024]; 4089185029Spjd char poolname[ZPOOL_MAXNAMELEN]; 4090185029Spjd int pathlen = strlen(ZVOL_FULL_DEV_DIR); 4091185029Spjd int ret = 1; 4092168404Spjd 4093185029Spjd if (strncmp(arg, ZVOL_FULL_DEV_DIR, pathlen)) { 4094168404Spjd return (-1); 4095185029Spjd } 4096168404Spjd 4097185029Spjd (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 4098185029Spjd "dump is not supported on device '%s'"), arg); 4099168404Spjd 4100185029Spjd if ((hdl = libzfs_init()) == NULL) 4101185029Spjd return (1); 4102185029Spjd libzfs_print_on_error(hdl, B_TRUE); 4103168404Spjd 4104185029Spjd volname = arg + pathlen; 4105185029Spjd 4106185029Spjd /* check the configuration of the pool */ 4107185029Spjd if ((p = strchr(volname, '/')) == NULL) { 4108185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4109185029Spjd "malformed dataset name")); 4110185029Spjd (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 4111185029Spjd return (1); 4112185029Spjd } else if (p - volname >= ZFS_MAXNAMELEN) { 4113185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4114185029Spjd "dataset name is too long")); 4115185029Spjd (void) zfs_error(hdl, EZFS_NAMETOOLONG, errbuf); 4116185029Spjd return (1); 4117185029Spjd } else { 4118185029Spjd (void) strncpy(poolname, volname, p - volname); 4119185029Spjd poolname[p - volname] = '\0'; 4120168404Spjd } 4121168404Spjd 4122185029Spjd if ((zhp = zpool_open(hdl, poolname)) == NULL) { 4123185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4124185029Spjd "could not open pool '%s'"), poolname); 4125185029Spjd (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf); 4126185029Spjd goto out; 4127185029Spjd } 4128185029Spjd config = zpool_get_config(zhp, NULL); 4129185029Spjd if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 4130185029Spjd &nvroot) != 0) { 4131185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4132185029Spjd "could not obtain vdev configuration for '%s'"), poolname); 4133185029Spjd (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf); 4134185029Spjd goto out; 4135185029Spjd } 4136185029Spjd 4137185029Spjd verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 4138185029Spjd &top, &toplevels) == 0); 4139185029Spjd 4140185029Spjd if (!supported_dump_vdev_type(hdl, top[0], errbuf)) { 4141185029Spjd goto out; 4142185029Spjd } 4143185029Spjd ret = 0; 4144185029Spjd 4145185029Spjdout: 4146185029Spjd if (zhp) 4147185029Spjd zpool_close(zhp); 4148185029Spjd libzfs_fini(hdl); 4149185029Spjd return (ret); 4150168404Spjd} 4151