libzfs_pool.c revision 325149
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. 24289562Smav * Copyright (c) 2011, 2015 by Delphix. All rights reserved. 25255750Sdelphij * Copyright (c) 2013, Joyent, Inc. All rights reserved. 26297763Smav * Copyright 2016 Nexenta Systems, Inc. 27307050Smav * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> 28324010Savg * Copyright (c) 2017 Datto Inc. 29168404Spjd */ 30168404Spjd 31168404Spjd#include <sys/types.h> 32168404Spjd#include <sys/stat.h> 33168404Spjd#include <ctype.h> 34168404Spjd#include <errno.h> 35168404Spjd#include <devid.h> 36168404Spjd#include <fcntl.h> 37168404Spjd#include <libintl.h> 38168404Spjd#include <stdio.h> 39168404Spjd#include <stdlib.h> 40168404Spjd#include <strings.h> 41168404Spjd#include <unistd.h> 42248571Smm#include <libgen.h> 43168404Spjd#include <sys/zfs_ioctl.h> 44219089Spjd#include <dlfcn.h> 45168404Spjd 46168404Spjd#include "zfs_namecheck.h" 47168404Spjd#include "zfs_prop.h" 48168404Spjd#include "libzfs_impl.h" 49219089Spjd#include "zfs_comutil.h" 50236884Smm#include "zfeature_common.h" 51168404Spjd 52185029Spjdstatic int read_efi_label(nvlist_t *config, diskaddr_t *sb); 53185029Spjd 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")); 204307050Smav 205307050Smav default: 206307050Smav break; 207185029Spjd } 208185029Spjd 209185029Spjd return (gettext("UNKNOWN")); 210185029Spjd} 211185029Spjd 212185029Spjd/* 213224169Sgibbs * Map POOL STATE to printed strings. 214224169Sgibbs */ 215224169Sgibbsconst char * 216224169Sgibbszpool_pool_state_to_name(pool_state_t state) 217224169Sgibbs{ 218224169Sgibbs switch (state) { 219224169Sgibbs case POOL_STATE_ACTIVE: 220224169Sgibbs return (gettext("ACTIVE")); 221224169Sgibbs case POOL_STATE_EXPORTED: 222224169Sgibbs return (gettext("EXPORTED")); 223224169Sgibbs case POOL_STATE_DESTROYED: 224224169Sgibbs return (gettext("DESTROYED")); 225224169Sgibbs case POOL_STATE_SPARE: 226224169Sgibbs return (gettext("SPARE")); 227224169Sgibbs case POOL_STATE_L2CACHE: 228224169Sgibbs return (gettext("L2CACHE")); 229224169Sgibbs case POOL_STATE_UNINITIALIZED: 230224169Sgibbs return (gettext("UNINITIALIZED")); 231224169Sgibbs case POOL_STATE_UNAVAIL: 232224169Sgibbs return (gettext("UNAVAIL")); 233224169Sgibbs case POOL_STATE_POTENTIALLY_ACTIVE: 234224169Sgibbs return (gettext("POTENTIALLY_ACTIVE")); 235224169Sgibbs } 236224169Sgibbs 237224169Sgibbs return (gettext("UNKNOWN")); 238224169Sgibbs} 239224169Sgibbs 240224169Sgibbs/* 241185029Spjd * Get a zpool property value for 'prop' and return the value in 242185029Spjd * a pre-allocated buffer. 243185029Spjd */ 244185029Spjdint 245185029Spjdzpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, 246263889Sdelphij zprop_source_t *srctype, boolean_t literal) 247185029Spjd{ 248185029Spjd uint64_t intval; 249185029Spjd const char *strval; 250185029Spjd zprop_source_t src = ZPROP_SRC_NONE; 251185029Spjd nvlist_t *nvroot; 252185029Spjd vdev_stat_t *vs; 253185029Spjd uint_t vsc; 254185029Spjd 255185029Spjd if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 256209962Smm switch (prop) { 257209962Smm case ZPOOL_PROP_NAME: 258185029Spjd (void) strlcpy(buf, zpool_get_name(zhp), len); 259209962Smm break; 260209962Smm 261209962Smm case ZPOOL_PROP_HEALTH: 262276446Ssmh (void) strlcpy(buf, 263276446Ssmh zpool_pool_state_to_name(POOL_STATE_UNAVAIL), len); 264209962Smm break; 265209962Smm 266209962Smm case ZPOOL_PROP_GUID: 267209962Smm intval = zpool_get_prop_int(zhp, prop, &src); 268209962Smm (void) snprintf(buf, len, "%llu", intval); 269209962Smm break; 270209962Smm 271209962Smm case ZPOOL_PROP_ALTROOT: 272209962Smm case ZPOOL_PROP_CACHEFILE: 273228103Smm case ZPOOL_PROP_COMMENT: 274209962Smm if (zhp->zpool_props != NULL || 275209962Smm zpool_get_all_props(zhp) == 0) { 276209962Smm (void) strlcpy(buf, 277209962Smm zpool_get_prop_string(zhp, prop, &src), 278209962Smm len); 279263889Sdelphij break; 280209962Smm } 281209962Smm /* FALLTHROUGH */ 282209962Smm default: 283185029Spjd (void) strlcpy(buf, "-", len); 284209962Smm break; 285209962Smm } 286209962Smm 287209962Smm if (srctype != NULL) 288209962Smm *srctype = src; 289185029Spjd return (0); 290185029Spjd } 291185029Spjd 292185029Spjd if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) && 293185029Spjd prop != ZPOOL_PROP_NAME) 294185029Spjd return (-1); 295185029Spjd 296185029Spjd switch (zpool_prop_get_type(prop)) { 297185029Spjd case PROP_TYPE_STRING: 298185029Spjd (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src), 299185029Spjd len); 300185029Spjd break; 301185029Spjd 302185029Spjd case PROP_TYPE_NUMBER: 303185029Spjd intval = zpool_get_prop_int(zhp, prop, &src); 304185029Spjd 305185029Spjd switch (prop) { 306185029Spjd case ZPOOL_PROP_SIZE: 307219089Spjd case ZPOOL_PROP_ALLOCATED: 308219089Spjd case ZPOOL_PROP_FREE: 309236884Smm case ZPOOL_PROP_FREEING: 310268079Sdelphij case ZPOOL_PROP_LEAKED: 311263889Sdelphij if (literal) { 312263889Sdelphij (void) snprintf(buf, len, "%llu", 313263889Sdelphij (u_longlong_t)intval); 314263889Sdelphij } else { 315263889Sdelphij (void) zfs_nicenum(intval, buf, len); 316263889Sdelphij } 317185029Spjd break; 318272502Sdelphij case ZPOOL_PROP_EXPANDSZ: 319272502Sdelphij if (intval == 0) { 320272502Sdelphij (void) strlcpy(buf, "-", len); 321272502Sdelphij } else if (literal) { 322272502Sdelphij (void) snprintf(buf, len, "%llu", 323272502Sdelphij (u_longlong_t)intval); 324272502Sdelphij } else { 325272502Sdelphij (void) zfs_nicenum(intval, buf, len); 326272502Sdelphij } 327272502Sdelphij break; 328185029Spjd case ZPOOL_PROP_CAPACITY: 329263889Sdelphij if (literal) { 330263889Sdelphij (void) snprintf(buf, len, "%llu", 331263889Sdelphij (u_longlong_t)intval); 332263889Sdelphij } else { 333263889Sdelphij (void) snprintf(buf, len, "%llu%%", 334263889Sdelphij (u_longlong_t)intval); 335263889Sdelphij } 336185029Spjd break; 337269118Sdelphij case ZPOOL_PROP_FRAGMENTATION: 338269118Sdelphij if (intval == UINT64_MAX) { 339269118Sdelphij (void) strlcpy(buf, "-", len); 340269118Sdelphij } else { 341269118Sdelphij (void) snprintf(buf, len, "%llu%%", 342269118Sdelphij (u_longlong_t)intval); 343269118Sdelphij } 344269118Sdelphij break; 345219089Spjd case ZPOOL_PROP_DEDUPRATIO: 346219089Spjd (void) snprintf(buf, len, "%llu.%02llux", 347219089Spjd (u_longlong_t)(intval / 100), 348219089Spjd (u_longlong_t)(intval % 100)); 349219089Spjd break; 350185029Spjd case ZPOOL_PROP_HEALTH: 351185029Spjd verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 352185029Spjd ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 353185029Spjd verify(nvlist_lookup_uint64_array(nvroot, 354219089Spjd ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &vsc) 355219089Spjd == 0); 356185029Spjd 357185029Spjd (void) strlcpy(buf, zpool_state_to_name(intval, 358185029Spjd vs->vs_aux), len); 359185029Spjd break; 360236884Smm case ZPOOL_PROP_VERSION: 361236884Smm if (intval >= SPA_VERSION_FEATURES) { 362236884Smm (void) snprintf(buf, len, "-"); 363236884Smm break; 364236884Smm } 365236884Smm /* FALLTHROUGH */ 366185029Spjd default: 367185029Spjd (void) snprintf(buf, len, "%llu", intval); 368185029Spjd } 369185029Spjd break; 370185029Spjd 371185029Spjd case PROP_TYPE_INDEX: 372185029Spjd intval = zpool_get_prop_int(zhp, prop, &src); 373185029Spjd if (zpool_prop_index_to_string(prop, intval, &strval) 374185029Spjd != 0) 375185029Spjd return (-1); 376185029Spjd (void) strlcpy(buf, strval, len); 377185029Spjd break; 378185029Spjd 379185029Spjd default: 380185029Spjd abort(); 381185029Spjd } 382185029Spjd 383185029Spjd if (srctype) 384185029Spjd *srctype = src; 385185029Spjd 386185029Spjd return (0); 387185029Spjd} 388185029Spjd 389185029Spjd/* 390185029Spjd * Check if the bootfs name has the same pool name as it is set to. 391185029Spjd * Assuming bootfs is a valid dataset name. 392185029Spjd */ 393185029Spjdstatic boolean_t 394185029Spjdbootfs_name_valid(const char *pool, char *bootfs) 395185029Spjd{ 396185029Spjd int len = strlen(pool); 397185029Spjd 398185029Spjd if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM|ZFS_TYPE_SNAPSHOT)) 399185029Spjd return (B_FALSE); 400185029Spjd 401185029Spjd if (strncmp(pool, bootfs, len) == 0 && 402185029Spjd (bootfs[len] == '/' || bootfs[len] == '\0')) 403185029Spjd return (B_TRUE); 404185029Spjd 405185029Spjd return (B_FALSE); 406185029Spjd} 407185029Spjd 408236155Smmboolean_t 409236155Smmzpool_is_bootable(zpool_handle_t *zhp) 410219089Spjd{ 411307108Smav char bootfs[ZFS_MAX_DATASET_NAME_LEN]; 412219089Spjd 413219089Spjd return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs, 414263889Sdelphij sizeof (bootfs), NULL, B_FALSE) == 0 && strncmp(bootfs, "-", 415219089Spjd sizeof (bootfs)) != 0); 416219089Spjd} 417219089Spjd 418219089Spjd 419185029Spjd/* 420185029Spjd * Given an nvlist of zpool properties to be set, validate that they are 421185029Spjd * correct, and parse any numeric properties (index, boolean, etc) if they are 422185029Spjd * specified as strings. 423185029Spjd */ 424185029Spjdstatic nvlist_t * 425185029Spjdzpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname, 426219089Spjd nvlist_t *props, uint64_t version, prop_flags_t flags, char *errbuf) 427185029Spjd{ 428185029Spjd nvpair_t *elem; 429185029Spjd nvlist_t *retprops; 430185029Spjd zpool_prop_t prop; 431185029Spjd char *strval; 432185029Spjd uint64_t intval; 433228103Smm char *slash, *check; 434185029Spjd struct stat64 statbuf; 435185029Spjd zpool_handle_t *zhp; 436185029Spjd 437185029Spjd if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) { 438185029Spjd (void) no_memory(hdl); 439185029Spjd return (NULL); 440185029Spjd } 441185029Spjd 442185029Spjd elem = NULL; 443185029Spjd while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 444185029Spjd const char *propname = nvpair_name(elem); 445185029Spjd 446236884Smm prop = zpool_name_to_prop(propname); 447236884Smm if (prop == ZPROP_INVAL && zpool_prop_feature(propname)) { 448236884Smm int err; 449236884Smm char *fname = strchr(propname, '@') + 1; 450236884Smm 451259813Sdelphij err = zfeature_lookup_name(fname, NULL); 452236884Smm if (err != 0) { 453236884Smm ASSERT3U(err, ==, ENOENT); 454236884Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 455236884Smm "invalid feature '%s'"), fname); 456236884Smm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 457236884Smm goto error; 458236884Smm } 459236884Smm 460236884Smm if (nvpair_type(elem) != DATA_TYPE_STRING) { 461236884Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 462236884Smm "'%s' must be a string"), propname); 463236884Smm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 464236884Smm goto error; 465236884Smm } 466236884Smm 467236884Smm (void) nvpair_value_string(elem, &strval); 468236884Smm if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0) { 469236884Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 470236884Smm "property '%s' can only be set to " 471236884Smm "'enabled'"), propname); 472236884Smm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 473236884Smm goto error; 474236884Smm } 475236884Smm 476236884Smm if (nvlist_add_uint64(retprops, propname, 0) != 0) { 477236884Smm (void) no_memory(hdl); 478236884Smm goto error; 479236884Smm } 480236884Smm continue; 481236884Smm } 482236884Smm 483185029Spjd /* 484185029Spjd * Make sure this property is valid and applies to this type. 485185029Spjd */ 486236884Smm if (prop == ZPROP_INVAL) { 487185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 488185029Spjd "invalid property '%s'"), propname); 489185029Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 490185029Spjd goto error; 491185029Spjd } 492185029Spjd 493185029Spjd if (zpool_prop_readonly(prop)) { 494185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 495185029Spjd "is readonly"), propname); 496185029Spjd (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); 497185029Spjd goto error; 498185029Spjd } 499185029Spjd 500185029Spjd if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops, 501185029Spjd &strval, &intval, errbuf) != 0) 502185029Spjd goto error; 503185029Spjd 504185029Spjd /* 505185029Spjd * Perform additional checking for specific properties. 506185029Spjd */ 507185029Spjd switch (prop) { 508185029Spjd case ZPOOL_PROP_VERSION: 509236884Smm if (intval < version || 510236884Smm !SPA_VERSION_IS_SUPPORTED(intval)) { 511185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 512185029Spjd "property '%s' number %d is invalid."), 513185029Spjd propname, intval); 514185029Spjd (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 515185029Spjd goto error; 516185029Spjd } 517185029Spjd break; 518185029Spjd 519185029Spjd case ZPOOL_PROP_BOOTFS: 520219089Spjd if (flags.create || flags.import) { 521185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 522185029Spjd "property '%s' cannot be set at creation " 523185029Spjd "or import time"), propname); 524185029Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 525185029Spjd goto error; 526185029Spjd } 527185029Spjd 528185029Spjd if (version < SPA_VERSION_BOOTFS) { 529185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 530185029Spjd "pool must be upgraded to support " 531185029Spjd "'%s' property"), propname); 532185029Spjd (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 533185029Spjd goto error; 534185029Spjd } 535185029Spjd 536185029Spjd /* 537185029Spjd * bootfs property value has to be a dataset name and 538185029Spjd * the dataset has to be in the same pool as it sets to. 539185029Spjd */ 540185029Spjd if (strval[0] != '\0' && !bootfs_name_valid(poolname, 541185029Spjd strval)) { 542185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 543185029Spjd "is an invalid name"), strval); 544185029Spjd (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 545185029Spjd goto error; 546185029Spjd } 547185029Spjd 548185029Spjd if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) { 549185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 550185029Spjd "could not open pool '%s'"), poolname); 551185029Spjd (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf); 552185029Spjd goto error; 553185029Spjd } 554185029Spjd zpool_close(zhp); 555185029Spjd break; 556185029Spjd 557185029Spjd case ZPOOL_PROP_ALTROOT: 558219089Spjd if (!flags.create && !flags.import) { 559185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 560185029Spjd "property '%s' can only be set during pool " 561185029Spjd "creation or import"), propname); 562185029Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 563185029Spjd goto error; 564185029Spjd } 565185029Spjd 566185029Spjd if (strval[0] != '/') { 567185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 568185029Spjd "bad alternate root '%s'"), strval); 569185029Spjd (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 570185029Spjd goto error; 571185029Spjd } 572185029Spjd break; 573185029Spjd 574185029Spjd case ZPOOL_PROP_CACHEFILE: 575185029Spjd if (strval[0] == '\0') 576185029Spjd break; 577185029Spjd 578185029Spjd if (strcmp(strval, "none") == 0) 579185029Spjd break; 580185029Spjd 581185029Spjd if (strval[0] != '/') { 582185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 583185029Spjd "property '%s' must be empty, an " 584185029Spjd "absolute path, or 'none'"), propname); 585185029Spjd (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 586185029Spjd goto error; 587185029Spjd } 588185029Spjd 589185029Spjd slash = strrchr(strval, '/'); 590185029Spjd 591185029Spjd if (slash[1] == '\0' || strcmp(slash, "/.") == 0 || 592185029Spjd strcmp(slash, "/..") == 0) { 593185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 594185029Spjd "'%s' is not a valid file"), strval); 595185029Spjd (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 596185029Spjd goto error; 597185029Spjd } 598185029Spjd 599185029Spjd *slash = '\0'; 600185029Spjd 601185029Spjd if (strval[0] != '\0' && 602185029Spjd (stat64(strval, &statbuf) != 0 || 603185029Spjd !S_ISDIR(statbuf.st_mode))) { 604185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 605185029Spjd "'%s' is not a valid directory"), 606185029Spjd strval); 607185029Spjd (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 608185029Spjd goto error; 609185029Spjd } 610185029Spjd 611185029Spjd *slash = '/'; 612185029Spjd break; 613219089Spjd 614228103Smm case ZPOOL_PROP_COMMENT: 615228103Smm for (check = strval; *check != '\0'; check++) { 616228103Smm if (!isprint(*check)) { 617228103Smm zfs_error_aux(hdl, 618228103Smm dgettext(TEXT_DOMAIN, 619228103Smm "comment may only have printable " 620228103Smm "characters")); 621228103Smm (void) zfs_error(hdl, EZFS_BADPROP, 622228103Smm errbuf); 623228103Smm goto error; 624228103Smm } 625228103Smm } 626228103Smm if (strlen(strval) > ZPROP_MAX_COMMENT) { 627228103Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 628228103Smm "comment must not exceed %d characters"), 629228103Smm ZPROP_MAX_COMMENT); 630228103Smm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 631228103Smm goto error; 632228103Smm } 633228103Smm break; 634219089Spjd case ZPOOL_PROP_READONLY: 635219089Spjd if (!flags.import) { 636219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 637219089Spjd "property '%s' can only be set at " 638219089Spjd "import time"), propname); 639219089Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 640219089Spjd goto error; 641219089Spjd } 642219089Spjd break; 643307050Smav 644307050Smav default: 645307050Smav zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 646307050Smav "property '%s'(%d) not defined"), propname, prop); 647307050Smav break; 648185029Spjd } 649185029Spjd } 650185029Spjd 651185029Spjd return (retprops); 652185029Spjderror: 653185029Spjd nvlist_free(retprops); 654185029Spjd return (NULL); 655185029Spjd} 656185029Spjd 657185029Spjd/* 658185029Spjd * Set zpool property : propname=propval. 659185029Spjd */ 660185029Spjdint 661185029Spjdzpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) 662185029Spjd{ 663185029Spjd zfs_cmd_t zc = { 0 }; 664185029Spjd int ret = -1; 665185029Spjd char errbuf[1024]; 666185029Spjd nvlist_t *nvl = NULL; 667185029Spjd nvlist_t *realprops; 668185029Spjd uint64_t version; 669219089Spjd prop_flags_t flags = { 0 }; 670185029Spjd 671185029Spjd (void) snprintf(errbuf, sizeof (errbuf), 672185029Spjd dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 673185029Spjd zhp->zpool_name); 674185029Spjd 675185029Spjd if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 676185029Spjd return (no_memory(zhp->zpool_hdl)); 677185029Spjd 678185029Spjd if (nvlist_add_string(nvl, propname, propval) != 0) { 679185029Spjd nvlist_free(nvl); 680185029Spjd return (no_memory(zhp->zpool_hdl)); 681185029Spjd } 682185029Spjd 683185029Spjd version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 684185029Spjd if ((realprops = zpool_valid_proplist(zhp->zpool_hdl, 685219089Spjd zhp->zpool_name, nvl, version, flags, errbuf)) == NULL) { 686185029Spjd nvlist_free(nvl); 687185029Spjd return (-1); 688185029Spjd } 689185029Spjd 690185029Spjd nvlist_free(nvl); 691185029Spjd nvl = realprops; 692185029Spjd 693185029Spjd /* 694185029Spjd * Execute the corresponding ioctl() to set this property. 695185029Spjd */ 696185029Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 697185029Spjd 698185029Spjd if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) { 699185029Spjd nvlist_free(nvl); 700185029Spjd return (-1); 701185029Spjd } 702185029Spjd 703185029Spjd ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc); 704185029Spjd 705185029Spjd zcmd_free_nvlists(&zc); 706185029Spjd nvlist_free(nvl); 707185029Spjd 708185029Spjd if (ret) 709185029Spjd (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); 710185029Spjd else 711185029Spjd (void) zpool_props_refresh(zhp); 712185029Spjd 713185029Spjd return (ret); 714185029Spjd} 715185029Spjd 716185029Spjdint 717185029Spjdzpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp) 718185029Spjd{ 719185029Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 720185029Spjd zprop_list_t *entry; 721185029Spjd char buf[ZFS_MAXPROPLEN]; 722236884Smm nvlist_t *features = NULL; 723236884Smm zprop_list_t **last; 724236884Smm boolean_t firstexpand = (NULL == *plp); 725185029Spjd 726185029Spjd if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0) 727185029Spjd return (-1); 728185029Spjd 729236884Smm last = plp; 730236884Smm while (*last != NULL) 731236884Smm last = &(*last)->pl_next; 732236884Smm 733236884Smm if ((*plp)->pl_all) 734236884Smm features = zpool_get_features(zhp); 735236884Smm 736236884Smm if ((*plp)->pl_all && firstexpand) { 737236884Smm for (int i = 0; i < SPA_FEATURES; i++) { 738236884Smm zprop_list_t *entry = zfs_alloc(hdl, 739236884Smm sizeof (zprop_list_t)); 740236884Smm entry->pl_prop = ZPROP_INVAL; 741236884Smm entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s", 742236884Smm spa_feature_table[i].fi_uname); 743236884Smm entry->pl_width = strlen(entry->pl_user_prop); 744236884Smm entry->pl_all = B_TRUE; 745236884Smm 746236884Smm *last = entry; 747236884Smm last = &entry->pl_next; 748236884Smm } 749236884Smm } 750236884Smm 751236884Smm /* add any unsupported features */ 752236884Smm for (nvpair_t *nvp = nvlist_next_nvpair(features, NULL); 753236884Smm nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) { 754236884Smm char *propname; 755236884Smm boolean_t found; 756236884Smm zprop_list_t *entry; 757236884Smm 758236884Smm if (zfeature_is_supported(nvpair_name(nvp))) 759236884Smm continue; 760236884Smm 761236884Smm propname = zfs_asprintf(hdl, "unsupported@%s", 762236884Smm nvpair_name(nvp)); 763236884Smm 764236884Smm /* 765236884Smm * Before adding the property to the list make sure that no 766236884Smm * other pool already added the same property. 767236884Smm */ 768236884Smm found = B_FALSE; 769236884Smm entry = *plp; 770236884Smm while (entry != NULL) { 771236884Smm if (entry->pl_user_prop != NULL && 772236884Smm strcmp(propname, entry->pl_user_prop) == 0) { 773236884Smm found = B_TRUE; 774236884Smm break; 775236884Smm } 776236884Smm entry = entry->pl_next; 777236884Smm } 778236884Smm if (found) { 779236884Smm free(propname); 780236884Smm continue; 781236884Smm } 782236884Smm 783236884Smm entry = zfs_alloc(hdl, sizeof (zprop_list_t)); 784236884Smm entry->pl_prop = ZPROP_INVAL; 785236884Smm entry->pl_user_prop = propname; 786236884Smm entry->pl_width = strlen(entry->pl_user_prop); 787236884Smm entry->pl_all = B_TRUE; 788236884Smm 789236884Smm *last = entry; 790236884Smm last = &entry->pl_next; 791236884Smm } 792236884Smm 793185029Spjd for (entry = *plp; entry != NULL; entry = entry->pl_next) { 794185029Spjd 795185029Spjd if (entry->pl_fixed) 796185029Spjd continue; 797185029Spjd 798185029Spjd if (entry->pl_prop != ZPROP_INVAL && 799185029Spjd zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), 800263889Sdelphij NULL, B_FALSE) == 0) { 801185029Spjd if (strlen(buf) > entry->pl_width) 802185029Spjd entry->pl_width = strlen(buf); 803185029Spjd } 804185029Spjd } 805185029Spjd 806185029Spjd return (0); 807185029Spjd} 808185029Spjd 809236884Smm/* 810236884Smm * Get the state for the given feature on the given ZFS pool. 811236884Smm */ 812236884Smmint 813236884Smmzpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf, 814236884Smm size_t len) 815236884Smm{ 816236884Smm uint64_t refcount; 817236884Smm boolean_t found = B_FALSE; 818236884Smm nvlist_t *features = zpool_get_features(zhp); 819236884Smm boolean_t supported; 820236884Smm const char *feature = strchr(propname, '@') + 1; 821185029Spjd 822236884Smm supported = zpool_prop_feature(propname); 823236884Smm ASSERT(supported || zpool_prop_unsupported(propname)); 824236884Smm 825236884Smm /* 826236884Smm * Convert from feature name to feature guid. This conversion is 827236884Smm * unecessary for unsupported@... properties because they already 828236884Smm * use guids. 829236884Smm */ 830236884Smm if (supported) { 831236884Smm int ret; 832259813Sdelphij spa_feature_t fid; 833236884Smm 834259813Sdelphij ret = zfeature_lookup_name(feature, &fid); 835236884Smm if (ret != 0) { 836236884Smm (void) strlcpy(buf, "-", len); 837236884Smm return (ENOTSUP); 838236884Smm } 839259813Sdelphij feature = spa_feature_table[fid].fi_guid; 840236884Smm } 841236884Smm 842236884Smm if (nvlist_lookup_uint64(features, feature, &refcount) == 0) 843236884Smm found = B_TRUE; 844236884Smm 845236884Smm if (supported) { 846236884Smm if (!found) { 847236884Smm (void) strlcpy(buf, ZFS_FEATURE_DISABLED, len); 848236884Smm } else { 849236884Smm if (refcount == 0) 850236884Smm (void) strlcpy(buf, ZFS_FEATURE_ENABLED, len); 851236884Smm else 852236884Smm (void) strlcpy(buf, ZFS_FEATURE_ACTIVE, len); 853236884Smm } 854236884Smm } else { 855236884Smm if (found) { 856236884Smm if (refcount == 0) { 857236884Smm (void) strcpy(buf, ZFS_UNSUPPORTED_INACTIVE); 858236884Smm } else { 859236884Smm (void) strcpy(buf, ZFS_UNSUPPORTED_READONLY); 860236884Smm } 861236884Smm } else { 862236884Smm (void) strlcpy(buf, "-", len); 863236884Smm return (ENOTSUP); 864236884Smm } 865236884Smm } 866236884Smm 867236884Smm return (0); 868236884Smm} 869236884Smm 870185029Spjd/* 871219089Spjd * Don't start the slice at the default block of 34; many storage 872219089Spjd * devices will use a stripe width of 128k, so start there instead. 873219089Spjd */ 874219089Spjd#define NEW_START_BLOCK 256 875219089Spjd 876219089Spjd/* 877168404Spjd * Validate the given pool name, optionally putting an extended error message in 878168404Spjd * 'buf'. 879168404Spjd */ 880185029Spjdboolean_t 881168404Spjdzpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) 882168404Spjd{ 883168404Spjd namecheck_err_t why; 884168404Spjd char what; 885168404Spjd int ret; 886168404Spjd 887168404Spjd ret = pool_namecheck(pool, &why, &what); 888168404Spjd 889168404Spjd /* 890168404Spjd * The rules for reserved pool names were extended at a later point. 891168404Spjd * But we need to support users with existing pools that may now be 892168404Spjd * invalid. So we only check for this expanded set of names during a 893168404Spjd * create (or import), and only in userland. 894168404Spjd */ 895168404Spjd if (ret == 0 && !isopen && 896168404Spjd (strncmp(pool, "mirror", 6) == 0 || 897168404Spjd strncmp(pool, "raidz", 5) == 0 || 898185029Spjd strncmp(pool, "spare", 5) == 0 || 899185029Spjd strcmp(pool, "log") == 0)) { 900185029Spjd if (hdl != NULL) 901185029Spjd zfs_error_aux(hdl, 902185029Spjd dgettext(TEXT_DOMAIN, "name is reserved")); 903168404Spjd return (B_FALSE); 904168404Spjd } 905168404Spjd 906168404Spjd 907168404Spjd if (ret != 0) { 908168404Spjd if (hdl != NULL) { 909168404Spjd switch (why) { 910168404Spjd case NAME_ERR_TOOLONG: 911168404Spjd zfs_error_aux(hdl, 912168404Spjd dgettext(TEXT_DOMAIN, "name is too long")); 913168404Spjd break; 914168404Spjd 915168404Spjd case NAME_ERR_INVALCHAR: 916168404Spjd zfs_error_aux(hdl, 917168404Spjd dgettext(TEXT_DOMAIN, "invalid character " 918168404Spjd "'%c' in pool name"), what); 919168404Spjd break; 920168404Spjd 921168404Spjd case NAME_ERR_NOLETTER: 922168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 923168404Spjd "name must begin with a letter")); 924168404Spjd break; 925168404Spjd 926168404Spjd case NAME_ERR_RESERVED: 927168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 928168404Spjd "name is reserved")); 929168404Spjd break; 930168404Spjd 931168404Spjd case NAME_ERR_DISKLIKE: 932168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 933168404Spjd "pool name is reserved")); 934168404Spjd break; 935168404Spjd 936168404Spjd case NAME_ERR_LEADING_SLASH: 937168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 938168404Spjd "leading slash in name")); 939168404Spjd break; 940168404Spjd 941168404Spjd case NAME_ERR_EMPTY_COMPONENT: 942168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 943168404Spjd "empty component in name")); 944168404Spjd break; 945168404Spjd 946168404Spjd case NAME_ERR_TRAILING_SLASH: 947168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 948168404Spjd "trailing slash in name")); 949168404Spjd break; 950168404Spjd 951321534Smav case NAME_ERR_MULTIPLE_DELIMITERS: 952168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 953321534Smav "multiple '@' and/or '#' delimiters in " 954321534Smav "name")); 955168404Spjd break; 956168404Spjd 957307050Smav default: 958307050Smav zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 959307050Smav "(%d) not defined"), why); 960307050Smav break; 961168404Spjd } 962168404Spjd } 963168404Spjd return (B_FALSE); 964168404Spjd } 965168404Spjd 966168404Spjd return (B_TRUE); 967168404Spjd} 968168404Spjd 969168404Spjd/* 970168404Spjd * Open a handle to the given pool, even if the pool is currently in the FAULTED 971168404Spjd * state. 972168404Spjd */ 973168404Spjdzpool_handle_t * 974168404Spjdzpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 975168404Spjd{ 976168404Spjd zpool_handle_t *zhp; 977168404Spjd boolean_t missing; 978168404Spjd 979168404Spjd /* 980168404Spjd * Make sure the pool name is valid. 981168404Spjd */ 982168404Spjd if (!zpool_name_valid(hdl, B_TRUE, pool)) { 983168404Spjd (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, 984168404Spjd dgettext(TEXT_DOMAIN, "cannot open '%s'"), 985168404Spjd pool); 986168404Spjd return (NULL); 987168404Spjd } 988168404Spjd 989168404Spjd if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 990168404Spjd return (NULL); 991168404Spjd 992168404Spjd zhp->zpool_hdl = hdl; 993168404Spjd (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 994168404Spjd 995168404Spjd if (zpool_refresh_stats(zhp, &missing) != 0) { 996168404Spjd zpool_close(zhp); 997168404Spjd return (NULL); 998168404Spjd } 999168404Spjd 1000168404Spjd if (missing) { 1001185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool")); 1002168404Spjd (void) zfs_error_fmt(hdl, EZFS_NOENT, 1003185029Spjd dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool); 1004168404Spjd zpool_close(zhp); 1005168404Spjd return (NULL); 1006168404Spjd } 1007168404Spjd 1008168404Spjd return (zhp); 1009168404Spjd} 1010168404Spjd 1011168404Spjd/* 1012168404Spjd * Like the above, but silent on error. Used when iterating over pools (because 1013168404Spjd * the configuration cache may be out of date). 1014168404Spjd */ 1015168404Spjdint 1016168404Spjdzpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 1017168404Spjd{ 1018168404Spjd zpool_handle_t *zhp; 1019168404Spjd boolean_t missing; 1020168404Spjd 1021168404Spjd if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 1022168404Spjd return (-1); 1023168404Spjd 1024168404Spjd zhp->zpool_hdl = hdl; 1025168404Spjd (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 1026168404Spjd 1027168404Spjd if (zpool_refresh_stats(zhp, &missing) != 0) { 1028168404Spjd zpool_close(zhp); 1029168404Spjd return (-1); 1030168404Spjd } 1031168404Spjd 1032168404Spjd if (missing) { 1033168404Spjd zpool_close(zhp); 1034168404Spjd *ret = NULL; 1035168404Spjd return (0); 1036168404Spjd } 1037168404Spjd 1038168404Spjd *ret = zhp; 1039168404Spjd return (0); 1040168404Spjd} 1041168404Spjd 1042168404Spjd/* 1043168404Spjd * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 1044168404Spjd * state. 1045168404Spjd */ 1046168404Spjdzpool_handle_t * 1047168404Spjdzpool_open(libzfs_handle_t *hdl, const char *pool) 1048168404Spjd{ 1049168404Spjd zpool_handle_t *zhp; 1050168404Spjd 1051168404Spjd if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 1052168404Spjd return (NULL); 1053168404Spjd 1054168404Spjd if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 1055168404Spjd (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, 1056168404Spjd dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 1057168404Spjd zpool_close(zhp); 1058168404Spjd return (NULL); 1059168404Spjd } 1060168404Spjd 1061168404Spjd return (zhp); 1062168404Spjd} 1063168404Spjd 1064168404Spjd/* 1065168404Spjd * Close the handle. Simply frees the memory associated with the handle. 1066168404Spjd */ 1067168404Spjdvoid 1068168404Spjdzpool_close(zpool_handle_t *zhp) 1069168404Spjd{ 1070296528Smav nvlist_free(zhp->zpool_config); 1071296528Smav nvlist_free(zhp->zpool_old_config); 1072296528Smav nvlist_free(zhp->zpool_props); 1073168404Spjd free(zhp); 1074168404Spjd} 1075168404Spjd 1076168404Spjd/* 1077168404Spjd * Return the name of the pool. 1078168404Spjd */ 1079168404Spjdconst char * 1080168404Spjdzpool_get_name(zpool_handle_t *zhp) 1081168404Spjd{ 1082168404Spjd return (zhp->zpool_name); 1083168404Spjd} 1084168404Spjd 1085168404Spjd 1086168404Spjd/* 1087168404Spjd * Return the state of the pool (ACTIVE or UNAVAILABLE) 1088168404Spjd */ 1089168404Spjdint 1090168404Spjdzpool_get_state(zpool_handle_t *zhp) 1091168404Spjd{ 1092168404Spjd return (zhp->zpool_state); 1093168404Spjd} 1094168404Spjd 1095168404Spjd/* 1096168404Spjd * Create the named pool, using the provided vdev list. It is assumed 1097168404Spjd * that the consumer has already validated the contents of the nvlist, so we 1098168404Spjd * don't have to worry about error semantics. 1099168404Spjd */ 1100168404Spjdint 1101168404Spjdzpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 1102185029Spjd nvlist_t *props, nvlist_t *fsprops) 1103168404Spjd{ 1104168404Spjd zfs_cmd_t zc = { 0 }; 1105185029Spjd nvlist_t *zc_fsprops = NULL; 1106185029Spjd nvlist_t *zc_props = NULL; 1107168404Spjd char msg[1024]; 1108185029Spjd int ret = -1; 1109168404Spjd 1110168404Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 1111168404Spjd "cannot create '%s'"), pool); 1112168404Spjd 1113168404Spjd if (!zpool_name_valid(hdl, B_FALSE, pool)) 1114168404Spjd return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 1115168404Spjd 1116185029Spjd if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 1117168404Spjd return (-1); 1118168404Spjd 1119185029Spjd if (props) { 1120219089Spjd prop_flags_t flags = { .create = B_TRUE, .import = B_FALSE }; 1121219089Spjd 1122185029Spjd if ((zc_props = zpool_valid_proplist(hdl, pool, props, 1123219089Spjd SPA_VERSION_1, flags, msg)) == NULL) { 1124185029Spjd goto create_failed; 1125185029Spjd } 1126185029Spjd } 1127185029Spjd 1128185029Spjd if (fsprops) { 1129185029Spjd uint64_t zoned; 1130185029Spjd char *zonestr; 1131185029Spjd 1132185029Spjd zoned = ((nvlist_lookup_string(fsprops, 1133185029Spjd zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) && 1134185029Spjd strcmp(zonestr, "on") == 0); 1135185029Spjd 1136289500Smav if ((zc_fsprops = zfs_valid_proplist(hdl, ZFS_TYPE_FILESYSTEM, 1137289500Smav fsprops, zoned, NULL, NULL, msg)) == NULL) { 1138185029Spjd goto create_failed; 1139185029Spjd } 1140185029Spjd if (!zc_props && 1141185029Spjd (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) { 1142185029Spjd goto create_failed; 1143185029Spjd } 1144185029Spjd if (nvlist_add_nvlist(zc_props, 1145185029Spjd ZPOOL_ROOTFS_PROPS, zc_fsprops) != 0) { 1146185029Spjd goto create_failed; 1147185029Spjd } 1148185029Spjd } 1149185029Spjd 1150185029Spjd if (zc_props && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0) 1151185029Spjd goto create_failed; 1152185029Spjd 1153168404Spjd (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 1154168404Spjd 1155185029Spjd if ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc)) != 0) { 1156168404Spjd 1157168404Spjd zcmd_free_nvlists(&zc); 1158185029Spjd nvlist_free(zc_props); 1159185029Spjd nvlist_free(zc_fsprops); 1160168404Spjd 1161168404Spjd switch (errno) { 1162168404Spjd case EBUSY: 1163168404Spjd /* 1164168404Spjd * This can happen if the user has specified the same 1165168404Spjd * device multiple times. We can't reliably detect this 1166168404Spjd * until we try to add it and see we already have a 1167168404Spjd * label. 1168168404Spjd */ 1169168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1170168404Spjd "one or more vdevs refer to the same device")); 1171168404Spjd return (zfs_error(hdl, EZFS_BADDEV, msg)); 1172168404Spjd 1173289500Smav case ERANGE: 1174289500Smav /* 1175289500Smav * This happens if the record size is smaller or larger 1176289500Smav * than the allowed size range, or not a power of 2. 1177289500Smav * 1178289500Smav * NOTE: although zfs_valid_proplist is called earlier, 1179289500Smav * this case may have slipped through since the 1180289500Smav * pool does not exist yet and it is therefore 1181289500Smav * impossible to read properties e.g. max blocksize 1182289500Smav * from the pool. 1183289500Smav */ 1184289500Smav zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1185289500Smav "record size invalid")); 1186289500Smav return (zfs_error(hdl, EZFS_BADPROP, msg)); 1187289500Smav 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 1233248571Smmzpool_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)); 1245248571Smm 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 1298185029Spjd if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) < 1299185029Spjd SPA_VERSION_L2CACHE && 1300185029Spjd nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 1301185029Spjd &l2cache, &nl2cache) == 0) { 1302185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 1303185029Spjd "upgraded to add cache devices")); 1304185029Spjd return (zfs_error(hdl, EZFS_BADVERSION, msg)); 1305185029Spjd } 1306185029Spjd 1307185029Spjd if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 1308168404Spjd return (-1); 1309168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1310168404Spjd 1311219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) { 1312168404Spjd switch (errno) { 1313168404Spjd case EBUSY: 1314168404Spjd /* 1315168404Spjd * This can happen if the user has specified the same 1316168404Spjd * device multiple times. We can't reliably detect this 1317168404Spjd * until we try to add it and see we already have a 1318168404Spjd * label. 1319168404Spjd */ 1320168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1321168404Spjd "one or more vdevs refer to the same device")); 1322168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 1323168404Spjd break; 1324168404Spjd 1325168404Spjd case EOVERFLOW: 1326168404Spjd /* 1327168404Spjd * This occurrs when one of the devices is below 1328168404Spjd * SPA_MINDEVSIZE. Unfortunately, we can't detect which 1329168404Spjd * device was the problem device since there's no 1330168404Spjd * reliable way to determine device size from userland. 1331168404Spjd */ 1332168404Spjd { 1333168404Spjd char buf[64]; 1334168404Spjd 1335168404Spjd zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 1336168404Spjd 1337168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1338168404Spjd "device is less than the minimum " 1339168404Spjd "size (%s)"), buf); 1340168404Spjd } 1341168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 1342168404Spjd break; 1343168404Spjd 1344168404Spjd case ENOTSUP: 1345168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1346185029Spjd "pool must be upgraded to add these vdevs")); 1347168404Spjd (void) zfs_error(hdl, EZFS_BADVERSION, msg); 1348168404Spjd break; 1349168404Spjd 1350168404Spjd case EDOM: 1351168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1352185029Spjd "root pool can not have multiple vdevs" 1353185029Spjd " or separate logs")); 1354168404Spjd (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg); 1355168404Spjd break; 1356168404Spjd 1357185029Spjd case ENOTBLK: 1358185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1359185029Spjd "cache device must be a disk or disk slice")); 1360185029Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 1361185029Spjd break; 1362185029Spjd 1363168404Spjd default: 1364168404Spjd (void) zpool_standard_error(hdl, errno, msg); 1365168404Spjd } 1366168404Spjd 1367168404Spjd ret = -1; 1368168404Spjd } else { 1369168404Spjd ret = 0; 1370168404Spjd } 1371168404Spjd 1372168404Spjd zcmd_free_nvlists(&zc); 1373168404Spjd 1374168404Spjd return (ret); 1375168404Spjd} 1376168404Spjd 1377168404Spjd/* 1378168404Spjd * Exports the pool from the system. The caller must ensure that there are no 1379168404Spjd * mounted datasets in the pool. 1380168404Spjd */ 1381248571Smmstatic int 1382248571Smmzpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce, 1383248571Smm const char *log_str) 1384168404Spjd{ 1385168404Spjd zfs_cmd_t zc = { 0 }; 1386185029Spjd char msg[1024]; 1387168404Spjd 1388185029Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 1389185029Spjd "cannot export '%s'"), zhp->zpool_name); 1390185029Spjd 1391168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1392185029Spjd zc.zc_cookie = force; 1393207670Smm zc.zc_guid = hardforce; 1394248571Smm zc.zc_history = (uint64_t)(uintptr_t)log_str; 1395168404Spjd 1396185029Spjd if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) { 1397185029Spjd switch (errno) { 1398185029Spjd case EXDEV: 1399185029Spjd zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, 1400185029Spjd "use '-f' to override the following errors:\n" 1401185029Spjd "'%s' has an active shared spare which could be" 1402185029Spjd " used by other pools once '%s' is exported."), 1403185029Spjd zhp->zpool_name, zhp->zpool_name); 1404185029Spjd return (zfs_error(zhp->zpool_hdl, EZFS_ACTIVE_SPARE, 1405185029Spjd msg)); 1406185029Spjd default: 1407185029Spjd return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 1408185029Spjd msg)); 1409185029Spjd } 1410185029Spjd } 1411185029Spjd 1412168404Spjd return (0); 1413168404Spjd} 1414168404Spjd 1415207670Smmint 1416248571Smmzpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str) 1417207670Smm{ 1418248571Smm return (zpool_export_common(zhp, force, B_FALSE, log_str)); 1419207670Smm} 1420207670Smm 1421207670Smmint 1422248571Smmzpool_export_force(zpool_handle_t *zhp, const char *log_str) 1423207670Smm{ 1424248571Smm return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str)); 1425207670Smm} 1426207670Smm 1427219089Spjdstatic void 1428219089Spjdzpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun, 1429219089Spjd nvlist_t *config) 1430219089Spjd{ 1431219089Spjd nvlist_t *nv = NULL; 1432219089Spjd uint64_t rewindto; 1433219089Spjd int64_t loss = -1; 1434219089Spjd struct tm t; 1435219089Spjd char timestr[128]; 1436219089Spjd 1437219089Spjd if (!hdl->libzfs_printerr || config == NULL) 1438219089Spjd return; 1439219089Spjd 1440236884Smm if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 || 1441236884Smm nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0) { 1442219089Spjd return; 1443236884Smm } 1444219089Spjd 1445219089Spjd if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0) 1446219089Spjd return; 1447219089Spjd (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss); 1448219089Spjd 1449219089Spjd if (localtime_r((time_t *)&rewindto, &t) != NULL && 1450219089Spjd strftime(timestr, 128, 0, &t) != 0) { 1451219089Spjd if (dryrun) { 1452219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1453219089Spjd "Would be able to return %s " 1454219089Spjd "to its state as of %s.\n"), 1455219089Spjd name, timestr); 1456219089Spjd } else { 1457219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1458219089Spjd "Pool %s returned to its state as of %s.\n"), 1459219089Spjd name, timestr); 1460219089Spjd } 1461219089Spjd if (loss > 120) { 1462219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1463219089Spjd "%s approximately %lld "), 1464219089Spjd dryrun ? "Would discard" : "Discarded", 1465219089Spjd (loss + 30) / 60); 1466219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1467219089Spjd "minutes of transactions.\n")); 1468219089Spjd } else if (loss > 0) { 1469219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1470219089Spjd "%s approximately %lld "), 1471219089Spjd dryrun ? "Would discard" : "Discarded", loss); 1472219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1473219089Spjd "seconds of transactions.\n")); 1474219089Spjd } 1475219089Spjd } 1476219089Spjd} 1477219089Spjd 1478219089Spjdvoid 1479219089Spjdzpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason, 1480219089Spjd nvlist_t *config) 1481219089Spjd{ 1482219089Spjd nvlist_t *nv = NULL; 1483219089Spjd int64_t loss = -1; 1484219089Spjd uint64_t edata = UINT64_MAX; 1485219089Spjd uint64_t rewindto; 1486219089Spjd struct tm t; 1487219089Spjd char timestr[128]; 1488219089Spjd 1489219089Spjd if (!hdl->libzfs_printerr) 1490219089Spjd return; 1491219089Spjd 1492219089Spjd if (reason >= 0) 1493219089Spjd (void) printf(dgettext(TEXT_DOMAIN, "action: ")); 1494219089Spjd else 1495219089Spjd (void) printf(dgettext(TEXT_DOMAIN, "\t")); 1496219089Spjd 1497219089Spjd /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */ 1498219089Spjd if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 || 1499236884Smm nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 || 1500219089Spjd nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0) 1501219089Spjd goto no_info; 1502219089Spjd 1503219089Spjd (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss); 1504219089Spjd (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS, 1505219089Spjd &edata); 1506219089Spjd 1507219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1508219089Spjd "Recovery is possible, but will result in some data loss.\n")); 1509219089Spjd 1510219089Spjd if (localtime_r((time_t *)&rewindto, &t) != NULL && 1511219089Spjd strftime(timestr, 128, 0, &t) != 0) { 1512219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1513219089Spjd "\tReturning the pool to its state as of %s\n" 1514219089Spjd "\tshould correct the problem. "), 1515219089Spjd timestr); 1516219089Spjd } else { 1517219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1518219089Spjd "\tReverting the pool to an earlier state " 1519219089Spjd "should correct the problem.\n\t")); 1520219089Spjd } 1521219089Spjd 1522219089Spjd if (loss > 120) { 1523219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1524219089Spjd "Approximately %lld minutes of data\n" 1525219089Spjd "\tmust be discarded, irreversibly. "), (loss + 30) / 60); 1526219089Spjd } else if (loss > 0) { 1527219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1528219089Spjd "Approximately %lld seconds of data\n" 1529219089Spjd "\tmust be discarded, irreversibly. "), loss); 1530219089Spjd } 1531219089Spjd if (edata != 0 && edata != UINT64_MAX) { 1532219089Spjd if (edata == 1) { 1533219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1534219089Spjd "After rewind, at least\n" 1535219089Spjd "\tone persistent user-data error will remain. ")); 1536219089Spjd } else { 1537219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1538219089Spjd "After rewind, several\n" 1539219089Spjd "\tpersistent user-data errors will remain. ")); 1540219089Spjd } 1541219089Spjd } 1542219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1543219089Spjd "Recovery can be attempted\n\tby executing 'zpool %s -F %s'. "), 1544219089Spjd reason >= 0 ? "clear" : "import", name); 1545219089Spjd 1546219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1547219089Spjd "A scrub of the pool\n" 1548219089Spjd "\tis strongly recommended after recovery.\n")); 1549219089Spjd return; 1550219089Spjd 1551219089Spjdno_info: 1552219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1553219089Spjd "Destroy and re-create the pool from\n\ta backup source.\n")); 1554219089Spjd} 1555219089Spjd 1556168404Spjd/* 1557185029Spjd * zpool_import() is a contracted interface. Should be kept the same 1558185029Spjd * if possible. 1559185029Spjd * 1560185029Spjd * Applications should use zpool_import_props() to import a pool with 1561185029Spjd * new properties value to be set. 1562168404Spjd */ 1563168404Spjdint 1564168404Spjdzpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 1565185029Spjd char *altroot) 1566168404Spjd{ 1567185029Spjd nvlist_t *props = NULL; 1568185029Spjd int ret; 1569185029Spjd 1570185029Spjd if (altroot != NULL) { 1571185029Spjd if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 1572185029Spjd return (zfs_error_fmt(hdl, EZFS_NOMEM, 1573185029Spjd dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1574185029Spjd newname)); 1575185029Spjd } 1576185029Spjd 1577185029Spjd if (nvlist_add_string(props, 1578209962Smm zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 || 1579209962Smm nvlist_add_string(props, 1580209962Smm zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) { 1581185029Spjd nvlist_free(props); 1582185029Spjd return (zfs_error_fmt(hdl, EZFS_NOMEM, 1583185029Spjd dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1584185029Spjd newname)); 1585185029Spjd } 1586185029Spjd } 1587185029Spjd 1588219089Spjd ret = zpool_import_props(hdl, config, newname, props, 1589219089Spjd ZFS_IMPORT_NORMAL); 1590296528Smav nvlist_free(props); 1591185029Spjd return (ret); 1592185029Spjd} 1593185029Spjd 1594219089Spjdstatic void 1595219089Spjdprint_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv, 1596219089Spjd int indent) 1597219089Spjd{ 1598219089Spjd nvlist_t **child; 1599219089Spjd uint_t c, children; 1600219089Spjd char *vname; 1601219089Spjd uint64_t is_log = 0; 1602219089Spjd 1603219089Spjd (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, 1604219089Spjd &is_log); 1605219089Spjd 1606219089Spjd if (name != NULL) 1607219089Spjd (void) printf("\t%*s%s%s\n", indent, "", name, 1608219089Spjd is_log ? " [log]" : ""); 1609219089Spjd 1610219089Spjd if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1611219089Spjd &child, &children) != 0) 1612219089Spjd return; 1613219089Spjd 1614219089Spjd for (c = 0; c < children; c++) { 1615219089Spjd vname = zpool_vdev_name(hdl, NULL, child[c], B_TRUE); 1616219089Spjd print_vdev_tree(hdl, vname, child[c], indent + 2); 1617219089Spjd free(vname); 1618219089Spjd } 1619219089Spjd} 1620219089Spjd 1621236884Smmvoid 1622236884Smmzpool_print_unsup_feat(nvlist_t *config) 1623236884Smm{ 1624236884Smm nvlist_t *nvinfo, *unsup_feat; 1625236884Smm 1626236884Smm verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 1627236884Smm 0); 1628236884Smm verify(nvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT, 1629236884Smm &unsup_feat) == 0); 1630236884Smm 1631236884Smm for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL); nvp != NULL; 1632236884Smm nvp = nvlist_next_nvpair(unsup_feat, nvp)) { 1633236884Smm char *desc; 1634236884Smm 1635236884Smm verify(nvpair_type(nvp) == DATA_TYPE_STRING); 1636236884Smm verify(nvpair_value_string(nvp, &desc) == 0); 1637236884Smm 1638236884Smm if (strlen(desc) > 0) 1639236884Smm (void) printf("\t%s (%s)\n", nvpair_name(nvp), desc); 1640236884Smm else 1641236884Smm (void) printf("\t%s\n", nvpair_name(nvp)); 1642236884Smm } 1643236884Smm} 1644236884Smm 1645185029Spjd/* 1646185029Spjd * Import the given pool using the known configuration and a list of 1647185029Spjd * properties to be set. The configuration should have come from 1648185029Spjd * zpool_find_import(). The 'newname' parameters control whether the pool 1649185029Spjd * is imported with a different name. 1650185029Spjd */ 1651185029Spjdint 1652185029Spjdzpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 1653219089Spjd nvlist_t *props, int flags) 1654185029Spjd{ 1655168404Spjd zfs_cmd_t zc = { 0 }; 1656219089Spjd zpool_rewind_policy_t policy; 1657219089Spjd nvlist_t *nv = NULL; 1658219089Spjd nvlist_t *nvinfo = NULL; 1659219089Spjd nvlist_t *missing = NULL; 1660168404Spjd char *thename; 1661168404Spjd char *origname; 1662168404Spjd int ret; 1663219089Spjd int error = 0; 1664185029Spjd char errbuf[1024]; 1665168404Spjd 1666168404Spjd verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1667168404Spjd &origname) == 0); 1668168404Spjd 1669185029Spjd (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 1670185029Spjd "cannot import pool '%s'"), origname); 1671185029Spjd 1672168404Spjd if (newname != NULL) { 1673168404Spjd if (!zpool_name_valid(hdl, B_FALSE, newname)) 1674168404Spjd return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 1675168404Spjd dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1676168404Spjd newname)); 1677168404Spjd thename = (char *)newname; 1678168404Spjd } else { 1679168404Spjd thename = origname; 1680168404Spjd } 1681168404Spjd 1682277433Sdelphij if (props != NULL) { 1683185029Spjd uint64_t version; 1684219089Spjd prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE }; 1685168404Spjd 1686185029Spjd verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 1687185029Spjd &version) == 0); 1688185029Spjd 1689185029Spjd if ((props = zpool_valid_proplist(hdl, origname, 1690277433Sdelphij props, version, flags, errbuf)) == NULL) 1691185029Spjd return (-1); 1692277433Sdelphij if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) { 1693185029Spjd nvlist_free(props); 1694185029Spjd return (-1); 1695185029Spjd } 1696277433Sdelphij nvlist_free(props); 1697185029Spjd } 1698185029Spjd 1699168404Spjd (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 1700168404Spjd 1701168404Spjd verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1702168404Spjd &zc.zc_guid) == 0); 1703168404Spjd 1704185029Spjd if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) { 1705277433Sdelphij zcmd_free_nvlists(&zc); 1706168404Spjd return (-1); 1707185029Spjd } 1708219089Spjd if (zcmd_alloc_dst_nvlist(hdl, &zc, zc.zc_nvlist_conf_size * 2) != 0) { 1709277433Sdelphij zcmd_free_nvlists(&zc); 1710219089Spjd return (-1); 1711219089Spjd } 1712168404Spjd 1713219089Spjd zc.zc_cookie = flags; 1714219089Spjd while ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc)) != 0 && 1715219089Spjd errno == ENOMEM) { 1716219089Spjd if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 1717219089Spjd zcmd_free_nvlists(&zc); 1718219089Spjd return (-1); 1719219089Spjd } 1720219089Spjd } 1721219089Spjd if (ret != 0) 1722219089Spjd error = errno; 1723219089Spjd 1724219089Spjd (void) zcmd_read_dst_nvlist(hdl, &zc, &nv); 1725277433Sdelphij 1726277433Sdelphij zcmd_free_nvlists(&zc); 1727277433Sdelphij 1728219089Spjd zpool_get_rewind_policy(config, &policy); 1729219089Spjd 1730219089Spjd if (error) { 1731168404Spjd char desc[1024]; 1732219089Spjd 1733219089Spjd /* 1734219089Spjd * Dry-run failed, but we print out what success 1735219089Spjd * looks like if we found a best txg 1736219089Spjd */ 1737219089Spjd if (policy.zrp_request & ZPOOL_TRY_REWIND) { 1738219089Spjd zpool_rewind_exclaim(hdl, newname ? origname : thename, 1739219089Spjd B_TRUE, nv); 1740219089Spjd nvlist_free(nv); 1741219089Spjd return (-1); 1742219089Spjd } 1743219089Spjd 1744168404Spjd if (newname == NULL) 1745168404Spjd (void) snprintf(desc, sizeof (desc), 1746168404Spjd dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1747168404Spjd thename); 1748168404Spjd else 1749168404Spjd (void) snprintf(desc, sizeof (desc), 1750168404Spjd dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 1751168404Spjd origname, thename); 1752168404Spjd 1753219089Spjd switch (error) { 1754168404Spjd case ENOTSUP: 1755236884Smm if (nv != NULL && nvlist_lookup_nvlist(nv, 1756236884Smm ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 && 1757236884Smm nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) { 1758236884Smm (void) printf(dgettext(TEXT_DOMAIN, "This " 1759236884Smm "pool uses the following feature(s) not " 1760236884Smm "supported by this system:\n")); 1761236884Smm zpool_print_unsup_feat(nv); 1762236884Smm if (nvlist_exists(nvinfo, 1763236884Smm ZPOOL_CONFIG_CAN_RDONLY)) { 1764236884Smm (void) printf(dgettext(TEXT_DOMAIN, 1765236884Smm "All unsupported features are only " 1766236884Smm "required for writing to the pool." 1767236884Smm "\nThe pool can be imported using " 1768236884Smm "'-o readonly=on'.\n")); 1769236884Smm } 1770236884Smm } 1771168404Spjd /* 1772168404Spjd * Unsupported version. 1773168404Spjd */ 1774168404Spjd (void) zfs_error(hdl, EZFS_BADVERSION, desc); 1775168404Spjd break; 1776168404Spjd 1777168404Spjd case EINVAL: 1778168404Spjd (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 1779168404Spjd break; 1780168404Spjd 1781219089Spjd case EROFS: 1782219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1783219089Spjd "one or more devices is read only")); 1784219089Spjd (void) zfs_error(hdl, EZFS_BADDEV, desc); 1785219089Spjd break; 1786219089Spjd 1787219089Spjd case ENXIO: 1788219089Spjd if (nv && nvlist_lookup_nvlist(nv, 1789219089Spjd ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 && 1790219089Spjd nvlist_lookup_nvlist(nvinfo, 1791219089Spjd ZPOOL_CONFIG_MISSING_DEVICES, &missing) == 0) { 1792219089Spjd (void) printf(dgettext(TEXT_DOMAIN, 1793219089Spjd "The devices below are missing, use " 1794219089Spjd "'-m' to import the pool anyway:\n")); 1795219089Spjd print_vdev_tree(hdl, NULL, missing, 2); 1796219089Spjd (void) printf("\n"); 1797219089Spjd } 1798219089Spjd (void) zpool_standard_error(hdl, error, desc); 1799219089Spjd break; 1800219089Spjd 1801219089Spjd case EEXIST: 1802219089Spjd (void) zpool_standard_error(hdl, error, desc); 1803219089Spjd break; 1804307100Smav case ENAMETOOLONG: 1805307100Smav zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1806307100Smav "new name of at least one dataset is longer than " 1807307100Smav "the maximum allowable length")); 1808307100Smav (void) zfs_error(hdl, EZFS_NAMETOOLONG, desc); 1809307100Smav break; 1810168404Spjd default: 1811219089Spjd (void) zpool_standard_error(hdl, error, desc); 1812219089Spjd zpool_explain_recover(hdl, 1813219089Spjd newname ? origname : thename, -error, nv); 1814219089Spjd break; 1815168404Spjd } 1816168404Spjd 1817219089Spjd nvlist_free(nv); 1818168404Spjd ret = -1; 1819168404Spjd } else { 1820168404Spjd zpool_handle_t *zhp; 1821185029Spjd 1822168404Spjd /* 1823168404Spjd * This should never fail, but play it safe anyway. 1824168404Spjd */ 1825219089Spjd if (zpool_open_silent(hdl, thename, &zhp) != 0) 1826168404Spjd ret = -1; 1827219089Spjd else if (zhp != NULL) 1828168404Spjd zpool_close(zhp); 1829219089Spjd if (policy.zrp_request & 1830219089Spjd (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) { 1831219089Spjd zpool_rewind_exclaim(hdl, newname ? origname : thename, 1832219089Spjd ((policy.zrp_request & ZPOOL_TRY_REWIND) != 0), nv); 1833168404Spjd } 1834219089Spjd nvlist_free(nv); 1835219089Spjd return (0); 1836168404Spjd } 1837168404Spjd 1838168404Spjd return (ret); 1839168404Spjd} 1840168404Spjd 1841168404Spjd/* 1842219089Spjd * Scan the pool. 1843168404Spjd */ 1844168404Spjdint 1845324010Savgzpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) 1846168404Spjd{ 1847168404Spjd zfs_cmd_t zc = { 0 }; 1848168404Spjd char msg[1024]; 1849324010Savg int err; 1850168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 1851168404Spjd 1852168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1853219089Spjd zc.zc_cookie = func; 1854324010Savg zc.zc_flags = cmd; 1855168404Spjd 1856324010Savg if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0) 1857168404Spjd return (0); 1858168404Spjd 1859324010Savg err = errno; 1860324010Savg 1861324010Savg /* ECANCELED on a scrub means we resumed a paused scrub */ 1862324010Savg if (err == ECANCELED && func == POOL_SCAN_SCRUB && 1863324010Savg cmd == POOL_SCRUB_NORMAL) 1864324010Savg return (0); 1865324010Savg 1866324010Savg if (err == ENOENT && func != POOL_SCAN_NONE && cmd == POOL_SCRUB_NORMAL) 1867324010Savg return (0); 1868324010Savg 1869219089Spjd if (func == POOL_SCAN_SCRUB) { 1870324010Savg if (cmd == POOL_SCRUB_PAUSE) { 1871324010Savg (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 1872324010Savg "cannot pause scrubbing %s"), zc.zc_name); 1873324010Savg } else { 1874324010Savg assert(cmd == POOL_SCRUB_NORMAL); 1875324010Savg (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 1876324010Savg "cannot scrub %s"), zc.zc_name); 1877324010Savg } 1878219089Spjd } else if (func == POOL_SCAN_NONE) { 1879219089Spjd (void) snprintf(msg, sizeof (msg), 1880219089Spjd dgettext(TEXT_DOMAIN, "cannot cancel scrubbing %s"), 1881219089Spjd zc.zc_name); 1882219089Spjd } else { 1883219089Spjd assert(!"unexpected result"); 1884219089Spjd } 1885168404Spjd 1886324010Savg if (err == EBUSY) { 1887219089Spjd nvlist_t *nvroot; 1888219089Spjd pool_scan_stat_t *ps = NULL; 1889219089Spjd uint_t psc; 1890219089Spjd 1891219089Spjd verify(nvlist_lookup_nvlist(zhp->zpool_config, 1892219089Spjd ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 1893219089Spjd (void) nvlist_lookup_uint64_array(nvroot, 1894219089Spjd ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc); 1895324010Savg if (ps && ps->pss_func == POOL_SCAN_SCRUB) { 1896324010Savg if (cmd == POOL_SCRUB_PAUSE) 1897324010Savg return (zfs_error(hdl, EZFS_SCRUB_PAUSED, msg)); 1898324010Savg else 1899324010Savg return (zfs_error(hdl, EZFS_SCRUBBING, msg)); 1900324010Savg } else { 1901219089Spjd return (zfs_error(hdl, EZFS_RESILVERING, msg)); 1902324010Savg } 1903324010Savg } else if (err == ENOENT) { 1904219089Spjd return (zfs_error(hdl, EZFS_NO_SCRUB, msg)); 1905219089Spjd } else { 1906324010Savg return (zpool_standard_error(hdl, err, msg)); 1907219089Spjd } 1908168404Spjd} 1909168404Spjd 1910277239Ssmh#ifdef illumos 1911168404Spjd/* 1912219089Spjd * This provides a very minimal check whether a given string is likely a 1913219089Spjd * c#t#d# style string. Users of this are expected to do their own 1914219089Spjd * verification of the s# part. 1915219089Spjd */ 1916219089Spjd#define CTD_CHECK(str) (str && str[0] == 'c' && isdigit(str[1])) 1917219089Spjd 1918219089Spjd/* 1919219089Spjd * More elaborate version for ones which may start with "/dev/dsk/" 1920219089Spjd * and the like. 1921219089Spjd */ 1922219089Spjdstatic int 1923289562Smavctd_check_path(char *str) 1924289562Smav{ 1925219089Spjd /* 1926219089Spjd * If it starts with a slash, check the last component. 1927219089Spjd */ 1928219089Spjd if (str && str[0] == '/') { 1929219089Spjd char *tmp = strrchr(str, '/'); 1930219089Spjd 1931219089Spjd /* 1932219089Spjd * If it ends in "/old", check the second-to-last 1933219089Spjd * component of the string instead. 1934219089Spjd */ 1935219089Spjd if (tmp != str && strcmp(tmp, "/old") == 0) { 1936219089Spjd for (tmp--; *tmp != '/'; tmp--) 1937219089Spjd ; 1938219089Spjd } 1939219089Spjd str = tmp + 1; 1940219089Spjd } 1941219089Spjd return (CTD_CHECK(str)); 1942219089Spjd} 1943277239Ssmh#endif 1944219089Spjd 1945219089Spjd/* 1946219089Spjd * Find a vdev that matches the search criteria specified. We use the 1947219089Spjd * the nvpair name to determine how we should look for the device. 1948168404Spjd * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 1949168404Spjd * spare; but FALSE if its an INUSE spare. 1950168404Spjd */ 1951168404Spjdstatic nvlist_t * 1952219089Spjdvdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare, 1953219089Spjd boolean_t *l2cache, boolean_t *log) 1954168404Spjd{ 1955168404Spjd uint_t c, children; 1956168404Spjd nvlist_t **child; 1957168404Spjd nvlist_t *ret; 1958185029Spjd uint64_t is_log; 1959219089Spjd char *srchkey; 1960219089Spjd nvpair_t *pair = nvlist_next_nvpair(search, NULL); 1961168404Spjd 1962219089Spjd /* Nothing to look for */ 1963219089Spjd if (search == NULL || pair == NULL) 1964219089Spjd return (NULL); 1965168404Spjd 1966219089Spjd /* Obtain the key we will use to search */ 1967219089Spjd srchkey = nvpair_name(pair); 1968219089Spjd 1969219089Spjd switch (nvpair_type(pair)) { 1970219089Spjd case DATA_TYPE_UINT64: 1971219089Spjd if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) { 1972219089Spjd uint64_t srchval, theguid; 1973219089Spjd 1974219089Spjd verify(nvpair_value_uint64(pair, &srchval) == 0); 1975219089Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1976219089Spjd &theguid) == 0); 1977219089Spjd if (theguid == srchval) 1978219089Spjd return (nv); 1979219089Spjd } 1980219089Spjd break; 1981219089Spjd 1982219089Spjd case DATA_TYPE_STRING: { 1983219089Spjd char *srchval, *val; 1984219089Spjd 1985219089Spjd verify(nvpair_value_string(pair, &srchval) == 0); 1986219089Spjd if (nvlist_lookup_string(nv, srchkey, &val) != 0) 1987219089Spjd break; 1988219089Spjd 1989168404Spjd /* 1990219089Spjd * Search for the requested value. Special cases: 1991219089Spjd * 1992219089Spjd * - ZPOOL_CONFIG_PATH for whole disk entries. These end in 1993219089Spjd * "s0" or "s0/old". The "s0" part is hidden from the user, 1994219089Spjd * but included in the string, so this matches around it. 1995219089Spjd * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE). 1996219089Spjd * 1997219089Spjd * Otherwise, all other searches are simple string compares. 1998168404Spjd */ 1999277239Ssmh#ifdef illumos 2000219089Spjd if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0 && 2001219089Spjd ctd_check_path(val)) { 2002219089Spjd uint64_t wholedisk = 0; 2003219089Spjd 2004219089Spjd (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 2005219089Spjd &wholedisk); 2006219089Spjd if (wholedisk) { 2007219089Spjd int slen = strlen(srchval); 2008219089Spjd int vlen = strlen(val); 2009219089Spjd 2010219089Spjd if (slen != vlen - 2) 2011219089Spjd break; 2012219089Spjd 2013219089Spjd /* 2014219089Spjd * make_leaf_vdev() should only set 2015219089Spjd * wholedisk for ZPOOL_CONFIG_PATHs which 2016219089Spjd * will include "/dev/dsk/", giving plenty of 2017219089Spjd * room for the indices used next. 2018219089Spjd */ 2019219089Spjd ASSERT(vlen >= 6); 2020219089Spjd 2021219089Spjd /* 2022219089Spjd * strings identical except trailing "s0" 2023219089Spjd */ 2024219089Spjd if (strcmp(&val[vlen - 2], "s0") == 0 && 2025219089Spjd strncmp(srchval, val, slen) == 0) 2026219089Spjd return (nv); 2027219089Spjd 2028219089Spjd /* 2029219089Spjd * strings identical except trailing "s0/old" 2030219089Spjd */ 2031219089Spjd if (strcmp(&val[vlen - 6], "s0/old") == 0 && 2032219089Spjd strcmp(&srchval[slen - 4], "/old") == 0 && 2033219089Spjd strncmp(srchval, val, slen - 4) == 0) 2034219089Spjd return (nv); 2035219089Spjd 2036219089Spjd break; 2037219089Spjd } 2038219089Spjd } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) { 2039277239Ssmh#else 2040277239Ssmh if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) { 2041277239Ssmh#endif 2042219089Spjd char *type, *idx, *end, *p; 2043219089Spjd uint64_t id, vdev_id; 2044219089Spjd 2045168404Spjd /* 2046219089Spjd * Determine our vdev type, keeping in mind 2047219089Spjd * that the srchval is composed of a type and 2048219089Spjd * vdev id pair (i.e. mirror-4). 2049168404Spjd */ 2050219089Spjd if ((type = strdup(srchval)) == NULL) 2051219089Spjd return (NULL); 2052219089Spjd 2053219089Spjd if ((p = strrchr(type, '-')) == NULL) { 2054219089Spjd free(type); 2055219089Spjd break; 2056219089Spjd } 2057219089Spjd idx = p + 1; 2058219089Spjd *p = '\0'; 2059219089Spjd 2060219089Spjd /* 2061219089Spjd * If the types don't match then keep looking. 2062219089Spjd */ 2063219089Spjd if (strncmp(val, type, strlen(val)) != 0) { 2064219089Spjd free(type); 2065219089Spjd break; 2066219089Spjd } 2067219089Spjd 2068219089Spjd verify(strncmp(type, VDEV_TYPE_RAIDZ, 2069219089Spjd strlen(VDEV_TYPE_RAIDZ)) == 0 || 2070219089Spjd strncmp(type, VDEV_TYPE_MIRROR, 2071219089Spjd strlen(VDEV_TYPE_MIRROR)) == 0); 2072219089Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID, 2073219089Spjd &id) == 0); 2074219089Spjd 2075219089Spjd errno = 0; 2076219089Spjd vdev_id = strtoull(idx, &end, 10); 2077219089Spjd 2078219089Spjd free(type); 2079219089Spjd if (errno != 0) 2080219089Spjd return (NULL); 2081219089Spjd 2082219089Spjd /* 2083219089Spjd * Now verify that we have the correct vdev id. 2084219089Spjd */ 2085219089Spjd if (vdev_id == id) 2086168404Spjd return (nv); 2087219089Spjd } 2088219089Spjd 2089219089Spjd /* 2090219089Spjd * Common case 2091219089Spjd */ 2092219089Spjd if (strcmp(srchval, val) == 0) 2093168404Spjd return (nv); 2094219089Spjd break; 2095168404Spjd } 2096168404Spjd 2097219089Spjd default: 2098219089Spjd break; 2099219089Spjd } 2100219089Spjd 2101168404Spjd if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2102168404Spjd &child, &children) != 0) 2103168404Spjd return (NULL); 2104168404Spjd 2105185029Spjd for (c = 0; c < children; c++) { 2106219089Spjd if ((ret = vdev_to_nvlist_iter(child[c], search, 2107185029Spjd avail_spare, l2cache, NULL)) != NULL) { 2108185029Spjd /* 2109185029Spjd * The 'is_log' value is only set for the toplevel 2110185029Spjd * vdev, not the leaf vdevs. So we always lookup the 2111185029Spjd * log device from the root of the vdev tree (where 2112185029Spjd * 'log' is non-NULL). 2113185029Spjd */ 2114185029Spjd if (log != NULL && 2115185029Spjd nvlist_lookup_uint64(child[c], 2116185029Spjd ZPOOL_CONFIG_IS_LOG, &is_log) == 0 && 2117185029Spjd is_log) { 2118185029Spjd *log = B_TRUE; 2119185029Spjd } 2120168404Spjd return (ret); 2121185029Spjd } 2122185029Spjd } 2123168404Spjd 2124168404Spjd if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 2125168404Spjd &child, &children) == 0) { 2126168404Spjd for (c = 0; c < children; c++) { 2127219089Spjd if ((ret = vdev_to_nvlist_iter(child[c], search, 2128185029Spjd avail_spare, l2cache, NULL)) != NULL) { 2129168404Spjd *avail_spare = B_TRUE; 2130168404Spjd return (ret); 2131168404Spjd } 2132168404Spjd } 2133168404Spjd } 2134168404Spjd 2135185029Spjd if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 2136185029Spjd &child, &children) == 0) { 2137185029Spjd for (c = 0; c < children; c++) { 2138219089Spjd if ((ret = vdev_to_nvlist_iter(child[c], search, 2139185029Spjd avail_spare, l2cache, NULL)) != NULL) { 2140185029Spjd *l2cache = B_TRUE; 2141185029Spjd return (ret); 2142185029Spjd } 2143185029Spjd } 2144185029Spjd } 2145185029Spjd 2146168404Spjd return (NULL); 2147168404Spjd} 2148168404Spjd 2149219089Spjd/* 2150219089Spjd * Given a physical path (minus the "/devices" prefix), find the 2151219089Spjd * associated vdev. 2152219089Spjd */ 2153168404Spjdnvlist_t * 2154219089Spjdzpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath, 2155219089Spjd boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log) 2156219089Spjd{ 2157219089Spjd nvlist_t *search, *nvroot, *ret; 2158219089Spjd 2159219089Spjd verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0); 2160219089Spjd verify(nvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath) == 0); 2161219089Spjd 2162219089Spjd verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 2163219089Spjd &nvroot) == 0); 2164219089Spjd 2165219089Spjd *avail_spare = B_FALSE; 2166219089Spjd *l2cache = B_FALSE; 2167219089Spjd if (log != NULL) 2168219089Spjd *log = B_FALSE; 2169219089Spjd ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log); 2170219089Spjd nvlist_free(search); 2171219089Spjd 2172219089Spjd return (ret); 2173219089Spjd} 2174219089Spjd 2175219089Spjd/* 2176219089Spjd * Determine if we have an "interior" top-level vdev (i.e mirror/raidz). 2177219089Spjd */ 2178219089Spjdboolean_t 2179219089Spjdzpool_vdev_is_interior(const char *name) 2180219089Spjd{ 2181219089Spjd if (strncmp(name, VDEV_TYPE_RAIDZ, strlen(VDEV_TYPE_RAIDZ)) == 0 || 2182219089Spjd strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0) 2183219089Spjd return (B_TRUE); 2184219089Spjd return (B_FALSE); 2185219089Spjd} 2186219089Spjd 2187219089Spjdnvlist_t * 2188185029Spjdzpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare, 2189185029Spjd boolean_t *l2cache, boolean_t *log) 2190168404Spjd{ 2191168404Spjd char buf[MAXPATHLEN]; 2192168404Spjd char *end; 2193219089Spjd nvlist_t *nvroot, *search, *ret; 2194168404Spjd uint64_t guid; 2195168404Spjd 2196219089Spjd verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0); 2197219089Spjd 2198168404Spjd guid = strtoull(path, &end, 10); 2199168404Spjd if (guid != 0 && *end == '\0') { 2200219089Spjd verify(nvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid) == 0); 2201219089Spjd } else if (zpool_vdev_is_interior(path)) { 2202219089Spjd verify(nvlist_add_string(search, ZPOOL_CONFIG_TYPE, path) == 0); 2203168404Spjd } else if (path[0] != '/') { 2204168404Spjd (void) snprintf(buf, sizeof (buf), "%s%s", _PATH_DEV, path); 2205219089Spjd verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, buf) == 0); 2206168404Spjd } else { 2207219089Spjd verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, path) == 0); 2208168404Spjd } 2209168404Spjd 2210168404Spjd verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 2211168404Spjd &nvroot) == 0); 2212168404Spjd 2213168404Spjd *avail_spare = B_FALSE; 2214185029Spjd *l2cache = B_FALSE; 2215185029Spjd if (log != NULL) 2216185029Spjd *log = B_FALSE; 2217219089Spjd ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log); 2218219089Spjd nvlist_free(search); 2219219089Spjd 2220219089Spjd return (ret); 2221168404Spjd} 2222168404Spjd 2223185029Spjdstatic int 2224185029Spjdvdev_online(nvlist_t *nv) 2225185029Spjd{ 2226185029Spjd uint64_t ival; 2227185029Spjd 2228185029Spjd if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE, &ival) == 0 || 2229185029Spjd nvlist_lookup_uint64(nv, ZPOOL_CONFIG_FAULTED, &ival) == 0 || 2230185029Spjd nvlist_lookup_uint64(nv, ZPOOL_CONFIG_REMOVED, &ival) == 0) 2231185029Spjd return (0); 2232185029Spjd 2233185029Spjd return (1); 2234185029Spjd} 2235185029Spjd 2236168404Spjd/* 2237219089Spjd * Helper function for zpool_get_physpaths(). 2238168404Spjd */ 2239219089Spjdstatic int 2240219089Spjdvdev_get_one_physpath(nvlist_t *config, char *physpath, size_t physpath_size, 2241219089Spjd size_t *bytes_written) 2242185029Spjd{ 2243219089Spjd size_t bytes_left, pos, rsz; 2244219089Spjd char *tmppath; 2245219089Spjd const char *format; 2246185029Spjd 2247219089Spjd if (nvlist_lookup_string(config, ZPOOL_CONFIG_PHYS_PATH, 2248219089Spjd &tmppath) != 0) 2249219089Spjd return (EZFS_NODEVICE); 2250185029Spjd 2251219089Spjd pos = *bytes_written; 2252219089Spjd bytes_left = physpath_size - pos; 2253219089Spjd format = (pos == 0) ? "%s" : " %s"; 2254185029Spjd 2255219089Spjd rsz = snprintf(physpath + pos, bytes_left, format, tmppath); 2256219089Spjd *bytes_written += rsz; 2257185029Spjd 2258219089Spjd if (rsz >= bytes_left) { 2259219089Spjd /* if physpath was not copied properly, clear it */ 2260219089Spjd if (bytes_left != 0) { 2261219089Spjd physpath[pos] = 0; 2262219089Spjd } 2263219089Spjd return (EZFS_NOSPC); 2264219089Spjd } 2265219089Spjd return (0); 2266219089Spjd} 2267185029Spjd 2268219089Spjdstatic int 2269219089Spjdvdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size, 2270219089Spjd size_t *rsz, boolean_t is_spare) 2271219089Spjd{ 2272219089Spjd char *type; 2273219089Spjd int ret; 2274185029Spjd 2275219089Spjd if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0) 2276219089Spjd return (EZFS_INVALCONFIG); 2277185029Spjd 2278219089Spjd if (strcmp(type, VDEV_TYPE_DISK) == 0) { 2279219089Spjd /* 2280219089Spjd * An active spare device has ZPOOL_CONFIG_IS_SPARE set. 2281219089Spjd * For a spare vdev, we only want to boot from the active 2282219089Spjd * spare device. 2283219089Spjd */ 2284219089Spjd if (is_spare) { 2285219089Spjd uint64_t spare = 0; 2286219089Spjd (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_SPARE, 2287219089Spjd &spare); 2288219089Spjd if (!spare) 2289219089Spjd return (EZFS_INVALCONFIG); 2290219089Spjd } 2291185029Spjd 2292219089Spjd if (vdev_online(nv)) { 2293219089Spjd if ((ret = vdev_get_one_physpath(nv, physpath, 2294219089Spjd phypath_size, rsz)) != 0) 2295219089Spjd return (ret); 2296219089Spjd } 2297219089Spjd } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 || 2298325149Savg strcmp(type, VDEV_TYPE_RAIDZ) == 0 || 2299219089Spjd strcmp(type, VDEV_TYPE_REPLACING) == 0 || 2300219089Spjd (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) { 2301219089Spjd nvlist_t **child; 2302219089Spjd uint_t count; 2303219089Spjd int i, ret; 2304185029Spjd 2305219089Spjd if (nvlist_lookup_nvlist_array(nv, 2306219089Spjd ZPOOL_CONFIG_CHILDREN, &child, &count) != 0) 2307219089Spjd return (EZFS_INVALCONFIG); 2308219089Spjd 2309219089Spjd for (i = 0; i < count; i++) { 2310219089Spjd ret = vdev_get_physpaths(child[i], physpath, 2311219089Spjd phypath_size, rsz, is_spare); 2312219089Spjd if (ret == EZFS_NOSPC) 2313219089Spjd return (ret); 2314185029Spjd } 2315185029Spjd } 2316185029Spjd 2317219089Spjd return (EZFS_POOL_INVALARG); 2318185029Spjd} 2319185029Spjd 2320185029Spjd/* 2321219089Spjd * Get phys_path for a root pool config. 2322219089Spjd * Return 0 on success; non-zero on failure. 2323185029Spjd */ 2324219089Spjdstatic int 2325219089Spjdzpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size) 2326168404Spjd{ 2327219089Spjd size_t rsz; 2328219089Spjd nvlist_t *vdev_root; 2329219089Spjd nvlist_t **child; 2330185029Spjd uint_t count; 2331219089Spjd char *type; 2332168404Spjd 2333219089Spjd rsz = 0; 2334219089Spjd 2335219089Spjd if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2336219089Spjd &vdev_root) != 0) 2337219089Spjd return (EZFS_INVALCONFIG); 2338219089Spjd 2339219089Spjd if (nvlist_lookup_string(vdev_root, ZPOOL_CONFIG_TYPE, &type) != 0 || 2340219089Spjd nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN, 2341219089Spjd &child, &count) != 0) 2342219089Spjd return (EZFS_INVALCONFIG); 2343219089Spjd 2344219089Spjd /* 2345289527Smav * root pool can only have a single top-level vdev. 2346219089Spjd */ 2347289527Smav if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1) 2348219089Spjd return (EZFS_POOL_INVALARG); 2349219089Spjd 2350219089Spjd (void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz, 2351219089Spjd B_FALSE); 2352219089Spjd 2353219089Spjd /* No online devices */ 2354219089Spjd if (rsz == 0) 2355219089Spjd return (EZFS_NODEVICE); 2356219089Spjd 2357219089Spjd return (0); 2358219089Spjd} 2359219089Spjd 2360219089Spjd/* 2361219089Spjd * Get phys_path for a root pool 2362219089Spjd * Return 0 on success; non-zero on failure. 2363219089Spjd */ 2364219089Spjdint 2365219089Spjdzpool_get_physpath(zpool_handle_t *zhp, char *physpath, size_t phypath_size) 2366219089Spjd{ 2367219089Spjd return (zpool_get_config_physpath(zhp->zpool_config, physpath, 2368219089Spjd phypath_size)); 2369219089Spjd} 2370219089Spjd 2371219089Spjd/* 2372219089Spjd * If the device has being dynamically expanded then we need to relabel 2373219089Spjd * the disk to use the new unallocated space. 2374219089Spjd */ 2375219089Spjdstatic int 2376219089Spjdzpool_relabel_disk(libzfs_handle_t *hdl, const char *name) 2377219089Spjd{ 2378277300Ssmh#ifdef illumos 2379219089Spjd char path[MAXPATHLEN]; 2380219089Spjd char errbuf[1024]; 2381219089Spjd int fd, error; 2382219089Spjd int (*_efi_use_whole_disk)(int); 2383219089Spjd 2384219089Spjd if ((_efi_use_whole_disk = (int (*)(int))dlsym(RTLD_DEFAULT, 2385219089Spjd "efi_use_whole_disk")) == NULL) 2386219089Spjd return (-1); 2387219089Spjd 2388297763Smav (void) snprintf(path, sizeof (path), "%s/%s", ZFS_RDISK_ROOT, name); 2389219089Spjd 2390219089Spjd if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) { 2391219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 2392219089Spjd "relabel '%s': unable to open device"), name); 2393219089Spjd return (zfs_error(hdl, EZFS_OPENFAILED, errbuf)); 2394168404Spjd } 2395168404Spjd 2396219089Spjd /* 2397219089Spjd * It's possible that we might encounter an error if the device 2398219089Spjd * does not have any unallocated space left. If so, we simply 2399219089Spjd * ignore that error and continue on. 2400219089Spjd */ 2401219089Spjd error = _efi_use_whole_disk(fd); 2402219089Spjd (void) close(fd); 2403219089Spjd if (error && error != VT_ENOSPC) { 2404219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 2405219089Spjd "relabel '%s': unable to read disk capacity"), name); 2406219089Spjd return (zfs_error(hdl, EZFS_NOCAP, errbuf)); 2407219089Spjd } 2408277300Ssmh#endif /* illumos */ 2409219089Spjd return (0); 2410168404Spjd} 2411168404Spjd 2412168404Spjd/* 2413185029Spjd * Bring the specified vdev online. The 'flags' parameter is a set of the 2414185029Spjd * ZFS_ONLINE_* flags. 2415168404Spjd */ 2416168404Spjdint 2417185029Spjdzpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags, 2418185029Spjd vdev_state_t *newstate) 2419168404Spjd{ 2420168404Spjd zfs_cmd_t zc = { 0 }; 2421168404Spjd char msg[1024]; 2422168404Spjd nvlist_t *tgt; 2423219089Spjd boolean_t avail_spare, l2cache, islog; 2424168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2425168404Spjd 2426219089Spjd if (flags & ZFS_ONLINE_EXPAND) { 2427219089Spjd (void) snprintf(msg, sizeof (msg), 2428219089Spjd dgettext(TEXT_DOMAIN, "cannot expand %s"), path); 2429219089Spjd } else { 2430219089Spjd (void) snprintf(msg, sizeof (msg), 2431219089Spjd dgettext(TEXT_DOMAIN, "cannot online %s"), path); 2432219089Spjd } 2433168404Spjd 2434168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2435185029Spjd if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, 2436219089Spjd &islog)) == NULL) 2437168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 2438168404Spjd 2439168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 2440168404Spjd 2441219089Spjd if (avail_spare) 2442168404Spjd return (zfs_error(hdl, EZFS_ISSPARE, msg)); 2443168404Spjd 2444219089Spjd if (flags & ZFS_ONLINE_EXPAND || 2445219089Spjd zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) { 2446219089Spjd char *pathname = NULL; 2447219089Spjd uint64_t wholedisk = 0; 2448219089Spjd 2449219089Spjd (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK, 2450219089Spjd &wholedisk); 2451219089Spjd verify(nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, 2452219089Spjd &pathname) == 0); 2453219089Spjd 2454219089Spjd /* 2455219089Spjd * XXX - L2ARC 1.0 devices can't support expansion. 2456219089Spjd */ 2457219089Spjd if (l2cache) { 2458219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2459219089Spjd "cannot expand cache devices")); 2460219089Spjd return (zfs_error(hdl, EZFS_VDEVNOTSUP, msg)); 2461219089Spjd } 2462219089Spjd 2463219089Spjd if (wholedisk) { 2464297763Smav pathname += strlen(ZFS_DISK_ROOT) + 1; 2465219089Spjd (void) zpool_relabel_disk(hdl, pathname); 2466219089Spjd } 2467219089Spjd } 2468219089Spjd 2469185029Spjd zc.zc_cookie = VDEV_STATE_ONLINE; 2470185029Spjd zc.zc_obj = flags; 2471168404Spjd 2472219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) { 2473219089Spjd if (errno == EINVAL) { 2474219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "was split " 2475219089Spjd "from this pool into a new one. Use '%s' " 2476219089Spjd "instead"), "zpool detach"); 2477219089Spjd return (zfs_error(hdl, EZFS_POSTSPLIT_ONLINE, msg)); 2478219089Spjd } 2479185029Spjd return (zpool_standard_error(hdl, errno, msg)); 2480219089Spjd } 2481185029Spjd 2482185029Spjd *newstate = zc.zc_cookie; 2483185029Spjd return (0); 2484168404Spjd} 2485168404Spjd 2486168404Spjd/* 2487168404Spjd * Take the specified vdev offline 2488168404Spjd */ 2489168404Spjdint 2490185029Spjdzpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp) 2491168404Spjd{ 2492168404Spjd zfs_cmd_t zc = { 0 }; 2493168404Spjd char msg[1024]; 2494168404Spjd nvlist_t *tgt; 2495185029Spjd boolean_t avail_spare, l2cache; 2496168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2497168404Spjd 2498168404Spjd (void) snprintf(msg, sizeof (msg), 2499168404Spjd dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 2500168404Spjd 2501168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2502185029Spjd if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, 2503185029Spjd NULL)) == NULL) 2504168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 2505168404Spjd 2506168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 2507168404Spjd 2508219089Spjd if (avail_spare) 2509168404Spjd return (zfs_error(hdl, EZFS_ISSPARE, msg)); 2510168404Spjd 2511185029Spjd zc.zc_cookie = VDEV_STATE_OFFLINE; 2512185029Spjd zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0; 2513168404Spjd 2514219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 2515168404Spjd return (0); 2516168404Spjd 2517168404Spjd switch (errno) { 2518168404Spjd case EBUSY: 2519168404Spjd 2520168404Spjd /* 2521168404Spjd * There are no other replicas of this device. 2522168404Spjd */ 2523168404Spjd return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 2524168404Spjd 2525219089Spjd case EEXIST: 2526219089Spjd /* 2527219089Spjd * The log device has unplayed logs 2528219089Spjd */ 2529219089Spjd return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, msg)); 2530219089Spjd 2531168404Spjd default: 2532168404Spjd return (zpool_standard_error(hdl, errno, msg)); 2533168404Spjd } 2534168404Spjd} 2535168404Spjd 2536168404Spjd/* 2537185029Spjd * Mark the given vdev faulted. 2538185029Spjd */ 2539185029Spjdint 2540219089Spjdzpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux) 2541185029Spjd{ 2542185029Spjd zfs_cmd_t zc = { 0 }; 2543185029Spjd char msg[1024]; 2544185029Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2545185029Spjd 2546185029Spjd (void) snprintf(msg, sizeof (msg), 2547185029Spjd dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid); 2548185029Spjd 2549185029Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2550185029Spjd zc.zc_guid = guid; 2551185029Spjd zc.zc_cookie = VDEV_STATE_FAULTED; 2552219089Spjd zc.zc_obj = aux; 2553185029Spjd 2554219089Spjd if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 2555185029Spjd return (0); 2556185029Spjd 2557185029Spjd switch (errno) { 2558185029Spjd case EBUSY: 2559185029Spjd 2560185029Spjd /* 2561185029Spjd * There are no other replicas of this device. 2562185029Spjd */ 2563185029Spjd return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 2564185029Spjd 2565185029Spjd default: 2566185029Spjd return (zpool_standard_error(hdl, errno, msg)); 2567185029Spjd } 2568185029Spjd 2569185029Spjd} 2570185029Spjd 2571185029Spjd/* 2572185029Spjd * Mark the given vdev degraded. 2573185029Spjd */ 2574185029Spjdint 2575219089Spjdzpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux) 2576185029Spjd{ 2577185029Spjd zfs_cmd_t zc = { 0 }; 2578185029Spjd char msg[1024]; 2579185029Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2580185029Spjd 2581185029Spjd (void) snprintf(msg, sizeof (msg), 2582185029Spjd dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid); 2583185029Spjd 2584185029Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2585185029Spjd zc.zc_guid = guid; 2586185029Spjd zc.zc_cookie = VDEV_STATE_DEGRADED; 2587219089Spjd zc.zc_obj = aux; 2588185029Spjd 2589219089Spjd if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 2590185029Spjd return (0); 2591185029Spjd 2592185029Spjd return (zpool_standard_error(hdl, errno, msg)); 2593185029Spjd} 2594185029Spjd 2595185029Spjd/* 2596168404Spjd * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 2597168404Spjd * a hot spare. 2598168404Spjd */ 2599168404Spjdstatic boolean_t 2600168404Spjdis_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 2601168404Spjd{ 2602168404Spjd nvlist_t **child; 2603168404Spjd uint_t c, children; 2604168404Spjd char *type; 2605168404Spjd 2606168404Spjd if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 2607168404Spjd &children) == 0) { 2608168404Spjd verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 2609168404Spjd &type) == 0); 2610168404Spjd 2611168404Spjd if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 2612168404Spjd children == 2 && child[which] == tgt) 2613168404Spjd return (B_TRUE); 2614168404Spjd 2615168404Spjd for (c = 0; c < children; c++) 2616168404Spjd if (is_replacing_spare(child[c], tgt, which)) 2617168404Spjd return (B_TRUE); 2618168404Spjd } 2619168404Spjd 2620168404Spjd return (B_FALSE); 2621168404Spjd} 2622168404Spjd 2623168404Spjd/* 2624168404Spjd * Attach new_disk (fully described by nvroot) to old_disk. 2625185029Spjd * If 'replacing' is specified, the new disk will replace the old one. 2626168404Spjd */ 2627168404Spjdint 2628168404Spjdzpool_vdev_attach(zpool_handle_t *zhp, 2629168404Spjd const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 2630168404Spjd{ 2631168404Spjd zfs_cmd_t zc = { 0 }; 2632168404Spjd char msg[1024]; 2633168404Spjd int ret; 2634168404Spjd nvlist_t *tgt; 2635185029Spjd boolean_t avail_spare, l2cache, islog; 2636168404Spjd uint64_t val; 2637219089Spjd char *newname; 2638168404Spjd nvlist_t **child; 2639168404Spjd uint_t children; 2640168404Spjd nvlist_t *config_root; 2641168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2642236155Smm boolean_t rootpool = zpool_is_bootable(zhp); 2643168404Spjd 2644168404Spjd if (replacing) 2645168404Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 2646168404Spjd "cannot replace %s with %s"), old_disk, new_disk); 2647168404Spjd else 2648168404Spjd (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 2649168404Spjd "cannot attach %s to %s"), new_disk, old_disk); 2650168404Spjd 2651168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2652185029Spjd if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache, 2653185029Spjd &islog)) == 0) 2654168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 2655168404Spjd 2656168404Spjd if (avail_spare) 2657168404Spjd return (zfs_error(hdl, EZFS_ISSPARE, msg)); 2658168404Spjd 2659185029Spjd if (l2cache) 2660185029Spjd return (zfs_error(hdl, EZFS_ISL2CACHE, msg)); 2661185029Spjd 2662168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 2663168404Spjd zc.zc_cookie = replacing; 2664168404Spjd 2665168404Spjd if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 2666168404Spjd &child, &children) != 0 || children != 1) { 2667168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2668168404Spjd "new device must be a single disk")); 2669168404Spjd return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 2670168404Spjd } 2671168404Spjd 2672168404Spjd verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 2673168404Spjd ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 2674168404Spjd 2675219089Spjd if ((newname = zpool_vdev_name(NULL, NULL, child[0], B_FALSE)) == NULL) 2676185029Spjd return (-1); 2677185029Spjd 2678168404Spjd /* 2679168404Spjd * If the target is a hot spare that has been swapped in, we can only 2680168404Spjd * replace it with another hot spare. 2681168404Spjd */ 2682168404Spjd if (replacing && 2683168404Spjd nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 2684185029Spjd (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache, 2685185029Spjd NULL) == NULL || !avail_spare) && 2686185029Spjd is_replacing_spare(config_root, tgt, 1)) { 2687168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2688168404Spjd "can only be replaced by another hot spare")); 2689185029Spjd free(newname); 2690168404Spjd return (zfs_error(hdl, EZFS_BADTARGET, msg)); 2691168404Spjd } 2692168404Spjd 2693185029Spjd free(newname); 2694185029Spjd 2695185029Spjd if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 2696168404Spjd return (-1); 2697168404Spjd 2698219089Spjd ret = zfs_ioctl(hdl, ZFS_IOC_VDEV_ATTACH, &zc); 2699168404Spjd 2700168404Spjd zcmd_free_nvlists(&zc); 2701168404Spjd 2702209962Smm if (ret == 0) { 2703209962Smm if (rootpool) { 2704219089Spjd /* 2705219089Spjd * XXX need a better way to prevent user from 2706219089Spjd * booting up a half-baked vdev. 2707219089Spjd */ 2708219089Spjd (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Make " 2709219089Spjd "sure to wait until resilver is done " 2710219089Spjd "before rebooting.\n")); 2711219089Spjd (void) fprintf(stderr, "\n"); 2712216293Smm (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "If " 2713216293Smm "you boot from pool '%s', you may need to update\n" 2714216293Smm "boot code on newly attached disk '%s'.\n\n" 2715216293Smm "Assuming you use GPT partitioning and 'da0' is " 2716216293Smm "your new boot disk\n" 2717216293Smm "you may use the following command:\n\n" 2718216293Smm "\tgpart bootcode -b /boot/pmbr -p " 2719216293Smm "/boot/gptzfsboot -i 1 da0\n\n"), 2720216293Smm zhp->zpool_name, new_disk); 2721209962Smm } 2722168404Spjd return (0); 2723209962Smm } 2724168404Spjd 2725168404Spjd switch (errno) { 2726168404Spjd case ENOTSUP: 2727168404Spjd /* 2728168404Spjd * Can't attach to or replace this type of vdev. 2729168404Spjd */ 2730185029Spjd if (replacing) { 2731219089Spjd uint64_t version = zpool_get_prop_int(zhp, 2732219089Spjd ZPOOL_PROP_VERSION, NULL); 2733219089Spjd 2734185029Spjd if (islog) 2735185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2736185029Spjd "cannot replace a log with a spare")); 2737219089Spjd else if (version >= SPA_VERSION_MULTI_REPLACE) 2738219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2739219089Spjd "already in replacing/spare config; wait " 2740219089Spjd "for completion or use 'zpool detach'")); 2741185029Spjd else 2742185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2743185029Spjd "cannot replace a replacing device")); 2744185029Spjd } else { 2745168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2746168404Spjd "can only attach to mirrors and top-level " 2747168404Spjd "disks")); 2748185029Spjd } 2749168404Spjd (void) zfs_error(hdl, EZFS_BADTARGET, msg); 2750168404Spjd break; 2751168404Spjd 2752168404Spjd case EINVAL: 2753168404Spjd /* 2754168404Spjd * The new device must be a single disk. 2755168404Spjd */ 2756168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2757168404Spjd "new device must be a single disk")); 2758168404Spjd (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 2759168404Spjd break; 2760168404Spjd 2761168404Spjd case EBUSY: 2762168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 2763168404Spjd new_disk); 2764168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 2765168404Spjd break; 2766168404Spjd 2767168404Spjd case EOVERFLOW: 2768168404Spjd /* 2769168404Spjd * The new device is too small. 2770168404Spjd */ 2771168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2772168404Spjd "device is too small")); 2773168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 2774168404Spjd break; 2775168404Spjd 2776168404Spjd case EDOM: 2777168404Spjd /* 2778168404Spjd * The new device has a different alignment requirement. 2779168404Spjd */ 2780168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2781168404Spjd "devices have different sector alignment")); 2782168404Spjd (void) zfs_error(hdl, EZFS_BADDEV, msg); 2783168404Spjd break; 2784168404Spjd 2785168404Spjd case ENAMETOOLONG: 2786168404Spjd /* 2787168404Spjd * The resulting top-level vdev spec won't fit in the label. 2788168404Spjd */ 2789168404Spjd (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 2790168404Spjd break; 2791168404Spjd 2792168404Spjd default: 2793168404Spjd (void) zpool_standard_error(hdl, errno, msg); 2794168404Spjd } 2795168404Spjd 2796168404Spjd return (-1); 2797168404Spjd} 2798168404Spjd 2799168404Spjd/* 2800168404Spjd * Detach the specified device. 2801168404Spjd */ 2802168404Spjdint 2803168404Spjdzpool_vdev_detach(zpool_handle_t *zhp, const char *path) 2804168404Spjd{ 2805168404Spjd zfs_cmd_t zc = { 0 }; 2806168404Spjd char msg[1024]; 2807168404Spjd nvlist_t *tgt; 2808185029Spjd boolean_t avail_spare, l2cache; 2809168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2810168404Spjd 2811168404Spjd (void) snprintf(msg, sizeof (msg), 2812168404Spjd dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 2813168404Spjd 2814168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 2815185029Spjd if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache, 2816185029Spjd NULL)) == 0) 2817168404Spjd return (zfs_error(hdl, EZFS_NODEVICE, msg)); 2818168404Spjd 2819168404Spjd if (avail_spare) 2820168404Spjd return (zfs_error(hdl, EZFS_ISSPARE, msg)); 2821168404Spjd 2822185029Spjd if (l2cache) 2823185029Spjd return (zfs_error(hdl, EZFS_ISL2CACHE, msg)); 2824185029Spjd 2825168404Spjd verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 2826168404Spjd 2827185029Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0) 2828168404Spjd return (0); 2829168404Spjd 2830168404Spjd switch (errno) { 2831168404Spjd 2832168404Spjd case ENOTSUP: 2833168404Spjd /* 2834168404Spjd * Can't detach from this type of vdev. 2835168404Spjd */ 2836168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 2837168404Spjd "applicable to mirror and replacing vdevs")); 2838219089Spjd (void) zfs_error(hdl, EZFS_BADTARGET, msg); 2839168404Spjd break; 2840168404Spjd 2841168404Spjd case EBUSY: 2842168404Spjd /* 2843168404Spjd * There are no other replicas of this device. 2844168404Spjd */ 2845168404Spjd (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 2846168404Spjd break; 2847168404Spjd 2848168404Spjd default: 2849168404Spjd (void) zpool_standard_error(hdl, errno, msg); 2850168404Spjd } 2851168404Spjd 2852168404Spjd return (-1); 2853168404Spjd} 2854168404Spjd 2855168404Spjd/* 2856219089Spjd * Find a mirror vdev in the source nvlist. 2857219089Spjd * 2858219089Spjd * The mchild array contains a list of disks in one of the top-level mirrors 2859219089Spjd * of the source pool. The schild array contains a list of disks that the 2860219089Spjd * user specified on the command line. We loop over the mchild array to 2861219089Spjd * see if any entry in the schild array matches. 2862219089Spjd * 2863219089Spjd * If a disk in the mchild array is found in the schild array, we return 2864219089Spjd * the index of that entry. Otherwise we return -1. 2865219089Spjd */ 2866219089Spjdstatic int 2867219089Spjdfind_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren, 2868219089Spjd nvlist_t **schild, uint_t schildren) 2869219089Spjd{ 2870219089Spjd uint_t mc; 2871219089Spjd 2872219089Spjd for (mc = 0; mc < mchildren; mc++) { 2873219089Spjd uint_t sc; 2874219089Spjd char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp, 2875219089Spjd mchild[mc], B_FALSE); 2876219089Spjd 2877219089Spjd for (sc = 0; sc < schildren; sc++) { 2878219089Spjd char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp, 2879219089Spjd schild[sc], B_FALSE); 2880219089Spjd boolean_t result = (strcmp(mpath, spath) == 0); 2881219089Spjd 2882219089Spjd free(spath); 2883219089Spjd if (result) { 2884219089Spjd free(mpath); 2885219089Spjd return (mc); 2886219089Spjd } 2887219089Spjd } 2888219089Spjd 2889219089Spjd free(mpath); 2890219089Spjd } 2891219089Spjd 2892219089Spjd return (-1); 2893219089Spjd} 2894219089Spjd 2895219089Spjd/* 2896219089Spjd * Split a mirror pool. If newroot points to null, then a new nvlist 2897219089Spjd * is generated and it is the responsibility of the caller to free it. 2898219089Spjd */ 2899219089Spjdint 2900219089Spjdzpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot, 2901219089Spjd nvlist_t *props, splitflags_t flags) 2902219089Spjd{ 2903219089Spjd zfs_cmd_t zc = { 0 }; 2904219089Spjd char msg[1024]; 2905219089Spjd nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL; 2906219089Spjd nvlist_t **varray = NULL, *zc_props = NULL; 2907219089Spjd uint_t c, children, newchildren, lastlog = 0, vcount, found = 0; 2908219089Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 2909219089Spjd uint64_t vers; 2910219089Spjd boolean_t freelist = B_FALSE, memory_err = B_TRUE; 2911219089Spjd int retval = 0; 2912219089Spjd 2913219089Spjd (void) snprintf(msg, sizeof (msg), 2914219089Spjd dgettext(TEXT_DOMAIN, "Unable to split %s"), zhp->zpool_name); 2915219089Spjd 2916219089Spjd if (!zpool_name_valid(hdl, B_FALSE, newname)) 2917219089Spjd return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 2918219089Spjd 2919219089Spjd if ((config = zpool_get_config(zhp, NULL)) == NULL) { 2920219089Spjd (void) fprintf(stderr, gettext("Internal error: unable to " 2921219089Spjd "retrieve pool configuration\n")); 2922219089Spjd return (-1); 2923219089Spjd } 2924219089Spjd 2925219089Spjd verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &tree) 2926219089Spjd == 0); 2927219089Spjd verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &vers) == 0); 2928219089Spjd 2929219089Spjd if (props) { 2930219089Spjd prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE }; 2931219089Spjd if ((zc_props = zpool_valid_proplist(hdl, zhp->zpool_name, 2932219089Spjd props, vers, flags, msg)) == NULL) 2933219089Spjd return (-1); 2934219089Spjd } 2935219089Spjd 2936219089Spjd if (nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child, 2937219089Spjd &children) != 0) { 2938219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2939219089Spjd "Source pool is missing vdev tree")); 2940296528Smav nvlist_free(zc_props); 2941219089Spjd return (-1); 2942219089Spjd } 2943219089Spjd 2944219089Spjd varray = zfs_alloc(hdl, children * sizeof (nvlist_t *)); 2945219089Spjd vcount = 0; 2946219089Spjd 2947219089Spjd if (*newroot == NULL || 2948219089Spjd nvlist_lookup_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN, 2949219089Spjd &newchild, &newchildren) != 0) 2950219089Spjd newchildren = 0; 2951219089Spjd 2952219089Spjd for (c = 0; c < children; c++) { 2953219089Spjd uint64_t is_log = B_FALSE, is_hole = B_FALSE; 2954219089Spjd char *type; 2955219089Spjd nvlist_t **mchild, *vdev; 2956219089Spjd uint_t mchildren; 2957219089Spjd int entry; 2958219089Spjd 2959219089Spjd /* 2960219089Spjd * Unlike cache & spares, slogs are stored in the 2961219089Spjd * ZPOOL_CONFIG_CHILDREN array. We filter them out here. 2962219089Spjd */ 2963219089Spjd (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 2964219089Spjd &is_log); 2965219089Spjd (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 2966219089Spjd &is_hole); 2967219089Spjd if (is_log || is_hole) { 2968219089Spjd /* 2969219089Spjd * Create a hole vdev and put it in the config. 2970219089Spjd */ 2971219089Spjd if (nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) != 0) 2972219089Spjd goto out; 2973219089Spjd if (nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, 2974219089Spjd VDEV_TYPE_HOLE) != 0) 2975219089Spjd goto out; 2976219089Spjd if (nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_HOLE, 2977219089Spjd 1) != 0) 2978219089Spjd goto out; 2979219089Spjd if (lastlog == 0) 2980219089Spjd lastlog = vcount; 2981219089Spjd varray[vcount++] = vdev; 2982219089Spjd continue; 2983219089Spjd } 2984219089Spjd lastlog = 0; 2985219089Spjd verify(nvlist_lookup_string(child[c], ZPOOL_CONFIG_TYPE, &type) 2986219089Spjd == 0); 2987219089Spjd if (strcmp(type, VDEV_TYPE_MIRROR) != 0) { 2988219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2989219089Spjd "Source pool must be composed only of mirrors\n")); 2990219089Spjd retval = zfs_error(hdl, EZFS_INVALCONFIG, msg); 2991219089Spjd goto out; 2992219089Spjd } 2993219089Spjd 2994219089Spjd verify(nvlist_lookup_nvlist_array(child[c], 2995219089Spjd ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0); 2996219089Spjd 2997219089Spjd /* find or add an entry for this top-level vdev */ 2998219089Spjd if (newchildren > 0 && 2999219089Spjd (entry = find_vdev_entry(zhp, mchild, mchildren, 3000219089Spjd newchild, newchildren)) >= 0) { 3001219089Spjd /* We found a disk that the user specified. */ 3002219089Spjd vdev = mchild[entry]; 3003219089Spjd ++found; 3004219089Spjd } else { 3005219089Spjd /* User didn't specify a disk for this vdev. */ 3006219089Spjd vdev = mchild[mchildren - 1]; 3007219089Spjd } 3008219089Spjd 3009219089Spjd if (nvlist_dup(vdev, &varray[vcount++], 0) != 0) 3010219089Spjd goto out; 3011219089Spjd } 3012219089Spjd 3013219089Spjd /* did we find every disk the user specified? */ 3014219089Spjd if (found != newchildren) { 3015219089Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Device list must " 3016219089Spjd "include at most one disk from each mirror")); 3017219089Spjd retval = zfs_error(hdl, EZFS_INVALCONFIG, msg); 3018219089Spjd goto out; 3019219089Spjd } 3020219089Spjd 3021219089Spjd /* Prepare the nvlist for populating. */ 3022219089Spjd if (*newroot == NULL) { 3023219089Spjd if (nvlist_alloc(newroot, NV_UNIQUE_NAME, 0) != 0) 3024219089Spjd goto out; 3025219089Spjd freelist = B_TRUE; 3026219089Spjd if (nvlist_add_string(*newroot, ZPOOL_CONFIG_TYPE, 3027219089Spjd VDEV_TYPE_ROOT) != 0) 3028219089Spjd goto out; 3029219089Spjd } else { 3030219089Spjd verify(nvlist_remove_all(*newroot, ZPOOL_CONFIG_CHILDREN) == 0); 3031219089Spjd } 3032219089Spjd 3033219089Spjd /* Add all the children we found */ 3034219089Spjd if (nvlist_add_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN, varray, 3035219089Spjd lastlog == 0 ? vcount : lastlog) != 0) 3036219089Spjd goto out; 3037219089Spjd 3038219089Spjd /* 3039219089Spjd * If we're just doing a dry run, exit now with success. 3040219089Spjd */ 3041219089Spjd if (flags.dryrun) { 3042219089Spjd memory_err = B_FALSE; 3043219089Spjd freelist = B_FALSE; 3044219089Spjd goto out; 3045219089Spjd } 3046219089Spjd 3047219089Spjd /* now build up the config list & call the ioctl */ 3048219089Spjd if (nvlist_alloc(&newconfig, NV_UNIQUE_NAME, 0) != 0) 3049219089Spjd goto out; 3050219089Spjd 3051219089Spjd if (nvlist_add_nvlist(newconfig, 3052219089Spjd ZPOOL_CONFIG_VDEV_TREE, *newroot) != 0 || 3053219089Spjd nvlist_add_string(newconfig, 3054219089Spjd ZPOOL_CONFIG_POOL_NAME, newname) != 0 || 3055219089Spjd nvlist_add_uint64(newconfig, ZPOOL_CONFIG_VERSION, vers) != 0) 3056219089Spjd goto out; 3057219089Spjd 3058219089Spjd /* 3059219089Spjd * The new pool is automatically part of the namespace unless we 3060219089Spjd * explicitly export it. 3061219089Spjd */ 3062219089Spjd if (!flags.import) 3063219089Spjd zc.zc_cookie = ZPOOL_EXPORT_AFTER_SPLIT; 3064219089Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3065219089Spjd (void) strlcpy(zc.zc_string, newname, sizeof (zc.zc_string)); 3066219089Spjd if (zcmd_write_conf_nvlist(hdl, &zc, newconfig) != 0) 3067219089Spjd goto out; 3068219089Spjd if (zc_props != NULL && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0) 3069219089Spjd goto out; 3070219089Spjd 3071219089Spjd if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SPLIT, &zc) != 0) { 3072219089Spjd retval = zpool_standard_error(hdl, errno, msg); 3073219089Spjd goto out; 3074219089Spjd } 3075219089Spjd 3076219089Spjd freelist = B_FALSE; 3077219089Spjd memory_err = B_FALSE; 3078219089Spjd 3079219089Spjdout: 3080219089Spjd if (varray != NULL) { 3081219089Spjd int v; 3082219089Spjd 3083219089Spjd for (v = 0; v < vcount; v++) 3084219089Spjd nvlist_free(varray[v]); 3085219089Spjd free(varray); 3086219089Spjd } 3087219089Spjd zcmd_free_nvlists(&zc); 3088296528Smav nvlist_free(zc_props); 3089296528Smav 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/* 3251228103Smm * Change the GUID for a pool. 3252228103Smm */ 3253228103Smmint 3254228103Smmzpool_reguid(zpool_handle_t *zhp) 3255228103Smm{ 3256228103Smm char msg[1024]; 3257228103Smm libzfs_handle_t *hdl = zhp->zpool_hdl; 3258228103Smm zfs_cmd_t zc = { 0 }; 3259228103Smm 3260228103Smm (void) snprintf(msg, sizeof (msg), 3261228103Smm dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name); 3262228103Smm 3263228103Smm (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3264228103Smm if (zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc) == 0) 3265228103Smm return (0); 3266228103Smm 3267228103Smm return (zpool_standard_error(hdl, errno, msg)); 3268228103Smm} 3269228103Smm 3270228103Smm/* 3271236155Smm * Reopen the pool. 3272236155Smm */ 3273236155Smmint 3274236155Smmzpool_reopen(zpool_handle_t *zhp) 3275236155Smm{ 3276236155Smm zfs_cmd_t zc = { 0 }; 3277236155Smm char msg[1024]; 3278236155Smm libzfs_handle_t *hdl = zhp->zpool_hdl; 3279236155Smm 3280236155Smm (void) snprintf(msg, sizeof (msg), 3281236155Smm dgettext(TEXT_DOMAIN, "cannot reopen '%s'"), 3282236155Smm zhp->zpool_name); 3283236155Smm 3284236155Smm (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3285236155Smm if (zfs_ioctl(hdl, ZFS_IOC_POOL_REOPEN, &zc) == 0) 3286236155Smm return (0); 3287236155Smm return (zpool_standard_error(hdl, errno, msg)); 3288236155Smm} 3289236155Smm 3290236155Smm/* 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 3313277433Sdelphij /* 3314277433Sdelphij * In a case the strdup() fails, we will just return NULL below. 3315277433Sdelphij */ 3316277433Sdelphij path = strdup(list[0].devname); 3317168404Spjd 3318168404Spjd devid_free_nmlist(list); 3319168404Spjd 3320168404Spjd return (path); 3321168404Spjd} 3322168404Spjd 3323168404Spjd/* 3324168404Spjd * Convert from a path to a devid string. 3325168404Spjd */ 3326168404Spjdstatic char * 3327168404Spjdpath_to_devid(const char *path) 3328168404Spjd{ 3329265821Smav#ifdef have_devid 3330168404Spjd int fd; 3331168404Spjd ddi_devid_t devid; 3332168404Spjd char *minor, *ret; 3333168404Spjd 3334168404Spjd if ((fd = open(path, O_RDONLY)) < 0) 3335168404Spjd return (NULL); 3336168404Spjd 3337168404Spjd minor = NULL; 3338168404Spjd ret = NULL; 3339168404Spjd if (devid_get(fd, &devid) == 0) { 3340168404Spjd if (devid_get_minor_name(fd, &minor) == 0) 3341168404Spjd ret = devid_str_encode(devid, minor); 3342168404Spjd if (minor != NULL) 3343168404Spjd devid_str_free(minor); 3344168404Spjd devid_free(devid); 3345168404Spjd } 3346168404Spjd (void) close(fd); 3347168404Spjd 3348168404Spjd return (ret); 3349265821Smav#else 3350265821Smav return (NULL); 3351265821Smav#endif 3352168404Spjd} 3353168404Spjd 3354168404Spjd/* 3355168404Spjd * Issue the necessary ioctl() to update the stored path value for the vdev. We 3356168404Spjd * ignore any failure here, since a common case is for an unprivileged user to 3357168404Spjd * type 'zpool status', and we'll display the correct information anyway. 3358168404Spjd */ 3359168404Spjdstatic void 3360168404Spjdset_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 3361168404Spjd{ 3362168404Spjd zfs_cmd_t zc = { 0 }; 3363168404Spjd 3364168404Spjd (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3365168404Spjd (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 3366168404Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 3367168404Spjd &zc.zc_guid) == 0); 3368168404Spjd 3369168404Spjd (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 3370168404Spjd} 3371168404Spjd 3372168404Spjd/* 3373168404Spjd * Given a vdev, return the name to display in iostat. If the vdev has a path, 3374168404Spjd * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 3375168404Spjd * We also check if this is a whole disk, in which case we strip off the 3376168404Spjd * trailing 's0' slice name. 3377168404Spjd * 3378168404Spjd * This routine is also responsible for identifying when disks have been 3379168404Spjd * reconfigured in a new location. The kernel will have opened the device by 3380168404Spjd * devid, but the path will still refer to the old location. To catch this, we 3381168404Spjd * first do a path -> devid translation (which is fast for the common case). If 3382168404Spjd * the devid matches, we're done. If not, we do a reverse devid -> path 3383168404Spjd * translation and issue the appropriate ioctl() to update the path of the vdev. 3384168404Spjd * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 3385168404Spjd * of these checks. 3386168404Spjd */ 3387168404Spjdchar * 3388219089Spjdzpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv, 3389219089Spjd boolean_t verbose) 3390168404Spjd{ 3391168404Spjd char *path, *devid; 3392168404Spjd uint64_t value; 3393168404Spjd char buf[64]; 3394185029Spjd vdev_stat_t *vs; 3395185029Spjd uint_t vsc; 3396224170Sgibbs int have_stats; 3397224170Sgibbs int have_path; 3398168404Spjd 3399224170Sgibbs have_stats = nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 3400224170Sgibbs (uint64_t **)&vs, &vsc) == 0; 3401224170Sgibbs have_path = nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0; 3402224170Sgibbs 3403224170Sgibbs /* 3404224170Sgibbs * If the device is not currently present, assume it will not 3405224170Sgibbs * come back at the same device path. Display the device by GUID. 3406224170Sgibbs */ 3407224170Sgibbs if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &value) == 0 || 3408224170Sgibbs have_path && have_stats && vs->vs_state <= VDEV_STATE_CANT_OPEN) { 3409168404Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 3410168404Spjd &value) == 0); 3411168404Spjd (void) snprintf(buf, sizeof (buf), "%llu", 3412168404Spjd (u_longlong_t)value); 3413168404Spjd path = buf; 3414224170Sgibbs } else if (have_path) { 3415168404Spjd 3416185029Spjd /* 3417185029Spjd * If the device is dead (faulted, offline, etc) then don't 3418185029Spjd * bother opening it. Otherwise we may be forcing the user to 3419185029Spjd * open a misbehaving device, which can have undesirable 3420185029Spjd * effects. 3421185029Spjd */ 3422224170Sgibbs if ((have_stats == 0 || 3423185029Spjd vs->vs_state >= VDEV_STATE_DEGRADED) && 3424185029Spjd zhp != NULL && 3425168404Spjd nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 3426168404Spjd /* 3427168404Spjd * Determine if the current path is correct. 3428168404Spjd */ 3429168404Spjd char *newdevid = path_to_devid(path); 3430168404Spjd 3431168404Spjd if (newdevid == NULL || 3432168404Spjd strcmp(devid, newdevid) != 0) { 3433168404Spjd char *newpath; 3434168404Spjd 3435168404Spjd if ((newpath = devid_to_path(devid)) != NULL) { 3436168404Spjd /* 3437168404Spjd * Update the path appropriately. 3438168404Spjd */ 3439168404Spjd set_path(zhp, nv, newpath); 3440168404Spjd if (nvlist_add_string(nv, 3441168404Spjd ZPOOL_CONFIG_PATH, newpath) == 0) 3442168404Spjd verify(nvlist_lookup_string(nv, 3443168404Spjd ZPOOL_CONFIG_PATH, 3444168404Spjd &path) == 0); 3445168404Spjd free(newpath); 3446168404Spjd } 3447168404Spjd } 3448168404Spjd 3449168404Spjd if (newdevid) 3450168404Spjd devid_str_free(newdevid); 3451168404Spjd } 3452168404Spjd 3453277300Ssmh#ifdef illumos 3454297763Smav if (strncmp(path, ZFS_DISK_ROOTD, strlen(ZFS_DISK_ROOTD)) == 0) 3455297763Smav path += strlen(ZFS_DISK_ROOTD); 3456168404Spjd 3457168404Spjd if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 3458168404Spjd &value) == 0 && value) { 3459219089Spjd int pathlen = strlen(path); 3460168404Spjd char *tmp = zfs_strdup(hdl, path); 3461219089Spjd 3462219089Spjd /* 3463219089Spjd * If it starts with c#, and ends with "s0", chop 3464219089Spjd * the "s0" off, or if it ends with "s0/old", remove 3465219089Spjd * the "s0" from the middle. 3466219089Spjd */ 3467219089Spjd if (CTD_CHECK(tmp)) { 3468219089Spjd if (strcmp(&tmp[pathlen - 2], "s0") == 0) { 3469219089Spjd tmp[pathlen - 2] = '\0'; 3470219089Spjd } else if (pathlen > 6 && 3471219089Spjd strcmp(&tmp[pathlen - 6], "s0/old") == 0) { 3472219089Spjd (void) strcpy(&tmp[pathlen - 6], 3473219089Spjd "/old"); 3474219089Spjd } 3475219089Spjd } 3476168404Spjd return (tmp); 3477168404Spjd } 3478277300Ssmh#else /* !illumos */ 3479219089Spjd if (strncmp(path, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 3480219089Spjd path += sizeof(_PATH_DEV) - 1; 3481277300Ssmh#endif /* illumos */ 3482168404Spjd } else { 3483168404Spjd verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 3484168404Spjd 3485168404Spjd /* 3486168404Spjd * If it's a raidz device, we need to stick in the parity level. 3487168404Spjd */ 3488168404Spjd if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 3489168404Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 3490168404Spjd &value) == 0); 3491168404Spjd (void) snprintf(buf, sizeof (buf), "%s%llu", path, 3492168404Spjd (u_longlong_t)value); 3493168404Spjd path = buf; 3494168404Spjd } 3495219089Spjd 3496219089Spjd /* 3497219089Spjd * We identify each top-level vdev by using a <type-id> 3498219089Spjd * naming convention. 3499219089Spjd */ 3500219089Spjd if (verbose) { 3501219089Spjd uint64_t id; 3502219089Spjd 3503219089Spjd verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID, 3504219089Spjd &id) == 0); 3505219089Spjd (void) snprintf(buf, sizeof (buf), "%s-%llu", path, 3506219089Spjd (u_longlong_t)id); 3507219089Spjd path = buf; 3508219089Spjd } 3509168404Spjd } 3510168404Spjd 3511168404Spjd return (zfs_strdup(hdl, path)); 3512168404Spjd} 3513168404Spjd 3514168404Spjdstatic int 3515286705Smavzbookmark_mem_compare(const void *a, const void *b) 3516168404Spjd{ 3517268123Sdelphij return (memcmp(a, b, sizeof (zbookmark_phys_t))); 3518168404Spjd} 3519168404Spjd 3520168404Spjd/* 3521168404Spjd * Retrieve the persistent error log, uniquify the members, and return to the 3522168404Spjd * caller. 3523168404Spjd */ 3524168404Spjdint 3525168404Spjdzpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) 3526168404Spjd{ 3527168404Spjd zfs_cmd_t zc = { 0 }; 3528168404Spjd uint64_t count; 3529268123Sdelphij zbookmark_phys_t *zb = NULL; 3530168404Spjd int i; 3531168404Spjd 3532168404Spjd /* 3533168404Spjd * Retrieve the raw error list from the kernel. If the number of errors 3534168404Spjd * has increased, allocate more space and continue until we get the 3535168404Spjd * entire list. 3536168404Spjd */ 3537168404Spjd verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 3538168404Spjd &count) == 0); 3539185029Spjd if (count == 0) 3540185029Spjd return (0); 3541168404Spjd if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 3542268123Sdelphij count * sizeof (zbookmark_phys_t))) == (uintptr_t)NULL) 3543168404Spjd return (-1); 3544168404Spjd zc.zc_nvlist_dst_size = count; 3545168404Spjd (void) strcpy(zc.zc_name, zhp->zpool_name); 3546168404Spjd for (;;) { 3547168404Spjd if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 3548168404Spjd &zc) != 0) { 3549168404Spjd free((void *)(uintptr_t)zc.zc_nvlist_dst); 3550168404Spjd if (errno == ENOMEM) { 3551268123Sdelphij void *dst; 3552268123Sdelphij 3553168404Spjd count = zc.zc_nvlist_dst_size; 3554268123Sdelphij dst = zfs_alloc(zhp->zpool_hdl, count * 3555268123Sdelphij sizeof (zbookmark_phys_t)); 3556268123Sdelphij if (dst == NULL) 3557168404Spjd return (-1); 3558268123Sdelphij zc.zc_nvlist_dst = (uintptr_t)dst; 3559168404Spjd } else { 3560168404Spjd return (-1); 3561168404Spjd } 3562168404Spjd } else { 3563168404Spjd break; 3564168404Spjd } 3565168404Spjd } 3566168404Spjd 3567168404Spjd /* 3568168404Spjd * Sort the resulting bookmarks. This is a little confusing due to the 3569168404Spjd * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 3570168404Spjd * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 3571168404Spjd * _not_ copied as part of the process. So we point the start of our 3572168404Spjd * array appropriate and decrement the total number of elements. 3573168404Spjd */ 3574268123Sdelphij zb = ((zbookmark_phys_t *)(uintptr_t)zc.zc_nvlist_dst) + 3575168404Spjd zc.zc_nvlist_dst_size; 3576168404Spjd count -= zc.zc_nvlist_dst_size; 3577168404Spjd 3578286705Smav qsort(zb, count, sizeof (zbookmark_phys_t), zbookmark_mem_compare); 3579168404Spjd 3580168404Spjd verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); 3581168404Spjd 3582168404Spjd /* 3583168404Spjd * Fill in the nverrlistp with nvlist's of dataset and object numbers. 3584168404Spjd */ 3585168404Spjd for (i = 0; i < count; i++) { 3586168404Spjd nvlist_t *nv; 3587168404Spjd 3588168404Spjd /* ignoring zb_blkid and zb_level for now */ 3589168404Spjd if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && 3590168404Spjd zb[i-1].zb_object == zb[i].zb_object) 3591168404Spjd continue; 3592168404Spjd 3593168404Spjd if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) 3594168404Spjd goto nomem; 3595168404Spjd if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, 3596168404Spjd zb[i].zb_objset) != 0) { 3597168404Spjd nvlist_free(nv); 3598168404Spjd goto nomem; 3599168404Spjd } 3600168404Spjd if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, 3601168404Spjd zb[i].zb_object) != 0) { 3602168404Spjd nvlist_free(nv); 3603168404Spjd goto nomem; 3604168404Spjd } 3605168404Spjd if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { 3606168404Spjd nvlist_free(nv); 3607168404Spjd goto nomem; 3608168404Spjd } 3609168404Spjd nvlist_free(nv); 3610168404Spjd } 3611168404Spjd 3612168404Spjd free((void *)(uintptr_t)zc.zc_nvlist_dst); 3613168404Spjd return (0); 3614168404Spjd 3615168404Spjdnomem: 3616168404Spjd free((void *)(uintptr_t)zc.zc_nvlist_dst); 3617168404Spjd return (no_memory(zhp->zpool_hdl)); 3618168404Spjd} 3619168404Spjd 3620168404Spjd/* 3621168404Spjd * Upgrade a ZFS pool to the latest on-disk version. 3622168404Spjd */ 3623168404Spjdint 3624185029Spjdzpool_upgrade(zpool_handle_t *zhp, uint64_t new_version) 3625168404Spjd{ 3626168404Spjd zfs_cmd_t zc = { 0 }; 3627168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 3628168404Spjd 3629168404Spjd (void) strcpy(zc.zc_name, zhp->zpool_name); 3630185029Spjd zc.zc_cookie = new_version; 3631185029Spjd 3632185029Spjd if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 3633168404Spjd return (zpool_standard_error_fmt(hdl, errno, 3634168404Spjd dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 3635168404Spjd zhp->zpool_name)); 3636168404Spjd return (0); 3637168404Spjd} 3638168404Spjd 3639168404Spjdvoid 3640248571Smmzfs_save_arguments(int argc, char **argv, char *string, int len) 3641168404Spjd{ 3642248571Smm (void) strlcpy(string, basename(argv[0]), len); 3643248571Smm for (int i = 1; i < argc; i++) { 3644248571Smm (void) strlcat(string, " ", len); 3645248571Smm (void) strlcat(string, argv[i], len); 3646168404Spjd } 3647185029Spjd} 3648168404Spjd 3649185029Spjdint 3650248571Smmzpool_log_history(libzfs_handle_t *hdl, const char *message) 3651185029Spjd{ 3652248571Smm zfs_cmd_t zc = { 0 }; 3653248571Smm nvlist_t *args; 3654248571Smm int err; 3655168404Spjd 3656248571Smm args = fnvlist_alloc(); 3657248571Smm fnvlist_add_string(args, "message", message); 3658248571Smm err = zcmd_write_src_nvlist(hdl, &zc, args); 3659248571Smm if (err == 0) 3660248571Smm err = ioctl(hdl->libzfs_fd, ZFS_IOC_LOG_HISTORY, &zc); 3661248571Smm nvlist_free(args); 3662248571Smm zcmd_free_nvlists(&zc); 3663248571Smm return (err); 3664168404Spjd} 3665168404Spjd 3666168404Spjd/* 3667168404Spjd * Perform ioctl to get some command history of a pool. 3668168404Spjd * 3669168404Spjd * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 3670168404Spjd * logical offset of the history buffer to start reading from. 3671168404Spjd * 3672168404Spjd * Upon return, 'off' is the next logical offset to read from and 3673168404Spjd * 'len' is the actual amount of bytes read into 'buf'. 3674168404Spjd */ 3675168404Spjdstatic int 3676168404Spjdget_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 3677168404Spjd{ 3678168404Spjd zfs_cmd_t zc = { 0 }; 3679168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 3680168404Spjd 3681168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3682168404Spjd 3683168404Spjd zc.zc_history = (uint64_t)(uintptr_t)buf; 3684168404Spjd zc.zc_history_len = *len; 3685168404Spjd zc.zc_history_offset = *off; 3686168404Spjd 3687168404Spjd if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 3688168404Spjd switch (errno) { 3689168404Spjd case EPERM: 3690168404Spjd return (zfs_error_fmt(hdl, EZFS_PERM, 3691168404Spjd dgettext(TEXT_DOMAIN, 3692168404Spjd "cannot show history for pool '%s'"), 3693168404Spjd zhp->zpool_name)); 3694168404Spjd case ENOENT: 3695168404Spjd return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 3696168404Spjd dgettext(TEXT_DOMAIN, "cannot get history for pool " 3697168404Spjd "'%s'"), zhp->zpool_name)); 3698168404Spjd case ENOTSUP: 3699168404Spjd return (zfs_error_fmt(hdl, EZFS_BADVERSION, 3700168404Spjd dgettext(TEXT_DOMAIN, "cannot get history for pool " 3701168404Spjd "'%s', pool must be upgraded"), zhp->zpool_name)); 3702168404Spjd default: 3703168404Spjd return (zpool_standard_error_fmt(hdl, errno, 3704168404Spjd dgettext(TEXT_DOMAIN, 3705168404Spjd "cannot get history for '%s'"), zhp->zpool_name)); 3706168404Spjd } 3707168404Spjd } 3708168404Spjd 3709168404Spjd *len = zc.zc_history_len; 3710168404Spjd *off = zc.zc_history_offset; 3711168404Spjd 3712168404Spjd return (0); 3713168404Spjd} 3714168404Spjd 3715168404Spjd/* 3716168404Spjd * Process the buffer of nvlists, unpacking and storing each nvlist record 3717168404Spjd * into 'records'. 'leftover' is set to the number of bytes that weren't 3718168404Spjd * processed as there wasn't a complete record. 3719168404Spjd */ 3720219089Spjdint 3721168404Spjdzpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 3722168404Spjd nvlist_t ***records, uint_t *numrecords) 3723168404Spjd{ 3724168404Spjd uint64_t reclen; 3725168404Spjd nvlist_t *nv; 3726168404Spjd int i; 3727168404Spjd 3728168404Spjd while (bytes_read > sizeof (reclen)) { 3729168404Spjd 3730168404Spjd /* get length of packed record (stored as little endian) */ 3731168404Spjd for (i = 0, reclen = 0; i < sizeof (reclen); i++) 3732168404Spjd reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 3733168404Spjd 3734168404Spjd if (bytes_read < sizeof (reclen) + reclen) 3735168404Spjd break; 3736168404Spjd 3737168404Spjd /* unpack record */ 3738168404Spjd if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 3739168404Spjd return (ENOMEM); 3740168404Spjd bytes_read -= sizeof (reclen) + reclen; 3741168404Spjd buf += sizeof (reclen) + reclen; 3742168404Spjd 3743168404Spjd /* add record to nvlist array */ 3744168404Spjd (*numrecords)++; 3745168404Spjd if (ISP2(*numrecords + 1)) { 3746168404Spjd *records = realloc(*records, 3747168404Spjd *numrecords * 2 * sizeof (nvlist_t *)); 3748168404Spjd } 3749168404Spjd (*records)[*numrecords - 1] = nv; 3750168404Spjd } 3751168404Spjd 3752168404Spjd *leftover = bytes_read; 3753168404Spjd return (0); 3754168404Spjd} 3755168404Spjd 3756264467Sdelphij/* from spa_history.c: spa_history_create_obj() */ 3757264467Sdelphij#define HIS_BUF_LEN_DEF (128 << 10) 3758264467Sdelphij#define HIS_BUF_LEN_MAX (1 << 30) 3759168404Spjd 3760168404Spjd/* 3761168404Spjd * Retrieve the command history of a pool. 3762168404Spjd */ 3763168404Spjdint 3764168404Spjdzpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 3765168404Spjd{ 3766289528Smav char *buf; 3767289528Smav uint64_t buflen = HIS_BUF_LEN_DEF; 3768168404Spjd uint64_t off = 0; 3769168404Spjd nvlist_t **records = NULL; 3770168404Spjd uint_t numrecords = 0; 3771168404Spjd int err, i; 3772168404Spjd 3773289528Smav buf = malloc(buflen); 3774289528Smav if (buf == NULL) 3775264467Sdelphij return (ENOMEM); 3776168404Spjd do { 3777289528Smav uint64_t bytes_read = buflen; 3778168404Spjd uint64_t leftover; 3779168404Spjd 3780168404Spjd if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 3781168404Spjd break; 3782168404Spjd 3783168404Spjd /* if nothing else was read in, we're at EOF, just return */ 3784264467Sdelphij if (bytes_read == 0) 3785168404Spjd break; 3786168404Spjd 3787168404Spjd if ((err = zpool_history_unpack(buf, bytes_read, 3788168404Spjd &leftover, &records, &numrecords)) != 0) 3789168404Spjd break; 3790168404Spjd off -= leftover; 3791264467Sdelphij if (leftover == bytes_read) { 3792289528Smav /* 3793289528Smav * no progress made, because buffer is not big enough 3794289528Smav * to hold this record; resize and retry. 3795289528Smav */ 3796289528Smav buflen *= 2; 3797264467Sdelphij free(buf); 3798264467Sdelphij buf = NULL; 3799289528Smav if ((buflen >= HIS_BUF_LEN_MAX) || 3800289528Smav ((buf = malloc(buflen)) == NULL)) { 3801264467Sdelphij err = ENOMEM; 3802264467Sdelphij break; 3803264467Sdelphij } 3804264467Sdelphij } 3805264467Sdelphij 3806168404Spjd /* CONSTCOND */ 3807168404Spjd } while (1); 3808289528Smav 3809264467Sdelphij free(buf); 3810168404Spjd 3811168404Spjd if (!err) { 3812168404Spjd verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 3813168404Spjd verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 3814168404Spjd records, numrecords) == 0); 3815168404Spjd } 3816168404Spjd for (i = 0; i < numrecords; i++) 3817168404Spjd nvlist_free(records[i]); 3818168404Spjd free(records); 3819168404Spjd 3820168404Spjd return (err); 3821168404Spjd} 3822168404Spjd 3823168404Spjdvoid 3824168404Spjdzpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, 3825168404Spjd char *pathname, size_t len) 3826168404Spjd{ 3827168404Spjd zfs_cmd_t zc = { 0 }; 3828168404Spjd boolean_t mounted = B_FALSE; 3829168404Spjd char *mntpnt = NULL; 3830307108Smav char dsname[ZFS_MAX_DATASET_NAME_LEN]; 3831168404Spjd 3832168404Spjd if (dsobj == 0) { 3833168404Spjd /* special case for the MOS */ 3834168404Spjd (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj); 3835168404Spjd return; 3836168404Spjd } 3837168404Spjd 3838168404Spjd /* get the dataset's name */ 3839168404Spjd (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 3840168404Spjd zc.zc_obj = dsobj; 3841168404Spjd if (ioctl(zhp->zpool_hdl->libzfs_fd, 3842168404Spjd ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { 3843168404Spjd /* just write out a path of two object numbers */ 3844168404Spjd (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", 3845168404Spjd dsobj, obj); 3846168404Spjd return; 3847168404Spjd } 3848168404Spjd (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); 3849168404Spjd 3850168404Spjd /* find out if the dataset is mounted */ 3851168404Spjd mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt); 3852168404Spjd 3853168404Spjd /* get the corrupted object's path */ 3854168404Spjd (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); 3855168404Spjd zc.zc_obj = obj; 3856168404Spjd if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH, 3857168404Spjd &zc) == 0) { 3858168404Spjd if (mounted) { 3859168404Spjd (void) snprintf(pathname, len, "%s%s", mntpnt, 3860168404Spjd zc.zc_value); 3861168404Spjd } else { 3862168404Spjd (void) snprintf(pathname, len, "%s:%s", 3863168404Spjd dsname, zc.zc_value); 3864168404Spjd } 3865168404Spjd } else { 3866168404Spjd (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj); 3867168404Spjd } 3868168404Spjd free(mntpnt); 3869168404Spjd} 3870168404Spjd 3871277300Ssmh#ifdef illumos 3872185029Spjd/* 3873185029Spjd * Read the EFI label from the config, if a label does not exist then 3874185029Spjd * pass back the error to the caller. If the caller has passed a non-NULL 3875185029Spjd * diskaddr argument then we set it to the starting address of the EFI 3876185029Spjd * partition. 3877185029Spjd */ 3878185029Spjdstatic int 3879185029Spjdread_efi_label(nvlist_t *config, diskaddr_t *sb) 3880168404Spjd{ 3881185029Spjd char *path; 3882185029Spjd int fd; 3883185029Spjd char diskname[MAXPATHLEN]; 3884185029Spjd int err = -1; 3885168404Spjd 3886185029Spjd if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0) 3887185029Spjd return (err); 3888168404Spjd 3889297763Smav (void) snprintf(diskname, sizeof (diskname), "%s%s", ZFS_RDISK_ROOT, 3890185029Spjd strrchr(path, '/')); 3891185029Spjd if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) { 3892185029Spjd struct dk_gpt *vtoc; 3893185029Spjd 3894185029Spjd if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) { 3895185029Spjd if (sb != NULL) 3896185029Spjd *sb = vtoc->efi_parts[0].p_start; 3897185029Spjd efi_free(vtoc); 3898185029Spjd } 3899185029Spjd (void) close(fd); 3900168404Spjd } 3901185029Spjd return (err); 3902185029Spjd} 3903168404Spjd 3904185029Spjd/* 3905185029Spjd * determine where a partition starts on a disk in the current 3906185029Spjd * configuration 3907185029Spjd */ 3908185029Spjdstatic diskaddr_t 3909185029Spjdfind_start_block(nvlist_t *config) 3910185029Spjd{ 3911185029Spjd nvlist_t **child; 3912185029Spjd uint_t c, children; 3913185029Spjd diskaddr_t sb = MAXOFFSET_T; 3914185029Spjd uint64_t wholedisk; 3915168404Spjd 3916185029Spjd if (nvlist_lookup_nvlist_array(config, 3917185029Spjd ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) { 3918185029Spjd if (nvlist_lookup_uint64(config, 3919185029Spjd ZPOOL_CONFIG_WHOLE_DISK, 3920185029Spjd &wholedisk) != 0 || !wholedisk) { 3921185029Spjd return (MAXOFFSET_T); 3922185029Spjd } 3923185029Spjd if (read_efi_label(config, &sb) < 0) 3924185029Spjd sb = MAXOFFSET_T; 3925185029Spjd return (sb); 3926168404Spjd } 3927168404Spjd 3928185029Spjd for (c = 0; c < children; c++) { 3929185029Spjd sb = find_start_block(child[c]); 3930185029Spjd if (sb != MAXOFFSET_T) { 3931185029Spjd return (sb); 3932185029Spjd } 3933168404Spjd } 3934185029Spjd return (MAXOFFSET_T); 3935185029Spjd} 3936277300Ssmh#endif /* illumos */ 3937168404Spjd 3938185029Spjd/* 3939185029Spjd * Label an individual disk. The name provided is the short name, 3940185029Spjd * stripped of any leading /dev path. 3941185029Spjd */ 3942185029Spjdint 3943224169Sgibbszpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name) 3944185029Spjd{ 3945277300Ssmh#ifdef illumos 3946185029Spjd char path[MAXPATHLEN]; 3947185029Spjd struct dk_gpt *vtoc; 3948185029Spjd int fd; 3949185029Spjd size_t resv = EFI_MIN_RESV_SIZE; 3950185029Spjd uint64_t slice_size; 3951185029Spjd diskaddr_t start_block; 3952185029Spjd char errbuf[1024]; 3953168404Spjd 3954185029Spjd /* prepare an error message just in case */ 3955185029Spjd (void) snprintf(errbuf, sizeof (errbuf), 3956185029Spjd dgettext(TEXT_DOMAIN, "cannot label '%s'"), name); 3957168404Spjd 3958185029Spjd if (zhp) { 3959185029Spjd nvlist_t *nvroot; 3960168404Spjd 3961185029Spjd verify(nvlist_lookup_nvlist(zhp->zpool_config, 3962185029Spjd ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 3963168404Spjd 3964185029Spjd if (zhp->zpool_start_block == 0) 3965185029Spjd start_block = find_start_block(nvroot); 3966185029Spjd else 3967185029Spjd start_block = zhp->zpool_start_block; 3968185029Spjd zhp->zpool_start_block = start_block; 3969185029Spjd } else { 3970185029Spjd /* new pool */ 3971185029Spjd start_block = NEW_START_BLOCK; 3972185029Spjd } 3973168404Spjd 3974297763Smav (void) snprintf(path, sizeof (path), "%s/%s%s", ZFS_RDISK_ROOT, name, 3975185029Spjd BACKUP_SLICE); 3976168404Spjd 3977185029Spjd if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) { 3978185029Spjd /* 3979185029Spjd * This shouldn't happen. We've long since verified that this 3980185029Spjd * is a valid device. 3981185029Spjd */ 3982185029Spjd zfs_error_aux(hdl, 3983185029Spjd dgettext(TEXT_DOMAIN, "unable to open device")); 3984185029Spjd return (zfs_error(hdl, EZFS_OPENFAILED, errbuf)); 3985185029Spjd } 3986168404Spjd 3987185029Spjd if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) { 3988185029Spjd /* 3989185029Spjd * The only way this can fail is if we run out of memory, or we 3990185029Spjd * were unable to read the disk's capacity 3991185029Spjd */ 3992185029Spjd if (errno == ENOMEM) 3993185029Spjd (void) no_memory(hdl); 3994168404Spjd 3995185029Spjd (void) close(fd); 3996185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3997185029Spjd "unable to read disk capacity"), name); 3998185029Spjd 3999185029Spjd return (zfs_error(hdl, EZFS_NOCAP, errbuf)); 4000168404Spjd } 4001168404Spjd 4002185029Spjd slice_size = vtoc->efi_last_u_lba + 1; 4003185029Spjd slice_size -= EFI_MIN_RESV_SIZE; 4004185029Spjd if (start_block == MAXOFFSET_T) 4005185029Spjd start_block = NEW_START_BLOCK; 4006185029Spjd slice_size -= start_block; 4007168404Spjd 4008185029Spjd vtoc->efi_parts[0].p_start = start_block; 4009185029Spjd vtoc->efi_parts[0].p_size = slice_size; 4010185029Spjd 4011168404Spjd /* 4012185029Spjd * Why we use V_USR: V_BACKUP confuses users, and is considered 4013185029Spjd * disposable by some EFI utilities (since EFI doesn't have a backup 4014185029Spjd * slice). V_UNASSIGNED is supposed to be used only for zero size 4015185029Spjd * partitions, and efi_write() will fail if we use it. V_ROOT, V_BOOT, 4016185029Spjd * etc. were all pretty specific. V_USR is as close to reality as we 4017185029Spjd * can get, in the absence of V_OTHER. 4018168404Spjd */ 4019185029Spjd vtoc->efi_parts[0].p_tag = V_USR; 4020185029Spjd (void) strcpy(vtoc->efi_parts[0].p_name, "zfs"); 4021168404Spjd 4022185029Spjd vtoc->efi_parts[8].p_start = slice_size + start_block; 4023185029Spjd vtoc->efi_parts[8].p_size = resv; 4024185029Spjd vtoc->efi_parts[8].p_tag = V_RESERVED; 4025168404Spjd 4026185029Spjd if (efi_write(fd, vtoc) != 0) { 4027185029Spjd /* 4028185029Spjd * Some block drivers (like pcata) may not support EFI 4029185029Spjd * GPT labels. Print out a helpful error message dir- 4030185029Spjd * ecting the user to manually label the disk and give 4031185029Spjd * a specific slice. 4032185029Spjd */ 4033185029Spjd (void) close(fd); 4034185029Spjd efi_free(vtoc); 4035168404Spjd 4036185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4037185029Spjd "try using fdisk(1M) and then provide a specific slice")); 4038185029Spjd return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); 4039168404Spjd } 4040185029Spjd 4041185029Spjd (void) close(fd); 4042185029Spjd efi_free(vtoc); 4043277300Ssmh#endif /* illumos */ 4044168404Spjd return (0); 4045168404Spjd} 4046168404Spjd 4047185029Spjdstatic boolean_t 4048185029Spjdsupported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf) 4049168404Spjd{ 4050185029Spjd char *type; 4051185029Spjd nvlist_t **child; 4052185029Spjd uint_t children, c; 4053185029Spjd 4054185029Spjd verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0); 4055255750Sdelphij if (strcmp(type, VDEV_TYPE_FILE) == 0 || 4056219089Spjd strcmp(type, VDEV_TYPE_HOLE) == 0 || 4057185029Spjd strcmp(type, VDEV_TYPE_MISSING) == 0) { 4058185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4059185029Spjd "vdev type '%s' is not supported"), type); 4060185029Spjd (void) zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf); 4061185029Spjd return (B_FALSE); 4062185029Spjd } 4063185029Spjd if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN, 4064185029Spjd &child, &children) == 0) { 4065185029Spjd for (c = 0; c < children; c++) { 4066185029Spjd if (!supported_dump_vdev_type(hdl, child[c], errbuf)) 4067185029Spjd return (B_FALSE); 4068185029Spjd } 4069185029Spjd } 4070185029Spjd return (B_TRUE); 4071168404Spjd} 4072168404Spjd 4073185029Spjd/* 4074255750Sdelphij * Check if this zvol is allowable for use as a dump device; zero if 4075255750Sdelphij * it is, > 0 if it isn't, < 0 if it isn't a zvol. 4076255750Sdelphij * 4077255750Sdelphij * Allowable storage configurations include mirrors, all raidz variants, and 4078255750Sdelphij * pools with log, cache, and spare devices. Pools which are backed by files or 4079255750Sdelphij * have missing/hole vdevs are not suitable. 4080185029Spjd */ 4081168404Spjdint 4082185029Spjdzvol_check_dump_config(char *arg) 4083168404Spjd{ 4084185029Spjd zpool_handle_t *zhp = NULL; 4085185029Spjd nvlist_t *config, *nvroot; 4086185029Spjd char *p, *volname; 4087185029Spjd nvlist_t **top; 4088185029Spjd uint_t toplevels; 4089185029Spjd libzfs_handle_t *hdl; 4090185029Spjd char errbuf[1024]; 4091307108Smav char poolname[ZFS_MAX_DATASET_NAME_LEN]; 4092185029Spjd int pathlen = strlen(ZVOL_FULL_DEV_DIR); 4093185029Spjd int ret = 1; 4094168404Spjd 4095185029Spjd if (strncmp(arg, ZVOL_FULL_DEV_DIR, pathlen)) { 4096168404Spjd return (-1); 4097185029Spjd } 4098168404Spjd 4099185029Spjd (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 4100185029Spjd "dump is not supported on device '%s'"), arg); 4101168404Spjd 4102185029Spjd if ((hdl = libzfs_init()) == NULL) 4103185029Spjd return (1); 4104185029Spjd libzfs_print_on_error(hdl, B_TRUE); 4105168404Spjd 4106185029Spjd volname = arg + pathlen; 4107185029Spjd 4108185029Spjd /* check the configuration of the pool */ 4109185029Spjd if ((p = strchr(volname, '/')) == NULL) { 4110185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4111185029Spjd "malformed dataset name")); 4112185029Spjd (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 4113185029Spjd return (1); 4114307108Smav } else if (p - volname >= ZFS_MAX_DATASET_NAME_LEN) { 4115185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4116185029Spjd "dataset name is too long")); 4117185029Spjd (void) zfs_error(hdl, EZFS_NAMETOOLONG, errbuf); 4118185029Spjd return (1); 4119185029Spjd } else { 4120185029Spjd (void) strncpy(poolname, volname, p - volname); 4121185029Spjd poolname[p - volname] = '\0'; 4122168404Spjd } 4123168404Spjd 4124185029Spjd if ((zhp = zpool_open(hdl, poolname)) == NULL) { 4125185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4126185029Spjd "could not open pool '%s'"), poolname); 4127185029Spjd (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf); 4128185029Spjd goto out; 4129185029Spjd } 4130185029Spjd config = zpool_get_config(zhp, NULL); 4131185029Spjd if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 4132185029Spjd &nvroot) != 0) { 4133185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4134185029Spjd "could not obtain vdev configuration for '%s'"), poolname); 4135185029Spjd (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf); 4136185029Spjd goto out; 4137185029Spjd } 4138185029Spjd 4139185029Spjd verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 4140185029Spjd &top, &toplevels) == 0); 4141185029Spjd 4142185029Spjd if (!supported_dump_vdev_type(hdl, top[0], errbuf)) { 4143185029Spjd goto out; 4144185029Spjd } 4145185029Spjd ret = 0; 4146185029Spjd 4147185029Spjdout: 4148185029Spjd if (zhp) 4149185029Spjd zpool_close(zhp); 4150185029Spjd libzfs_fini(hdl); 4151185029Spjd return (ret); 4152168404Spjd} 4153308914Savg 4154308914Savgint 4155308914Savgzpool_nextboot(libzfs_handle_t *hdl, uint64_t pool_guid, uint64_t dev_guid, 4156308914Savg const char *command) 4157308914Savg{ 4158308914Savg zfs_cmd_t zc = { 0 }; 4159308914Savg nvlist_t *args; 4160308914Savg char *packed; 4161308914Savg size_t size; 4162308914Savg int error; 4163308914Savg 4164308914Savg args = fnvlist_alloc(); 4165308914Savg fnvlist_add_uint64(args, ZPOOL_CONFIG_POOL_GUID, pool_guid); 4166308914Savg fnvlist_add_uint64(args, ZPOOL_CONFIG_GUID, dev_guid); 4167308914Savg fnvlist_add_string(args, "command", command); 4168308914Savg error = zcmd_write_src_nvlist(hdl, &zc, args); 4169308914Savg if (error == 0) 4170308914Savg error = ioctl(hdl->libzfs_fd, ZFS_IOC_NEXTBOOT, &zc); 4171308914Savg zcmd_free_nvlists(&zc); 4172308914Savg nvlist_free(args); 4173308914Savg return (error); 4174308914Savg} 4175