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 /* 236289Smmusante * Copyright 2008 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*7042Sgw25295 static int read_efi_label(nvlist_t *config, diskaddr_t *sb); 525094Slling 535094Slling /* 545094Slling * ==================================================================== 555094Slling * zpool property functions 565094Slling * ==================================================================== 575094Slling */ 585094Slling 595094Slling static int 605094Slling zpool_get_all_props(zpool_handle_t *zhp) 615094Slling { 625094Slling zfs_cmd_t zc = { 0 }; 635094Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 645094Slling 655094Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 665094Slling 675094Slling if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 685094Slling return (-1); 695094Slling 705094Slling while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) { 715094Slling if (errno == ENOMEM) { 725094Slling if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 735094Slling zcmd_free_nvlists(&zc); 745094Slling return (-1); 755094Slling } 765094Slling } else { 775094Slling zcmd_free_nvlists(&zc); 785094Slling return (-1); 795094Slling } 805094Slling } 815094Slling 825094Slling if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) { 835094Slling zcmd_free_nvlists(&zc); 845094Slling return (-1); 855094Slling } 865094Slling 875094Slling zcmd_free_nvlists(&zc); 885094Slling 895094Slling return (0); 905094Slling } 915094Slling 925094Slling static int 935094Slling zpool_props_refresh(zpool_handle_t *zhp) 945094Slling { 955094Slling nvlist_t *old_props; 965094Slling 975094Slling old_props = zhp->zpool_props; 985094Slling 995094Slling if (zpool_get_all_props(zhp) != 0) 1005094Slling return (-1); 1015094Slling 1025094Slling nvlist_free(old_props); 1035094Slling return (0); 1045094Slling } 1055094Slling 1065094Slling static char * 1075094Slling zpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop, 1085094Slling zprop_source_t *src) 1095094Slling { 1105094Slling nvlist_t *nv, *nvl; 1115094Slling uint64_t ival; 1125094Slling char *value; 1135094Slling zprop_source_t source; 1145094Slling 1155094Slling nvl = zhp->zpool_props; 1165094Slling if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) { 1175094Slling verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0); 1185094Slling source = ival; 1195094Slling verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0); 1205094Slling } else { 1215094Slling source = ZPROP_SRC_DEFAULT; 1225094Slling if ((value = (char *)zpool_prop_default_string(prop)) == NULL) 1235094Slling value = "-"; 1245094Slling } 1255094Slling 1265094Slling if (src) 1275094Slling *src = source; 1285094Slling 1295094Slling return (value); 1305094Slling } 1315094Slling 1325094Slling uint64_t 1335094Slling zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src) 1345094Slling { 1355094Slling nvlist_t *nv, *nvl; 1365094Slling uint64_t value; 1375094Slling zprop_source_t source; 1385094Slling 1395094Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 1405094Slling return (zpool_prop_default_numeric(prop)); 1415094Slling 1425094Slling nvl = zhp->zpool_props; 1435094Slling if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) { 1445094Slling verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &value) == 0); 1455094Slling source = value; 1465094Slling verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0); 1475094Slling } else { 1485094Slling source = ZPROP_SRC_DEFAULT; 1495094Slling value = zpool_prop_default_numeric(prop); 1505094Slling } 1515094Slling 1525094Slling if (src) 1535094Slling *src = source; 1545094Slling 1555094Slling return (value); 1565094Slling } 1575094Slling 1585094Slling /* 1595094Slling * Map VDEV STATE to printed strings. 1605094Slling */ 1615094Slling char * 1625094Slling zpool_state_to_name(vdev_state_t state, vdev_aux_t aux) 1635094Slling { 1645094Slling switch (state) { 1655094Slling case VDEV_STATE_CLOSED: 1665094Slling case VDEV_STATE_OFFLINE: 1675094Slling return (gettext("OFFLINE")); 1685094Slling case VDEV_STATE_REMOVED: 1695094Slling return (gettext("REMOVED")); 1705094Slling case VDEV_STATE_CANT_OPEN: 1715094Slling if (aux == VDEV_AUX_CORRUPT_DATA) 1725094Slling return (gettext("FAULTED")); 1735094Slling else 1745094Slling return (gettext("UNAVAIL")); 1755094Slling case VDEV_STATE_FAULTED: 1765094Slling return (gettext("FAULTED")); 1775094Slling case VDEV_STATE_DEGRADED: 1785094Slling return (gettext("DEGRADED")); 1795094Slling case VDEV_STATE_HEALTHY: 1805094Slling return (gettext("ONLINE")); 1815094Slling } 1825094Slling 1835094Slling return (gettext("UNKNOWN")); 1845094Slling } 1855094Slling 1865094Slling /* 1875094Slling * Get a zpool property value for 'prop' and return the value in 1885094Slling * a pre-allocated buffer. 1895094Slling */ 1905094Slling int 1915094Slling zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, 1925094Slling zprop_source_t *srctype) 1935094Slling { 1945094Slling uint64_t intval; 1955094Slling const char *strval; 1965094Slling zprop_source_t src = ZPROP_SRC_NONE; 1975094Slling nvlist_t *nvroot; 1985094Slling vdev_stat_t *vs; 1995094Slling uint_t vsc; 2005094Slling 2015094Slling if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 2025094Slling if (prop == ZPOOL_PROP_NAME) 2035094Slling (void) strlcpy(buf, zpool_get_name(zhp), len); 2045094Slling else if (prop == ZPOOL_PROP_HEALTH) 2055094Slling (void) strlcpy(buf, "FAULTED", len); 2065094Slling else 2075094Slling (void) strlcpy(buf, "-", len); 2085094Slling return (0); 2095094Slling } 2105094Slling 2115094Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) && 2125094Slling prop != ZPOOL_PROP_NAME) 2135094Slling return (-1); 2145094Slling 2155094Slling switch (zpool_prop_get_type(prop)) { 2165094Slling case PROP_TYPE_STRING: 2175094Slling (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src), 2185094Slling len); 2195094Slling break; 2205094Slling 2215094Slling case PROP_TYPE_NUMBER: 2225094Slling intval = zpool_get_prop_int(zhp, prop, &src); 2235094Slling 2245094Slling switch (prop) { 2255094Slling case ZPOOL_PROP_SIZE: 2265094Slling case ZPOOL_PROP_USED: 2275094Slling case ZPOOL_PROP_AVAILABLE: 2285094Slling (void) zfs_nicenum(intval, buf, len); 2295094Slling break; 2305094Slling 2315094Slling case ZPOOL_PROP_CAPACITY: 2325094Slling (void) snprintf(buf, len, "%llu%%", 2335094Slling (u_longlong_t)intval); 2345094Slling break; 2355094Slling 2365094Slling case ZPOOL_PROP_HEALTH: 2375094Slling verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 2385094Slling ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 2395094Slling verify(nvlist_lookup_uint64_array(nvroot, 2405094Slling ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &vsc) == 0); 2415094Slling 2425094Slling (void) strlcpy(buf, zpool_state_to_name(intval, 2435094Slling vs->vs_aux), len); 2445094Slling break; 2455094Slling default: 2465094Slling (void) snprintf(buf, len, "%llu", intval); 2475094Slling } 2485094Slling break; 2495094Slling 2505094Slling case PROP_TYPE_INDEX: 2515094Slling intval = zpool_get_prop_int(zhp, prop, &src); 2525094Slling if (zpool_prop_index_to_string(prop, intval, &strval) 2535094Slling != 0) 2545094Slling return (-1); 2555094Slling (void) strlcpy(buf, strval, len); 2565094Slling break; 2575094Slling 2585094Slling default: 2595094Slling abort(); 2605094Slling } 2615094Slling 2625094Slling if (srctype) 2635094Slling *srctype = src; 2645094Slling 2655094Slling return (0); 2665094Slling } 2675094Slling 2685094Slling /* 2695094Slling * Check if the bootfs name has the same pool name as it is set to. 2705094Slling * Assuming bootfs is a valid dataset name. 2715094Slling */ 2725094Slling static boolean_t 2735094Slling bootfs_name_valid(const char *pool, char *bootfs) 2745094Slling { 2755094Slling int len = strlen(pool); 2765094Slling 2775094Slling if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM)) 2785094Slling return (B_FALSE); 2795094Slling 2805094Slling if (strncmp(pool, bootfs, len) == 0 && 2815094Slling (bootfs[len] == '/' || bootfs[len] == '\0')) 2825094Slling return (B_TRUE); 2835094Slling 2845094Slling return (B_FALSE); 2855094Slling } 2865094Slling 2875094Slling /* 288*7042Sgw25295 * Inspect the configuration to determine if any of the devices contain 289*7042Sgw25295 * an EFI label. 290*7042Sgw25295 */ 291*7042Sgw25295 static boolean_t 292*7042Sgw25295 pool_uses_efi(nvlist_t *config) 293*7042Sgw25295 { 294*7042Sgw25295 nvlist_t **child; 295*7042Sgw25295 uint_t c, children; 296*7042Sgw25295 297*7042Sgw25295 if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN, 298*7042Sgw25295 &child, &children) != 0) 299*7042Sgw25295 return (read_efi_label(config, NULL) >= 0); 300*7042Sgw25295 301*7042Sgw25295 for (c = 0; c < children; c++) { 302*7042Sgw25295 if (pool_uses_efi(child[c])) 303*7042Sgw25295 return (B_TRUE); 304*7042Sgw25295 } 305*7042Sgw25295 return (B_FALSE); 306*7042Sgw25295 } 307*7042Sgw25295 308*7042Sgw25295 /* 3095094Slling * Given an nvlist of zpool properties to be set, validate that they are 3105094Slling * correct, and parse any numeric properties (index, boolean, etc) if they are 3115094Slling * specified as strings. 3125094Slling */ 3135094Slling static nvlist_t * 3145094Slling zpool_validate_properties(libzfs_handle_t *hdl, const char *poolname, 3155094Slling nvlist_t *props, uint64_t version, boolean_t create_or_import, char *errbuf) 3165094Slling { 3175094Slling nvpair_t *elem; 3185094Slling nvlist_t *retprops; 3195094Slling zpool_prop_t prop; 3205094Slling char *strval; 3215094Slling uint64_t intval; 3225363Seschrock char *slash; 3235363Seschrock struct stat64 statbuf; 324*7042Sgw25295 zpool_handle_t *zhp; 325*7042Sgw25295 nvlist_t *nvroot; 3265094Slling 3275094Slling if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) { 3285094Slling (void) no_memory(hdl); 3295094Slling return (NULL); 3305094Slling } 3315094Slling 3325094Slling elem = NULL; 3335094Slling while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 3345094Slling const char *propname = nvpair_name(elem); 3355094Slling 3365094Slling /* 3375094Slling * Make sure this property is valid and applies to this type. 3385094Slling */ 3395094Slling if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) { 3405094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3415094Slling "invalid property '%s'"), propname); 3425094Slling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 3435094Slling goto error; 3445094Slling } 3455094Slling 3465094Slling if (zpool_prop_readonly(prop)) { 3475094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 3485094Slling "is readonly"), propname); 3495094Slling (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); 3505094Slling goto error; 3515094Slling } 3525094Slling 3535094Slling if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops, 3545094Slling &strval, &intval, errbuf) != 0) 3555094Slling goto error; 3565094Slling 3575094Slling /* 3585094Slling * Perform additional checking for specific properties. 3595094Slling */ 3605094Slling switch (prop) { 3615094Slling case ZPOOL_PROP_VERSION: 3625094Slling if (intval < version || intval > SPA_VERSION) { 3635094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3645094Slling "property '%s' number %d is invalid."), 3655094Slling propname, intval); 3665094Slling (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 3675094Slling goto error; 3685094Slling } 3695094Slling break; 3705094Slling 3715094Slling case ZPOOL_PROP_BOOTFS: 3725094Slling if (create_or_import) { 3735094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3745094Slling "property '%s' cannot be set at creation " 3755094Slling "or import time"), propname); 3765094Slling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 3775094Slling goto error; 3785094Slling } 3795094Slling 3805094Slling if (version < SPA_VERSION_BOOTFS) { 3815094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3825094Slling "pool must be upgraded to support " 3835094Slling "'%s' property"), propname); 3845094Slling (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 3855094Slling goto error; 3865094Slling } 3875094Slling 3885094Slling /* 3895094Slling * bootfs property value has to be a dataset name and 3905094Slling * the dataset has to be in the same pool as it sets to. 3915094Slling */ 3925094Slling if (strval[0] != '\0' && !bootfs_name_valid(poolname, 3935094Slling strval)) { 3945094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 3955094Slling "is an invalid name"), strval); 3965094Slling (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 3975094Slling goto error; 3985094Slling } 399*7042Sgw25295 400*7042Sgw25295 if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) { 401*7042Sgw25295 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 402*7042Sgw25295 "could not open pool '%s'"), poolname); 403*7042Sgw25295 (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf); 404*7042Sgw25295 goto error; 405*7042Sgw25295 } 406*7042Sgw25295 verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 407*7042Sgw25295 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 408*7042Sgw25295 409*7042Sgw25295 /* 410*7042Sgw25295 * bootfs property cannot be set on a disk which has 411*7042Sgw25295 * been EFI labeled. 412*7042Sgw25295 */ 413*7042Sgw25295 if (pool_uses_efi(nvroot)) { 414*7042Sgw25295 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 415*7042Sgw25295 "property '%s' not supported on " 416*7042Sgw25295 "EFI labeled devices"), propname); 417*7042Sgw25295 (void) zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf); 418*7042Sgw25295 zpool_close(zhp); 419*7042Sgw25295 goto error; 420*7042Sgw25295 } 421*7042Sgw25295 zpool_close(zhp); 4225094Slling break; 4235094Slling 4245094Slling case ZPOOL_PROP_ALTROOT: 4255094Slling if (!create_or_import) { 4265094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4275094Slling "property '%s' can only be set during pool " 4285094Slling "creation or import"), propname); 4295094Slling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 4305094Slling goto error; 4315094Slling } 4325094Slling 4335094Slling if (strval[0] != '/') { 4345094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4355094Slling "bad alternate root '%s'"), strval); 4365094Slling (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 4375094Slling goto error; 4385094Slling } 4395094Slling break; 4405363Seschrock 4415363Seschrock case ZPOOL_PROP_CACHEFILE: 4425363Seschrock if (strval[0] == '\0') 4435363Seschrock break; 4445363Seschrock 4455363Seschrock if (strcmp(strval, "none") == 0) 4465363Seschrock break; 4475363Seschrock 4485363Seschrock if (strval[0] != '/') { 4495363Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4505363Seschrock "property '%s' must be empty, an " 4515363Seschrock "absolute path, or 'none'"), propname); 4525363Seschrock (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 4535363Seschrock goto error; 4545363Seschrock } 4555363Seschrock 4565363Seschrock slash = strrchr(strval, '/'); 4575363Seschrock 4585363Seschrock if (slash[1] == '\0' || strcmp(slash, "/.") == 0 || 4595363Seschrock strcmp(slash, "/..") == 0) { 4605363Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4615363Seschrock "'%s' is not a valid file"), strval); 4625363Seschrock (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 4635363Seschrock goto error; 4645363Seschrock } 4655363Seschrock 4665363Seschrock *slash = '\0'; 4675363Seschrock 4685621Seschrock if (strval[0] != '\0' && 4695621Seschrock (stat64(strval, &statbuf) != 0 || 4705621Seschrock !S_ISDIR(statbuf.st_mode))) { 4715363Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4725363Seschrock "'%s' is not a valid directory"), 4735363Seschrock strval); 4745363Seschrock (void) zfs_error(hdl, EZFS_BADPATH, errbuf); 4755363Seschrock goto error; 4765363Seschrock } 4775363Seschrock 4785363Seschrock *slash = '/'; 4795363Seschrock break; 4805094Slling } 4815094Slling } 4825094Slling 4835094Slling return (retprops); 4845094Slling error: 4855094Slling nvlist_free(retprops); 4865094Slling return (NULL); 4875094Slling } 4885094Slling 4895094Slling /* 4905094Slling * Set zpool property : propname=propval. 4915094Slling */ 4925094Slling int 4935094Slling zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) 4945094Slling { 4955094Slling zfs_cmd_t zc = { 0 }; 4965094Slling int ret = -1; 4975094Slling char errbuf[1024]; 4985094Slling nvlist_t *nvl = NULL; 4995094Slling nvlist_t *realprops; 5005094Slling uint64_t version; 5015094Slling 5025094Slling (void) snprintf(errbuf, sizeof (errbuf), 5035094Slling dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 5045094Slling zhp->zpool_name); 5055094Slling 5065094Slling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) 5075094Slling return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, errbuf)); 5085094Slling 5095094Slling if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 5105094Slling return (no_memory(zhp->zpool_hdl)); 5115094Slling 5125094Slling if (nvlist_add_string(nvl, propname, propval) != 0) { 5135094Slling nvlist_free(nvl); 5145094Slling return (no_memory(zhp->zpool_hdl)); 5155094Slling } 5165094Slling 5175094Slling version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 5185094Slling if ((realprops = zpool_validate_properties(zhp->zpool_hdl, 5195094Slling zhp->zpool_name, nvl, version, B_FALSE, errbuf)) == NULL) { 5205094Slling nvlist_free(nvl); 5215094Slling return (-1); 5225094Slling } 5235094Slling 5245094Slling nvlist_free(nvl); 5255094Slling nvl = realprops; 5265094Slling 5275094Slling /* 5285094Slling * Execute the corresponding ioctl() to set this property. 5295094Slling */ 5305094Slling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 5315094Slling 5325094Slling if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) { 5335094Slling nvlist_free(nvl); 5345094Slling return (-1); 5355094Slling } 5365094Slling 5375094Slling ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc); 5385094Slling 5395094Slling zcmd_free_nvlists(&zc); 5405094Slling nvlist_free(nvl); 5415094Slling 5425094Slling if (ret) 5435094Slling (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); 5445094Slling else 5455094Slling (void) zpool_props_refresh(zhp); 5465094Slling 5475094Slling return (ret); 5485094Slling } 5495094Slling 5505094Slling int 5515094Slling zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp) 5525094Slling { 5535094Slling libzfs_handle_t *hdl = zhp->zpool_hdl; 5545094Slling zprop_list_t *entry; 5555094Slling char buf[ZFS_MAXPROPLEN]; 5565094Slling 5575094Slling if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0) 5585094Slling return (-1); 5595094Slling 5605094Slling for (entry = *plp; entry != NULL; entry = entry->pl_next) { 5615094Slling 5625094Slling if (entry->pl_fixed) 5635094Slling continue; 5645094Slling 5655094Slling if (entry->pl_prop != ZPROP_INVAL && 5665094Slling zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), 5675094Slling NULL) == 0) { 5685094Slling if (strlen(buf) > entry->pl_width) 5695094Slling entry->pl_width = strlen(buf); 5705094Slling } 5715094Slling } 5725094Slling 5735094Slling return (0); 5745094Slling } 5755094Slling 5765094Slling 577789Sahrens /* 578789Sahrens * Validate the given pool name, optionally putting an extended error message in 579789Sahrens * 'buf'. 580789Sahrens */ 5816423Sgw25295 boolean_t 5822082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool) 583789Sahrens { 584789Sahrens namecheck_err_t why; 585789Sahrens char what; 5861773Seschrock int ret; 587789Sahrens 5881773Seschrock ret = pool_namecheck(pool, &why, &what); 5891773Seschrock 5901773Seschrock /* 5911773Seschrock * The rules for reserved pool names were extended at a later point. 5921773Seschrock * But we need to support users with existing pools that may now be 5931773Seschrock * invalid. So we only check for this expanded set of names during a 5941773Seschrock * create (or import), and only in userland. 5951773Seschrock */ 5961773Seschrock if (ret == 0 && !isopen && 5971773Seschrock (strncmp(pool, "mirror", 6) == 0 || 5981773Seschrock strncmp(pool, "raidz", 5) == 0 || 5994527Sperrin strncmp(pool, "spare", 5) == 0 || 6004527Sperrin strcmp(pool, "log") == 0)) { 6016423Sgw25295 if (hdl != NULL) 6026423Sgw25295 zfs_error_aux(hdl, 6036423Sgw25295 dgettext(TEXT_DOMAIN, "name is reserved")); 6042082Seschrock return (B_FALSE); 6051773Seschrock } 6061773Seschrock 6071773Seschrock 6081773Seschrock if (ret != 0) { 6092082Seschrock if (hdl != NULL) { 610789Sahrens switch (why) { 6111003Slling case NAME_ERR_TOOLONG: 6122082Seschrock zfs_error_aux(hdl, 6131003Slling dgettext(TEXT_DOMAIN, "name is too long")); 6141003Slling break; 6151003Slling 616789Sahrens case NAME_ERR_INVALCHAR: 6172082Seschrock zfs_error_aux(hdl, 618789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 619789Sahrens "'%c' in pool name"), what); 620789Sahrens break; 621789Sahrens 622789Sahrens case NAME_ERR_NOLETTER: 6232082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6242082Seschrock "name must begin with a letter")); 625789Sahrens break; 626789Sahrens 627789Sahrens case NAME_ERR_RESERVED: 6282082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6292082Seschrock "name is reserved")); 630789Sahrens break; 631789Sahrens 632789Sahrens case NAME_ERR_DISKLIKE: 6332082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6342082Seschrock "pool name is reserved")); 635789Sahrens break; 6362856Snd150628 6372856Snd150628 case NAME_ERR_LEADING_SLASH: 6382856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6392856Snd150628 "leading slash in name")); 6402856Snd150628 break; 6412856Snd150628 6422856Snd150628 case NAME_ERR_EMPTY_COMPONENT: 6432856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6442856Snd150628 "empty component in name")); 6452856Snd150628 break; 6462856Snd150628 6472856Snd150628 case NAME_ERR_TRAILING_SLASH: 6482856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6492856Snd150628 "trailing slash in name")); 6502856Snd150628 break; 6512856Snd150628 6522856Snd150628 case NAME_ERR_MULTIPLE_AT: 6532856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6542856Snd150628 "multiple '@' delimiters in name")); 6552856Snd150628 break; 6562856Snd150628 657789Sahrens } 658789Sahrens } 6592082Seschrock return (B_FALSE); 660789Sahrens } 661789Sahrens 6622082Seschrock return (B_TRUE); 663789Sahrens } 664789Sahrens 665789Sahrens /* 666789Sahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED 667789Sahrens * state. 668789Sahrens */ 669789Sahrens zpool_handle_t * 6702082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool) 671789Sahrens { 672789Sahrens zpool_handle_t *zhp; 6732142Seschrock boolean_t missing; 674789Sahrens 675789Sahrens /* 676789Sahrens * Make sure the pool name is valid. 677789Sahrens */ 6782082Seschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) { 6793237Slling (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME, 6802082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), 6812082Seschrock pool); 682789Sahrens return (NULL); 683789Sahrens } 684789Sahrens 6852082Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 6862082Seschrock return (NULL); 687789Sahrens 6882082Seschrock zhp->zpool_hdl = hdl; 689789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 690789Sahrens 6912142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 6922142Seschrock zpool_close(zhp); 6932142Seschrock return (NULL); 6942142Seschrock } 6952142Seschrock 6962142Seschrock if (missing) { 6975094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool")); 6983237Slling (void) zfs_error_fmt(hdl, EZFS_NOENT, 6995094Slling dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool); 7002142Seschrock zpool_close(zhp); 7012142Seschrock return (NULL); 702789Sahrens } 703789Sahrens 704789Sahrens return (zhp); 705789Sahrens } 706789Sahrens 707789Sahrens /* 708789Sahrens * Like the above, but silent on error. Used when iterating over pools (because 709789Sahrens * the configuration cache may be out of date). 710789Sahrens */ 7112142Seschrock int 7122142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret) 713789Sahrens { 714789Sahrens zpool_handle_t *zhp; 7152142Seschrock boolean_t missing; 716789Sahrens 7172142Seschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL) 7182142Seschrock return (-1); 719789Sahrens 7202082Seschrock zhp->zpool_hdl = hdl; 721789Sahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name)); 722789Sahrens 7232142Seschrock if (zpool_refresh_stats(zhp, &missing) != 0) { 7242142Seschrock zpool_close(zhp); 7252142Seschrock return (-1); 726789Sahrens } 727789Sahrens 7282142Seschrock if (missing) { 7292142Seschrock zpool_close(zhp); 7302142Seschrock *ret = NULL; 7312142Seschrock return (0); 7322142Seschrock } 7332142Seschrock 7342142Seschrock *ret = zhp; 7352142Seschrock return (0); 736789Sahrens } 737789Sahrens 738789Sahrens /* 739789Sahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted 740789Sahrens * state. 741789Sahrens */ 742789Sahrens zpool_handle_t * 7432082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool) 744789Sahrens { 745789Sahrens zpool_handle_t *zhp; 746789Sahrens 7472082Seschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL) 748789Sahrens return (NULL); 749789Sahrens 750789Sahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) { 7513237Slling (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL, 7522082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name); 753789Sahrens zpool_close(zhp); 754789Sahrens return (NULL); 755789Sahrens } 756789Sahrens 757789Sahrens return (zhp); 758789Sahrens } 759789Sahrens 760789Sahrens /* 761789Sahrens * Close the handle. Simply frees the memory associated with the handle. 762789Sahrens */ 763789Sahrens void 764789Sahrens zpool_close(zpool_handle_t *zhp) 765789Sahrens { 766789Sahrens if (zhp->zpool_config) 767789Sahrens nvlist_free(zhp->zpool_config); 768952Seschrock if (zhp->zpool_old_config) 769952Seschrock nvlist_free(zhp->zpool_old_config); 7703912Slling if (zhp->zpool_props) 7713912Slling nvlist_free(zhp->zpool_props); 772789Sahrens free(zhp); 773789Sahrens } 774789Sahrens 775789Sahrens /* 776789Sahrens * Return the name of the pool. 777789Sahrens */ 778789Sahrens const char * 779789Sahrens zpool_get_name(zpool_handle_t *zhp) 780789Sahrens { 781789Sahrens return (zhp->zpool_name); 782789Sahrens } 783789Sahrens 784789Sahrens 785789Sahrens /* 786789Sahrens * Return the state of the pool (ACTIVE or UNAVAILABLE) 787789Sahrens */ 788789Sahrens int 789789Sahrens zpool_get_state(zpool_handle_t *zhp) 790789Sahrens { 791789Sahrens return (zhp->zpool_state); 792789Sahrens } 793789Sahrens 794789Sahrens /* 795789Sahrens * Create the named pool, using the provided vdev list. It is assumed 796789Sahrens * that the consumer has already validated the contents of the nvlist, so we 797789Sahrens * don't have to worry about error semantics. 798789Sahrens */ 799789Sahrens int 8002082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, 8015094Slling nvlist_t *props) 802789Sahrens { 803789Sahrens zfs_cmd_t zc = { 0 }; 8042082Seschrock char msg[1024]; 8055094Slling char *altroot; 8062082Seschrock 8072082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 8082082Seschrock "cannot create '%s'"), pool); 809789Sahrens 8102082Seschrock if (!zpool_name_valid(hdl, B_FALSE, pool)) 8112082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg)); 8122082Seschrock 8135320Slling if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 8145320Slling return (-1); 8155320Slling 8165094Slling if (props && (props = zpool_validate_properties(hdl, pool, props, 8175094Slling SPA_VERSION_1, B_TRUE, msg)) == NULL) 8185094Slling return (-1); 8195094Slling 8205320Slling if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0) { 8215320Slling nvlist_free(props); 8225094Slling return (-1); 8235320Slling } 824789Sahrens 825789Sahrens (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 826789Sahrens 8274543Smarks if (zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc) != 0) { 8285320Slling 8292676Seschrock zcmd_free_nvlists(&zc); 8305320Slling nvlist_free(props); 8312082Seschrock 832789Sahrens switch (errno) { 833789Sahrens case EBUSY: 834789Sahrens /* 835789Sahrens * This can happen if the user has specified the same 836789Sahrens * device multiple times. We can't reliably detect this 837789Sahrens * until we try to add it and see we already have a 838789Sahrens * label. 839789Sahrens */ 8402082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8412082Seschrock "one or more vdevs refer to the same device")); 8422082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 843789Sahrens 844789Sahrens case EOVERFLOW: 845789Sahrens /* 8462082Seschrock * This occurs when one of the devices is below 847789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 848789Sahrens * device was the problem device since there's no 849789Sahrens * reliable way to determine device size from userland. 850789Sahrens */ 851789Sahrens { 852789Sahrens char buf[64]; 853789Sahrens 854789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 855789Sahrens 8562082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8572082Seschrock "one or more devices is less than the " 8582082Seschrock "minimum size (%s)"), buf); 859789Sahrens } 8602082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 861789Sahrens 862789Sahrens case ENOSPC: 8632082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8642082Seschrock "one or more devices is out of space")); 8652082Seschrock return (zfs_error(hdl, EZFS_BADDEV, msg)); 866789Sahrens 8675450Sbrendan case ENOTBLK: 8685450Sbrendan zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8695450Sbrendan "cache device must be a disk or disk slice")); 8705450Sbrendan return (zfs_error(hdl, EZFS_BADDEV, msg)); 8715450Sbrendan 872789Sahrens default: 8732082Seschrock return (zpool_standard_error(hdl, errno, msg)); 874789Sahrens } 875789Sahrens } 876789Sahrens 877789Sahrens /* 878789Sahrens * If this is an alternate root pool, then we automatically set the 8792676Seschrock * mountpoint of the root dataset to be '/'. 880789Sahrens */ 8815094Slling if (nvlist_lookup_string(props, zpool_prop_to_name(ZPOOL_PROP_ALTROOT), 8825094Slling &altroot) == 0) { 883789Sahrens zfs_handle_t *zhp; 884789Sahrens 8855094Slling verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_DATASET)) != NULL); 8862676Seschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 8872676Seschrock "/") == 0); 888789Sahrens 889789Sahrens zfs_close(zhp); 890789Sahrens } 891789Sahrens 8925320Slling zcmd_free_nvlists(&zc); 8935320Slling nvlist_free(props); 894789Sahrens return (0); 895789Sahrens } 896789Sahrens 897789Sahrens /* 898789Sahrens * Destroy the given pool. It is up to the caller to ensure that there are no 899789Sahrens * datasets left in the pool. 900789Sahrens */ 901789Sahrens int 902789Sahrens zpool_destroy(zpool_handle_t *zhp) 903789Sahrens { 904789Sahrens zfs_cmd_t zc = { 0 }; 905789Sahrens zfs_handle_t *zfp = NULL; 9062082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 9072082Seschrock char msg[1024]; 908789Sahrens 909789Sahrens if (zhp->zpool_state == POOL_STATE_ACTIVE && 9102082Seschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 9112082Seschrock ZFS_TYPE_FILESYSTEM)) == NULL) 912789Sahrens return (-1); 913789Sahrens 9142856Snd150628 if (zpool_remove_zvol_links(zhp) != 0) 915789Sahrens return (-1); 916789Sahrens 917789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 918789Sahrens 9194543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) { 9202082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9212082Seschrock "cannot destroy '%s'"), zhp->zpool_name); 922789Sahrens 9232082Seschrock if (errno == EROFS) { 9242082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9252082Seschrock "one or more devices is read only")); 9262082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 9272082Seschrock } else { 9282082Seschrock (void) zpool_standard_error(hdl, errno, msg); 929789Sahrens } 930789Sahrens 931789Sahrens if (zfp) 932789Sahrens zfs_close(zfp); 933789Sahrens return (-1); 934789Sahrens } 935789Sahrens 936789Sahrens if (zfp) { 937789Sahrens remove_mountpoint(zfp); 938789Sahrens zfs_close(zfp); 939789Sahrens } 940789Sahrens 941789Sahrens return (0); 942789Sahrens } 943789Sahrens 944789Sahrens /* 945789Sahrens * Add the given vdevs to the pool. The caller must have already performed the 946789Sahrens * necessary verification to ensure that the vdev specification is well-formed. 947789Sahrens */ 948789Sahrens int 949789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) 950789Sahrens { 9512676Seschrock zfs_cmd_t zc = { 0 }; 9522082Seschrock int ret; 9532082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 9542082Seschrock char msg[1024]; 9555450Sbrendan nvlist_t **spares, **l2cache; 9565450Sbrendan uint_t nspares, nl2cache; 9572082Seschrock 9582082Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 9592082Seschrock "cannot add to '%s'"), zhp->zpool_name); 9602082Seschrock 9615450Sbrendan if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) < 9625450Sbrendan SPA_VERSION_SPARES && 9632082Seschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 9642082Seschrock &spares, &nspares) == 0) { 9652082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 9662082Seschrock "upgraded to add hot spares")); 9672082Seschrock return (zfs_error(hdl, EZFS_BADVERSION, msg)); 9682082Seschrock } 969789Sahrens 9705450Sbrendan if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) < 9715450Sbrendan SPA_VERSION_L2CACHE && 9725450Sbrendan nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 9735450Sbrendan &l2cache, &nl2cache) == 0) { 9745450Sbrendan zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " 9755450Sbrendan "upgraded to add cache devices")); 9765450Sbrendan return (zfs_error(hdl, EZFS_BADVERSION, msg)); 9775450Sbrendan } 9785450Sbrendan 9795094Slling if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 9802082Seschrock return (-1); 981789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 982789Sahrens 9834543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) { 984789Sahrens switch (errno) { 985789Sahrens case EBUSY: 986789Sahrens /* 987789Sahrens * This can happen if the user has specified the same 988789Sahrens * device multiple times. We can't reliably detect this 989789Sahrens * until we try to add it and see we already have a 990789Sahrens * label. 991789Sahrens */ 9922082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9932082Seschrock "one or more vdevs refer to the same device")); 9942082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 995789Sahrens break; 996789Sahrens 997789Sahrens case EOVERFLOW: 998789Sahrens /* 999789Sahrens * This occurrs when one of the devices is below 1000789Sahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which 1001789Sahrens * device was the problem device since there's no 1002789Sahrens * reliable way to determine device size from userland. 1003789Sahrens */ 1004789Sahrens { 1005789Sahrens char buf[64]; 1006789Sahrens 1007789Sahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); 1008789Sahrens 10092082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10102082Seschrock "device is less than the minimum " 10112082Seschrock "size (%s)"), buf); 1012789Sahrens } 10132082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 10142082Seschrock break; 10152082Seschrock 10162082Seschrock case ENOTSUP: 10172082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10184527Sperrin "pool must be upgraded to add these vdevs")); 10192082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg); 1020789Sahrens break; 1021789Sahrens 10223912Slling case EDOM: 10233912Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10244527Sperrin "root pool can not have multiple vdevs" 10254527Sperrin " or separate logs")); 10263912Slling (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg); 10273912Slling break; 10283912Slling 10295450Sbrendan case ENOTBLK: 10305450Sbrendan zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10315450Sbrendan "cache device must be a disk or disk slice")); 10325450Sbrendan (void) zfs_error(hdl, EZFS_BADDEV, msg); 10335450Sbrendan break; 10345450Sbrendan 1035789Sahrens default: 10362082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1037789Sahrens } 1038789Sahrens 10392082Seschrock ret = -1; 10402082Seschrock } else { 10412082Seschrock ret = 0; 1042789Sahrens } 1043789Sahrens 10442676Seschrock zcmd_free_nvlists(&zc); 1045789Sahrens 10462082Seschrock return (ret); 1047789Sahrens } 1048789Sahrens 1049789Sahrens /* 1050789Sahrens * Exports the pool from the system. The caller must ensure that there are no 1051789Sahrens * mounted datasets in the pool. 1052789Sahrens */ 1053789Sahrens int 1054789Sahrens zpool_export(zpool_handle_t *zhp) 1055789Sahrens { 1056789Sahrens zfs_cmd_t zc = { 0 }; 1057789Sahrens 1058789Sahrens if (zpool_remove_zvol_links(zhp) != 0) 1059789Sahrens return (-1); 1060789Sahrens 1061789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1062789Sahrens 10634543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) 10643237Slling return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, 10652082Seschrock dgettext(TEXT_DOMAIN, "cannot export '%s'"), 10662082Seschrock zhp->zpool_name)); 1067789Sahrens return (0); 1068789Sahrens } 1069789Sahrens 1070789Sahrens /* 10715094Slling * zpool_import() is a contracted interface. Should be kept the same 10725094Slling * if possible. 10735094Slling * 10745094Slling * Applications should use zpool_import_props() to import a pool with 10755094Slling * new properties value to be set. 1076789Sahrens */ 1077789Sahrens int 10782082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 10795094Slling char *altroot) 10805094Slling { 10815094Slling nvlist_t *props = NULL; 10825094Slling int ret; 10835094Slling 10845094Slling if (altroot != NULL) { 10855094Slling if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 10865094Slling return (zfs_error_fmt(hdl, EZFS_NOMEM, 10875094Slling dgettext(TEXT_DOMAIN, "cannot import '%s'"), 10885094Slling newname)); 10895094Slling } 10905094Slling 10915094Slling if (nvlist_add_string(props, 10925094Slling zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0) { 10935094Slling nvlist_free(props); 10945094Slling return (zfs_error_fmt(hdl, EZFS_NOMEM, 10955094Slling dgettext(TEXT_DOMAIN, "cannot import '%s'"), 10965094Slling newname)); 10975094Slling } 10985094Slling } 10995094Slling 11006643Seschrock ret = zpool_import_props(hdl, config, newname, props, B_FALSE); 11015094Slling if (props) 11025094Slling nvlist_free(props); 11035094Slling return (ret); 11045094Slling } 11055094Slling 11065094Slling /* 11075094Slling * Import the given pool using the known configuration and a list of 11085094Slling * properties to be set. The configuration should have come from 11095094Slling * zpool_find_import(). The 'newname' parameters control whether the pool 11105094Slling * is imported with a different name. 11115094Slling */ 11125094Slling int 11135094Slling zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname, 11146643Seschrock nvlist_t *props, boolean_t importfaulted) 1115789Sahrens { 11162676Seschrock zfs_cmd_t zc = { 0 }; 1117789Sahrens char *thename; 1118789Sahrens char *origname; 1119789Sahrens int ret; 11205094Slling char errbuf[1024]; 1121789Sahrens 1122789Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1123789Sahrens &origname) == 0); 1124789Sahrens 11255094Slling (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 11265094Slling "cannot import pool '%s'"), origname); 11275094Slling 1128789Sahrens if (newname != NULL) { 11292082Seschrock if (!zpool_name_valid(hdl, B_FALSE, newname)) 11303237Slling return (zfs_error_fmt(hdl, EZFS_INVALIDNAME, 11312082Seschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"), 11322082Seschrock newname)); 1133789Sahrens thename = (char *)newname; 1134789Sahrens } else { 1135789Sahrens thename = origname; 1136789Sahrens } 1137789Sahrens 11385094Slling if (props) { 11395094Slling uint64_t version; 11405094Slling 11415094Slling verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 11425094Slling &version) == 0); 11435094Slling 11445094Slling if ((props = zpool_validate_properties(hdl, origname, 11455320Slling props, version, B_TRUE, errbuf)) == NULL) { 11465094Slling return (-1); 11475320Slling } else if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) { 11485320Slling nvlist_free(props); 11495094Slling return (-1); 11505320Slling } 11515094Slling } 1152789Sahrens 1153789Sahrens (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name)); 1154789Sahrens 1155789Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 11561544Seschrock &zc.zc_guid) == 0); 1157789Sahrens 11585320Slling if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) { 11595320Slling nvlist_free(props); 11602082Seschrock return (-1); 11615320Slling } 1162789Sahrens 11636643Seschrock zc.zc_cookie = (uint64_t)importfaulted; 1164789Sahrens ret = 0; 11654543Smarks if (zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc) != 0) { 1166789Sahrens char desc[1024]; 1167789Sahrens if (newname == NULL) 1168789Sahrens (void) snprintf(desc, sizeof (desc), 1169789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"), 1170789Sahrens thename); 1171789Sahrens else 1172789Sahrens (void) snprintf(desc, sizeof (desc), 1173789Sahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"), 1174789Sahrens origname, thename); 1175789Sahrens 1176789Sahrens switch (errno) { 11771544Seschrock case ENOTSUP: 11781544Seschrock /* 11791544Seschrock * Unsupported version. 11801544Seschrock */ 11812082Seschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc); 11821544Seschrock break; 11831544Seschrock 11842174Seschrock case EINVAL: 11852174Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc); 11862174Seschrock break; 11872174Seschrock 1188789Sahrens default: 11892082Seschrock (void) zpool_standard_error(hdl, errno, desc); 1190789Sahrens } 1191789Sahrens 1192789Sahrens ret = -1; 1193789Sahrens } else { 1194789Sahrens zpool_handle_t *zhp; 11954543Smarks 1196789Sahrens /* 1197789Sahrens * This should never fail, but play it safe anyway. 1198789Sahrens */ 11992142Seschrock if (zpool_open_silent(hdl, thename, &zhp) != 0) { 12002142Seschrock ret = -1; 12012142Seschrock } else if (zhp != NULL) { 1202789Sahrens ret = zpool_create_zvol_links(zhp); 1203789Sahrens zpool_close(zhp); 1204789Sahrens } 12054543Smarks 1206789Sahrens } 1207789Sahrens 12082676Seschrock zcmd_free_nvlists(&zc); 12095320Slling nvlist_free(props); 12105320Slling 1211789Sahrens return (ret); 1212789Sahrens } 1213789Sahrens 1214789Sahrens /* 1215789Sahrens * Scrub the pool. 1216789Sahrens */ 1217789Sahrens int 1218789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type) 1219789Sahrens { 1220789Sahrens zfs_cmd_t zc = { 0 }; 1221789Sahrens char msg[1024]; 12222082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1223789Sahrens 1224789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 1225789Sahrens zc.zc_cookie = type; 1226789Sahrens 12274543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SCRUB, &zc) == 0) 1228789Sahrens return (0); 1229789Sahrens 1230789Sahrens (void) snprintf(msg, sizeof (msg), 1231789Sahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); 1232789Sahrens 12332082Seschrock if (errno == EBUSY) 12342082Seschrock return (zfs_error(hdl, EZFS_RESILVERING, msg)); 12352082Seschrock else 12362082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1237789Sahrens } 1238789Sahrens 12392468Sek110237 /* 12402468Sek110237 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL 12412468Sek110237 * spare; but FALSE if its an INUSE spare. 12422468Sek110237 */ 12432082Seschrock static nvlist_t * 12442082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid, 12455450Sbrendan boolean_t *avail_spare, boolean_t *l2cache) 12461544Seschrock { 12471544Seschrock uint_t c, children; 12481544Seschrock nvlist_t **child; 12492082Seschrock uint64_t theguid, present; 12501544Seschrock char *path; 12511544Seschrock uint64_t wholedisk = 0; 12522082Seschrock nvlist_t *ret; 12531544Seschrock 12542082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0); 12551544Seschrock 12561544Seschrock if (search == NULL && 12571544Seschrock nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) { 12581544Seschrock /* 12591544Seschrock * If the device has never been present since import, the only 12601544Seschrock * reliable way to match the vdev is by GUID. 12611544Seschrock */ 12622082Seschrock if (theguid == guid) 12632082Seschrock return (nv); 12641544Seschrock } else if (search != NULL && 12651544Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 12661544Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 12671544Seschrock &wholedisk); 12681544Seschrock if (wholedisk) { 12691544Seschrock /* 12701544Seschrock * For whole disks, the internal path has 's0', but the 12711544Seschrock * path passed in by the user doesn't. 12721544Seschrock */ 12731544Seschrock if (strlen(search) == strlen(path) - 2 && 12741544Seschrock strncmp(search, path, strlen(search)) == 0) 12752082Seschrock return (nv); 12761544Seschrock } else if (strcmp(search, path) == 0) { 12772082Seschrock return (nv); 12781544Seschrock } 12791544Seschrock } 12801544Seschrock 12811544Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 12821544Seschrock &child, &children) != 0) 12832082Seschrock return (NULL); 12841544Seschrock 12851544Seschrock for (c = 0; c < children; c++) 12862082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 12875450Sbrendan avail_spare, l2cache)) != NULL) 12881544Seschrock return (ret); 12891544Seschrock 12902082Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 12912082Seschrock &child, &children) == 0) { 12922082Seschrock for (c = 0; c < children; c++) { 12932082Seschrock if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 12945450Sbrendan avail_spare, l2cache)) != NULL) { 12952468Sek110237 *avail_spare = B_TRUE; 12962082Seschrock return (ret); 12972082Seschrock } 12982082Seschrock } 12992082Seschrock } 13002082Seschrock 13015450Sbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 13025450Sbrendan &child, &children) == 0) { 13035450Sbrendan for (c = 0; c < children; c++) { 13045450Sbrendan if ((ret = vdev_to_nvlist_iter(child[c], search, guid, 13055450Sbrendan avail_spare, l2cache)) != NULL) { 13065450Sbrendan *l2cache = B_TRUE; 13075450Sbrendan return (ret); 13085450Sbrendan } 13095450Sbrendan } 13105450Sbrendan } 13115450Sbrendan 13122082Seschrock return (NULL); 13131544Seschrock } 13141544Seschrock 13152082Seschrock nvlist_t * 13165450Sbrendan zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare, 13175450Sbrendan boolean_t *l2cache) 13181544Seschrock { 13191544Seschrock char buf[MAXPATHLEN]; 13201544Seschrock const char *search; 13211544Seschrock char *end; 13221544Seschrock nvlist_t *nvroot; 13231544Seschrock uint64_t guid; 13241544Seschrock 13251613Seschrock guid = strtoull(path, &end, 10); 13261544Seschrock if (guid != 0 && *end == '\0') { 13271544Seschrock search = NULL; 13281544Seschrock } else if (path[0] != '/') { 13291544Seschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path); 13301544Seschrock search = buf; 13311544Seschrock } else { 13321544Seschrock search = path; 13331544Seschrock } 13341544Seschrock 13351544Seschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 13361544Seschrock &nvroot) == 0); 13371544Seschrock 13382468Sek110237 *avail_spare = B_FALSE; 13395450Sbrendan *l2cache = B_FALSE; 13405450Sbrendan return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare, 13415450Sbrendan l2cache)); 13422468Sek110237 } 13432468Sek110237 13442468Sek110237 /* 13455450Sbrendan * Returns TRUE if the given guid corresponds to the given type. 13465450Sbrendan * This is used to check for hot spares (INUSE or not), and level 2 cache 13475450Sbrendan * devices. 13482468Sek110237 */ 13492468Sek110237 static boolean_t 13505450Sbrendan is_guid_type(zpool_handle_t *zhp, uint64_t guid, const char *type) 13512468Sek110237 { 13525450Sbrendan uint64_t target_guid; 13532468Sek110237 nvlist_t *nvroot; 13545450Sbrendan nvlist_t **list; 13555450Sbrendan uint_t count; 13562468Sek110237 int i; 13572468Sek110237 13582468Sek110237 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 13592468Sek110237 &nvroot) == 0); 13605450Sbrendan if (nvlist_lookup_nvlist_array(nvroot, type, &list, &count) == 0) { 13615450Sbrendan for (i = 0; i < count; i++) { 13625450Sbrendan verify(nvlist_lookup_uint64(list[i], ZPOOL_CONFIG_GUID, 13635450Sbrendan &target_guid) == 0); 13645450Sbrendan if (guid == target_guid) 13652468Sek110237 return (B_TRUE); 13662468Sek110237 } 13672468Sek110237 } 13682468Sek110237 13692468Sek110237 return (B_FALSE); 13701544Seschrock } 13711544Seschrock 1372789Sahrens /* 13734451Seschrock * Bring the specified vdev online. The 'flags' parameter is a set of the 13744451Seschrock * ZFS_ONLINE_* flags. 1375789Sahrens */ 1376789Sahrens int 13774451Seschrock zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags, 13784451Seschrock vdev_state_t *newstate) 1379789Sahrens { 1380789Sahrens zfs_cmd_t zc = { 0 }; 1381789Sahrens char msg[1024]; 13822082Seschrock nvlist_t *tgt; 13835450Sbrendan boolean_t avail_spare, l2cache; 13842082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1385789Sahrens 13861544Seschrock (void) snprintf(msg, sizeof (msg), 13871544Seschrock dgettext(TEXT_DOMAIN, "cannot online %s"), path); 1388789Sahrens 13891544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 13905450Sbrendan if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache)) == NULL) 13912082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1392789Sahrens 13932468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 13942468Sek110237 13955450Sbrendan if (avail_spare || 13965450Sbrendan is_guid_type(zhp, zc.zc_guid, ZPOOL_CONFIG_SPARES) == B_TRUE) 13972082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 13982082Seschrock 13994451Seschrock zc.zc_cookie = VDEV_STATE_ONLINE; 14004451Seschrock zc.zc_obj = flags; 14014451Seschrock 14024543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) 14034451Seschrock return (zpool_standard_error(hdl, errno, msg)); 14044451Seschrock 14054451Seschrock *newstate = zc.zc_cookie; 14064451Seschrock return (0); 1407789Sahrens } 1408789Sahrens 1409789Sahrens /* 1410789Sahrens * Take the specified vdev offline 1411789Sahrens */ 1412789Sahrens int 14134451Seschrock zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp) 1414789Sahrens { 1415789Sahrens zfs_cmd_t zc = { 0 }; 1416789Sahrens char msg[1024]; 14172082Seschrock nvlist_t *tgt; 14185450Sbrendan boolean_t avail_spare, l2cache; 14192082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1420789Sahrens 14211544Seschrock (void) snprintf(msg, sizeof (msg), 14221544Seschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path); 14231544Seschrock 1424789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 14255450Sbrendan if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache)) == NULL) 14262082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 14272082Seschrock 14282468Sek110237 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 14292468Sek110237 14305450Sbrendan if (avail_spare || 14315450Sbrendan is_guid_type(zhp, zc.zc_guid, ZPOOL_CONFIG_SPARES) == B_TRUE) 14322082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 14332082Seschrock 14344451Seschrock zc.zc_cookie = VDEV_STATE_OFFLINE; 14354451Seschrock zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0; 14361485Slling 14374543Smarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 1438789Sahrens return (0); 1439789Sahrens 1440789Sahrens switch (errno) { 14412082Seschrock case EBUSY: 1442789Sahrens 1443789Sahrens /* 1444789Sahrens * There are no other replicas of this device. 1445789Sahrens */ 14462082Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 14472082Seschrock 14482082Seschrock default: 14492082Seschrock return (zpool_standard_error(hdl, errno, msg)); 14502082Seschrock } 14512082Seschrock } 1452789Sahrens 14532082Seschrock /* 14544451Seschrock * Mark the given vdev faulted. 14554451Seschrock */ 14564451Seschrock int 14574451Seschrock zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid) 14584451Seschrock { 14594451Seschrock zfs_cmd_t zc = { 0 }; 14604451Seschrock char msg[1024]; 14614451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 14624451Seschrock 14634451Seschrock (void) snprintf(msg, sizeof (msg), 14644451Seschrock dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid); 14654451Seschrock 14664451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 14674451Seschrock zc.zc_guid = guid; 14684451Seschrock zc.zc_cookie = VDEV_STATE_FAULTED; 14694451Seschrock 14704451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 14714451Seschrock return (0); 14724451Seschrock 14734451Seschrock switch (errno) { 14744451Seschrock case EBUSY: 14754451Seschrock 14764451Seschrock /* 14774451Seschrock * There are no other replicas of this device. 14784451Seschrock */ 14794451Seschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg)); 14804451Seschrock 14814451Seschrock default: 14824451Seschrock return (zpool_standard_error(hdl, errno, msg)); 14834451Seschrock } 14844451Seschrock 14854451Seschrock } 14864451Seschrock 14874451Seschrock /* 14884451Seschrock * Mark the given vdev degraded. 14894451Seschrock */ 14904451Seschrock int 14914451Seschrock zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid) 14924451Seschrock { 14934451Seschrock zfs_cmd_t zc = { 0 }; 14944451Seschrock char msg[1024]; 14954451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 14964451Seschrock 14974451Seschrock (void) snprintf(msg, sizeof (msg), 14984451Seschrock dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid); 14994451Seschrock 15004451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 15014451Seschrock zc.zc_guid = guid; 15024451Seschrock zc.zc_cookie = VDEV_STATE_DEGRADED; 15034451Seschrock 15044451Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 15054451Seschrock return (0); 15064451Seschrock 15074451Seschrock return (zpool_standard_error(hdl, errno, msg)); 15084451Seschrock } 15094451Seschrock 15104451Seschrock /* 15112082Seschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as 15122082Seschrock * a hot spare. 15132082Seschrock */ 15142082Seschrock static boolean_t 15152082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which) 15162082Seschrock { 15172082Seschrock nvlist_t **child; 15182082Seschrock uint_t c, children; 15192082Seschrock char *type; 15202082Seschrock 15212082Seschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child, 15222082Seschrock &children) == 0) { 15232082Seschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE, 15242082Seschrock &type) == 0); 15252082Seschrock 15262082Seschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 && 15272082Seschrock children == 2 && child[which] == tgt) 15282082Seschrock return (B_TRUE); 15292082Seschrock 15302082Seschrock for (c = 0; c < children; c++) 15312082Seschrock if (is_replacing_spare(child[c], tgt, which)) 15322082Seschrock return (B_TRUE); 1533789Sahrens } 15342082Seschrock 15352082Seschrock return (B_FALSE); 1536789Sahrens } 1537789Sahrens 1538789Sahrens /* 1539789Sahrens * Attach new_disk (fully described by nvroot) to old_disk. 15404527Sperrin * If 'replacing' is specified, the new disk will replace the old one. 1541789Sahrens */ 1542789Sahrens int 1543789Sahrens zpool_vdev_attach(zpool_handle_t *zhp, 1544789Sahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing) 1545789Sahrens { 1546789Sahrens zfs_cmd_t zc = { 0 }; 1547789Sahrens char msg[1024]; 1548789Sahrens int ret; 15492082Seschrock nvlist_t *tgt; 15505450Sbrendan boolean_t avail_spare, l2cache; 15514527Sperrin uint64_t val, is_log; 15527041Seschrock char *path, *newname; 15532082Seschrock nvlist_t **child; 15542082Seschrock uint_t children; 15552082Seschrock nvlist_t *config_root; 15562082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1557789Sahrens 15581544Seschrock if (replacing) 15591544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 15601544Seschrock "cannot replace %s with %s"), old_disk, new_disk); 15611544Seschrock else 15621544Seschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, 15631544Seschrock "cannot attach %s to %s"), new_disk, old_disk); 15641544Seschrock 1565789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 15665450Sbrendan if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache)) == 0) 15672082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 15682082Seschrock 15692468Sek110237 if (avail_spare) 15702082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 15712082Seschrock 15725450Sbrendan if (l2cache) 15735450Sbrendan return (zfs_error(hdl, EZFS_ISL2CACHE, msg)); 15745450Sbrendan 15752082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 15762082Seschrock zc.zc_cookie = replacing; 15772082Seschrock 15782082Seschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 15792082Seschrock &child, &children) != 0 || children != 1) { 15802082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 15812082Seschrock "new device must be a single disk")); 15822082Seschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg)); 15831544Seschrock } 15842082Seschrock 15852082Seschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 15862082Seschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); 15872082Seschrock 15887041Seschrock if ((newname = zpool_vdev_name(NULL, NULL, child[0])) == NULL) 15897041Seschrock return (-1); 15907041Seschrock 15912082Seschrock /* 15922082Seschrock * If the target is a hot spare that has been swapped in, we can only 15932082Seschrock * replace it with another hot spare. 15942082Seschrock */ 15952082Seschrock if (replacing && 15962082Seschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 && 15977041Seschrock (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache) == NULL || 15982468Sek110237 !avail_spare) && is_replacing_spare(config_root, tgt, 1)) { 15992082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 16002082Seschrock "can only be replaced by another hot spare")); 16017041Seschrock free(newname); 16022082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 16032082Seschrock } 16042082Seschrock 16052082Seschrock /* 16062082Seschrock * If we are attempting to replace a spare, it canot be applied to an 16072082Seschrock * already spared device. 16082082Seschrock */ 16092082Seschrock if (replacing && 16102082Seschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 && 16117041Seschrock zpool_find_vdev(zhp, newname, &avail_spare, &l2cache) != NULL && 16125450Sbrendan avail_spare && is_replacing_spare(config_root, tgt, 0)) { 16132082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 16142082Seschrock "device has already been replaced with a spare")); 16157041Seschrock free(newname); 16162082Seschrock return (zfs_error(hdl, EZFS_BADTARGET, msg)); 16172082Seschrock } 1618789Sahrens 16197041Seschrock free(newname); 16207041Seschrock 16215094Slling if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0) 16222082Seschrock return (-1); 1623789Sahrens 16244543Smarks ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ATTACH, &zc); 1625789Sahrens 16262676Seschrock zcmd_free_nvlists(&zc); 1627789Sahrens 1628789Sahrens if (ret == 0) 1629789Sahrens return (0); 1630789Sahrens 1631789Sahrens switch (errno) { 16321544Seschrock case ENOTSUP: 1633789Sahrens /* 1634789Sahrens * Can't attach to or replace this type of vdev. 1635789Sahrens */ 16364527Sperrin if (replacing) { 16374527Sperrin is_log = B_FALSE; 16384527Sperrin (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_LOG, 16394527Sperrin &is_log); 16404527Sperrin if (is_log) 16414527Sperrin zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 16424527Sperrin "cannot replace a log with a spare")); 16434527Sperrin else 16444527Sperrin zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 16454527Sperrin "cannot replace a replacing device")); 16464527Sperrin } else { 16472082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 16482082Seschrock "can only attach to mirrors and top-level " 16492082Seschrock "disks")); 16504527Sperrin } 16512082Seschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg); 1652789Sahrens break; 1653789Sahrens 16541544Seschrock case EINVAL: 1655789Sahrens /* 1656789Sahrens * The new device must be a single disk. 1657789Sahrens */ 16582082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 16592082Seschrock "new device must be a single disk")); 16602082Seschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg); 1661789Sahrens break; 1662789Sahrens 16631544Seschrock case EBUSY: 16642082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), 16652082Seschrock new_disk); 16662082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1667789Sahrens break; 1668789Sahrens 16691544Seschrock case EOVERFLOW: 1670789Sahrens /* 1671789Sahrens * The new device is too small. 1672789Sahrens */ 16732082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 16742082Seschrock "device is too small")); 16752082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1676789Sahrens break; 1677789Sahrens 16781544Seschrock case EDOM: 1679789Sahrens /* 1680789Sahrens * The new device has a different alignment requirement. 1681789Sahrens */ 16822082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 16832082Seschrock "devices have different sector alignment")); 16842082Seschrock (void) zfs_error(hdl, EZFS_BADDEV, msg); 1685789Sahrens break; 1686789Sahrens 16871544Seschrock case ENAMETOOLONG: 1688789Sahrens /* 1689789Sahrens * The resulting top-level vdev spec won't fit in the label. 1690789Sahrens */ 16912082Seschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg); 1692789Sahrens break; 1693789Sahrens 16941544Seschrock default: 16952082Seschrock (void) zpool_standard_error(hdl, errno, msg); 1696789Sahrens } 1697789Sahrens 16982082Seschrock return (-1); 1699789Sahrens } 1700789Sahrens 1701789Sahrens /* 1702789Sahrens * Detach the specified device. 1703789Sahrens */ 1704789Sahrens int 1705789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path) 1706789Sahrens { 1707789Sahrens zfs_cmd_t zc = { 0 }; 1708789Sahrens char msg[1024]; 17092082Seschrock nvlist_t *tgt; 17105450Sbrendan boolean_t avail_spare, l2cache; 17112082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1712789Sahrens 17131544Seschrock (void) snprintf(msg, sizeof (msg), 17141544Seschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path); 17151544Seschrock 1716789Sahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 17175450Sbrendan if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache)) == 0) 17182082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 1719789Sahrens 17202468Sek110237 if (avail_spare) 17212082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 17222082Seschrock 17235450Sbrendan if (l2cache) 17245450Sbrendan return (zfs_error(hdl, EZFS_ISL2CACHE, msg)); 17255450Sbrendan 17262082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 17272082Seschrock 17284543Smarks if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0) 1729789Sahrens return (0); 1730789Sahrens 1731789Sahrens switch (errno) { 1732789Sahrens 17331544Seschrock case ENOTSUP: 1734789Sahrens /* 1735789Sahrens * Can't detach from this type of vdev. 1736789Sahrens */ 17372082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only " 17382082Seschrock "applicable to mirror and replacing vdevs")); 17392082Seschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg); 1740789Sahrens break; 1741789Sahrens 17421544Seschrock case EBUSY: 1743789Sahrens /* 1744789Sahrens * There are no other replicas of this device. 1745789Sahrens */ 17462082Seschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg); 1747789Sahrens break; 1748789Sahrens 17491544Seschrock default: 17502082Seschrock (void) zpool_standard_error(hdl, errno, msg); 17511544Seschrock } 17521544Seschrock 17532082Seschrock return (-1); 17542082Seschrock } 17552082Seschrock 17562082Seschrock /* 17575450Sbrendan * Remove the given device. Currently, this is supported only for hot spares 17585450Sbrendan * and level 2 cache devices. 17592082Seschrock */ 17602082Seschrock int 17612082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path) 17622082Seschrock { 17632082Seschrock zfs_cmd_t zc = { 0 }; 17642082Seschrock char msg[1024]; 17652082Seschrock nvlist_t *tgt; 17665450Sbrendan boolean_t avail_spare, l2cache; 17672082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 17682082Seschrock 17692082Seschrock (void) snprintf(msg, sizeof (msg), 17702082Seschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path); 17712082Seschrock 17722082Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 17735450Sbrendan if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache)) == 0) 17742082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 17752082Seschrock 17765450Sbrendan if (!avail_spare && !l2cache) { 17772082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 17785450Sbrendan "only inactive hot spares or cache devices " 17795450Sbrendan "can be removed")); 17802082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 17812082Seschrock } 17822082Seschrock 17832082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0); 17842082Seschrock 17854543Smarks if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0) 17862082Seschrock return (0); 17872082Seschrock 17882082Seschrock return (zpool_standard_error(hdl, errno, msg)); 17891544Seschrock } 17901544Seschrock 17911544Seschrock /* 17921544Seschrock * Clear the errors for the pool, or the particular device if specified. 17931544Seschrock */ 17941544Seschrock int 17951544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path) 17961544Seschrock { 17971544Seschrock zfs_cmd_t zc = { 0 }; 17981544Seschrock char msg[1024]; 17992082Seschrock nvlist_t *tgt; 18005450Sbrendan boolean_t avail_spare, l2cache; 18012082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 18021544Seschrock 18031544Seschrock if (path) 18041544Seschrock (void) snprintf(msg, sizeof (msg), 18051544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 18062676Seschrock path); 18071544Seschrock else 18081544Seschrock (void) snprintf(msg, sizeof (msg), 18091544Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"), 18101544Seschrock zhp->zpool_name); 18111544Seschrock 18121544Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 18132082Seschrock if (path) { 18145450Sbrendan if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, 18155450Sbrendan &l2cache)) == 0) 18162082Seschrock return (zfs_error(hdl, EZFS_NODEVICE, msg)); 18172082Seschrock 18185450Sbrendan /* 18195450Sbrendan * Don't allow error clearing for hot spares. Do allow 18205450Sbrendan * error clearing for l2cache devices. 18215450Sbrendan */ 18222468Sek110237 if (avail_spare) 18232082Seschrock return (zfs_error(hdl, EZFS_ISSPARE, msg)); 18242082Seschrock 18252082Seschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, 18262082Seschrock &zc.zc_guid) == 0); 18271544Seschrock } 18281544Seschrock 18294543Smarks if (zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc) == 0) 18301544Seschrock return (0); 18311544Seschrock 18322082Seschrock return (zpool_standard_error(hdl, errno, msg)); 1833789Sahrens } 1834789Sahrens 18353126Sahl /* 18364451Seschrock * Similar to zpool_clear(), but takes a GUID (used by fmd). 18374451Seschrock */ 18384451Seschrock int 18394451Seschrock zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid) 18404451Seschrock { 18414451Seschrock zfs_cmd_t zc = { 0 }; 18424451Seschrock char msg[1024]; 18434451Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 18444451Seschrock 18454451Seschrock (void) snprintf(msg, sizeof (msg), 18464451Seschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"), 18474451Seschrock guid); 18484451Seschrock 18494451Seschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 18504451Seschrock zc.zc_guid = guid; 18514451Seschrock 18524451Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0) 18534451Seschrock return (0); 18544451Seschrock 18554451Seschrock return (zpool_standard_error(hdl, errno, msg)); 18564451Seschrock } 18574451Seschrock 18584451Seschrock /* 18593126Sahl * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> 18603126Sahl * hierarchy. 18613126Sahl */ 18623126Sahl int 18633126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *), 18643126Sahl void *data) 1865789Sahrens { 18663126Sahl libzfs_handle_t *hdl = zhp->zpool_hdl; 18673126Sahl char (*paths)[MAXPATHLEN]; 18683126Sahl size_t size = 4; 18693126Sahl int curr, fd, base, ret = 0; 18703126Sahl DIR *dirp; 18713126Sahl struct dirent *dp; 18723126Sahl struct stat st; 18733126Sahl 18743126Sahl if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0) 18753126Sahl return (errno == ENOENT ? 0 : -1); 18763126Sahl 18773126Sahl if (fstatat(base, zhp->zpool_name, &st, 0) != 0) { 18783126Sahl int err = errno; 18793126Sahl (void) close(base); 18803126Sahl return (err == ENOENT ? 0 : -1); 18813126Sahl } 1882789Sahrens 1883789Sahrens /* 18843126Sahl * Oddly this wasn't a directory -- ignore that failure since we 18853126Sahl * know there are no links lower in the (non-existant) hierarchy. 1886789Sahrens */ 18873126Sahl if (!S_ISDIR(st.st_mode)) { 18883126Sahl (void) close(base); 18893126Sahl return (0); 18903126Sahl } 18913126Sahl 18923126Sahl if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) { 18933126Sahl (void) close(base); 18943126Sahl return (-1); 1895789Sahrens } 1896789Sahrens 18973126Sahl (void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0])); 18983126Sahl curr = 0; 18993126Sahl 19003126Sahl while (curr >= 0) { 19013126Sahl if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0) 19023126Sahl goto err; 19033126Sahl 19043126Sahl if (S_ISDIR(st.st_mode)) { 19053126Sahl if ((fd = openat(base, paths[curr], O_RDONLY)) < 0) 19063126Sahl goto err; 19073126Sahl 19083126Sahl if ((dirp = fdopendir(fd)) == NULL) { 19093126Sahl (void) close(fd); 19103126Sahl goto err; 19113126Sahl } 19123126Sahl 19133126Sahl while ((dp = readdir(dirp)) != NULL) { 19143126Sahl if (dp->d_name[0] == '.') 19153126Sahl continue; 19163126Sahl 19173126Sahl if (curr + 1 == size) { 19183126Sahl paths = zfs_realloc(hdl, paths, 19193126Sahl size * sizeof (paths[0]), 19203126Sahl size * 2 * sizeof (paths[0])); 19213126Sahl if (paths == NULL) { 19223126Sahl (void) closedir(dirp); 19233126Sahl (void) close(fd); 19243126Sahl goto err; 19253126Sahl } 19263126Sahl 19273126Sahl size *= 2; 19283126Sahl } 19293126Sahl 19303126Sahl (void) strlcpy(paths[curr + 1], paths[curr], 19313126Sahl sizeof (paths[curr + 1])); 19323126Sahl (void) strlcat(paths[curr], "/", 19333126Sahl sizeof (paths[curr])); 19343126Sahl (void) strlcat(paths[curr], dp->d_name, 19353126Sahl sizeof (paths[curr])); 19363126Sahl curr++; 19373126Sahl } 19383126Sahl 19393126Sahl (void) closedir(dirp); 19403126Sahl 19413126Sahl } else { 19423126Sahl if ((ret = cb(paths[curr], data)) != 0) 19433126Sahl break; 19443126Sahl } 19453126Sahl 19463126Sahl curr--; 19473126Sahl } 19483126Sahl 19493126Sahl free(paths); 19503126Sahl (void) close(base); 19513126Sahl 19523126Sahl return (ret); 19533126Sahl 19543126Sahl err: 19553126Sahl free(paths); 19563126Sahl (void) close(base); 19573126Sahl return (-1); 19583126Sahl } 19593126Sahl 19603126Sahl typedef struct zvol_cb { 19613126Sahl zpool_handle_t *zcb_pool; 19623126Sahl boolean_t zcb_create; 19633126Sahl } zvol_cb_t; 19643126Sahl 19653126Sahl /*ARGSUSED*/ 19663126Sahl static int 19673126Sahl do_zvol_create(zfs_handle_t *zhp, void *data) 19683126Sahl { 19694657Sahrens int ret = 0; 19703126Sahl 19714657Sahrens if (ZFS_IS_VOLUME(zhp)) { 19723126Sahl (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 19734657Sahrens ret = zfs_iter_snapshots(zhp, do_zvol_create, NULL); 19744657Sahrens } 19753126Sahl 19764657Sahrens if (ret == 0) 19774657Sahrens ret = zfs_iter_filesystems(zhp, do_zvol_create, NULL); 1978789Sahrens 1979789Sahrens zfs_close(zhp); 19803126Sahl 1981789Sahrens return (ret); 1982789Sahrens } 1983789Sahrens 1984789Sahrens /* 1985789Sahrens * Iterate over all zvols in the pool and make any necessary minor nodes. 1986789Sahrens */ 1987789Sahrens int 1988789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp) 1989789Sahrens { 1990789Sahrens zfs_handle_t *zfp; 1991789Sahrens int ret; 1992789Sahrens 1993789Sahrens /* 1994789Sahrens * If the pool is unavailable, just return success. 1995789Sahrens */ 19962082Seschrock if ((zfp = make_dataset_handle(zhp->zpool_hdl, 19972082Seschrock zhp->zpool_name)) == NULL) 1998789Sahrens return (0); 1999789Sahrens 20004657Sahrens ret = zfs_iter_filesystems(zfp, do_zvol_create, NULL); 2001789Sahrens 2002789Sahrens zfs_close(zfp); 2003789Sahrens return (ret); 2004789Sahrens } 2005789Sahrens 20063126Sahl static int 20073126Sahl do_zvol_remove(const char *dataset, void *data) 20083126Sahl { 20093126Sahl zpool_handle_t *zhp = data; 20103126Sahl 20113126Sahl return (zvol_remove_link(zhp->zpool_hdl, dataset)); 20123126Sahl } 20133126Sahl 2014789Sahrens /* 20153126Sahl * Iterate over all zvols in the pool and remove any minor nodes. We iterate 20163126Sahl * by examining the /dev links so that a corrupted pool doesn't impede this 20173126Sahl * operation. 2018789Sahrens */ 2019789Sahrens int 2020789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp) 2021789Sahrens { 20223126Sahl return (zpool_iter_zvol(zhp, do_zvol_remove, zhp)); 2023789Sahrens } 20241354Seschrock 20251354Seschrock /* 20261354Seschrock * Convert from a devid string to a path. 20271354Seschrock */ 20281354Seschrock static char * 20291354Seschrock devid_to_path(char *devid_str) 20301354Seschrock { 20311354Seschrock ddi_devid_t devid; 20321354Seschrock char *minor; 20331354Seschrock char *path; 20341354Seschrock devid_nmlist_t *list = NULL; 20351354Seschrock int ret; 20361354Seschrock 20371354Seschrock if (devid_str_decode(devid_str, &devid, &minor) != 0) 20381354Seschrock return (NULL); 20391354Seschrock 20401354Seschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list); 20411354Seschrock 20421354Seschrock devid_str_free(minor); 20431354Seschrock devid_free(devid); 20441354Seschrock 20451354Seschrock if (ret != 0) 20461354Seschrock return (NULL); 20471354Seschrock 20482082Seschrock if ((path = strdup(list[0].devname)) == NULL) 20492082Seschrock return (NULL); 20502082Seschrock 20511354Seschrock devid_free_nmlist(list); 20521354Seschrock 20531354Seschrock return (path); 20541354Seschrock } 20551354Seschrock 20561354Seschrock /* 20571354Seschrock * Convert from a path to a devid string. 20581354Seschrock */ 20591354Seschrock static char * 20601354Seschrock path_to_devid(const char *path) 20611354Seschrock { 20621354Seschrock int fd; 20631354Seschrock ddi_devid_t devid; 20641354Seschrock char *minor, *ret; 20651354Seschrock 20661354Seschrock if ((fd = open(path, O_RDONLY)) < 0) 20671354Seschrock return (NULL); 20681354Seschrock 20691354Seschrock minor = NULL; 20701354Seschrock ret = NULL; 20711354Seschrock if (devid_get(fd, &devid) == 0) { 20721354Seschrock if (devid_get_minor_name(fd, &minor) == 0) 20731354Seschrock ret = devid_str_encode(devid, minor); 20741354Seschrock if (minor != NULL) 20751354Seschrock devid_str_free(minor); 20761354Seschrock devid_free(devid); 20771354Seschrock } 20781354Seschrock (void) close(fd); 20791354Seschrock 20801354Seschrock return (ret); 20811354Seschrock } 20821354Seschrock 20831354Seschrock /* 20841354Seschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We 20851354Seschrock * ignore any failure here, since a common case is for an unprivileged user to 20861354Seschrock * type 'zpool status', and we'll display the correct information anyway. 20871354Seschrock */ 20881354Seschrock static void 20891354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path) 20901354Seschrock { 20911354Seschrock zfs_cmd_t zc = { 0 }; 20921354Seschrock 20931354Seschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 20942676Seschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value)); 20951354Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 20961544Seschrock &zc.zc_guid) == 0); 20971354Seschrock 20982082Seschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc); 20991354Seschrock } 21001354Seschrock 21011354Seschrock /* 21021354Seschrock * Given a vdev, return the name to display in iostat. If the vdev has a path, 21031354Seschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type. 21041354Seschrock * We also check if this is a whole disk, in which case we strip off the 21051354Seschrock * trailing 's0' slice name. 21061354Seschrock * 21071354Seschrock * This routine is also responsible for identifying when disks have been 21081354Seschrock * reconfigured in a new location. The kernel will have opened the device by 21091354Seschrock * devid, but the path will still refer to the old location. To catch this, we 21101354Seschrock * first do a path -> devid translation (which is fast for the common case). If 21111354Seschrock * the devid matches, we're done. If not, we do a reverse devid -> path 21121354Seschrock * translation and issue the appropriate ioctl() to update the path of the vdev. 21131354Seschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any 21141354Seschrock * of these checks. 21151354Seschrock */ 21161354Seschrock char * 21172082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv) 21181354Seschrock { 21191354Seschrock char *path, *devid; 21201544Seschrock uint64_t value; 21211544Seschrock char buf[64]; 21224451Seschrock vdev_stat_t *vs; 21234451Seschrock uint_t vsc; 21241354Seschrock 21251544Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 21261544Seschrock &value) == 0) { 21271544Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 21281544Seschrock &value) == 0); 21292856Snd150628 (void) snprintf(buf, sizeof (buf), "%llu", 21302856Snd150628 (u_longlong_t)value); 21311544Seschrock path = buf; 21321544Seschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 21331354Seschrock 21344451Seschrock /* 21354451Seschrock * If the device is dead (faulted, offline, etc) then don't 21364451Seschrock * bother opening it. Otherwise we may be forcing the user to 21374451Seschrock * open a misbehaving device, which can have undesirable 21384451Seschrock * effects. 21394451Seschrock */ 21404451Seschrock if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 21414451Seschrock (uint64_t **)&vs, &vsc) != 0 || 21424451Seschrock vs->vs_state >= VDEV_STATE_DEGRADED) && 21434451Seschrock zhp != NULL && 21441354Seschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) { 21451354Seschrock /* 21461354Seschrock * Determine if the current path is correct. 21471354Seschrock */ 21481354Seschrock char *newdevid = path_to_devid(path); 21491354Seschrock 21501354Seschrock if (newdevid == NULL || 21511354Seschrock strcmp(devid, newdevid) != 0) { 21521354Seschrock char *newpath; 21531354Seschrock 21541354Seschrock if ((newpath = devid_to_path(devid)) != NULL) { 21551354Seschrock /* 21561354Seschrock * Update the path appropriately. 21571354Seschrock */ 21581354Seschrock set_path(zhp, nv, newpath); 21592082Seschrock if (nvlist_add_string(nv, 21602082Seschrock ZPOOL_CONFIG_PATH, newpath) == 0) 21612082Seschrock verify(nvlist_lookup_string(nv, 21622082Seschrock ZPOOL_CONFIG_PATH, 21632082Seschrock &path) == 0); 21641354Seschrock free(newpath); 21651354Seschrock } 21661354Seschrock } 21671354Seschrock 21682082Seschrock if (newdevid) 21692082Seschrock devid_str_free(newdevid); 21701354Seschrock } 21711354Seschrock 21721354Seschrock if (strncmp(path, "/dev/dsk/", 9) == 0) 21731354Seschrock path += 9; 21741354Seschrock 21751354Seschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, 21761544Seschrock &value) == 0 && value) { 21772082Seschrock char *tmp = zfs_strdup(hdl, path); 21782082Seschrock if (tmp == NULL) 21792082Seschrock return (NULL); 21801354Seschrock tmp[strlen(path) - 2] = '\0'; 21811354Seschrock return (tmp); 21821354Seschrock } 21831354Seschrock } else { 21841354Seschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0); 21852082Seschrock 21862082Seschrock /* 21872082Seschrock * If it's a raidz device, we need to stick in the parity level. 21882082Seschrock */ 21892082Seschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) { 21902082Seschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, 21912082Seschrock &value) == 0); 21922082Seschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path, 21932856Snd150628 (u_longlong_t)value); 21942082Seschrock path = buf; 21952082Seschrock } 21961354Seschrock } 21971354Seschrock 21982082Seschrock return (zfs_strdup(hdl, path)); 21991354Seschrock } 22001544Seschrock 22011544Seschrock static int 22021544Seschrock zbookmark_compare(const void *a, const void *b) 22031544Seschrock { 22041544Seschrock return (memcmp(a, b, sizeof (zbookmark_t))); 22051544Seschrock } 22061544Seschrock 22071544Seschrock /* 22081544Seschrock * Retrieve the persistent error log, uniquify the members, and return to the 22091544Seschrock * caller. 22101544Seschrock */ 22111544Seschrock int 22123444Sek110237 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp) 22131544Seschrock { 22141544Seschrock zfs_cmd_t zc = { 0 }; 22151544Seschrock uint64_t count; 22162676Seschrock zbookmark_t *zb = NULL; 22173444Sek110237 int i; 22181544Seschrock 22191544Seschrock /* 22201544Seschrock * Retrieve the raw error list from the kernel. If the number of errors 22211544Seschrock * has increased, allocate more space and continue until we get the 22221544Seschrock * entire list. 22231544Seschrock */ 22241544Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT, 22251544Seschrock &count) == 0); 22264820Sek110237 if (count == 0) 22274820Sek110237 return (0); 22282676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl, 22292856Snd150628 count * sizeof (zbookmark_t))) == (uintptr_t)NULL) 22302082Seschrock return (-1); 22312676Seschrock zc.zc_nvlist_dst_size = count; 22321544Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 22331544Seschrock for (;;) { 22342082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG, 22352082Seschrock &zc) != 0) { 22362676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 22371544Seschrock if (errno == ENOMEM) { 22383823Svb160487 count = zc.zc_nvlist_dst_size; 22392676Seschrock if ((zc.zc_nvlist_dst = (uintptr_t) 22403823Svb160487 zfs_alloc(zhp->zpool_hdl, count * 22413823Svb160487 sizeof (zbookmark_t))) == (uintptr_t)NULL) 22422082Seschrock return (-1); 22431544Seschrock } else { 22441544Seschrock return (-1); 22451544Seschrock } 22461544Seschrock } else { 22471544Seschrock break; 22481544Seschrock } 22491544Seschrock } 22501544Seschrock 22511544Seschrock /* 22521544Seschrock * Sort the resulting bookmarks. This is a little confusing due to the 22531544Seschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last 22542676Seschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks 22551544Seschrock * _not_ copied as part of the process. So we point the start of our 22561544Seschrock * array appropriate and decrement the total number of elements. 22571544Seschrock */ 22582676Seschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) + 22592676Seschrock zc.zc_nvlist_dst_size; 22602676Seschrock count -= zc.zc_nvlist_dst_size; 22611544Seschrock 22621544Seschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare); 22631544Seschrock 22643444Sek110237 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0); 22651544Seschrock 22661544Seschrock /* 22673444Sek110237 * Fill in the nverrlistp with nvlist's of dataset and object numbers. 22681544Seschrock */ 22691544Seschrock for (i = 0; i < count; i++) { 22701544Seschrock nvlist_t *nv; 22711544Seschrock 22723700Sek110237 /* ignoring zb_blkid and zb_level for now */ 22733700Sek110237 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset && 22743700Sek110237 zb[i-1].zb_object == zb[i].zb_object) 22751544Seschrock continue; 22761544Seschrock 22773444Sek110237 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0) 22783444Sek110237 goto nomem; 22793444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET, 22803444Sek110237 zb[i].zb_objset) != 0) { 22813444Sek110237 nvlist_free(nv); 22822082Seschrock goto nomem; 22833444Sek110237 } 22843444Sek110237 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT, 22853444Sek110237 zb[i].zb_object) != 0) { 22863444Sek110237 nvlist_free(nv); 22873444Sek110237 goto nomem; 22881544Seschrock } 22893444Sek110237 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) { 22903444Sek110237 nvlist_free(nv); 22913444Sek110237 goto nomem; 22923444Sek110237 } 22933444Sek110237 nvlist_free(nv); 22941544Seschrock } 22951544Seschrock 22963265Sahrens free((void *)(uintptr_t)zc.zc_nvlist_dst); 22971544Seschrock return (0); 22982082Seschrock 22992082Seschrock nomem: 23002676Seschrock free((void *)(uintptr_t)zc.zc_nvlist_dst); 23012082Seschrock return (no_memory(zhp->zpool_hdl)); 23021544Seschrock } 23031760Seschrock 23041760Seschrock /* 23051760Seschrock * Upgrade a ZFS pool to the latest on-disk version. 23061760Seschrock */ 23071760Seschrock int 23085094Slling zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version) 23091760Seschrock { 23101760Seschrock zfs_cmd_t zc = { 0 }; 23112082Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 23121760Seschrock 23131760Seschrock (void) strcpy(zc.zc_name, zhp->zpool_name); 23145094Slling zc.zc_cookie = new_version; 23155094Slling 23164543Smarks if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0) 23173237Slling return (zpool_standard_error_fmt(hdl, errno, 23182082Seschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"), 23192082Seschrock zhp->zpool_name)); 23201760Seschrock return (0); 23211760Seschrock } 23222926Sek110237 23234988Sek110237 void 23244988Sek110237 zpool_set_history_str(const char *subcommand, int argc, char **argv, 23254988Sek110237 char *history_str) 23264988Sek110237 { 23274988Sek110237 int i; 23284988Sek110237 23294988Sek110237 (void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN); 23304988Sek110237 for (i = 1; i < argc; i++) { 23314988Sek110237 if (strlen(history_str) + 1 + strlen(argv[i]) > 23324988Sek110237 HIS_MAX_RECORD_LEN) 23334988Sek110237 break; 23344988Sek110237 (void) strlcat(history_str, " ", HIS_MAX_RECORD_LEN); 23354988Sek110237 (void) strlcat(history_str, argv[i], HIS_MAX_RECORD_LEN); 23364988Sek110237 } 23374988Sek110237 } 23384988Sek110237 23392926Sek110237 /* 23404988Sek110237 * Stage command history for logging. 23412926Sek110237 */ 23424988Sek110237 int 23434988Sek110237 zpool_stage_history(libzfs_handle_t *hdl, const char *history_str) 23442926Sek110237 { 23454988Sek110237 if (history_str == NULL) 23464988Sek110237 return (EINVAL); 23474988Sek110237 23484988Sek110237 if (strlen(history_str) > HIS_MAX_RECORD_LEN) 23494988Sek110237 return (EINVAL); 23502926Sek110237 23514715Sek110237 if (hdl->libzfs_log_str != NULL) 23524543Smarks free(hdl->libzfs_log_str); 23532926Sek110237 23544988Sek110237 if ((hdl->libzfs_log_str = strdup(history_str)) == NULL) 23554988Sek110237 return (no_memory(hdl)); 23564543Smarks 23574988Sek110237 return (0); 23582926Sek110237 } 23592926Sek110237 23602926Sek110237 /* 23612926Sek110237 * Perform ioctl to get some command history of a pool. 23622926Sek110237 * 23632926Sek110237 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the 23642926Sek110237 * logical offset of the history buffer to start reading from. 23652926Sek110237 * 23662926Sek110237 * Upon return, 'off' is the next logical offset to read from and 23672926Sek110237 * 'len' is the actual amount of bytes read into 'buf'. 23682926Sek110237 */ 23692926Sek110237 static int 23702926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len) 23712926Sek110237 { 23722926Sek110237 zfs_cmd_t zc = { 0 }; 23732926Sek110237 libzfs_handle_t *hdl = zhp->zpool_hdl; 23742926Sek110237 23752926Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 23762926Sek110237 23772926Sek110237 zc.zc_history = (uint64_t)(uintptr_t)buf; 23782926Sek110237 zc.zc_history_len = *len; 23792926Sek110237 zc.zc_history_offset = *off; 23802926Sek110237 23812926Sek110237 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) { 23822926Sek110237 switch (errno) { 23832926Sek110237 case EPERM: 23843237Slling return (zfs_error_fmt(hdl, EZFS_PERM, 23853237Slling dgettext(TEXT_DOMAIN, 23862926Sek110237 "cannot show history for pool '%s'"), 23872926Sek110237 zhp->zpool_name)); 23882926Sek110237 case ENOENT: 23893237Slling return (zfs_error_fmt(hdl, EZFS_NOHISTORY, 23902926Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 23912926Sek110237 "'%s'"), zhp->zpool_name)); 23923863Sek110237 case ENOTSUP: 23933863Sek110237 return (zfs_error_fmt(hdl, EZFS_BADVERSION, 23943863Sek110237 dgettext(TEXT_DOMAIN, "cannot get history for pool " 23953863Sek110237 "'%s', pool must be upgraded"), zhp->zpool_name)); 23962926Sek110237 default: 23973237Slling return (zpool_standard_error_fmt(hdl, errno, 23982926Sek110237 dgettext(TEXT_DOMAIN, 23992926Sek110237 "cannot get history for '%s'"), zhp->zpool_name)); 24002926Sek110237 } 24012926Sek110237 } 24022926Sek110237 24032926Sek110237 *len = zc.zc_history_len; 24042926Sek110237 *off = zc.zc_history_offset; 24052926Sek110237 24062926Sek110237 return (0); 24072926Sek110237 } 24082926Sek110237 24092926Sek110237 /* 24102926Sek110237 * Process the buffer of nvlists, unpacking and storing each nvlist record 24112926Sek110237 * into 'records'. 'leftover' is set to the number of bytes that weren't 24122926Sek110237 * processed as there wasn't a complete record. 24132926Sek110237 */ 24142926Sek110237 static int 24152926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 24162926Sek110237 nvlist_t ***records, uint_t *numrecords) 24172926Sek110237 { 24182926Sek110237 uint64_t reclen; 24192926Sek110237 nvlist_t *nv; 24202926Sek110237 int i; 24212926Sek110237 24222926Sek110237 while (bytes_read > sizeof (reclen)) { 24232926Sek110237 24242926Sek110237 /* get length of packed record (stored as little endian) */ 24252926Sek110237 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 24262926Sek110237 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 24272926Sek110237 24282926Sek110237 if (bytes_read < sizeof (reclen) + reclen) 24292926Sek110237 break; 24302926Sek110237 24312926Sek110237 /* unpack record */ 24322926Sek110237 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 24332926Sek110237 return (ENOMEM); 24342926Sek110237 bytes_read -= sizeof (reclen) + reclen; 24352926Sek110237 buf += sizeof (reclen) + reclen; 24362926Sek110237 24372926Sek110237 /* add record to nvlist array */ 24382926Sek110237 (*numrecords)++; 24392926Sek110237 if (ISP2(*numrecords + 1)) { 24402926Sek110237 *records = realloc(*records, 24412926Sek110237 *numrecords * 2 * sizeof (nvlist_t *)); 24422926Sek110237 } 24432926Sek110237 (*records)[*numrecords - 1] = nv; 24442926Sek110237 } 24452926Sek110237 24462926Sek110237 *leftover = bytes_read; 24472926Sek110237 return (0); 24482926Sek110237 } 24492926Sek110237 24502926Sek110237 #define HIS_BUF_LEN (128*1024) 24512926Sek110237 24522926Sek110237 /* 24532926Sek110237 * Retrieve the command history of a pool. 24542926Sek110237 */ 24552926Sek110237 int 24562926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) 24572926Sek110237 { 24582926Sek110237 char buf[HIS_BUF_LEN]; 24592926Sek110237 uint64_t off = 0; 24602926Sek110237 nvlist_t **records = NULL; 24612926Sek110237 uint_t numrecords = 0; 24622926Sek110237 int err, i; 24632926Sek110237 24642926Sek110237 do { 24652926Sek110237 uint64_t bytes_read = sizeof (buf); 24662926Sek110237 uint64_t leftover; 24672926Sek110237 24682926Sek110237 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) 24692926Sek110237 break; 24702926Sek110237 24712926Sek110237 /* if nothing else was read in, we're at EOF, just return */ 24722926Sek110237 if (!bytes_read) 24732926Sek110237 break; 24742926Sek110237 24752926Sek110237 if ((err = zpool_history_unpack(buf, bytes_read, 24762926Sek110237 &leftover, &records, &numrecords)) != 0) 24772926Sek110237 break; 24782926Sek110237 off -= leftover; 24792926Sek110237 24802926Sek110237 /* CONSTCOND */ 24812926Sek110237 } while (1); 24822926Sek110237 24832926Sek110237 if (!err) { 24842926Sek110237 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0); 24852926Sek110237 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD, 24862926Sek110237 records, numrecords) == 0); 24872926Sek110237 } 24882926Sek110237 for (i = 0; i < numrecords; i++) 24892926Sek110237 nvlist_free(records[i]); 24902926Sek110237 free(records); 24912926Sek110237 24922926Sek110237 return (err); 24932926Sek110237 } 24943444Sek110237 24953444Sek110237 void 24963444Sek110237 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj, 24973444Sek110237 char *pathname, size_t len) 24983444Sek110237 { 24993444Sek110237 zfs_cmd_t zc = { 0 }; 25003444Sek110237 boolean_t mounted = B_FALSE; 25013444Sek110237 char *mntpnt = NULL; 25023444Sek110237 char dsname[MAXNAMELEN]; 25033444Sek110237 25043444Sek110237 if (dsobj == 0) { 25053444Sek110237 /* special case for the MOS */ 25063444Sek110237 (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj); 25073444Sek110237 return; 25083444Sek110237 } 25093444Sek110237 25103444Sek110237 /* get the dataset's name */ 25113444Sek110237 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); 25123444Sek110237 zc.zc_obj = dsobj; 25133444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, 25143444Sek110237 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) { 25153444Sek110237 /* just write out a path of two object numbers */ 25163444Sek110237 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>", 25173444Sek110237 dsobj, obj); 25183444Sek110237 return; 25193444Sek110237 } 25203444Sek110237 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname)); 25213444Sek110237 25223444Sek110237 /* find out if the dataset is mounted */ 25233444Sek110237 mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt); 25243444Sek110237 25253444Sek110237 /* get the corrupted object's path */ 25263444Sek110237 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name)); 25273444Sek110237 zc.zc_obj = obj; 25283444Sek110237 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH, 25293444Sek110237 &zc) == 0) { 25303444Sek110237 if (mounted) { 25313444Sek110237 (void) snprintf(pathname, len, "%s%s", mntpnt, 25323444Sek110237 zc.zc_value); 25333444Sek110237 } else { 25343444Sek110237 (void) snprintf(pathname, len, "%s:%s", 25353444Sek110237 dsname, zc.zc_value); 25363444Sek110237 } 25373444Sek110237 } else { 25383444Sek110237 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj); 25393444Sek110237 } 25403444Sek110237 free(mntpnt); 25413444Sek110237 } 25423912Slling 25434276Staylor #define RDISK_ROOT "/dev/rdsk" 25444276Staylor #define BACKUP_SLICE "s2" 25454276Staylor /* 25464276Staylor * Don't start the slice at the default block of 34; many storage 25474276Staylor * devices will use a stripe width of 128k, so start there instead. 25484276Staylor */ 25494276Staylor #define NEW_START_BLOCK 256 25504276Staylor 25514276Staylor /* 2552*7042Sgw25295 * Read the EFI label from the config, if a label does not exist then 2553*7042Sgw25295 * pass back the error to the caller. If the caller has passed a non-NULL 2554*7042Sgw25295 * diskaddr argument then we set it to the starting address of the EFI 2555*7042Sgw25295 * partition. 2556*7042Sgw25295 */ 2557*7042Sgw25295 static int 2558*7042Sgw25295 read_efi_label(nvlist_t *config, diskaddr_t *sb) 2559*7042Sgw25295 { 2560*7042Sgw25295 char *path; 2561*7042Sgw25295 int fd; 2562*7042Sgw25295 char diskname[MAXPATHLEN]; 2563*7042Sgw25295 int err = -1; 2564*7042Sgw25295 2565*7042Sgw25295 if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0) 2566*7042Sgw25295 return (err); 2567*7042Sgw25295 2568*7042Sgw25295 (void) snprintf(diskname, sizeof (diskname), "%s%s", RDISK_ROOT, 2569*7042Sgw25295 strrchr(path, '/')); 2570*7042Sgw25295 if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) { 2571*7042Sgw25295 struct dk_gpt *vtoc; 2572*7042Sgw25295 2573*7042Sgw25295 if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) { 2574*7042Sgw25295 if (sb != NULL) 2575*7042Sgw25295 *sb = vtoc->efi_parts[0].p_start; 2576*7042Sgw25295 efi_free(vtoc); 2577*7042Sgw25295 } 2578*7042Sgw25295 (void) close(fd); 2579*7042Sgw25295 } 2580*7042Sgw25295 return (err); 2581*7042Sgw25295 } 2582*7042Sgw25295 2583*7042Sgw25295 /* 25844276Staylor * determine where a partition starts on a disk in the current 25854276Staylor * configuration 25864276Staylor */ 25874276Staylor static diskaddr_t 25884276Staylor find_start_block(nvlist_t *config) 25894276Staylor { 25904276Staylor nvlist_t **child; 25914276Staylor uint_t c, children; 25924276Staylor diskaddr_t sb = MAXOFFSET_T; 25934276Staylor uint64_t wholedisk; 25944276Staylor 25954276Staylor if (nvlist_lookup_nvlist_array(config, 25964276Staylor ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) { 25974276Staylor if (nvlist_lookup_uint64(config, 25984276Staylor ZPOOL_CONFIG_WHOLE_DISK, 25994276Staylor &wholedisk) != 0 || !wholedisk) { 26004276Staylor return (MAXOFFSET_T); 26014276Staylor } 2602*7042Sgw25295 if (read_efi_label(config, &sb) < 0) 2603*7042Sgw25295 sb = MAXOFFSET_T; 26044276Staylor return (sb); 26054276Staylor } 26064276Staylor 26074276Staylor for (c = 0; c < children; c++) { 26084276Staylor sb = find_start_block(child[c]); 26094276Staylor if (sb != MAXOFFSET_T) { 26104276Staylor return (sb); 26114276Staylor } 26124276Staylor } 26134276Staylor return (MAXOFFSET_T); 26144276Staylor } 26154276Staylor 26164276Staylor /* 26174276Staylor * Label an individual disk. The name provided is the short name, 26184276Staylor * stripped of any leading /dev path. 26194276Staylor */ 26204276Staylor int 26214276Staylor zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name) 26224276Staylor { 26234276Staylor char path[MAXPATHLEN]; 26244276Staylor struct dk_gpt *vtoc; 26254276Staylor int fd; 26264276Staylor size_t resv = EFI_MIN_RESV_SIZE; 26274276Staylor uint64_t slice_size; 26284276Staylor diskaddr_t start_block; 26294276Staylor char errbuf[1024]; 26304276Staylor 26316289Smmusante /* prepare an error message just in case */ 26326289Smmusante (void) snprintf(errbuf, sizeof (errbuf), 26336289Smmusante dgettext(TEXT_DOMAIN, "cannot label '%s'"), name); 26346289Smmusante 26354276Staylor if (zhp) { 26364276Staylor nvlist_t *nvroot; 26374276Staylor 26384276Staylor verify(nvlist_lookup_nvlist(zhp->zpool_config, 26394276Staylor ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 26404276Staylor 26414276Staylor if (zhp->zpool_start_block == 0) 26424276Staylor start_block = find_start_block(nvroot); 26434276Staylor else 26444276Staylor start_block = zhp->zpool_start_block; 26454276Staylor zhp->zpool_start_block = start_block; 26464276Staylor } else { 26474276Staylor /* new pool */ 26484276Staylor start_block = NEW_START_BLOCK; 26494276Staylor } 26504276Staylor 26514276Staylor (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name, 26524276Staylor BACKUP_SLICE); 26534276Staylor 26544276Staylor if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) { 26554276Staylor /* 26564276Staylor * This shouldn't happen. We've long since verified that this 26574276Staylor * is a valid device. 26584276Staylor */ 26596289Smmusante zfs_error_aux(hdl, 26606289Smmusante dgettext(TEXT_DOMAIN, "unable to open device")); 26614276Staylor return (zfs_error(hdl, EZFS_OPENFAILED, errbuf)); 26624276Staylor } 26634276Staylor 26644276Staylor if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) { 26654276Staylor /* 26664276Staylor * The only way this can fail is if we run out of memory, or we 26674276Staylor * were unable to read the disk's capacity 26684276Staylor */ 26694276Staylor if (errno == ENOMEM) 26704276Staylor (void) no_memory(hdl); 26714276Staylor 26724276Staylor (void) close(fd); 26736289Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 26746289Smmusante "unable to read disk capacity"), name); 26754276Staylor 26764276Staylor return (zfs_error(hdl, EZFS_NOCAP, errbuf)); 26774276Staylor } 26784276Staylor 26794276Staylor slice_size = vtoc->efi_last_u_lba + 1; 26804276Staylor slice_size -= EFI_MIN_RESV_SIZE; 26814276Staylor if (start_block == MAXOFFSET_T) 26824276Staylor start_block = NEW_START_BLOCK; 26834276Staylor slice_size -= start_block; 26844276Staylor 26854276Staylor vtoc->efi_parts[0].p_start = start_block; 26864276Staylor vtoc->efi_parts[0].p_size = slice_size; 26874276Staylor 26884276Staylor /* 26894276Staylor * Why we use V_USR: V_BACKUP confuses users, and is considered 26904276Staylor * disposable by some EFI utilities (since EFI doesn't have a backup 26914276Staylor * slice). V_UNASSIGNED is supposed to be used only for zero size 26924276Staylor * partitions, and efi_write() will fail if we use it. V_ROOT, V_BOOT, 26934276Staylor * etc. were all pretty specific. V_USR is as close to reality as we 26944276Staylor * can get, in the absence of V_OTHER. 26954276Staylor */ 26964276Staylor vtoc->efi_parts[0].p_tag = V_USR; 26974276Staylor (void) strcpy(vtoc->efi_parts[0].p_name, "zfs"); 26984276Staylor 26994276Staylor vtoc->efi_parts[8].p_start = slice_size + start_block; 27004276Staylor vtoc->efi_parts[8].p_size = resv; 27014276Staylor vtoc->efi_parts[8].p_tag = V_RESERVED; 27024276Staylor 27034276Staylor if (efi_write(fd, vtoc) != 0) { 27044276Staylor /* 27054276Staylor * Some block drivers (like pcata) may not support EFI 27064276Staylor * GPT labels. Print out a helpful error message dir- 27074276Staylor * ecting the user to manually label the disk and give 27084276Staylor * a specific slice. 27094276Staylor */ 27104276Staylor (void) close(fd); 27114276Staylor efi_free(vtoc); 27124276Staylor 27134276Staylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 27146289Smmusante "try using fdisk(1M) and then provide a specific slice")); 27154276Staylor return (zfs_error(hdl, EZFS_LABELFAILED, errbuf)); 27164276Staylor } 27174276Staylor 27184276Staylor (void) close(fd); 27194276Staylor efi_free(vtoc); 27204276Staylor return (0); 27214276Staylor } 27226423Sgw25295 27236423Sgw25295 static boolean_t 27246423Sgw25295 supported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf) 27256423Sgw25295 { 27266423Sgw25295 char *type; 27276423Sgw25295 nvlist_t **child; 27286423Sgw25295 uint_t children, c; 27296423Sgw25295 27306423Sgw25295 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0); 27316423Sgw25295 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 || 27326423Sgw25295 strcmp(type, VDEV_TYPE_FILE) == 0 || 27336423Sgw25295 strcmp(type, VDEV_TYPE_LOG) == 0 || 27346423Sgw25295 strcmp(type, VDEV_TYPE_MISSING) == 0) { 27356423Sgw25295 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 27366423Sgw25295 "vdev type '%s' is not supported"), type); 27376423Sgw25295 (void) zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf); 27386423Sgw25295 return (B_FALSE); 27396423Sgw25295 } 27406423Sgw25295 if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN, 27416423Sgw25295 &child, &children) == 0) { 27426423Sgw25295 for (c = 0; c < children; c++) { 27436423Sgw25295 if (!supported_dump_vdev_type(hdl, child[c], errbuf)) 27446423Sgw25295 return (B_FALSE); 27456423Sgw25295 } 27466423Sgw25295 } 27476423Sgw25295 return (B_TRUE); 27486423Sgw25295 } 27496423Sgw25295 27506423Sgw25295 /* 27516423Sgw25295 * check if this zvol is allowable for use as a dump device; zero if 27526423Sgw25295 * it is, > 0 if it isn't, < 0 if it isn't a zvol 27536423Sgw25295 */ 27546423Sgw25295 int 27556423Sgw25295 zvol_check_dump_config(char *arg) 27566423Sgw25295 { 27576423Sgw25295 zpool_handle_t *zhp = NULL; 27586423Sgw25295 nvlist_t *config, *nvroot; 27596423Sgw25295 char *p, *volname; 27606423Sgw25295 nvlist_t **top; 27616423Sgw25295 uint_t toplevels; 27626423Sgw25295 libzfs_handle_t *hdl; 27636423Sgw25295 char errbuf[1024]; 27646423Sgw25295 char poolname[ZPOOL_MAXNAMELEN]; 27656423Sgw25295 int pathlen = strlen(ZVOL_FULL_DEV_DIR); 27666423Sgw25295 int ret = 1; 27676423Sgw25295 27686423Sgw25295 if (strncmp(arg, ZVOL_FULL_DEV_DIR, pathlen)) { 27696423Sgw25295 return (-1); 27706423Sgw25295 } 27716423Sgw25295 27726423Sgw25295 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 27736423Sgw25295 "dump is not supported on device '%s'"), arg); 27746423Sgw25295 27756423Sgw25295 if ((hdl = libzfs_init()) == NULL) 27766423Sgw25295 return (1); 27776423Sgw25295 libzfs_print_on_error(hdl, B_TRUE); 27786423Sgw25295 27796423Sgw25295 volname = arg + pathlen; 27806423Sgw25295 27816423Sgw25295 /* check the configuration of the pool */ 27826423Sgw25295 if ((p = strchr(volname, '/')) == NULL) { 27836423Sgw25295 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 27846423Sgw25295 "malformed dataset name")); 27856423Sgw25295 (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 27866423Sgw25295 return (1); 27876423Sgw25295 } else if (p - volname >= ZFS_MAXNAMELEN) { 27886423Sgw25295 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 27896423Sgw25295 "dataset name is too long")); 27906423Sgw25295 (void) zfs_error(hdl, EZFS_NAMETOOLONG, errbuf); 27916423Sgw25295 return (1); 27926423Sgw25295 } else { 27936423Sgw25295 (void) strncpy(poolname, volname, p - volname); 27946423Sgw25295 poolname[p - volname] = '\0'; 27956423Sgw25295 } 27966423Sgw25295 27976423Sgw25295 if ((zhp = zpool_open(hdl, poolname)) == NULL) { 27986423Sgw25295 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 27996423Sgw25295 "could not open pool '%s'"), poolname); 28006423Sgw25295 (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf); 28016423Sgw25295 goto out; 28026423Sgw25295 } 28036423Sgw25295 config = zpool_get_config(zhp, NULL); 28046423Sgw25295 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 28056423Sgw25295 &nvroot) != 0) { 28066423Sgw25295 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 28076423Sgw25295 "could not obtain vdev configuration for '%s'"), poolname); 28086423Sgw25295 (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf); 28096423Sgw25295 goto out; 28106423Sgw25295 } 28116423Sgw25295 28126423Sgw25295 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 28136423Sgw25295 &top, &toplevels) == 0); 28146423Sgw25295 if (toplevels != 1) { 28156423Sgw25295 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 28166423Sgw25295 "'%s' has multiple top level vdevs"), poolname); 28176423Sgw25295 (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf); 28186423Sgw25295 goto out; 28196423Sgw25295 } 28206423Sgw25295 28216423Sgw25295 if (!supported_dump_vdev_type(hdl, top[0], errbuf)) { 28226423Sgw25295 goto out; 28236423Sgw25295 } 28246423Sgw25295 ret = 0; 28256423Sgw25295 28266423Sgw25295 out: 28276423Sgw25295 if (zhp) 28286423Sgw25295 zpool_close(zhp); 28296423Sgw25295 libzfs_fini(hdl); 28306423Sgw25295 return (ret); 28316423Sgw25295 } 2832