1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51485Slling * Common Development and Distribution License (the "License"). 61485Slling * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 212082Seschrock 22789Sahrens /* 233377Seschrock * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24789Sahrens * Use is subject to license terms. 25789Sahrens */ 26789Sahrens 27789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28789Sahrens 293126Sahl #include <alloca.h> 30789Sahrens #include <assert.h> 31789Sahrens #include <ctype.h> 32789Sahrens #include <errno.h> 33789Sahrens #include <devid.h> 343126Sahl #include <dirent.h> 35789Sahrens #include <fcntl.h> 36789Sahrens #include <libintl.h> 37789Sahrens #include <stdio.h> 38789Sahrens #include <stdlib.h> 393126Sahl #include <strings.h> 40789Sahrens #include <unistd.h> 414276Staylor #include <sys/efi_partition.h> 424276Staylor #include <sys/vtoc.h> 43789Sahrens #include <sys/zfs_ioctl.h> 441544Seschrock #include <sys/zio.h> 452926Sek110237 #include <strings.h> 46789Sahrens 47789Sahrens #include "zfs_namecheck.h" 483912Slling #include "zfs_prop.h" 49789Sahrens #include "libzfs_impl.h" 50789Sahrens 51*5094Slling 52*5094Slling /* 53*5094Slling * ==================================================================== 54*5094Slling * zpool property functions 55*5094Slling * ==================================================================== 56*5094Slling */ 57*5094Slling 58*5094Slling static int 59*5094Slling zpool_get_all_props(zpool_handle_t *zhp) 60*5094Slling { 61*5094Slling zfs_cmd_t zc = { 0 }; 62*5094Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 63*5094Slling 64*5094Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 65*5094Slling 66*5094Slling if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 67*5094Slling return (-1); 68*5094Slling 69*5094Slling while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) { 70*5094Slling if (errno == ENOMEM) { 71*5094Slling if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 72*5094Slling zcmd_free_nvlists(&zc); 73*5094Slling return (-1); 74*5094Slling } 75*5094Slling } else { 76*5094Slling zcmd_free_nvlists(&zc); 77*5094Slling return (-1); 78*5094Slling } 79*5094Slling } 80*5094Slling 81*5094Slling if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) { 82*5094Slling zcmd_free_nvlists(&zc); 83*5094Slling return (-1); 84*5094Slling } 85*5094Slling 86*5094Slling zcmd_free_nvlists(&zc); 87*5094Slling 88*5094Slling return (0); 89*5094Slling } 90*5094Slling 91*5094Slling static int 92*5094Slling zpool_props_refresh(zpool_handle_t *zhp) 93*5094Slling { 94*5094Slling nvlist_t *old_props; 95*5094Slling 96*5094Slling old_props = zhp->zpool_props; 97*5094Slling 98*5094Slling if (zpool_get_all_props(zhp) != 0) 99*5094Slling return (-1); 100*5094Slling 101*5094Slling nvlist_free(old_props); 102*5094Slling return (0); 103*5094Slling } 104*5094Slling 105*5094Slling static char * 106*5094Slling zpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop, 107*5094Slling zprop_source_t *src) 108*5094Slling { 109*5094Slling nvlist_t *nv, *nvl; 110*5094Slling uint64_t ival; 111*5094Slling char *value; 112*5094Slling zprop_source_t source; 113*5094Slling 114*5094Slling nvl = zhp->zpool_props; 115*5094Slling if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) { 116*5094Slling verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0); 117*5094Slling source = ival; 118*5094Slling verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0); 119*5094Slling } else { 120*5094Slling source = ZPROP_SRC_DEFAULT; 121*5094Slling if ((value = (char *)zpool_prop_default_string(prop)) == NULL) 122*5094Slling value = "-"; 123*5094Slling } 124*5094Slling 125*5094Slling if (src) 126*5094Slling *src = source; 127*5094Slling 128*5094Slling return (value); 129*5094Slling } 130*5094Slling 131*5094Slling uint64_t 132*5094Slling zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src) 133*5094Slling { 134*5094Slling nvlist_t *nv, *nvl; 135*5094Slling uint64_t value; 136*5094Slling zprop_source_t source; 137*5094Slling 138*5094Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 139*5094Slling return (zpool_prop_default_numeric(prop)); 140*5094Slling 141*5094Slling nvl = zhp->zpool_props; 142*5094Slling if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) { 143*5094Slling verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &value) == 0); 144*5094Slling source = value; 145*5094Slling verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0); 146*5094Slling } else { 147*5094Slling source = ZPROP_SRC_DEFAULT; 148*5094Slling value = zpool_prop_default_numeric(prop); 149*5094Slling } 150*5094Slling 151*5094Slling if (src) 152*5094Slling *src = source; 153*5094Slling 154*5094Slling return (value); 155*5094Slling } 156*5094Slling 157*5094Slling /* 158*5094Slling * Map VDEV STATE to printed strings. 159*5094Slling */ 160*5094Slling char * 161*5094Slling zpool_state_to_name(vdev_state_t state, vdev_aux_t aux) 162*5094Slling { 163*5094Slling switch (state) { 164*5094Slling case VDEV_STATE_CLOSED: 165*5094Slling case VDEV_STATE_OFFLINE: 166*5094Slling return (gettext("OFFLINE")); 167*5094Slling case VDEV_STATE_REMOVED: 168*5094Slling return (gettext("REMOVED")); 169*5094Slling case VDEV_STATE_CANT_OPEN: 170*5094Slling if (aux == VDEV_AUX_CORRUPT_DATA) 171*5094Slling return (gettext("FAULTED")); 172*5094Slling else 173*5094Slling return (gettext("UNAVAIL")); 174*5094Slling case VDEV_STATE_FAULTED: 175*5094Slling return (gettext("FAULTED")); 176*5094Slling case VDEV_STATE_DEGRADED: 177*5094Slling return (gettext("DEGRADED")); 178*5094Slling case VDEV_STATE_HEALTHY: 179*5094Slling return (gettext("ONLINE")); 180*5094Slling } 181*5094Slling 182*5094Slling return (gettext("UNKNOWN")); 183*5094Slling } 184*5094Slling 185*5094Slling /* 186*5094Slling * Get a zpool property value for 'prop' and return the value in 187*5094Slling * a pre-allocated buffer. 188*5094Slling */ 189*5094Slling int 190*5094Slling zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, 191*5094Slling zprop_source_t *srctype) 192*5094Slling { 193*5094Slling uint64_t intval; 194*5094Slling const char *strval; 195*5094Slling zprop_source_t src = ZPROP_SRC_NONE; 196*5094Slling nvlist_t *nvroot; 197*5094Slling vdev_stat_t *vs; 198*5094Slling uint_t vsc; 199*5094Slling 200*5094Slling if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 201*5094Slling if (prop == ZPOOL_PROP_NAME) 202*5094Slling (void) strlcpy(buf, zpool_get_name(zhp), len); 203*5094Slling else if (prop == ZPOOL_PROP_HEALTH) 204*5094Slling (void) strlcpy(buf, "FAULTED", len); 205*5094Slling else 206*5094Slling (void) strlcpy(buf, "-", len); 207*5094Slling return (0); 208*5094Slling } 209*5094Slling 210*5094Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) && 211*5094Slling prop != ZPOOL_PROP_NAME) 212*5094Slling return (-1); 213*5094Slling 214*5094Slling switch (zpool_prop_get_type(prop)) { 215*5094Slling case PROP_TYPE_STRING: 216*5094Slling (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src), 217*5094Slling len); 218*5094Slling break; 219*5094Slling 220*5094Slling case PROP_TYPE_NUMBER: 221*5094Slling intval = zpool_get_prop_int(zhp, prop, &src); 222*5094Slling 223*5094Slling switch (prop) { 224*5094Slling case ZPOOL_PROP_SIZE: 225*5094Slling case ZPOOL_PROP_USED: 226*5094Slling case ZPOOL_PROP_AVAILABLE: 227*5094Slling (void) zfs_nicenum(intval, buf, len); 228*5094Slling break; 229*5094Slling 230*5094Slling case ZPOOL_PROP_CAPACITY: 231*5094Slling (void) snprintf(buf, len, "%llu%%", 232*5094Slling (u_longlong_t)intval); 233*5094Slling break; 234*5094Slling 235*5094Slling case ZPOOL_PROP_HEALTH: 236*5094Slling verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 237*5094Slling ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 238*5094Slling verify(nvlist_lookup_uint64_array(nvroot, 239*5094Slling ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &vsc) == 0); 240*5094Slling 241*5094Slling (void) strlcpy(buf, zpool_state_to_name(intval, 242*5094Slling vs->vs_aux), len); 243*5094Slling break; 244*5094Slling default: 245*5094Slling (void) snprintf(buf, len, "%llu", intval); 246*5094Slling } 247*5094Slling break; 248*5094Slling 249*5094Slling case PROP_TYPE_INDEX: 250*5094Slling intval = zpool_get_prop_int(zhp, prop, &src); 251*5094Slling if (zpool_prop_index_to_string(prop, intval, &strval) 252*5094Slling != 0) 253*5094Slling return (-1); 254*5094Slling (void) strlcpy(buf, strval, len); 255*5094Slling break; 256*5094Slling 257*5094Slling default: 258*5094Slling abort(); 259*5094Slling } 260*5094Slling 261*5094Slling if (srctype) 262*5094Slling *srctype = src; 263*5094Slling 264*5094Slling return (0); 265*5094Slling } 266*5094Slling 267*5094Slling /* 268*5094Slling * Check if the bootfs name has the same pool name as it is set to. 269*5094Slling * Assuming bootfs is a valid dataset name. 270*5094Slling */ 271*5094Slling static boolean_t 272*5094Slling bootfs_name_valid(const char *pool, char *bootfs) 273*5094Slling { 274*5094Slling int len = strlen(pool); 275*5094Slling 276*5094Slling if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM)) 277*5094Slling return (B_FALSE); 278*5094Slling 279*5094Slling if (strncmp(pool, bootfs, len) == 0 && 280*5094Slling (bootfs[len] == '/' || bootfs[len] == '\0')) 281*5094Slling return (B_TRUE); 282*5094Slling 283*5094Slling return (B_FALSE); 284*5094Slling } 285*5094Slling 286*5094Slling /* 287*5094Slling * Given an nvlist of zpool properties to be set, validate that they are 288*5094Slling * correct, and parse any numeric properties (index, boolean, etc) if they are 289*5094Slling * specified as strings. 290*5094Slling */ 291*5094Slling static nvlist_t * 292*5094Slling zpool_validate_properties(libzfs_handle_t *hdl, const char *poolname, 293*5094Slling nvlist_t *props, uint64_t version, boolean_t create_or_import, char *errbuf) 294*5094Slling { 295*5094Slling nvpair_t *elem; 296*5094Slling nvlist_t *retprops; 297*5094Slling zpool_prop_t prop; 298*5094Slling char *strval; 299*5094Slling uint64_t intval; 300*5094Slling int temp = -1; 301*5094Slling boolean_t has_altroot = B_FALSE; 302*5094Slling 303*5094Slling if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) { 304*5094Slling (void) no_memory(hdl); 305*5094Slling return (NULL); 306*5094Slling } 307*5094Slling 308*5094Slling elem = NULL; 309*5094Slling while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 310*5094Slling const char *propname = nvpair_name(elem); 311*5094Slling 312*5094Slling /* 313*5094Slling * Make sure this property is valid and applies to this type. 314*5094Slling */ 315*5094Slling if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) { 316*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 317*5094Slling "invalid property '%s'"), propname); 318*5094Slling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 319*5094Slling goto error; 320*5094Slling } 321*5094Slling 322*5094Slling if (zpool_prop_readonly(prop)) { 323*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 324*5094Slling "is readonly"), propname); 325*5094Slling (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); 326*5094Slling goto error; 327*5094Slling } 328*5094Slling 329*5094Slling if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops, 330*5094Slling &strval, &intval, errbuf) != 0) 331*5094Slling goto error; 332*5094Slling 333*5094Slling /* 334*5094Slling * Perform additional checking for specific properties. 335*5094Slling */ 336*5094Slling switch (prop) { 337*5094Slling case ZPOOL_PROP_VERSION: 338*5094Slling if (intval < version || intval > SPA_VERSION) { 339*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 340*5094Slling "property '%s' number %d is invalid."), 341*5094Slling propname, intval); 342*5094Slling (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 343*5094Slling goto error; 344*5094Slling } 345*5094Slling break; 346*5094Slling 347*5094Slling case ZPOOL_PROP_BOOTFS: 348*5094Slling if (create_or_import) { 349*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 350*5094Slling "property '%s' cannot be set at creation " 351*5094Slling "or import time"), propname); 352*5094Slling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 353*5094Slling goto error; 354*5094Slling } 355*5094Slling 356*5094Slling if (version < SPA_VERSION_BOOTFS) { 357*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 358*5094Slling "pool must be upgraded to support " 359*5094Slling "'%s' property"), propname); 360*5094Slling (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 361*5094Slling goto error; 362*5094Slling } 363*5094Slling 364*5094Slling /* 365*5094Slling * bootfs property value has to be a dataset name and 366*5094Slling * the dataset has to be in the same pool as it sets to. 367*5094Slling */ 368*5094Slling if (strval[0] != '\0' && !bootfs_name_valid(poolname, 369*5094Slling strval)) { 370*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 371*5094Slling "is an invalid name"), strval); 372*5094Slling (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 373*5094Slling goto error; 374*5094Slling } 375*5094Slling break; 376*5094Slling 377*5094Slling case ZPOOL_PROP_TEMPORARY: 378*5094Slling if (!create_or_import) { 379*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 380*5094Slling "property '%s' can only be set during pool " 381*5094Slling "creation or import"), propname); 382*5094Slling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 383*5094Slling goto error; 384*5094Slling } 385*5094Slling temp = intval; 386*5094Slling break; 387*5094Slling 388*5094Slling case ZPOOL_PROP_ALTROOT: 389*5094Slling if (!create_or_import) { 390*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 391*5094Slling "property '%s' can only be set during pool " 392*5094Slling "creation or import"), propname); 393*5094Slling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 394*5094Slling goto error; 395*5094Slling } 396*5094Slling 397*5094Slling if (strval[0] != '/') { 398*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 399*5094Slling "bad alternate root '%s'"), strval); 400*5094Slling (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 401*5094Slling goto error; 402*5094Slling } 403*5094Slling 404*5094Slling has_altroot = B_TRUE; 405*5094Slling break; 406*5094Slling } 407*5094Slling } 408*5094Slling 409*5094Slling if (has_altroot) { 410*5094Slling if (temp == 0) { 411*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 412*5094Slling "temporary property must be set to 'on' when " 413*5094Slling "altroot is set")); 414*5094Slling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 415*5094Slling goto error; 416*5094Slling 417*5094Slling } else if (temp == -1 && 418*5094Slling nvlist_add_uint64(retprops, 419*5094Slling zpool_prop_to_name(ZPOOL_PROP_TEMPORARY), 1) != 0) { 420*5094Slling (void) no_memory(hdl); 421*5094Slling goto error; 422*5094Slling } 423*5094Slling } 424*5094Slling 425*5094Slling return (retprops); 426*5094Slling error: 427*5094Slling nvlist_free(retprops); 428*5094Slling return (NULL); 429*5094Slling } 430*5094Slling 431*5094Slling /* 432*5094Slling * Set zpool property : propname=propval. 433*5094Slling */ 434*5094Slling int 435*5094Slling zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) 436*5094Slling { 437*5094Slling zfs_cmd_t zc = { 0 }; 438*5094Slling int ret = -1; 439*5094Slling char errbuf[1024]; 440*5094Slling nvlist_t *nvl = NULL; 441*5094Slling nvlist_t *realprops; 442*5094Slling uint64_t version; 443*5094Slling 444*5094Slling (void) snprintf(errbuf, sizeof (errbuf), 445*5094Slling dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 446*5094Slling zhp->zpool_name); 447*5094Slling 448*5094Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 449*5094Slling return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, errbuf)); 450*5094Slling 451*5094Slling if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 452*5094Slling return (no_memory(zhp->zpool_hdl)); 453*5094Slling 454*5094Slling if (nvlist_add_string(nvl, propname, propval) != 0) { 455*5094Slling nvlist_free(nvl); 456*5094Slling return (no_memory(zhp->zpool_hdl)); 457*5094Slling } 458*5094Slling 459*5094Slling version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 460*5094Slling if ((realprops = zpool_validate_properties(zhp->zpool_hdl, 461*5094Slling zhp->zpool_name, nvl, version, B_FALSE, errbuf)) == NULL) { 462*5094Slling nvlist_free(nvl); 463*5094Slling return (-1); 464*5094Slling } 465*5094Slling 466*5094Slling nvlist_free(nvl); 467*5094Slling nvl = realprops; 468*5094Slling 469*5094Slling /* 470*5094Slling * Execute the corresponding ioctl() to set this property. 471*5094Slling */ 472*5094Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 473*5094Slling 474*5094Slling if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) { 475*5094Slling nvlist_free(nvl); 476*5094Slling return (-1); 477*5094Slling } 478*5094Slling 479*5094Slling ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc); 480*5094Slling 481*5094Slling zcmd_free_nvlists(&zc); 482*5094Slling nvlist_free(nvl); 483*5094Slling 484*5094Slling if (ret) 485*5094Slling (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); 486*5094Slling else 487*5094Slling (void) zpool_props_refresh(zhp); 488*5094Slling 489*5094Slling return (ret); 490*5094Slling } 491*5094Slling 492*5094Slling int 493*5094Slling zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp) 494*5094Slling { 495*5094Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 496*5094Slling zprop_list_t *entry; 497*5094Slling char buf[ZFS_MAXPROPLEN]; 498*5094Slling 499*5094Slling if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0) 500*5094Slling return (-1); 501*5094Slling 502*5094Slling for (entry = *plp; entry != NULL; entry = entry->pl_next) { 503*5094Slling 504*5094Slling if (entry->pl_fixed) 505*5094Slling continue; 506*5094Slling 507*5094Slling if (entry->pl_prop != ZPROP_INVAL && 508*5094Slling zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), 509*5094Slling NULL) == 0) { 510*5094Slling if (strlen(buf) > entry->pl_width) 511*5094Slling entry->pl_width = strlen(buf); 512*5094Slling } 513*5094Slling } 514*5094Slling 515*5094Slling return (0); 516*5094Slling } 517*5094Slling 518*5094Slling 519789Sahrens /* 520789Sahrens * Validate the given pool name, optionally putting an extended error message in 521789Sahrens * 'buf'. 522789Sahrens */ 5232082Seschrock static boolean_t 5242082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) 525789Sahrens { 526789Sahrens namecheck_err_t why; 527789Sahrens char what; 5281773Seschrock int ret; 529789Sahrens 5301773Seschrock ret = pool_namecheck(pool, &why, &what); 5311773Seschrock 5321773Seschrock /* 5331773Seschrock * The rules for reserved pool names were extended at a later point. 5341773Seschrock * But we need to support users with existing pools that may now be 5351773Seschrock * invalid. So we only check for this expanded set of names during a 5361773Seschrock * create (or import), and only in userland. 5371773Seschrock */ 5381773Seschrock if (ret == 0 && !isopen && 5391773Seschrock (strncmp(pool, "mirror", 6) == 0 || 5401773Seschrock strncmp(pool, "raidz", 5) == 0 || 5414527Sperrin strncmp(pool, "spare", 5) == 0 || 5424527Sperrin strcmp(pool, "log") == 0)) { 5432082Seschrock zfs_error_aux(hdl, 5442082Seschrock dgettext(TEXT_DOMAIN, "name is reserved")); 5452082Seschrock return (B_FALSE); 5461773Seschrock } 5471773Seschrock 5481773Seschrock 5491773Seschrock if (ret != 0) { 5502082Seschrock if (hdl != NULL) { 551789Sahrens switch (why) { 5521003Slling case NAME_ERR_TOOLONG: 5532082Seschrock zfs_error_aux(hdl, 5541003Slling dgettext(TEXT_DOMAIN, "name is too long")); 5551003Slling break; 5561003Slling 557789Sahrens case NAME_ERR_INVALCHAR: 5582082Seschrock zfs_error_aux(hdl, 559789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 560789Sahrens "'%c' in pool name"), what); 561789Sahrens break; 562789Sahrens 563789Sahrens case NAME_ERR_NOLETTER: 5642082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5652082Seschrock "name must begin with a letter")); 566789Sahrens break; 567789Sahrens 568789Sahrens case NAME_ERR_RESERVED: 5692082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5702082Seschrock "name is reserved")); 571789Sahrens break; 572789Sahrens 573789Sahrens case NAME_ERR_DISKLIKE: 5742082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5752082Seschrock "pool name is reserved")); 576789Sahrens break; 5772856Snd150628 5782856Snd150628 case NAME_ERR_LEADING_SLASH: 5792856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5802856Snd150628 "leading slash in name")); 5812856Snd150628 break; 5822856Snd150628 5832856Snd150628 case NAME_ERR_EMPTY_COMPONENT: 5842856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5852856Snd150628 "empty component in name")); 5862856Snd150628 break; 5872856Snd150628 5882856Snd150628 case NAME_ERR_TRAILING_SLASH: 5892856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5902856Snd150628 "trailing slash in name")); 5912856Snd150628 break; 5922856Snd150628 5932856Snd150628 case NAME_ERR_MULTIPLE_AT: 5942856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5952856Snd150628 "multiple '@' delimiters in name")); 5962856Snd150628 break; 5972856Snd150628 598789Sahrens } 599789Sahrens } 6002082Seschrock return (B_FALSE); 601789Sahrens } 602789Sahrens 6032082Seschrock return (B_TRUE); 604789Sahrens } 605789Sahrens 606789Sahrens /* 607789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 608789Sahrens * state. 609789Sahrens */ 610789Sahrens zpool_handle_t * 6112082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 612789Sahrens { 613789Sahrens zpool_handle_t *zhp; 6142142Seschrock boolean_t missing; 615789Sahrens 616789Sahrens /* 617789Sahrens * Make sure the pool name is valid. 618789Sahrens */ 6192082Seschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) { 6203237Slling (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, 6212082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 6222082Seschrock pool); 623789Sahrens return (NULL); 624789Sahrens } 625789Sahrens 6262082Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 6272082Seschrock return (NULL); 628789Sahrens 6292082Seschrock zhp->zpool_hdl = hdl; 630789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 631789Sahrens 6322142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 6332142Seschrock zpool_close(zhp); 6342142Seschrock return (NULL); 6352142Seschrock } 6362142Seschrock 6372142Seschrock if (missing) { 638*5094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool")); 6393237Slling (void) zfs_error_fmt(hdl, EZFS_NOENT, 640*5094Slling dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool); 6412142Seschrock zpool_close(zhp); 6422142Seschrock return (NULL); 643789Sahrens } 644789Sahrens 645789Sahrens return (zhp); 646789Sahrens } 647789Sahrens 648789Sahrens /* 649789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 650789Sahrens * the configuration cache may be out of date). 651789Sahrens */ 6522142Seschrock int 6532142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 654789Sahrens { 655789Sahrens zpool_handle_t *zhp; 6562142Seschrock boolean_t missing; 657789Sahrens 6582142Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 6592142Seschrock return (-1); 660789Sahrens 6612082Seschrock zhp->zpool_hdl = hdl; 662789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 663789Sahrens 6642142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 6652142Seschrock zpool_close(zhp); 6662142Seschrock return (-1); 667789Sahrens } 668789Sahrens 6692142Seschrock if (missing) { 6702142Seschrock zpool_close(zhp); 6712142Seschrock *ret = NULL; 6722142Seschrock return (0); 6732142Seschrock } 6742142Seschrock 6752142Seschrock *ret = zhp; 6762142Seschrock return (0); 677789Sahrens } 678789Sahrens 679789Sahrens /* 680789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 681789Sahrens * state. 682789Sahrens */ 683789Sahrens zpool_handle_t * 6842082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool) 685789Sahrens { 686789Sahrens zpool_handle_t *zhp; 687789Sahrens 6882082Seschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 689789Sahrens return (NULL); 690789Sahrens 691789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 6923237Slling (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, 6932082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 694789Sahrens zpool_close(zhp); 695789Sahrens return (NULL); 696789Sahrens } 697789Sahrens 698789Sahrens return (zhp); 699789Sahrens } 700789Sahrens 701789Sahrens /* 702789Sahrens * Close the handle. Simply frees the memory associated with the handle. 703789Sahrens */ 704789Sahrens void 705789Sahrens zpool_close(zpool_handle_t *zhp) 706789Sahrens { 707789Sahrens if (zhp->zpool_config) 708789Sahrens nvlist_free(zhp->zpool_config); 709952Seschrock if (zhp->zpool_old_config) 710952Seschrock nvlist_free(zhp->zpool_old_config); 7113912Slling if (zhp->zpool_props) 7123912Slling nvlist_free(zhp->zpool_props); 713789Sahrens free(zhp); 714789Sahrens } 715789Sahrens 716789Sahrens /* 717789Sahrens * Return the name of the pool. 718789Sahrens */ 719789Sahrens const char * 720789Sahrens zpool_get_name(zpool_handle_t *zhp) 721789Sahrens { 722789Sahrens return (zhp->zpool_name); 723789Sahrens } 724789Sahrens 725789Sahrens 726789Sahrens /* 727789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 728789Sahrens */ 729789Sahrens int 730789Sahrens zpool_get_state(zpool_handle_t *zhp) 731789Sahrens { 732789Sahrens return (zhp->zpool_state); 733789Sahrens } 734789Sahrens 735789Sahrens /* 736789Sahrens * Create the named pool, using the provided vdev list. It is assumed 737789Sahrens * that the consumer has already validated the contents of the nvlist, so we 738789Sahrens * don't have to worry about error semantics. 739789Sahrens */ 740789Sahrens int 7412082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 742*5094Slling nvlist_t *props) 743789Sahrens { 744789Sahrens zfs_cmd_t zc = { 0 }; 7452082Seschrock char msg[1024]; 746*5094Slling char *altroot; 7472082Seschrock 7482082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 7492082Seschrock "cannot create '%s'"), pool); 750789Sahrens 7512082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 7522082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 7532082Seschrock 754*5094Slling if (props && (props = zpool_validate_properties(hdl, pool, props, 755*5094Slling SPA_VERSION_1, B_TRUE, msg)) == NULL) 756*5094Slling return (-1); 757*5094Slling 758*5094Slling if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 759*5094Slling return (-1); 760*5094Slling 761*5094Slling if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0) 762789Sahrens return (-1); 763789Sahrens 764789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 765789Sahrens 7664543Smarks if (zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc) != 0) { 7672676Seschrock zcmd_free_nvlists(&zc); 7682082Seschrock 769789Sahrens switch (errno) { 770789Sahrens case EBUSY: 771789Sahrens /* 772789Sahrens * This can happen if the user has specified the same 773789Sahrens * device multiple times. We can't reliably detect this 774789Sahrens * until we try to add it and see we already have a 775789Sahrens * label. 776789Sahrens */ 7772082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7782082Seschrock "one or more vdevs refer to the same device")); 7792082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 780789Sahrens 781789Sahrens case EOVERFLOW: 782789Sahrens /* 7832082Seschrock * This occurs when one of the devices is below 784789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 785789Sahrens * device was the problem device since there's no 786789Sahrens * reliable way to determine device size from userland. 787789Sahrens */ 788789Sahrens { 789789Sahrens char buf[64]; 790789Sahrens 791789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 792789Sahrens 7932082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7942082Seschrock "one or more devices is less than the " 7952082Seschrock "minimum size (%s)"), buf); 796789Sahrens } 7972082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 798789Sahrens 799789Sahrens case ENOSPC: 8002082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8012082Seschrock "one or more devices is out of space")); 8022082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 803789Sahrens 804789Sahrens default: 8052082Seschrock return (zpool_standard_error(hdl, errno, msg)); 806789Sahrens } 807789Sahrens } 8082676Seschrock zcmd_free_nvlists(&zc); 809789Sahrens 810789Sahrens /* 811789Sahrens * If this is an alternate root pool, then we automatically set the 8122676Seschrock * mountpoint of the root dataset to be '/'. 813789Sahrens */ 814*5094Slling if (nvlist_lookup_string(props, zpool_prop_to_name(ZPOOL_PROP_ALTROOT), 815*5094Slling &altroot) == 0) { 816789Sahrens zfs_handle_t *zhp; 817789Sahrens 818*5094Slling verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_DATASET)) != NULL); 8192676Seschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 8202676Seschrock "/") == 0); 821789Sahrens 822789Sahrens zfs_close(zhp); 823789Sahrens } 824789Sahrens 825789Sahrens return (0); 826789Sahrens } 827789Sahrens 828789Sahrens /* 829789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 830789Sahrens * datasets left in the pool. 831789Sahrens */ 832789Sahrens int 833789Sahrens zpool_destroy(zpool_handle_t *zhp) 834789Sahrens { 835789Sahrens zfs_cmd_t zc = { 0 }; 836789Sahrens zfs_handle_t *zfp = NULL; 8372082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 8382082Seschrock char msg[1024]; 839789Sahrens 840789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 8412082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 8422082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 843789Sahrens return (-1); 844789Sahrens 8452856Snd150628 if (zpool_remove_zvol_links(zhp) != 0) 846789Sahrens return (-1); 847789Sahrens 848789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 849789Sahrens 8504543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 8512082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 8522082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 853789Sahrens 8542082Seschrock if (errno == EROFS) { 8552082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8562082Seschrock "one or more devices is read only")); 8572082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 8582082Seschrock } else { 8592082Seschrock (void) zpool_standard_error(hdl, errno, msg); 860789Sahrens } 861789Sahrens 862789Sahrens if (zfp) 863789Sahrens zfs_close(zfp); 864789Sahrens return (-1); 865789Sahrens } 866789Sahrens 867789Sahrens if (zfp) { 868789Sahrens remove_mountpoint(zfp); 869789Sahrens zfs_close(zfp); 870789Sahrens } 871789Sahrens 872789Sahrens return (0); 873789Sahrens } 874789Sahrens 875789Sahrens /* 876789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 877789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 878789Sahrens */ 879789Sahrens int 880789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 881789Sahrens { 8822676Seschrock zfs_cmd_t zc = { 0 }; 8832082Seschrock int ret; 8842082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 8852082Seschrock char msg[1024]; 8862082Seschrock nvlist_t **spares; 8872082Seschrock uint_t nspares; 8882082Seschrock 8892082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 8902082Seschrock "cannot add to '%s'"), zhp->zpool_name); 8912082Seschrock 892*5094Slling if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) 893*5094Slling < SPA_VERSION_SPARES && 8942082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 8952082Seschrock &spares, &nspares) == 0) { 8962082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 8972082Seschrock "upgraded to add hot spares")); 8982082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 8992082Seschrock } 900789Sahrens 901*5094Slling if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 9022082Seschrock return (-1); 903789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 904789Sahrens 9054543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) { 906789Sahrens switch (errno) { 907789Sahrens case EBUSY: 908789Sahrens /* 909789Sahrens * This can happen if the user has specified the same 910789Sahrens * device multiple times. We can't reliably detect this 911789Sahrens * until we try to add it and see we already have a 912789Sahrens * label. 913789Sahrens */ 9142082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9152082Seschrock "one or more vdevs refer to the same device")); 9162082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 917789Sahrens break; 918789Sahrens 919789Sahrens case EOVERFLOW: 920789Sahrens /* 921789Sahrens * This occurrs when one of the devices is below 922789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 923789Sahrens * device was the problem device since there's no 924789Sahrens * reliable way to determine device size from userland. 925789Sahrens */ 926789Sahrens { 927789Sahrens char buf[64]; 928789Sahrens 929789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 930789Sahrens 9312082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9322082Seschrock "device is less than the minimum " 9332082Seschrock "size (%s)"), buf); 934789Sahrens } 9352082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 9362082Seschrock break; 9372082Seschrock 9382082Seschrock case ENOTSUP: 9392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9404527Sperrin "pool must be upgraded to add these vdevs")); 9412082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 942789Sahrens break; 943789Sahrens 9443912Slling case EDOM: 9453912Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9464527Sperrin "root pool can not have multiple vdevs" 9474527Sperrin " or separate logs")); 9483912Slling (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg); 9493912Slling break; 9503912Slling 951789Sahrens default: 9522082Seschrock (void) zpool_standard_error(hdl, errno, msg); 953789Sahrens } 954789Sahrens 9552082Seschrock ret = -1; 9562082Seschrock } else { 9572082Seschrock ret = 0; 958789Sahrens } 959789Sahrens 9602676Seschrock zcmd_free_nvlists(&zc); 961789Sahrens 9622082Seschrock return (ret); 963789Sahrens } 964789Sahrens 965789Sahrens /* 966789Sahrens * Exports the pool from the system. The caller must ensure that there are no 967789Sahrens * mounted datasets in the pool. 968789Sahrens */ 969789Sahrens int 970789Sahrens zpool_export(zpool_handle_t *zhp) 971789Sahrens { 972789Sahrens zfs_cmd_t zc = { 0 }; 973789Sahrens 974789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 975789Sahrens return (-1); 976789Sahrens 977789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 978789Sahrens 9794543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) 9803237Slling return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 9812082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 9822082Seschrock zhp->zpool_name)); 983789Sahrens return (0); 984789Sahrens } 985789Sahrens 986789Sahrens /* 987*5094Slling * zpool_import() is a contracted interface. Should be kept the same 988*5094Slling * if possible. 989*5094Slling * 990*5094Slling * Applications should use zpool_import_props() to import a pool with 991*5094Slling * new properties value to be set. 992789Sahrens */ 993789Sahrens int 9942082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 995*5094Slling char *altroot) 996*5094Slling { 997*5094Slling nvlist_t *props = NULL; 998*5094Slling int ret; 999*5094Slling 1000*5094Slling if (altroot != NULL) { 1001*5094Slling if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 1002*5094Slling return (zfs_error_fmt(hdl, EZFS_NOMEM, 1003*5094Slling dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1004*5094Slling newname)); 1005*5094Slling } 1006*5094Slling 1007*5094Slling if (nvlist_add_string(props, 1008*5094Slling zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0) { 1009*5094Slling nvlist_free(props); 1010*5094Slling return (zfs_error_fmt(hdl, EZFS_NOMEM, 1011*5094Slling dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1012*5094Slling newname)); 1013*5094Slling } 1014*5094Slling } 1015*5094Slling 1016*5094Slling ret = zpool_import_props(hdl, config, newname, props); 1017*5094Slling if (props) 1018*5094Slling nvlist_free(props); 1019*5094Slling return (ret); 1020*5094Slling } 1021*5094Slling 1022*5094Slling /* 1023*5094Slling * Import the given pool using the known configuration and a list of 1024*5094Slling * properties to be set. The configuration should have come from 1025*5094Slling * zpool_find_import(). The 'newname' parameters control whether the pool 1026*5094Slling * is imported with a different name. 1027*5094Slling */ 1028*5094Slling int 1029*5094Slling zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 1030*5094Slling nvlist_t *props) 1031789Sahrens { 10322676Seschrock zfs_cmd_t zc = { 0 }; 1033789Sahrens char *thename; 1034789Sahrens char *origname; 1035789Sahrens int ret; 1036*5094Slling char errbuf[1024]; 1037789Sahrens 1038789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1039789Sahrens &origname) == 0); 1040789Sahrens 1041*5094Slling (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 1042*5094Slling "cannot import pool '%s'"), origname); 1043*5094Slling 1044789Sahrens if (newname != NULL) { 10452082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 10463237Slling return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 10472082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 10482082Seschrock newname)); 1049789Sahrens thename = (char *)newname; 1050789Sahrens } else { 1051789Sahrens thename = origname; 1052789Sahrens } 1053789Sahrens 1054*5094Slling if (props) { 1055*5094Slling uint64_t version; 1056*5094Slling 1057*5094Slling verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 1058*5094Slling &version) == 0); 1059*5094Slling 1060*5094Slling if ((props = zpool_validate_properties(hdl, origname, 1061*5094Slling props, version, B_TRUE, errbuf)) == NULL) 1062*5094Slling return (-1); 1063*5094Slling else if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) 1064*5094Slling return (-1); 1065*5094Slling } 1066789Sahrens 1067789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 1068789Sahrens 1069789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 10701544Seschrock &zc.zc_guid) == 0); 1071789Sahrens 1072*5094Slling if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) 10732082Seschrock return (-1); 1074789Sahrens 1075789Sahrens ret = 0; 10764543Smarks if (zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 1077789Sahrens char desc[1024]; 1078789Sahrens if (newname == NULL) 1079789Sahrens (void) snprintf(desc, sizeof (desc), 1080789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1081789Sahrens thename); 1082789Sahrens else 1083789Sahrens (void) snprintf(desc, sizeof (desc), 1084789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 1085789Sahrens origname, thename); 1086789Sahrens 1087789Sahrens switch (errno) { 10881544Seschrock case ENOTSUP: 10891544Seschrock /* 10901544Seschrock * Unsupported version. 10911544Seschrock */ 10922082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 10931544Seschrock break; 10941544Seschrock 10952174Seschrock case EINVAL: 10962174Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 10972174Seschrock break; 10982174Seschrock 1099789Sahrens default: 11002082Seschrock (void) zpool_standard_error(hdl, errno, desc); 1101789Sahrens } 1102789Sahrens 1103789Sahrens ret = -1; 1104789Sahrens } else { 1105789Sahrens zpool_handle_t *zhp; 11064543Smarks 1107789Sahrens /* 1108789Sahrens * This should never fail, but play it safe anyway. 1109789Sahrens */ 11102142Seschrock if (zpool_open_silent(hdl, thename, &zhp) != 0) { 11112142Seschrock ret = -1; 11122142Seschrock } else if (zhp != NULL) { 1113789Sahrens ret = zpool_create_zvol_links(zhp); 1114789Sahrens zpool_close(zhp); 1115789Sahrens } 11164543Smarks 1117789Sahrens } 1118789Sahrens 11194543Smarks 11202676Seschrock zcmd_free_nvlists(&zc); 1121789Sahrens return (ret); 1122789Sahrens } 1123789Sahrens 1124789Sahrens /* 1125789Sahrens * Scrub the pool. 1126789Sahrens */ 1127789Sahrens int 1128789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 1129789Sahrens { 1130789Sahrens zfs_cmd_t zc = { 0 }; 1131789Sahrens char msg[1024]; 11322082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1133789Sahrens 1134789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1135789Sahrens zc.zc_cookie = type; 1136789Sahrens 11374543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SCRUB, &zc) == 0) 1138789Sahrens return (0); 1139789Sahrens 1140789Sahrens (void) snprintf(msg, sizeof (msg), 1141789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 1142789Sahrens 11432082Seschrock if (errno == EBUSY) 11442082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 11452082Seschrock else 11462082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1147789Sahrens } 1148789Sahrens 11492468Sek110237 /* 11502468Sek110237 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 11512468Sek110237 * spare; but FALSE if its an INUSE spare. 11522468Sek110237 */ 11532082Seschrock static nvlist_t * 11542082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 11552468Sek110237 boolean_t *avail_spare) 11561544Seschrock { 11571544Seschrock uint_t c, children; 11581544Seschrock nvlist_t **child; 11592082Seschrock uint64_t theguid, present; 11601544Seschrock char *path; 11611544Seschrock uint64_t wholedisk = 0; 11622082Seschrock nvlist_t *ret; 11631544Seschrock 11642082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 11651544Seschrock 11661544Seschrock if (search == NULL && 11671544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 11681544Seschrock /* 11691544Seschrock * If the device has never been present since import, the only 11701544Seschrock * reliable way to match the vdev is by GUID. 11711544Seschrock */ 11722082Seschrock if (theguid == guid) 11732082Seschrock return (nv); 11741544Seschrock } else if (search != NULL && 11751544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 11761544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 11771544Seschrock &wholedisk); 11781544Seschrock if (wholedisk) { 11791544Seschrock /* 11801544Seschrock * For whole disks, the internal path has 's0', but the 11811544Seschrock * path passed in by the user doesn't. 11821544Seschrock */ 11831544Seschrock if (strlen(search) == strlen(path) - 2 && 11841544Seschrock strncmp(search, path, strlen(search)) == 0) 11852082Seschrock return (nv); 11861544Seschrock } else if (strcmp(search, path) == 0) { 11872082Seschrock return (nv); 11881544Seschrock } 11891544Seschrock } 11901544Seschrock 11911544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 11921544Seschrock &child, &children) != 0) 11932082Seschrock return (NULL); 11941544Seschrock 11951544Seschrock for (c = 0; c < children; c++) 11962082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 11972468Sek110237 avail_spare)) != NULL) 11981544Seschrock return (ret); 11991544Seschrock 12002082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 12012082Seschrock &child, &children) == 0) { 12022082Seschrock for (c = 0; c < children; c++) { 12032082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 12042468Sek110237 avail_spare)) != NULL) { 12052468Sek110237 *avail_spare = B_TRUE; 12062082Seschrock return (ret); 12072082Seschrock } 12082082Seschrock } 12092082Seschrock } 12102082Seschrock 12112082Seschrock return (NULL); 12121544Seschrock } 12131544Seschrock 12142082Seschrock nvlist_t * 12152468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare) 12161544Seschrock { 12171544Seschrock char buf[MAXPATHLEN]; 12181544Seschrock const char *search; 12191544Seschrock char *end; 12201544Seschrock nvlist_t *nvroot; 12211544Seschrock uint64_t guid; 12221544Seschrock 12231613Seschrock guid = strtoull(path, &end, 10); 12241544Seschrock if (guid != 0 && *end == '\0') { 12251544Seschrock search = NULL; 12261544Seschrock } else if (path[0] != '/') { 12271544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 12281544Seschrock search = buf; 12291544Seschrock } else { 12301544Seschrock search = path; 12311544Seschrock } 12321544Seschrock 12331544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 12341544Seschrock &nvroot) == 0); 12351544Seschrock 12362468Sek110237 *avail_spare = B_FALSE; 12372468Sek110237 return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare)); 12382468Sek110237 } 12392468Sek110237 12402468Sek110237 /* 12412468Sek110237 * Returns TRUE if the given guid corresponds to a spare (INUSE or not). 12422468Sek110237 */ 12432468Sek110237 static boolean_t 12442468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid) 12452468Sek110237 { 12462468Sek110237 uint64_t spare_guid; 12472468Sek110237 nvlist_t *nvroot; 12482468Sek110237 nvlist_t **spares; 12492468Sek110237 uint_t nspares; 12502468Sek110237 int i; 12512468Sek110237 12522468Sek110237 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 12532468Sek110237 &nvroot) == 0); 12542468Sek110237 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 12552468Sek110237 &spares, &nspares) == 0) { 12562468Sek110237 for (i = 0; i < nspares; i++) { 12572468Sek110237 verify(nvlist_lookup_uint64(spares[i], 12582468Sek110237 ZPOOL_CONFIG_GUID, &spare_guid) == 0); 12592468Sek110237 if (guid == spare_guid) 12602468Sek110237 return (B_TRUE); 12612468Sek110237 } 12622468Sek110237 } 12632468Sek110237 12642468Sek110237 return (B_FALSE); 12651544Seschrock } 12661544Seschrock 1267789Sahrens /* 12684451Seschrock * Bring the specified vdev online. The 'flags' parameter is a set of the 12694451Seschrock * ZFS_ONLINE_* flags. 1270789Sahrens */ 1271789Sahrens int 12724451Seschrock zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags, 12734451Seschrock vdev_state_t *newstate) 1274789Sahrens { 1275789Sahrens zfs_cmd_t zc = { 0 }; 1276789Sahrens char msg[1024]; 12772082Seschrock nvlist_t *tgt; 12782468Sek110237 boolean_t avail_spare; 12792082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1280789Sahrens 12811544Seschrock (void) snprintf(msg, sizeof (msg), 12821544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 1283789Sahrens 12841544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 12852468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 12862082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1287789Sahrens 12882468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 12892468Sek110237 12902468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 12912082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 12922082Seschrock 12934451Seschrock zc.zc_cookie = VDEV_STATE_ONLINE; 12944451Seschrock zc.zc_obj = flags; 12954451Seschrock 1296789Sahrens 12974543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) 12984451Seschrock return (zpool_standard_error(hdl, errno, msg)); 12994451Seschrock 13004451Seschrock *newstate = zc.zc_cookie; 13014451Seschrock return (0); 1302789Sahrens } 1303789Sahrens 1304789Sahrens /* 1305789Sahrens * Take the specified vdev offline 1306789Sahrens */ 1307789Sahrens int 13084451Seschrock zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp) 1309789Sahrens { 1310789Sahrens zfs_cmd_t zc = { 0 }; 1311789Sahrens char msg[1024]; 13122082Seschrock nvlist_t *tgt; 13132468Sek110237 boolean_t avail_spare; 13142082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1315789Sahrens 13161544Seschrock (void) snprintf(msg, sizeof (msg), 13171544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 13181544Seschrock 1319789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 13202468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL) 13212082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 13222082Seschrock 13232468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 13242468Sek110237 13252468Sek110237 if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE) 13262082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 13272082Seschrock 13284451Seschrock zc.zc_cookie = VDEV_STATE_OFFLINE; 13294451Seschrock zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0; 13301485Slling 13314543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 1332789Sahrens return (0); 1333789Sahrens 1334789Sahrens switch (errno) { 13352082Seschrock case EBUSY: 1336789Sahrens 1337789Sahrens /* 1338789Sahrens * There are no other replicas of this device. 1339789Sahrens */ 13402082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 13412082Seschrock 13422082Seschrock default: 13432082Seschrock return (zpool_standard_error(hdl, errno, msg)); 13442082Seschrock } 13452082Seschrock } 1346789Sahrens 13472082Seschrock /* 13484451Seschrock * Mark the given vdev faulted. 13494451Seschrock */ 13504451Seschrock int 13514451Seschrock zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid) 13524451Seschrock { 13534451Seschrock zfs_cmd_t zc = { 0 }; 13544451Seschrock char msg[1024]; 13554451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 13564451Seschrock 13574451Seschrock (void) snprintf(msg, sizeof (msg), 13584451Seschrock dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid); 13594451Seschrock 13604451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 13614451Seschrock zc.zc_guid = guid; 13624451Seschrock zc.zc_cookie = VDEV_STATE_FAULTED; 13634451Seschrock 13644451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 13654451Seschrock return (0); 13664451Seschrock 13674451Seschrock switch (errno) { 13684451Seschrock case EBUSY: 13694451Seschrock 13704451Seschrock /* 13714451Seschrock * There are no other replicas of this device. 13724451Seschrock */ 13734451Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 13744451Seschrock 13754451Seschrock default: 13764451Seschrock return (zpool_standard_error(hdl, errno, msg)); 13774451Seschrock } 13784451Seschrock 13794451Seschrock } 13804451Seschrock 13814451Seschrock /* 13824451Seschrock * Mark the given vdev degraded. 13834451Seschrock */ 13844451Seschrock int 13854451Seschrock zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid) 13864451Seschrock { 13874451Seschrock zfs_cmd_t zc = { 0 }; 13884451Seschrock char msg[1024]; 13894451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 13904451Seschrock 13914451Seschrock (void) snprintf(msg, sizeof (msg), 13924451Seschrock dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid); 13934451Seschrock 13944451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 13954451Seschrock zc.zc_guid = guid; 13964451Seschrock zc.zc_cookie = VDEV_STATE_DEGRADED; 13974451Seschrock 13984451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 13994451Seschrock return (0); 14004451Seschrock 14014451Seschrock return (zpool_standard_error(hdl, errno, msg)); 14024451Seschrock } 14034451Seschrock 14044451Seschrock /* 14052082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 14062082Seschrock * a hot spare. 14072082Seschrock */ 14082082Seschrock static boolean_t 14092082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 14102082Seschrock { 14112082Seschrock nvlist_t **child; 14122082Seschrock uint_t c, children; 14132082Seschrock char *type; 14142082Seschrock 14152082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 14162082Seschrock &children) == 0) { 14172082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 14182082Seschrock &type) == 0); 14192082Seschrock 14202082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 14212082Seschrock children == 2 && child[which] == tgt) 14222082Seschrock return (B_TRUE); 14232082Seschrock 14242082Seschrock for (c = 0; c < children; c++) 14252082Seschrock if (is_replacing_spare(child[c], tgt, which)) 14262082Seschrock return (B_TRUE); 1427789Sahrens } 14282082Seschrock 14292082Seschrock return (B_FALSE); 1430789Sahrens } 1431789Sahrens 1432789Sahrens /* 1433789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 14344527Sperrin * If 'replacing' is specified, the new disk will replace the old one. 1435789Sahrens */ 1436789Sahrens int 1437789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 1438789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 1439789Sahrens { 1440789Sahrens zfs_cmd_t zc = { 0 }; 1441789Sahrens char msg[1024]; 1442789Sahrens int ret; 14432082Seschrock nvlist_t *tgt; 14442468Sek110237 boolean_t avail_spare; 14454527Sperrin uint64_t val, is_log; 14462082Seschrock char *path; 14472082Seschrock nvlist_t **child; 14482082Seschrock uint_t children; 14492082Seschrock nvlist_t *config_root; 14502082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1451789Sahrens 14521544Seschrock if (replacing) 14531544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 14541544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 14551544Seschrock else 14561544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 14571544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 14581544Seschrock 1459789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 14602468Sek110237 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0) 14612082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 14622082Seschrock 14632468Sek110237 if (avail_spare) 14642082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 14652082Seschrock 14662082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 14672082Seschrock zc.zc_cookie = replacing; 14682082Seschrock 14692082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 14702082Seschrock &child, &children) != 0 || children != 1) { 14712082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 14722082Seschrock "new device must be a single disk")); 14732082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 14741544Seschrock } 14752082Seschrock 14762082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 14772082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 14782082Seschrock 14792082Seschrock /* 14802082Seschrock * If the target is a hot spare that has been swapped in, we can only 14812082Seschrock * replace it with another hot spare. 14822082Seschrock */ 14832082Seschrock if (replacing && 14842082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 14852082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 14862468Sek110237 (zpool_find_vdev(zhp, path, &avail_spare) == NULL || 14872468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 14882082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 14892082Seschrock "can only be replaced by another hot spare")); 14902082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 14912082Seschrock } 14922082Seschrock 14932082Seschrock /* 14942082Seschrock * If we are attempting to replace a spare, it canot be applied to an 14952082Seschrock * already spared device. 14962082Seschrock */ 14972082Seschrock if (replacing && 14982082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 14992468Sek110237 zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare && 15002082Seschrock is_replacing_spare(config_root, tgt, 0)) { 15012082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 15022082Seschrock "device has already been replaced with a spare")); 15032082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 15042082Seschrock } 1505789Sahrens 1506*5094Slling if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 15072082Seschrock return (-1); 1508789Sahrens 15094543Smarks ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ATTACH, &zc); 1510789Sahrens 15112676Seschrock zcmd_free_nvlists(&zc); 1512789Sahrens 1513789Sahrens if (ret == 0) 1514789Sahrens return (0); 1515789Sahrens 1516789Sahrens switch (errno) { 15171544Seschrock case ENOTSUP: 1518789Sahrens /* 1519789Sahrens * Can't attach to or replace this type of vdev. 1520789Sahrens */ 15214527Sperrin if (replacing) { 15224527Sperrin is_log = B_FALSE; 15234527Sperrin (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_LOG, 15244527Sperrin &is_log); 15254527Sperrin if (is_log) 15264527Sperrin zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 15274527Sperrin "cannot replace a log with a spare")); 15284527Sperrin else 15294527Sperrin zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 15304527Sperrin "cannot replace a replacing device")); 15314527Sperrin } else { 15322082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 15332082Seschrock "can only attach to mirrors and top-level " 15342082Seschrock "disks")); 15354527Sperrin } 15362082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1537789Sahrens break; 1538789Sahrens 15391544Seschrock case EINVAL: 1540789Sahrens /* 1541789Sahrens * The new device must be a single disk. 1542789Sahrens */ 15432082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 15442082Seschrock "new device must be a single disk")); 15452082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1546789Sahrens break; 1547789Sahrens 15481544Seschrock case EBUSY: 15492082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 15502082Seschrock new_disk); 15512082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1552789Sahrens break; 1553789Sahrens 15541544Seschrock case EOVERFLOW: 1555789Sahrens /* 1556789Sahrens * The new device is too small. 1557789Sahrens */ 15582082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 15592082Seschrock "device is too small")); 15602082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1561789Sahrens break; 1562789Sahrens 15631544Seschrock case EDOM: 1564789Sahrens /* 1565789Sahrens * The new device has a different alignment requirement. 1566789Sahrens */ 15672082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 15682082Seschrock "devices have different sector alignment")); 15692082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1570789Sahrens break; 1571789Sahrens 15721544Seschrock case ENAMETOOLONG: 1573789Sahrens /* 1574789Sahrens * The resulting top-level vdev spec won't fit in the label. 1575789Sahrens */ 15762082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1577789Sahrens break; 1578789Sahrens 15791544Seschrock default: 15802082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1581789Sahrens } 1582789Sahrens 15832082Seschrock return (-1); 1584789Sahrens } 1585789Sahrens 1586789Sahrens /* 1587789Sahrens * Detach the specified device. 1588789Sahrens */ 1589789Sahrens int 1590789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1591789Sahrens { 1592789Sahrens zfs_cmd_t zc = { 0 }; 1593789Sahrens char msg[1024]; 15942082Seschrock nvlist_t *tgt; 15952468Sek110237 boolean_t avail_spare; 15962082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1597789Sahrens 15981544Seschrock (void) snprintf(msg, sizeof (msg), 15991544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 16001544Seschrock 1601789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 16022468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 16032082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1604789Sahrens 16052468Sek110237 if (avail_spare) 16062082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 16072082Seschrock 16082082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 16092082Seschrock 16104543Smarks if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1611789Sahrens return (0); 1612789Sahrens 1613789Sahrens switch (errno) { 1614789Sahrens 16151544Seschrock case ENOTSUP: 1616789Sahrens /* 1617789Sahrens * Can't detach from this type of vdev. 1618789Sahrens */ 16192082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 16202082Seschrock "applicable to mirror and replacing vdevs")); 16212082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1622789Sahrens break; 1623789Sahrens 16241544Seschrock case EBUSY: 1625789Sahrens /* 1626789Sahrens * There are no other replicas of this device. 1627789Sahrens */ 16282082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1629789Sahrens break; 1630789Sahrens 16311544Seschrock default: 16322082Seschrock (void) zpool_standard_error(hdl, errno, msg); 16331544Seschrock } 16341544Seschrock 16352082Seschrock return (-1); 16362082Seschrock } 16372082Seschrock 16382082Seschrock /* 16392082Seschrock * Remove the given device. Currently, this is supported only for hot spares. 16402082Seschrock */ 16412082Seschrock int 16422082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 16432082Seschrock { 16442082Seschrock zfs_cmd_t zc = { 0 }; 16452082Seschrock char msg[1024]; 16462082Seschrock nvlist_t *tgt; 16472468Sek110237 boolean_t avail_spare; 16482082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 16492082Seschrock 16502082Seschrock (void) snprintf(msg, sizeof (msg), 16512082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 16522082Seschrock 16532082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 16542468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 16552082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 16562082Seschrock 16572468Sek110237 if (!avail_spare) { 16582082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 16593377Seschrock "only inactive hot spares can be removed")); 16602082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 16612082Seschrock } 16622082Seschrock 16632082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 16642082Seschrock 16654543Smarks if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 16662082Seschrock return (0); 16672082Seschrock 16682082Seschrock return (zpool_standard_error(hdl, errno, msg)); 16691544Seschrock } 16701544Seschrock 16711544Seschrock /* 16721544Seschrock * Clear the errors for the pool, or the particular device if specified. 16731544Seschrock */ 16741544Seschrock int 16751544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 16761544Seschrock { 16771544Seschrock zfs_cmd_t zc = { 0 }; 16781544Seschrock char msg[1024]; 16792082Seschrock nvlist_t *tgt; 16802468Sek110237 boolean_t avail_spare; 16812082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 16821544Seschrock 16831544Seschrock if (path) 16841544Seschrock (void) snprintf(msg, sizeof (msg), 16851544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 16862676Seschrock path); 16871544Seschrock else 16881544Seschrock (void) snprintf(msg, sizeof (msg), 16891544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 16901544Seschrock zhp->zpool_name); 16911544Seschrock 16921544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 16932082Seschrock if (path) { 16942468Sek110237 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0) 16952082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 16962082Seschrock 16972468Sek110237 if (avail_spare) 16982082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 16992082Seschrock 17002082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 17012082Seschrock &zc.zc_guid) == 0); 17021544Seschrock } 17031544Seschrock 17044543Smarks if (zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc) == 0) 17051544Seschrock return (0); 17061544Seschrock 17072082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1708789Sahrens } 1709789Sahrens 17103126Sahl /* 17114451Seschrock * Similar to zpool_clear(), but takes a GUID (used by fmd). 17124451Seschrock */ 17134451Seschrock int 17144451Seschrock zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid) 17154451Seschrock { 17164451Seschrock zfs_cmd_t zc = { 0 }; 17174451Seschrock char msg[1024]; 17184451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 17194451Seschrock 17204451Seschrock (void) snprintf(msg, sizeof (msg), 17214451Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"), 17224451Seschrock guid); 17234451Seschrock 17244451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 17254451Seschrock zc.zc_guid = guid; 17264451Seschrock 17274451Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 17284451Seschrock return (0); 17294451Seschrock 17304451Seschrock return (zpool_standard_error(hdl, errno, msg)); 17314451Seschrock } 17324451Seschrock 17334451Seschrock /* 17343126Sahl * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> 17353126Sahl * hierarchy. 17363126Sahl */ 17373126Sahl int 17383126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *), 17393126Sahl void *data) 1740789Sahrens { 17413126Sahl libzfs_handle_t *hdl = zhp->zpool_hdl; 17423126Sahl char (*paths)[MAXPATHLEN]; 17433126Sahl size_t size = 4; 17443126Sahl int curr, fd, base, ret = 0; 17453126Sahl DIR *dirp; 17463126Sahl struct dirent *dp; 17473126Sahl struct stat st; 17483126Sahl 17493126Sahl if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0) 17503126Sahl return (errno == ENOENT ? 0 : -1); 17513126Sahl 17523126Sahl if (fstatat(base, zhp->zpool_name, &st, 0) != 0) { 17533126Sahl int err = errno; 17543126Sahl (void) close(base); 17553126Sahl return (err == ENOENT ? 0 : -1); 17563126Sahl } 1757789Sahrens 1758789Sahrens /* 17593126Sahl * Oddly this wasn't a directory -- ignore that failure since we 17603126Sahl * know there are no links lower in the (non-existant) hierarchy. 1761789Sahrens */ 17623126Sahl if (!S_ISDIR(st.st_mode)) { 17633126Sahl (void) close(base); 17643126Sahl return (0); 17653126Sahl } 17663126Sahl 17673126Sahl if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) { 17683126Sahl (void) close(base); 17693126Sahl return (-1); 1770789Sahrens } 1771789Sahrens 17723126Sahl (void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0])); 17733126Sahl curr = 0; 17743126Sahl 17753126Sahl while (curr >= 0) { 17763126Sahl if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0) 17773126Sahl goto err; 17783126Sahl 17793126Sahl if (S_ISDIR(st.st_mode)) { 17803126Sahl if ((fd = openat(base, paths[curr], O_RDONLY)) < 0) 17813126Sahl goto err; 17823126Sahl 17833126Sahl if ((dirp = fdopendir(fd)) == NULL) { 17843126Sahl (void) close(fd); 17853126Sahl goto err; 17863126Sahl } 17873126Sahl 17883126Sahl while ((dp = readdir(dirp)) != NULL) { 17893126Sahl if (dp->d_name[0] == '.') 17903126Sahl continue; 17913126Sahl 17923126Sahl if (curr + 1 == size) { 17933126Sahl paths = zfs_realloc(hdl, paths, 17943126Sahl size * sizeof (paths[0]), 17953126Sahl size * 2 * sizeof (paths[0])); 17963126Sahl if (paths == NULL) { 17973126Sahl (void) closedir(dirp); 17983126Sahl (void) close(fd); 17993126Sahl goto err; 18003126Sahl } 18013126Sahl 18023126Sahl size *= 2; 18033126Sahl } 18043126Sahl 18053126Sahl (void) strlcpy(paths[curr + 1], paths[curr], 18063126Sahl sizeof (paths[curr + 1])); 18073126Sahl (void) strlcat(paths[curr], "/", 18083126Sahl sizeof (paths[curr])); 18093126Sahl (void) strlcat(paths[curr], dp->d_name, 18103126Sahl sizeof (paths[curr])); 18113126Sahl curr++; 18123126Sahl } 18133126Sahl 18143126Sahl (void) closedir(dirp); 18153126Sahl 18163126Sahl } else { 18173126Sahl if ((ret = cb(paths[curr], data)) != 0) 18183126Sahl break; 18193126Sahl } 18203126Sahl 18213126Sahl curr--; 18223126Sahl } 18233126Sahl 18243126Sahl free(paths); 18253126Sahl (void) close(base); 18263126Sahl 18273126Sahl return (ret); 18283126Sahl 18293126Sahl err: 18303126Sahl free(paths); 18313126Sahl (void) close(base); 18323126Sahl return (-1); 18333126Sahl } 18343126Sahl 18353126Sahl typedef struct zvol_cb { 18363126Sahl zpool_handle_t *zcb_pool; 18373126Sahl boolean_t zcb_create; 18383126Sahl } zvol_cb_t; 18393126Sahl 18403126Sahl /*ARGSUSED*/ 18413126Sahl static int 18423126Sahl do_zvol_create(zfs_handle_t *zhp, void *data) 18433126Sahl { 18444657Sahrens int ret = 0; 18453126Sahl 18464657Sahrens if (ZFS_IS_VOLUME(zhp)) { 18473126Sahl (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 18484657Sahrens ret = zfs_iter_snapshots(zhp, do_zvol_create, NULL); 18494657Sahrens } 18503126Sahl 18514657Sahrens if (ret == 0) 18524657Sahrens ret = zfs_iter_filesystems(zhp, do_zvol_create, NULL); 1853789Sahrens 1854789Sahrens zfs_close(zhp); 18553126Sahl 1856789Sahrens return (ret); 1857789Sahrens } 1858789Sahrens 1859789Sahrens /* 1860789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1861789Sahrens */ 1862789Sahrens int 1863789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1864789Sahrens { 1865789Sahrens zfs_handle_t *zfp; 1866789Sahrens int ret; 1867789Sahrens 1868789Sahrens /* 1869789Sahrens * If the pool is unavailable, just return success. 1870789Sahrens */ 18712082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 18722082Seschrock zhp->zpool_name)) == NULL) 1873789Sahrens return (0); 1874789Sahrens 18754657Sahrens ret = zfs_iter_filesystems(zfp, do_zvol_create, NULL); 1876789Sahrens 1877789Sahrens zfs_close(zfp); 1878789Sahrens return (ret); 1879789Sahrens } 1880789Sahrens 18813126Sahl static int 18823126Sahl do_zvol_remove(const char *dataset, void *data) 18833126Sahl { 18843126Sahl zpool_handle_t *zhp = data; 18853126Sahl 18863126Sahl return (zvol_remove_link(zhp->zpool_hdl, dataset)); 18873126Sahl } 18883126Sahl 1889789Sahrens /* 18903126Sahl * Iterate over all zvols in the pool and remove any minor nodes. We iterate 18913126Sahl * by examining the /dev links so that a corrupted pool doesn't impede this 18923126Sahl * operation. 1893789Sahrens */ 1894789Sahrens int 1895789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 1896789Sahrens { 18973126Sahl return (zpool_iter_zvol(zhp, do_zvol_remove, zhp)); 1898789Sahrens } 18991354Seschrock 19001354Seschrock /* 19011354Seschrock * Convert from a devid string to a path. 19021354Seschrock */ 19031354Seschrock static char * 19041354Seschrock devid_to_path(char *devid_str) 19051354Seschrock { 19061354Seschrock ddi_devid_t devid; 19071354Seschrock char *minor; 19081354Seschrock char *path; 19091354Seschrock devid_nmlist_t *list = NULL; 19101354Seschrock int ret; 19111354Seschrock 19121354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 19131354Seschrock return (NULL); 19141354Seschrock 19151354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 19161354Seschrock 19171354Seschrock devid_str_free(minor); 19181354Seschrock devid_free(devid); 19191354Seschrock 19201354Seschrock if (ret != 0) 19211354Seschrock return (NULL); 19221354Seschrock 19232082Seschrock if ((path = strdup(list[0].devname)) == NULL) 19242082Seschrock return (NULL); 19252082Seschrock 19261354Seschrock devid_free_nmlist(list); 19271354Seschrock 19281354Seschrock return (path); 19291354Seschrock } 19301354Seschrock 19311354Seschrock /* 19321354Seschrock * Convert from a path to a devid string. 19331354Seschrock */ 19341354Seschrock static char * 19351354Seschrock path_to_devid(const char *path) 19361354Seschrock { 19371354Seschrock int fd; 19381354Seschrock ddi_devid_t devid; 19391354Seschrock char *minor, *ret; 19401354Seschrock 19411354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 19421354Seschrock return (NULL); 19431354Seschrock 19441354Seschrock minor = NULL; 19451354Seschrock ret = NULL; 19461354Seschrock if (devid_get(fd, &devid) == 0) { 19471354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 19481354Seschrock ret = devid_str_encode(devid, minor); 19491354Seschrock if (minor != NULL) 19501354Seschrock devid_str_free(minor); 19511354Seschrock devid_free(devid); 19521354Seschrock } 19531354Seschrock (void) close(fd); 19541354Seschrock 19551354Seschrock return (ret); 19561354Seschrock } 19571354Seschrock 19581354Seschrock /* 19591354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 19601354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 19611354Seschrock * type 'zpool status', and we'll display the correct information anyway. 19621354Seschrock */ 19631354Seschrock static void 19641354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 19651354Seschrock { 19661354Seschrock zfs_cmd_t zc = { 0 }; 19671354Seschrock 19681354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 19692676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 19701354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 19711544Seschrock &zc.zc_guid) == 0); 19721354Seschrock 19732082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 19741354Seschrock } 19751354Seschrock 19761354Seschrock /* 19771354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 19781354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 19791354Seschrock * We also check if this is a whole disk, in which case we strip off the 19801354Seschrock * trailing 's0' slice name. 19811354Seschrock * 19821354Seschrock * This routine is also responsible for identifying when disks have been 19831354Seschrock * reconfigured in a new location. The kernel will have opened the device by 19841354Seschrock * devid, but the path will still refer to the old location. To catch this, we 19851354Seschrock * first do a path -> devid translation (which is fast for the common case). If 19861354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 19871354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 19881354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 19891354Seschrock * of these checks. 19901354Seschrock */ 19911354Seschrock char * 19922082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 19931354Seschrock { 19941354Seschrock char *path, *devid; 19951544Seschrock uint64_t value; 19961544Seschrock char buf[64]; 19974451Seschrock vdev_stat_t *vs; 19984451Seschrock uint_t vsc; 19991354Seschrock 20001544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 20011544Seschrock &value) == 0) { 20021544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 20031544Seschrock &value) == 0); 20042856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 20052856Snd150628 (u_longlong_t)value); 20061544Seschrock path = buf; 20071544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 20081354Seschrock 20094451Seschrock /* 20104451Seschrock * If the device is dead (faulted, offline, etc) then don't 20114451Seschrock * bother opening it. Otherwise we may be forcing the user to 20124451Seschrock * open a misbehaving device, which can have undesirable 20134451Seschrock * effects. 20144451Seschrock */ 20154451Seschrock if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 20164451Seschrock (uint64_t **)&vs, &vsc) != 0 || 20174451Seschrock vs->vs_state >= VDEV_STATE_DEGRADED) && 20184451Seschrock zhp != NULL && 20191354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 20201354Seschrock /* 20211354Seschrock * Determine if the current path is correct. 20221354Seschrock */ 20231354Seschrock char *newdevid = path_to_devid(path); 20241354Seschrock 20251354Seschrock if (newdevid == NULL || 20261354Seschrock strcmp(devid, newdevid) != 0) { 20271354Seschrock char *newpath; 20281354Seschrock 20291354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 20301354Seschrock /* 20311354Seschrock * Update the path appropriately. 20321354Seschrock */ 20331354Seschrock set_path(zhp, nv, newpath); 20342082Seschrock if (nvlist_add_string(nv, 20352082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 20362082Seschrock verify(nvlist_lookup_string(nv, 20372082Seschrock ZPOOL_CONFIG_PATH, 20382082Seschrock &path) == 0); 20391354Seschrock free(newpath); 20401354Seschrock } 20411354Seschrock } 20421354Seschrock 20432082Seschrock if (newdevid) 20442082Seschrock devid_str_free(newdevid); 20451354Seschrock } 20461354Seschrock 20471354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 20481354Seschrock path += 9; 20491354Seschrock 20501354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 20511544Seschrock &value) == 0 && value) { 20522082Seschrock char *tmp = zfs_strdup(hdl, path); 20532082Seschrock if (tmp == NULL) 20542082Seschrock return (NULL); 20551354Seschrock tmp[strlen(path) - 2] = '\0'; 20561354Seschrock return (tmp); 20571354Seschrock } 20581354Seschrock } else { 20591354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 20602082Seschrock 20612082Seschrock /* 20622082Seschrock * If it's a raidz device, we need to stick in the parity level. 20632082Seschrock */ 20642082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 20652082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 20662082Seschrock &value) == 0); 20672082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 20682856Snd150628 (u_longlong_t)value); 20692082Seschrock path = buf; 20702082Seschrock } 20711354Seschrock } 20721354Seschrock 20732082Seschrock return (zfs_strdup(hdl, path)); 20741354Seschrock } 20751544Seschrock 20761544Seschrock static int 20771544Seschrock zbookmark_compare(const void *a, const void *b) 20781544Seschrock { 20791544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 20801544Seschrock } 20811544Seschrock 20821544Seschrock /* 20831544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 20841544Seschrock * caller. 20851544Seschrock */ 20861544Seschrock int 20873444Sek110237 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) 20881544Seschrock { 20891544Seschrock zfs_cmd_t zc = { 0 }; 20901544Seschrock uint64_t count; 20912676Seschrock zbookmark_t *zb = NULL; 20923444Sek110237 int i; 20931544Seschrock 20941544Seschrock /* 20951544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 20961544Seschrock * has increased, allocate more space and continue until we get the 20971544Seschrock * entire list. 20981544Seschrock */ 20991544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 21001544Seschrock &count) == 0); 21014820Sek110237 if (count == 0) 21024820Sek110237 return (0); 21032676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 21042856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 21052082Seschrock return (-1); 21062676Seschrock zc.zc_nvlist_dst_size = count; 21071544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 21081544Seschrock for (;;) { 21092082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 21102082Seschrock &zc) != 0) { 21112676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 21121544Seschrock if (errno == ENOMEM) { 21133823Svb160487 count = zc.zc_nvlist_dst_size; 21142676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 21153823Svb160487 zfs_alloc(zhp->zpool_hdl, count * 21163823Svb160487 sizeof (zbookmark_t))) == (uintptr_t)NULL) 21172082Seschrock return (-1); 21181544Seschrock } else { 21191544Seschrock return (-1); 21201544Seschrock } 21211544Seschrock } else { 21221544Seschrock break; 21231544Seschrock } 21241544Seschrock } 21251544Seschrock 21261544Seschrock /* 21271544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 21281544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 21292676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 21301544Seschrock * _not_ copied as part of the process. So we point the start of our 21311544Seschrock * array appropriate and decrement the total number of elements. 21321544Seschrock */ 21332676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 21342676Seschrock zc.zc_nvlist_dst_size; 21352676Seschrock count -= zc.zc_nvlist_dst_size; 21361544Seschrock 21371544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 21381544Seschrock 21393444Sek110237 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); 21401544Seschrock 21411544Seschrock /* 21423444Sek110237 * Fill in the nverrlistp with nvlist's of dataset and object numbers. 21431544Seschrock */ 21441544Seschrock for (i = 0; i < count; i++) { 21451544Seschrock nvlist_t *nv; 21461544Seschrock 21473700Sek110237 /* ignoring zb_blkid and zb_level for now */ 21483700Sek110237 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && 21493700Sek110237 zb[i-1].zb_object == zb[i].zb_object) 21501544Seschrock continue; 21511544Seschrock 21523444Sek110237 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) 21533444Sek110237 goto nomem; 21543444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, 21553444Sek110237 zb[i].zb_objset) != 0) { 21563444Sek110237 nvlist_free(nv); 21572082Seschrock goto nomem; 21583444Sek110237 } 21593444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, 21603444Sek110237 zb[i].zb_object) != 0) { 21613444Sek110237 nvlist_free(nv); 21623444Sek110237 goto nomem; 21631544Seschrock } 21643444Sek110237 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { 21653444Sek110237 nvlist_free(nv); 21663444Sek110237 goto nomem; 21673444Sek110237 } 21683444Sek110237 nvlist_free(nv); 21691544Seschrock } 21701544Seschrock 21713265Sahrens free((void *)(uintptr_t)zc.zc_nvlist_dst); 21721544Seschrock return (0); 21732082Seschrock 21742082Seschrock nomem: 21752676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 21762082Seschrock return (no_memory(zhp->zpool_hdl)); 21771544Seschrock } 21781760Seschrock 21791760Seschrock /* 21801760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 21811760Seschrock */ 21821760Seschrock int 2183*5094Slling zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version) 21841760Seschrock { 21851760Seschrock zfs_cmd_t zc = { 0 }; 21862082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 21871760Seschrock 21881760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 2189*5094Slling zc.zc_cookie = new_version; 2190*5094Slling 21914543Smarks if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 21923237Slling return (zpool_standard_error_fmt(hdl, errno, 21932082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 21942082Seschrock zhp->zpool_name)); 21951760Seschrock return (0); 21961760Seschrock } 21972926Sek110237 21984988Sek110237 void 21994988Sek110237 zpool_set_history_str(const char *subcommand, int argc, char **argv, 22004988Sek110237 char *history_str) 22014988Sek110237 { 22024988Sek110237 int i; 22034988Sek110237 22044988Sek110237 (void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN); 22054988Sek110237 for (i = 1; i < argc; i++) { 22064988Sek110237 if (strlen(history_str) + 1 + strlen(argv[i]) > 22074988Sek110237 HIS_MAX_RECORD_LEN) 22084988Sek110237 break; 22094988Sek110237 (void) strlcat(history_str, " ", HIS_MAX_RECORD_LEN); 22104988Sek110237 (void) strlcat(history_str, argv[i], HIS_MAX_RECORD_LEN); 22114988Sek110237 } 22124988Sek110237 } 22134988Sek110237 22142926Sek110237 /* 22154988Sek110237 * Stage command history for logging. 22162926Sek110237 */ 22174988Sek110237 int 22184988Sek110237 zpool_stage_history(libzfs_handle_t *hdl, const char *history_str) 22192926Sek110237 { 22204988Sek110237 if (history_str == NULL) 22214988Sek110237 return (EINVAL); 22224988Sek110237 22234988Sek110237 if (strlen(history_str) > HIS_MAX_RECORD_LEN) 22244988Sek110237 return (EINVAL); 22252926Sek110237 22264715Sek110237 if (hdl->libzfs_log_str != NULL) 22274543Smarks free(hdl->libzfs_log_str); 22282926Sek110237 22294988Sek110237 if ((hdl->libzfs_log_str = strdup(history_str)) == NULL) 22304988Sek110237 return (no_memory(hdl)); 22314543Smarks 22324988Sek110237 return (0); 22332926Sek110237 } 22342926Sek110237 22352926Sek110237 /* 22362926Sek110237 * Perform ioctl to get some command history of a pool. 22372926Sek110237 * 22382926Sek110237 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 22392926Sek110237 * logical offset of the history buffer to start reading from. 22402926Sek110237 * 22412926Sek110237 * Upon return, 'off' is the next logical offset to read from and 22422926Sek110237 * 'len' is the actual amount of bytes read into 'buf'. 22432926Sek110237 */ 22442926Sek110237 static int 22452926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 22462926Sek110237 { 22472926Sek110237 zfs_cmd_t zc = { 0 }; 22482926Sek110237 libzfs_handle_t *hdl = zhp->zpool_hdl; 22492926Sek110237 22502926Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 22512926Sek110237 22522926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)buf; 22532926Sek110237 zc.zc_history_len = *len; 22542926Sek110237 zc.zc_history_offset = *off; 22552926Sek110237 22562926Sek110237 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 22572926Sek110237 switch (errno) { 22582926Sek110237 case EPERM: 22593237Slling return (zfs_error_fmt(hdl, EZFS_PERM, 22603237Slling dgettext(TEXT_DOMAIN, 22612926Sek110237 "cannot show history for pool '%s'"), 22622926Sek110237 zhp->zpool_name)); 22632926Sek110237 case ENOENT: 22643237Slling return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 22652926Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 22662926Sek110237 "'%s'"), zhp->zpool_name)); 22673863Sek110237 case ENOTSUP: 22683863Sek110237 return (zfs_error_fmt(hdl, EZFS_BADVERSION, 22693863Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 22703863Sek110237 "'%s', pool must be upgraded"), zhp->zpool_name)); 22712926Sek110237 default: 22723237Slling return (zpool_standard_error_fmt(hdl, errno, 22732926Sek110237 dgettext(TEXT_DOMAIN, 22742926Sek110237 "cannot get history for '%s'"), zhp->zpool_name)); 22752926Sek110237 } 22762926Sek110237 } 22772926Sek110237 22782926Sek110237 *len = zc.zc_history_len; 22792926Sek110237 *off = zc.zc_history_offset; 22802926Sek110237 22812926Sek110237 return (0); 22822926Sek110237 } 22832926Sek110237 22842926Sek110237 /* 22852926Sek110237 * Process the buffer of nvlists, unpacking and storing each nvlist record 22862926Sek110237 * into 'records'. 'leftover' is set to the number of bytes that weren't 22872926Sek110237 * processed as there wasn't a complete record. 22882926Sek110237 */ 22892926Sek110237 static int 22902926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 22912926Sek110237 nvlist_t ***records, uint_t *numrecords) 22922926Sek110237 { 22932926Sek110237 uint64_t reclen; 22942926Sek110237 nvlist_t *nv; 22952926Sek110237 int i; 22962926Sek110237 22972926Sek110237 while (bytes_read > sizeof (reclen)) { 22982926Sek110237 22992926Sek110237 /* get length of packed record (stored as little endian) */ 23002926Sek110237 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 23012926Sek110237 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 23022926Sek110237 23032926Sek110237 if (bytes_read < sizeof (reclen) + reclen) 23042926Sek110237 break; 23052926Sek110237 23062926Sek110237 /* unpack record */ 23072926Sek110237 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 23082926Sek110237 return (ENOMEM); 23092926Sek110237 bytes_read -= sizeof (reclen) + reclen; 23102926Sek110237 buf += sizeof (reclen) + reclen; 23112926Sek110237 23122926Sek110237 /* add record to nvlist array */ 23132926Sek110237 (*numrecords)++; 23142926Sek110237 if (ISP2(*numrecords + 1)) { 23152926Sek110237 *records = realloc(*records, 23162926Sek110237 *numrecords * 2 * sizeof (nvlist_t *)); 23172926Sek110237 } 23182926Sek110237 (*records)[*numrecords - 1] = nv; 23192926Sek110237 } 23202926Sek110237 23212926Sek110237 *leftover = bytes_read; 23222926Sek110237 return (0); 23232926Sek110237 } 23242926Sek110237 23252926Sek110237 #define HIS_BUF_LEN (128*1024) 23262926Sek110237 23272926Sek110237 /* 23282926Sek110237 * Retrieve the command history of a pool. 23292926Sek110237 */ 23302926Sek110237 int 23312926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 23322926Sek110237 { 23332926Sek110237 char buf[HIS_BUF_LEN]; 23342926Sek110237 uint64_t off = 0; 23352926Sek110237 nvlist_t **records = NULL; 23362926Sek110237 uint_t numrecords = 0; 23372926Sek110237 int err, i; 23382926Sek110237 23392926Sek110237 do { 23402926Sek110237 uint64_t bytes_read = sizeof (buf); 23412926Sek110237 uint64_t leftover; 23422926Sek110237 23432926Sek110237 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 23442926Sek110237 break; 23452926Sek110237 23462926Sek110237 /* if nothing else was read in, we're at EOF, just return */ 23472926Sek110237 if (!bytes_read) 23482926Sek110237 break; 23492926Sek110237 23502926Sek110237 if ((err = zpool_history_unpack(buf, bytes_read, 23512926Sek110237 &leftover, &records, &numrecords)) != 0) 23522926Sek110237 break; 23532926Sek110237 off -= leftover; 23542926Sek110237 23552926Sek110237 /* CONSTCOND */ 23562926Sek110237 } while (1); 23572926Sek110237 23582926Sek110237 if (!err) { 23592926Sek110237 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 23602926Sek110237 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 23612926Sek110237 records, numrecords) == 0); 23622926Sek110237 } 23632926Sek110237 for (i = 0; i < numrecords; i++) 23642926Sek110237 nvlist_free(records[i]); 23652926Sek110237 free(records); 23662926Sek110237 23672926Sek110237 return (err); 23682926Sek110237 } 23693444Sek110237 23703444Sek110237 void 23713444Sek110237 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, 23723444Sek110237 char *pathname, size_t len) 23733444Sek110237 { 23743444Sek110237 zfs_cmd_t zc = { 0 }; 23753444Sek110237 boolean_t mounted = B_FALSE; 23763444Sek110237 char *mntpnt = NULL; 23773444Sek110237 char dsname[MAXNAMELEN]; 23783444Sek110237 23793444Sek110237 if (dsobj == 0) { 23803444Sek110237 /* special case for the MOS */ 23813444Sek110237 (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj); 23823444Sek110237 return; 23833444Sek110237 } 23843444Sek110237 23853444Sek110237 /* get the dataset's name */ 23863444Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 23873444Sek110237 zc.zc_obj = dsobj; 23883444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, 23893444Sek110237 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { 23903444Sek110237 /* just write out a path of two object numbers */ 23913444Sek110237 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", 23923444Sek110237 dsobj, obj); 23933444Sek110237 return; 23943444Sek110237 } 23953444Sek110237 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); 23963444Sek110237 23973444Sek110237 /* find out if the dataset is mounted */ 23983444Sek110237 mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt); 23993444Sek110237 24003444Sek110237 /* get the corrupted object's path */ 24013444Sek110237 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); 24023444Sek110237 zc.zc_obj = obj; 24033444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH, 24043444Sek110237 &zc) == 0) { 24053444Sek110237 if (mounted) { 24063444Sek110237 (void) snprintf(pathname, len, "%s%s", mntpnt, 24073444Sek110237 zc.zc_value); 24083444Sek110237 } else { 24093444Sek110237 (void) snprintf(pathname, len, "%s:%s", 24103444Sek110237 dsname, zc.zc_value); 24113444Sek110237 } 24123444Sek110237 } else { 24133444Sek110237 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj); 24143444Sek110237 } 24153444Sek110237 free(mntpnt); 24163444Sek110237 } 24173912Slling 24184276Staylor #define RDISK_ROOT "/dev/rdsk" 24194276Staylor #define BACKUP_SLICE "s2" 24204276Staylor /* 24214276Staylor * Don't start the slice at the default block of 34; many storage 24224276Staylor * devices will use a stripe width of 128k, so start there instead. 24234276Staylor */ 24244276Staylor #define NEW_START_BLOCK 256 24254276Staylor 24264276Staylor /* 24274276Staylor * determine where a partition starts on a disk in the current 24284276Staylor * configuration 24294276Staylor */ 24304276Staylor static diskaddr_t 24314276Staylor find_start_block(nvlist_t *config) 24324276Staylor { 24334276Staylor nvlist_t **child; 24344276Staylor uint_t c, children; 24354276Staylor char *path; 24364276Staylor diskaddr_t sb = MAXOFFSET_T; 24374276Staylor int fd; 24384276Staylor char diskname[MAXPATHLEN]; 24394276Staylor uint64_t wholedisk; 24404276Staylor 24414276Staylor if (nvlist_lookup_nvlist_array(config, 24424276Staylor ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) { 24434276Staylor if (nvlist_lookup_uint64(config, 24444276Staylor ZPOOL_CONFIG_WHOLE_DISK, 24454276Staylor &wholedisk) != 0 || !wholedisk) { 24464276Staylor return (MAXOFFSET_T); 24474276Staylor } 24484276Staylor if (nvlist_lookup_string(config, 24494276Staylor ZPOOL_CONFIG_PATH, &path) != 0) { 24504276Staylor return (MAXOFFSET_T); 24514276Staylor } 24524276Staylor 24534276Staylor (void) snprintf(diskname, sizeof (diskname), "%s%s", 24544276Staylor RDISK_ROOT, strrchr(path, '/')); 24554276Staylor if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) { 24564276Staylor struct dk_gpt *vtoc; 24574276Staylor if (efi_alloc_and_read(fd, &vtoc) >= 0) { 24584276Staylor sb = vtoc->efi_parts[0].p_start; 24594276Staylor efi_free(vtoc); 24604276Staylor } 24614276Staylor (void) close(fd); 24624276Staylor } 24634276Staylor return (sb); 24644276Staylor } 24654276Staylor 24664276Staylor for (c = 0; c < children; c++) { 24674276Staylor sb = find_start_block(child[c]); 24684276Staylor if (sb != MAXOFFSET_T) { 24694276Staylor return (sb); 24704276Staylor } 24714276Staylor } 24724276Staylor return (MAXOFFSET_T); 24734276Staylor } 24744276Staylor 24754276Staylor /* 24764276Staylor * Label an individual disk. The name provided is the short name, 24774276Staylor * stripped of any leading /dev path. 24784276Staylor */ 24794276Staylor int 24804276Staylor zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name) 24814276Staylor { 24824276Staylor char path[MAXPATHLEN]; 24834276Staylor struct dk_gpt *vtoc; 24844276Staylor int fd; 24854276Staylor size_t resv = EFI_MIN_RESV_SIZE; 24864276Staylor uint64_t slice_size; 24874276Staylor diskaddr_t start_block; 24884276Staylor char errbuf[1024]; 24894276Staylor 24904276Staylor if (zhp) { 24914276Staylor nvlist_t *nvroot; 24924276Staylor 24934276Staylor verify(nvlist_lookup_nvlist(zhp->zpool_config, 24944276Staylor ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 24954276Staylor 24964276Staylor if (zhp->zpool_start_block == 0) 24974276Staylor start_block = find_start_block(nvroot); 24984276Staylor else 24994276Staylor start_block = zhp->zpool_start_block; 25004276Staylor zhp->zpool_start_block = start_block; 25014276Staylor } else { 25024276Staylor /* new pool */ 25034276Staylor start_block = NEW_START_BLOCK; 25044276Staylor } 25054276Staylor 25064276Staylor (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name, 25074276Staylor BACKUP_SLICE); 25084276Staylor 25094276Staylor if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) { 25104276Staylor /* 25114276Staylor * This shouldn't happen. We've long since verified that this 25124276Staylor * is a valid device. 25134276Staylor */ 25144276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 25154276Staylor "label '%s': unable to open device"), name); 25164276Staylor return (zfs_error(hdl, EZFS_OPENFAILED, errbuf)); 25174276Staylor } 25184276Staylor 25194276Staylor if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) { 25204276Staylor /* 25214276Staylor * The only way this can fail is if we run out of memory, or we 25224276Staylor * were unable to read the disk's capacity 25234276Staylor */ 25244276Staylor if (errno == ENOMEM) 25254276Staylor (void) no_memory(hdl); 25264276Staylor 25274276Staylor (void) close(fd); 25284276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot " 25294276Staylor "label '%s': unable to read disk capacity"), name); 25304276Staylor 25314276Staylor return (zfs_error(hdl, EZFS_NOCAP, errbuf)); 25324276Staylor } 25334276Staylor 25344276Staylor slice_size = vtoc->efi_last_u_lba + 1; 25354276Staylor slice_size -= EFI_MIN_RESV_SIZE; 25364276Staylor if (start_block == MAXOFFSET_T) 25374276Staylor start_block = NEW_START_BLOCK; 25384276Staylor slice_size -= start_block; 25394276Staylor 25404276Staylor vtoc->efi_parts[0].p_start = start_block; 25414276Staylor vtoc->efi_parts[0].p_size = slice_size; 25424276Staylor 25434276Staylor /* 25444276Staylor * Why we use V_USR: V_BACKUP confuses users, and is considered 25454276Staylor * disposable by some EFI utilities (since EFI doesn't have a backup 25464276Staylor * slice). V_UNASSIGNED is supposed to be used only for zero size 25474276Staylor * partitions, and efi_write() will fail if we use it. V_ROOT, V_BOOT, 25484276Staylor * etc. were all pretty specific. V_USR is as close to reality as we 25494276Staylor * can get, in the absence of V_OTHER. 25504276Staylor */ 25514276Staylor vtoc->efi_parts[0].p_tag = V_USR; 25524276Staylor (void) strcpy(vtoc->efi_parts[0].p_name, "zfs"); 25534276Staylor 25544276Staylor vtoc->efi_parts[8].p_start = slice_size + start_block; 25554276Staylor vtoc->efi_parts[8].p_size = resv; 25564276Staylor vtoc->efi_parts[8].p_tag = V_RESERVED; 25574276Staylor 25584276Staylor if (efi_write(fd, vtoc) != 0) { 25594276Staylor /* 25604276Staylor * Some block drivers (like pcata) may not support EFI 25614276Staylor * GPT labels. Print out a helpful error message dir- 25624276Staylor * ecting the user to manually label the disk and give 25634276Staylor * a specific slice. 25644276Staylor */ 25654276Staylor (void) close(fd); 25664276Staylor efi_free(vtoc); 25674276Staylor 25684276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 25694276Staylor "cannot label '%s': try using fdisk(1M) and then " 25704276Staylor "provide a specific slice"), name); 25714276Staylor return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); 25724276Staylor } 25734276Staylor 25744276Staylor (void) close(fd); 25754276Staylor efi_free(vtoc); 25764276Staylor return (0); 25774276Staylor } 2578