1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * 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 */ 213126Sahl 22789Sahrens /* 233363Sgw25295 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24789Sahrens * Use is subject to license terms. 25789Sahrens */ 26789Sahrens 27789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28789Sahrens 29789Sahrens #include <assert.h> 30789Sahrens #include <ctype.h> 31789Sahrens #include <errno.h> 32789Sahrens #include <libdevinfo.h> 33789Sahrens #include <libintl.h> 34789Sahrens #include <math.h> 35789Sahrens #include <stdio.h> 36789Sahrens #include <stdlib.h> 37789Sahrens #include <strings.h> 38789Sahrens #include <unistd.h> 39789Sahrens #include <zone.h> 402082Seschrock #include <fcntl.h> 41789Sahrens #include <sys/mntent.h> 42789Sahrens #include <sys/mnttab.h> 431294Slling #include <sys/mount.h> 44789Sahrens 45789Sahrens #include <sys/spa.h> 46789Sahrens #include <sys/zio.h> 472676Seschrock #include <sys/zap.h> 48789Sahrens #include <libzfs.h> 49789Sahrens 50789Sahrens #include "zfs_namecheck.h" 51789Sahrens #include "zfs_prop.h" 52789Sahrens #include "libzfs_impl.h" 53789Sahrens 544007Smmusante static int zvol_create_link_common(libzfs_handle_t *, const char *, int); 554007Smmusante 56789Sahrens /* 57789Sahrens * Given a single type (not a mask of types), return the type in a human 58789Sahrens * readable form. 59789Sahrens */ 60789Sahrens const char * 61789Sahrens zfs_type_to_name(zfs_type_t type) 62789Sahrens { 63789Sahrens switch (type) { 64789Sahrens case ZFS_TYPE_FILESYSTEM: 65789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 66789Sahrens case ZFS_TYPE_SNAPSHOT: 67789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 68789Sahrens case ZFS_TYPE_VOLUME: 69789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 70789Sahrens } 71789Sahrens 72789Sahrens return (NULL); 73789Sahrens } 74789Sahrens 75789Sahrens /* 76789Sahrens * Given a path and mask of ZFS types, return a string describing this dataset. 77789Sahrens * This is used when we fail to open a dataset and we cannot get an exact type. 78789Sahrens * We guess what the type would have been based on the path and the mask of 79789Sahrens * acceptable types. 80789Sahrens */ 81789Sahrens static const char * 82789Sahrens path_to_str(const char *path, int types) 83789Sahrens { 84789Sahrens /* 85789Sahrens * When given a single type, always report the exact type. 86789Sahrens */ 87789Sahrens if (types == ZFS_TYPE_SNAPSHOT) 88789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 89789Sahrens if (types == ZFS_TYPE_FILESYSTEM) 90789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 91789Sahrens if (types == ZFS_TYPE_VOLUME) 92789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 93789Sahrens 94789Sahrens /* 95789Sahrens * The user is requesting more than one type of dataset. If this is the 96789Sahrens * case, consult the path itself. If we're looking for a snapshot, and 97789Sahrens * a '@' is found, then report it as "snapshot". Otherwise, remove the 98789Sahrens * snapshot attribute and try again. 99789Sahrens */ 100789Sahrens if (types & ZFS_TYPE_SNAPSHOT) { 101789Sahrens if (strchr(path, '@') != NULL) 102789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 103789Sahrens return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 104789Sahrens } 105789Sahrens 106789Sahrens 107789Sahrens /* 108789Sahrens * The user has requested either filesystems or volumes. 109789Sahrens * We have no way of knowing a priori what type this would be, so always 110789Sahrens * report it as "filesystem" or "volume", our two primitive types. 111789Sahrens */ 112789Sahrens if (types & ZFS_TYPE_FILESYSTEM) 113789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 114789Sahrens 115789Sahrens assert(types & ZFS_TYPE_VOLUME); 116789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 117789Sahrens } 118789Sahrens 119789Sahrens /* 120789Sahrens * Validate a ZFS path. This is used even before trying to open the dataset, to 121789Sahrens * provide a more meaningful error message. We place a more useful message in 122789Sahrens * 'buf' detailing exactly why the name was not valid. 123789Sahrens */ 124789Sahrens static int 1252082Seschrock zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type) 126789Sahrens { 127789Sahrens namecheck_err_t why; 128789Sahrens char what; 129789Sahrens 130789Sahrens if (dataset_namecheck(path, &why, &what) != 0) { 1312082Seschrock if (hdl != NULL) { 132789Sahrens switch (why) { 1331003Slling case NAME_ERR_TOOLONG: 1342082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1352082Seschrock "name is too long")); 1361003Slling break; 1371003Slling 138789Sahrens case NAME_ERR_LEADING_SLASH: 1392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1402082Seschrock "leading slash in name")); 141789Sahrens break; 142789Sahrens 143789Sahrens case NAME_ERR_EMPTY_COMPONENT: 1442082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1452082Seschrock "empty component in name")); 146789Sahrens break; 147789Sahrens 148789Sahrens case NAME_ERR_TRAILING_SLASH: 1492082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1502082Seschrock "trailing slash in name")); 151789Sahrens break; 152789Sahrens 153789Sahrens case NAME_ERR_INVALCHAR: 1542082Seschrock zfs_error_aux(hdl, 155789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 1562082Seschrock "'%c' in name"), what); 157789Sahrens break; 158789Sahrens 159789Sahrens case NAME_ERR_MULTIPLE_AT: 1602082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1612082Seschrock "multiple '@' delimiters in name")); 162789Sahrens break; 1632856Snd150628 1642856Snd150628 case NAME_ERR_NOLETTER: 1652856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1662856Snd150628 "pool doesn't begin with a letter")); 1672856Snd150628 break; 1682856Snd150628 1692856Snd150628 case NAME_ERR_RESERVED: 1702856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1712856Snd150628 "name is reserved")); 1722856Snd150628 break; 1732856Snd150628 1742856Snd150628 case NAME_ERR_DISKLIKE: 1752856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1762856Snd150628 "reserved disk name")); 1772856Snd150628 break; 178789Sahrens } 179789Sahrens } 180789Sahrens 181789Sahrens return (0); 182789Sahrens } 183789Sahrens 184789Sahrens if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) { 1852082Seschrock if (hdl != NULL) 1862082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1872082Seschrock "snapshot delimiter '@' in filesystem name")); 188789Sahrens return (0); 189789Sahrens } 190789Sahrens 1912199Sahrens if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) { 1922199Sahrens if (hdl != NULL) 1932199Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1943413Smmusante "missing '@' delimiter in snapshot name")); 1952199Sahrens return (0); 1962199Sahrens } 1972199Sahrens 1982082Seschrock return (-1); 199789Sahrens } 200789Sahrens 201789Sahrens int 202789Sahrens zfs_name_valid(const char *name, zfs_type_t type) 203789Sahrens { 2042082Seschrock return (zfs_validate_name(NULL, name, type)); 205789Sahrens } 206789Sahrens 207789Sahrens /* 2082676Seschrock * This function takes the raw DSL properties, and filters out the user-defined 2092676Seschrock * properties into a separate nvlist. 2102676Seschrock */ 2114217Seschrock static nvlist_t * 2124217Seschrock process_user_props(zfs_handle_t *zhp, nvlist_t *props) 2132676Seschrock { 2142676Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 2152676Seschrock nvpair_t *elem; 2162676Seschrock nvlist_t *propval; 2174217Seschrock nvlist_t *nvl; 2184217Seschrock 2194217Seschrock if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 2204217Seschrock (void) no_memory(hdl); 2214217Seschrock return (NULL); 2224217Seschrock } 2232676Seschrock 2242676Seschrock elem = NULL; 2254217Seschrock while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 2262676Seschrock if (!zfs_prop_user(nvpair_name(elem))) 2272676Seschrock continue; 2282676Seschrock 2292676Seschrock verify(nvpair_value_nvlist(elem, &propval) == 0); 2304217Seschrock if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) { 2314217Seschrock nvlist_free(nvl); 2324217Seschrock (void) no_memory(hdl); 2334217Seschrock return (NULL); 2344217Seschrock } 2352676Seschrock } 2362676Seschrock 2374217Seschrock return (nvl); 2382676Seschrock } 2392676Seschrock 2402676Seschrock /* 241789Sahrens * Utility function to gather stats (objset and zpl) for the given object. 242789Sahrens */ 243789Sahrens static int 244789Sahrens get_stats(zfs_handle_t *zhp) 245789Sahrens { 246789Sahrens zfs_cmd_t zc = { 0 }; 2472676Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 2484217Seschrock nvlist_t *allprops, *userprops; 249789Sahrens 250789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 251789Sahrens 2522676Seschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 2532082Seschrock return (-1); 2541356Seschrock 2552082Seschrock while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) { 2561356Seschrock if (errno == ENOMEM) { 2572676Seschrock if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 2582676Seschrock zcmd_free_nvlists(&zc); 2592082Seschrock return (-1); 2602676Seschrock } 2611356Seschrock } else { 2622676Seschrock zcmd_free_nvlists(&zc); 2631356Seschrock return (-1); 2641356Seschrock } 2651356Seschrock } 266789Sahrens 2672885Sahrens zhp->zfs_dmustats = zc.zc_objset_stats; /* structure assignment */ 268789Sahrens 2692676Seschrock (void) strlcpy(zhp->zfs_root, zc.zc_value, sizeof (zhp->zfs_root)); 2701544Seschrock 2714217Seschrock if (zcmd_read_dst_nvlist(hdl, &zc, &allprops) != 0) { 2722676Seschrock zcmd_free_nvlists(&zc); 2732082Seschrock return (-1); 2742082Seschrock } 275789Sahrens 2762676Seschrock zcmd_free_nvlists(&zc); 2772676Seschrock 2784217Seschrock if ((userprops = process_user_props(zhp, allprops)) == NULL) { 2794217Seschrock nvlist_free(allprops); 2802676Seschrock return (-1); 2814217Seschrock } 2824217Seschrock 2834217Seschrock nvlist_free(zhp->zfs_props); 2844217Seschrock nvlist_free(zhp->zfs_user_props); 2854217Seschrock 2864217Seschrock zhp->zfs_props = allprops; 2874217Seschrock zhp->zfs_user_props = userprops; 2882082Seschrock 289789Sahrens return (0); 290789Sahrens } 291789Sahrens 292789Sahrens /* 293789Sahrens * Refresh the properties currently stored in the handle. 294789Sahrens */ 295789Sahrens void 296789Sahrens zfs_refresh_properties(zfs_handle_t *zhp) 297789Sahrens { 298789Sahrens (void) get_stats(zhp); 299789Sahrens } 300789Sahrens 301789Sahrens /* 302789Sahrens * Makes a handle from the given dataset name. Used by zfs_open() and 303789Sahrens * zfs_iter_* to create child handles on the fly. 304789Sahrens */ 305789Sahrens zfs_handle_t * 3062082Seschrock make_dataset_handle(libzfs_handle_t *hdl, const char *path) 307789Sahrens { 3082082Seschrock zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1); 3092082Seschrock 3102082Seschrock if (zhp == NULL) 3112082Seschrock return (NULL); 3122082Seschrock 3132082Seschrock zhp->zfs_hdl = hdl; 314789Sahrens 3151758Sahrens top: 316789Sahrens (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); 317789Sahrens 318789Sahrens if (get_stats(zhp) != 0) { 319789Sahrens free(zhp); 320789Sahrens return (NULL); 321789Sahrens } 322789Sahrens 3231758Sahrens if (zhp->zfs_dmustats.dds_inconsistent) { 3241758Sahrens zfs_cmd_t zc = { 0 }; 3251758Sahrens 3261758Sahrens /* 3271758Sahrens * If it is dds_inconsistent, then we've caught it in 3281758Sahrens * the middle of a 'zfs receive' or 'zfs destroy', and 3291758Sahrens * it is inconsistent from the ZPL's point of view, so 3301758Sahrens * can't be mounted. However, it could also be that we 3311758Sahrens * have crashed in the middle of one of those 3321758Sahrens * operations, in which case we need to get rid of the 3331758Sahrens * inconsistent state. We do that by either rolling 3341758Sahrens * back to the previous snapshot (which will fail if 3351758Sahrens * there is none), or destroying the filesystem. Note 3361758Sahrens * that if we are still in the middle of an active 3371758Sahrens * 'receive' or 'destroy', then the rollback and destroy 3381758Sahrens * will fail with EBUSY and we will drive on as usual. 3391758Sahrens */ 3401758Sahrens 3411758Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3421758Sahrens 3432885Sahrens if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) { 3442082Seschrock (void) zvol_remove_link(hdl, zhp->zfs_name); 3451758Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3461758Sahrens } else { 3471758Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3481758Sahrens } 3491758Sahrens 3501758Sahrens /* If we can successfully roll it back, reget the stats */ 3512082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_ROLLBACK, &zc) == 0) 3521758Sahrens goto top; 3531758Sahrens /* 3541758Sahrens * If we can sucessfully destroy it, pretend that it 3551758Sahrens * never existed. 3561758Sahrens */ 3572082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) == 0) { 3581758Sahrens free(zhp); 3591758Sahrens errno = ENOENT; 3601758Sahrens return (NULL); 3611758Sahrens } 3621758Sahrens } 3631758Sahrens 364789Sahrens /* 365789Sahrens * We've managed to open the dataset and gather statistics. Determine 366789Sahrens * the high-level type. 367789Sahrens */ 3682885Sahrens if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 3692885Sahrens zhp->zfs_head_type = ZFS_TYPE_VOLUME; 3702885Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 3712885Sahrens zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM; 3722885Sahrens else 3732885Sahrens abort(); 3742885Sahrens 375789Sahrens if (zhp->zfs_dmustats.dds_is_snapshot) 376789Sahrens zhp->zfs_type = ZFS_TYPE_SNAPSHOT; 377789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 378789Sahrens zhp->zfs_type = ZFS_TYPE_VOLUME; 379789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 380789Sahrens zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 381789Sahrens else 3822082Seschrock abort(); /* we should never see any other types */ 383789Sahrens 384789Sahrens return (zhp); 385789Sahrens } 386789Sahrens 387789Sahrens /* 388789Sahrens * Opens the given snapshot, filesystem, or volume. The 'types' 389789Sahrens * argument is a mask of acceptable types. The function will print an 390789Sahrens * appropriate error message and return NULL if it can't be opened. 391789Sahrens */ 392789Sahrens zfs_handle_t * 3932082Seschrock zfs_open(libzfs_handle_t *hdl, const char *path, int types) 394789Sahrens { 395789Sahrens zfs_handle_t *zhp; 3962082Seschrock char errbuf[1024]; 3972082Seschrock 3982082Seschrock (void) snprintf(errbuf, sizeof (errbuf), 3992082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), path); 400789Sahrens 401789Sahrens /* 4022082Seschrock * Validate the name before we even try to open it. 403789Sahrens */ 4042082Seschrock if (!zfs_validate_name(hdl, path, ZFS_TYPE_ANY)) { 4052082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4062082Seschrock "invalid dataset name")); 4072082Seschrock (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 408789Sahrens return (NULL); 409789Sahrens } 410789Sahrens 411789Sahrens /* 412789Sahrens * Try to get stats for the dataset, which will tell us if it exists. 413789Sahrens */ 414789Sahrens errno = 0; 4152082Seschrock if ((zhp = make_dataset_handle(hdl, path)) == NULL) { 4163237Slling (void) zfs_standard_error(hdl, errno, errbuf); 417789Sahrens return (NULL); 418789Sahrens } 419789Sahrens 420789Sahrens if (!(types & zhp->zfs_type)) { 4212082Seschrock (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 4222142Seschrock zfs_close(zhp); 423789Sahrens return (NULL); 424789Sahrens } 425789Sahrens 426789Sahrens return (zhp); 427789Sahrens } 428789Sahrens 429789Sahrens /* 430789Sahrens * Release a ZFS handle. Nothing to do but free the associated memory. 431789Sahrens */ 432789Sahrens void 433789Sahrens zfs_close(zfs_handle_t *zhp) 434789Sahrens { 435789Sahrens if (zhp->zfs_mntopts) 436789Sahrens free(zhp->zfs_mntopts); 4372676Seschrock nvlist_free(zhp->zfs_props); 4382676Seschrock nvlist_free(zhp->zfs_user_props); 439789Sahrens free(zhp); 440789Sahrens } 441789Sahrens 442789Sahrens /* 443789Sahrens * Given a numeric suffix, convert the value into a number of bits that the 444789Sahrens * resulting value must be shifted. 445789Sahrens */ 446789Sahrens static int 4472082Seschrock str2shift(libzfs_handle_t *hdl, const char *buf) 448789Sahrens { 449789Sahrens const char *ends = "BKMGTPEZ"; 450789Sahrens int i; 451789Sahrens 452789Sahrens if (buf[0] == '\0') 453789Sahrens return (0); 454789Sahrens for (i = 0; i < strlen(ends); i++) { 455789Sahrens if (toupper(buf[0]) == ends[i]) 456789Sahrens break; 457789Sahrens } 458789Sahrens if (i == strlen(ends)) { 4592082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4602082Seschrock "invalid numeric suffix '%s'"), buf); 461789Sahrens return (-1); 462789Sahrens } 463789Sahrens 464789Sahrens /* 465789Sahrens * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 466789Sahrens * allow 'BB' - that's just weird. 467789Sahrens */ 468789Sahrens if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 4692082Seschrock toupper(buf[0]) != 'B')) 470789Sahrens return (10*i); 4712082Seschrock 4722082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4732082Seschrock "invalid numeric suffix '%s'"), buf); 474789Sahrens return (-1); 475789Sahrens } 476789Sahrens 477789Sahrens /* 478789Sahrens * Convert a string of the form '100G' into a real number. Used when setting 479789Sahrens * properties or creating a volume. 'buf' is used to place an extended error 480789Sahrens * message for the caller to use. 481789Sahrens */ 482789Sahrens static int 4832082Seschrock nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) 484789Sahrens { 485789Sahrens char *end; 486789Sahrens int shift; 487789Sahrens 488789Sahrens *num = 0; 489789Sahrens 490789Sahrens /* Check to see if this looks like a number. */ 491789Sahrens if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 4922082Seschrock if (hdl) 4932082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4942082Seschrock "bad numeric value '%s'"), value); 495789Sahrens return (-1); 496789Sahrens } 497789Sahrens 498789Sahrens /* Rely on stroll() to process the numeric portion. */ 499789Sahrens errno = 0; 500789Sahrens *num = strtoll(value, &end, 10); 501789Sahrens 502789Sahrens /* 503789Sahrens * Check for ERANGE, which indicates that the value is too large to fit 504789Sahrens * in a 64-bit value. 505789Sahrens */ 506789Sahrens if (errno == ERANGE) { 5072082Seschrock if (hdl) 5082082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5092082Seschrock "numeric value is too large")); 510789Sahrens return (-1); 511789Sahrens } 512789Sahrens 513789Sahrens /* 514789Sahrens * If we have a decimal value, then do the computation with floating 515789Sahrens * point arithmetic. Otherwise, use standard arithmetic. 516789Sahrens */ 517789Sahrens if (*end == '.') { 518789Sahrens double fval = strtod(value, &end); 519789Sahrens 5202082Seschrock if ((shift = str2shift(hdl, end)) == -1) 521789Sahrens return (-1); 522789Sahrens 523789Sahrens fval *= pow(2, shift); 524789Sahrens 525789Sahrens if (fval > UINT64_MAX) { 5262082Seschrock if (hdl) 5272082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5282082Seschrock "numeric value is too large")); 529789Sahrens return (-1); 530789Sahrens } 531789Sahrens 532789Sahrens *num = (uint64_t)fval; 533789Sahrens } else { 5342082Seschrock if ((shift = str2shift(hdl, end)) == -1) 535789Sahrens return (-1); 536789Sahrens 537789Sahrens /* Check for overflow */ 538789Sahrens if (shift >= 64 || (*num << shift) >> shift != *num) { 5392082Seschrock if (hdl) 5402082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5412082Seschrock "numeric value is too large")); 542789Sahrens return (-1); 543789Sahrens } 544789Sahrens 545789Sahrens *num <<= shift; 546789Sahrens } 547789Sahrens 548789Sahrens return (0); 549789Sahrens } 550789Sahrens 551789Sahrens int 5522676Seschrock zfs_nicestrtonum(libzfs_handle_t *hdl, const char *str, uint64_t *val) 5532676Seschrock { 5542676Seschrock return (nicestrtonum(hdl, str, val)); 5552676Seschrock } 5562676Seschrock 5572676Seschrock /* 5582676Seschrock * The prop_parse_*() functions are designed to allow flexibility in callers 5592676Seschrock * when setting properties. At the DSL layer, all properties are either 64-bit 5602676Seschrock * numbers or strings. We want the user to be able to ignore this fact and 5612676Seschrock * specify properties as native values (boolean, for example) or as strings (to 5622676Seschrock * simplify command line utilities). This also handles converting index types 5632676Seschrock * (compression, checksum, etc) from strings to their on-disk index. 5642676Seschrock */ 5652676Seschrock 5662676Seschrock static int 5672676Seschrock prop_parse_boolean(libzfs_handle_t *hdl, nvpair_t *elem, uint64_t *val) 568789Sahrens { 5692676Seschrock uint64_t ret; 5702676Seschrock 5712676Seschrock switch (nvpair_type(elem)) { 5722676Seschrock case DATA_TYPE_STRING: 5732676Seschrock { 5742676Seschrock char *value; 5753363Sgw25295 verify(nvpair_value_string(elem, &value) == 0); 5762676Seschrock 5772676Seschrock if (strcmp(value, "on") == 0) { 5782676Seschrock ret = 1; 5792676Seschrock } else if (strcmp(value, "off") == 0) { 5802676Seschrock ret = 0; 5812676Seschrock } else { 5822676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5832676Seschrock "property '%s' must be 'on' or 'off'"), 5842676Seschrock nvpair_name(elem)); 5852676Seschrock return (-1); 5862676Seschrock } 5872676Seschrock break; 5882676Seschrock } 5892676Seschrock 5902676Seschrock case DATA_TYPE_UINT64: 5912676Seschrock { 5923363Sgw25295 verify(nvpair_value_uint64(elem, &ret) == 0); 5932676Seschrock if (ret > 1) { 5942676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5952676Seschrock "'%s' must be a boolean value"), 5962676Seschrock nvpair_name(elem)); 5972676Seschrock return (-1); 5982676Seschrock } 5992676Seschrock break; 6002676Seschrock } 6012676Seschrock 6022676Seschrock case DATA_TYPE_BOOLEAN_VALUE: 6032676Seschrock { 6042676Seschrock boolean_t value; 6053363Sgw25295 verify(nvpair_value_boolean_value(elem, &value) == 0); 6062676Seschrock ret = value; 6072676Seschrock break; 6082676Seschrock } 6092676Seschrock 6102676Seschrock default: 6112676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6122676Seschrock "'%s' must be a boolean value"), 6132676Seschrock nvpair_name(elem)); 6142676Seschrock return (-1); 6152676Seschrock } 6162676Seschrock 6172676Seschrock *val = ret; 6182676Seschrock return (0); 6192676Seschrock } 6202676Seschrock 6212676Seschrock static int 6222676Seschrock prop_parse_number(libzfs_handle_t *hdl, nvpair_t *elem, zfs_prop_t prop, 6232676Seschrock uint64_t *val) 6242676Seschrock { 6252676Seschrock uint64_t ret; 6262676Seschrock boolean_t isnone = B_FALSE; 6272676Seschrock 6282676Seschrock switch (nvpair_type(elem)) { 6292676Seschrock case DATA_TYPE_STRING: 6302676Seschrock { 6312676Seschrock char *value; 6322676Seschrock (void) nvpair_value_string(elem, &value); 6332676Seschrock if (strcmp(value, "none") == 0) { 6342676Seschrock isnone = B_TRUE; 6352676Seschrock ret = 0; 6362676Seschrock } else if (nicestrtonum(hdl, value, &ret) != 0) { 6372676Seschrock return (-1); 6382676Seschrock } 6392676Seschrock break; 6402676Seschrock } 6412676Seschrock 6422676Seschrock case DATA_TYPE_UINT64: 6432676Seschrock (void) nvpair_value_uint64(elem, &ret); 6442676Seschrock break; 6452676Seschrock 6462676Seschrock default: 6472676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6482676Seschrock "'%s' must be a number"), 6492676Seschrock nvpair_name(elem)); 6502676Seschrock return (-1); 6512676Seschrock } 6522676Seschrock 6532676Seschrock /* 6542676Seschrock * Quota special: force 'none' and don't allow 0. 6552676Seschrock */ 6562676Seschrock if (ret == 0 && !isnone && prop == ZFS_PROP_QUOTA) { 6572676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6582676Seschrock "use 'none' to disable quota")); 6592676Seschrock return (-1); 6602676Seschrock } 6612676Seschrock 6622676Seschrock *val = ret; 6632676Seschrock return (0); 6642676Seschrock } 6652676Seschrock 6662676Seschrock static int 6672676Seschrock prop_parse_index(libzfs_handle_t *hdl, nvpair_t *elem, zfs_prop_t prop, 6682676Seschrock uint64_t *val) 6692676Seschrock { 6702676Seschrock char *propname = nvpair_name(elem); 6712676Seschrock char *value; 6722676Seschrock 6732676Seschrock if (nvpair_type(elem) != DATA_TYPE_STRING) { 6742676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6752676Seschrock "'%s' must be a string"), propname); 6762676Seschrock return (-1); 6772676Seschrock } 6782676Seschrock 6792676Seschrock (void) nvpair_value_string(elem, &value); 6802676Seschrock 6812676Seschrock if (zfs_prop_string_to_index(prop, value, val) != 0) { 6822676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6832676Seschrock "'%s' must be one of '%s'"), propname, 6842676Seschrock zfs_prop_values(prop)); 6852676Seschrock return (-1); 6862676Seschrock } 6872676Seschrock 6882676Seschrock return (0); 689789Sahrens } 690789Sahrens 691789Sahrens /* 6923912Slling * Check if the bootfs name has the same pool name as it is set to. 6933912Slling * Assuming bootfs is a valid dataset name. 6943912Slling */ 6953912Slling static boolean_t 6963912Slling bootfs_poolname_valid(char *pool, char *bootfs) 6973912Slling { 6983912Slling char ch, *pname; 6993912Slling 7003912Slling /* get the pool name from the bootfs name */ 7013912Slling pname = bootfs; 7023912Slling while (*bootfs && !isspace(*bootfs) && *bootfs != '/') 7033912Slling bootfs++; 7043912Slling 7053912Slling ch = *bootfs; 7063912Slling *bootfs = 0; 7073912Slling 7083912Slling if (strcmp(pool, pname) == 0) { 7093912Slling *bootfs = ch; 7103912Slling return (B_TRUE); 7113912Slling } 7123912Slling 7133912Slling *bootfs = ch; 7143912Slling return (B_FALSE); 7153912Slling } 7163912Slling 7173912Slling /* 7182676Seschrock * Given an nvlist of properties to set, validates that they are correct, and 7192676Seschrock * parses any numeric properties (index, boolean, etc) if they are specified as 7202676Seschrock * strings. 721789Sahrens */ 7223912Slling nvlist_t * 7233912Slling zfs_validate_properties(libzfs_handle_t *hdl, zfs_type_t type, char *pool_name, 7243912Slling nvlist_t *nvl, uint64_t zoned, zfs_handle_t *zhp, const char *errbuf) 725789Sahrens { 7262676Seschrock nvpair_t *elem; 7272676Seschrock const char *propname; 7282676Seschrock zfs_prop_t prop; 7292676Seschrock uint64_t intval; 7302676Seschrock char *strval; 7312676Seschrock nvlist_t *ret; 7323912Slling int isuser; 7332676Seschrock 7342676Seschrock if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) { 7352676Seschrock (void) no_memory(hdl); 7362676Seschrock return (NULL); 7372676Seschrock } 7382676Seschrock 7392676Seschrock if (type == ZFS_TYPE_SNAPSHOT) { 7402676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7413413Smmusante "snapshot properties cannot be modified")); 7422676Seschrock (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 7432676Seschrock goto error; 744789Sahrens } 745789Sahrens 7462676Seschrock elem = NULL; 7472676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 7482676Seschrock propname = nvpair_name(elem); 7492676Seschrock 7502676Seschrock /* 7512676Seschrock * Make sure this property is valid and applies to this type. 7522676Seschrock */ 7533912Slling if ((prop = zfs_name_to_prop_common(propname, type)) 7543912Slling == ZFS_PROP_INVAL) { 7553912Slling isuser = zfs_prop_user(propname); 7563912Slling if (!isuser || (isuser && (type & ZFS_TYPE_POOL))) { 7572676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7582676Seschrock "invalid property '%s'"), 7592676Seschrock propname); 7602676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 7612676Seschrock goto error; 7622676Seschrock } else { 7632676Seschrock /* 7642676Seschrock * If this is a user property, make sure it's a 7652676Seschrock * string, and that it's less than 7662676Seschrock * ZAP_MAXNAMELEN. 7672676Seschrock */ 7682676Seschrock if (nvpair_type(elem) != DATA_TYPE_STRING) { 7692676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7702676Seschrock "'%s' must be a string"), 7712676Seschrock propname); 7722676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 7732676Seschrock errbuf); 7742676Seschrock goto error; 7752676Seschrock } 7762676Seschrock 7772676Seschrock if (strlen(nvpair_name(elem)) >= 7782676Seschrock ZAP_MAXNAMELEN) { 7792676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7802676Seschrock "property name '%s' is too long"), 7812676Seschrock propname); 7822676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 7832676Seschrock errbuf); 7842676Seschrock goto error; 7852676Seschrock } 7862676Seschrock } 7872676Seschrock 7882676Seschrock (void) nvpair_value_string(elem, &strval); 7892676Seschrock if (nvlist_add_string(ret, propname, strval) != 0) { 7902676Seschrock (void) no_memory(hdl); 7912676Seschrock goto error; 7922676Seschrock } 7932676Seschrock continue; 794789Sahrens } 7952676Seschrock 7962676Seschrock /* 7972676Seschrock * Normalize the name, to get rid of shorthand abbrevations. 7982676Seschrock */ 7992676Seschrock propname = zfs_prop_to_name(prop); 8002676Seschrock 8012676Seschrock if (!zfs_prop_valid_for_type(prop, type)) { 8022676Seschrock zfs_error_aux(hdl, 8032676Seschrock dgettext(TEXT_DOMAIN, "'%s' does not " 8042676Seschrock "apply to datasets of this type"), propname); 8052676Seschrock (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 8062676Seschrock goto error; 8072676Seschrock } 8082676Seschrock 8092676Seschrock if (zfs_prop_readonly(prop) && 8102676Seschrock (prop != ZFS_PROP_VOLBLOCKSIZE || zhp != NULL)) { 8112676Seschrock zfs_error_aux(hdl, 8122676Seschrock dgettext(TEXT_DOMAIN, "'%s' is readonly"), 8132676Seschrock propname); 8142676Seschrock (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); 8152676Seschrock goto error; 8162676Seschrock } 8172676Seschrock 8182676Seschrock /* 8192676Seschrock * Convert any properties to the internal DSL value types. 8202676Seschrock */ 8212676Seschrock strval = NULL; 8222676Seschrock switch (zfs_prop_get_type(prop)) { 8232676Seschrock case prop_type_boolean: 8242676Seschrock if (prop_parse_boolean(hdl, elem, &intval) != 0) { 8252676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8262676Seschrock goto error; 8272676Seschrock } 828789Sahrens break; 8292676Seschrock 8302676Seschrock case prop_type_string: 8312676Seschrock if (nvpair_type(elem) != DATA_TYPE_STRING) { 8322082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8332676Seschrock "'%s' must be a string"), 8342676Seschrock propname); 8352676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8362676Seschrock goto error; 837789Sahrens } 8382676Seschrock (void) nvpair_value_string(elem, &strval); 8392676Seschrock if (strlen(strval) >= ZFS_MAXPROPLEN) { 8402082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8412676Seschrock "'%s' is too long"), propname); 8422676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8432676Seschrock goto error; 8442676Seschrock } 8452676Seschrock break; 8462676Seschrock 8472676Seschrock case prop_type_number: 8482676Seschrock if (prop_parse_number(hdl, elem, prop, &intval) != 0) { 8492676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8502676Seschrock goto error; 8512676Seschrock } 8522676Seschrock break; 8532676Seschrock 8542676Seschrock case prop_type_index: 8552676Seschrock if (prop_parse_index(hdl, elem, prop, &intval) != 0) { 8562676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8572676Seschrock goto error; 858789Sahrens } 859789Sahrens break; 860789Sahrens 8612676Seschrock default: 8622676Seschrock abort(); 8632676Seschrock } 8642676Seschrock 8652676Seschrock /* 8662676Seschrock * Add the result to our return set of properties. 8672676Seschrock */ 8682676Seschrock if (strval) { 8692676Seschrock if (nvlist_add_string(ret, propname, strval) != 0) { 8702676Seschrock (void) no_memory(hdl); 8712676Seschrock goto error; 872789Sahrens } 8732676Seschrock } else if (nvlist_add_uint64(ret, propname, intval) != 0) { 8742676Seschrock (void) no_memory(hdl); 8752676Seschrock goto error; 8762676Seschrock } 8772676Seschrock 8782676Seschrock /* 8792676Seschrock * Perform some additional checks for specific properties. 8802676Seschrock */ 8812676Seschrock switch (prop) { 8822676Seschrock case ZFS_PROP_RECORDSIZE: 8832676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 8842676Seschrock /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */ 8852676Seschrock if (intval < SPA_MINBLOCKSIZE || 8862676Seschrock intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) { 8872082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8882676Seschrock "'%s' must be power of 2 from %u " 8892676Seschrock "to %uk"), propname, 8902676Seschrock (uint_t)SPA_MINBLOCKSIZE, 8912676Seschrock (uint_t)SPA_MAXBLOCKSIZE >> 10); 8922676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8932676Seschrock goto error; 894789Sahrens } 895789Sahrens break; 896789Sahrens 8973126Sahl case ZFS_PROP_SHAREISCSI: 8983126Sahl if (strcmp(strval, "off") != 0 && 8993126Sahl strcmp(strval, "on") != 0 && 9003126Sahl strcmp(strval, "type=disk") != 0) { 9013126Sahl zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9023126Sahl "'%s' must be 'on', 'off', or 'type=disk'"), 9033126Sahl propname); 9043126Sahl (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 9053126Sahl goto error; 9063126Sahl } 9073126Sahl 9083126Sahl break; 9093126Sahl 9102676Seschrock case ZFS_PROP_MOUNTPOINT: 9112676Seschrock if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 || 9122676Seschrock strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0) 9132676Seschrock break; 9142676Seschrock 9152676Seschrock if (strval[0] != '/') { 9162082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9172676Seschrock "'%s' must be an absolute path, " 9182676Seschrock "'none', or 'legacy'"), propname); 9192676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 9202676Seschrock goto error; 921789Sahrens } 9223126Sahl /*FALLTHRU*/ 9233126Sahl 9243126Sahl case ZFS_PROP_SHARENFS: 9253126Sahl /* 9263126Sahl * For the mountpoint and sharenfs properties, check if 9273126Sahl * it can be set in a global/non-global zone based on 9283126Sahl * the zoned property value: 9293126Sahl * 9303126Sahl * global zone non-global zone 9313126Sahl * -------------------------------------------------- 9323126Sahl * zoned=on mountpoint (no) mountpoint (yes) 9333126Sahl * sharenfs (no) sharenfs (no) 9343126Sahl * 9353126Sahl * zoned=off mountpoint (yes) N/A 9363126Sahl * sharenfs (yes) 9373126Sahl */ 9382676Seschrock if (zoned) { 9392676Seschrock if (getzoneid() == GLOBAL_ZONEID) { 9402676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9412676Seschrock "'%s' cannot be set on " 9422676Seschrock "dataset in a non-global zone"), 9432676Seschrock propname); 9442676Seschrock (void) zfs_error(hdl, EZFS_ZONED, 9452676Seschrock errbuf); 9462676Seschrock goto error; 9472676Seschrock } else if (prop == ZFS_PROP_SHARENFS) { 9482676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9492676Seschrock "'%s' cannot be set in " 9502676Seschrock "a non-global zone"), propname); 9512676Seschrock (void) zfs_error(hdl, EZFS_ZONED, 9522676Seschrock errbuf); 9532676Seschrock goto error; 9542676Seschrock } 9552676Seschrock } else if (getzoneid() != GLOBAL_ZONEID) { 9562676Seschrock /* 9572676Seschrock * If zoned property is 'off', this must be in 9582676Seschrock * a globle zone. If not, something is wrong. 9592676Seschrock */ 9602676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9612676Seschrock "'%s' cannot be set while dataset " 9622676Seschrock "'zoned' property is set"), propname); 9632676Seschrock (void) zfs_error(hdl, EZFS_ZONED, errbuf); 9642676Seschrock goto error; 9652676Seschrock } 9663126Sahl 9674180Sdougm /* 9684180Sdougm * At this point, it is legitimate to set the 9694180Sdougm * property. Now we want to make sure that the 9704180Sdougm * property value is valid if it is sharenfs. 9714180Sdougm */ 9724180Sdougm if (prop == ZFS_PROP_SHARENFS && 9734217Seschrock strcmp(strval, "on") != 0 && 9744217Seschrock strcmp(strval, "off") != 0) { 9754180Sdougm 9764180Sdougm /* 9774180Sdougm * Must be an NFS option string so 9784180Sdougm * init the libshare in order to 9794180Sdougm * enable the parser and then parse 9804180Sdougm * the options. We use the control API 9814180Sdougm * since we don't care about the 9824180Sdougm * current configuration and don't 9834180Sdougm * want the overhead of loading it 9844180Sdougm * until we actually do something. 9854180Sdougm */ 9864180Sdougm 9874217Seschrock if (zfs_init_libshare(hdl, 9884217Seschrock SA_INIT_CONTROL_API) != SA_OK) { 9894217Seschrock /* 9904217Seschrock * An error occurred so we can't do 9914217Seschrock * anything 9924217Seschrock */ 9934217Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9944217Seschrock "'%s' cannot be set: problem " 9954217Seschrock "in share initialization"), 9964217Seschrock propname); 9974217Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 9984217Seschrock errbuf); 9994217Seschrock goto error; 10004217Seschrock } 10014217Seschrock 10024217Seschrock if (zfs_parse_options(strval, "nfs") != SA_OK) { 10034217Seschrock /* 10044217Seschrock * There was an error in parsing so 10054217Seschrock * deal with it by issuing an error 10064217Seschrock * message and leaving after 10074217Seschrock * uninitializing the the libshare 10084217Seschrock * interface. 10094217Seschrock */ 10104217Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10114217Seschrock "'%s' cannot be set to invalid " 10124217Seschrock "options"), propname); 10134217Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10144217Seschrock errbuf); 10154217Seschrock zfs_uninit_libshare(hdl); 10164217Seschrock goto error; 10174217Seschrock } 10184180Sdougm zfs_uninit_libshare(hdl); 10194180Sdougm } 10204180Sdougm 10213126Sahl break; 10223912Slling 1023*4451Seschrock case ZPOOL_PROP_BOOTFS: 10243912Slling /* 10253912Slling * bootfs property value has to be a dataset name and 10263912Slling * the dataset has to be in the same pool as it sets to. 10273912Slling */ 10283912Slling if (strval[0] != '\0' && (!zfs_name_valid(strval, 10293912Slling ZFS_TYPE_FILESYSTEM) || !bootfs_poolname_valid( 10303912Slling pool_name, strval))) { 10313912Slling 10323912Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 10333912Slling "is an invalid name"), strval); 10343912Slling (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 10353912Slling goto error; 10363912Slling } 10373912Slling break; 10382676Seschrock } 10392676Seschrock 10402676Seschrock /* 10412676Seschrock * For changes to existing volumes, we have some additional 10422676Seschrock * checks to enforce. 10432676Seschrock */ 10442676Seschrock if (type == ZFS_TYPE_VOLUME && zhp != NULL) { 10452676Seschrock uint64_t volsize = zfs_prop_get_int(zhp, 10462676Seschrock ZFS_PROP_VOLSIZE); 10472676Seschrock uint64_t blocksize = zfs_prop_get_int(zhp, 10482676Seschrock ZFS_PROP_VOLBLOCKSIZE); 10492676Seschrock char buf[64]; 10502676Seschrock 10512676Seschrock switch (prop) { 10522676Seschrock case ZFS_PROP_RESERVATION: 10532676Seschrock if (intval > volsize) { 10542676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10552676Seschrock "'%s' is greater than current " 10562676Seschrock "volume size"), propname); 10572676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10582676Seschrock errbuf); 10592676Seschrock goto error; 10602676Seschrock } 10612676Seschrock break; 10622676Seschrock 10632676Seschrock case ZFS_PROP_VOLSIZE: 10642676Seschrock if (intval % blocksize != 0) { 10652676Seschrock zfs_nicenum(blocksize, buf, 10662676Seschrock sizeof (buf)); 10672676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10682676Seschrock "'%s' must be a multiple of " 10692676Seschrock "volume block size (%s)"), 10702676Seschrock propname, buf); 10712676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10722676Seschrock errbuf); 10732676Seschrock goto error; 10742676Seschrock } 10752676Seschrock 10762676Seschrock if (intval == 0) { 10772676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10782676Seschrock "'%s' cannot be zero"), 10792676Seschrock propname); 10802676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10812676Seschrock errbuf); 10822676Seschrock goto error; 1083789Sahrens } 10843126Sahl break; 1085789Sahrens } 1086789Sahrens } 1087789Sahrens } 1088789Sahrens 10892676Seschrock /* 10902676Seschrock * If this is an existing volume, and someone is setting the volsize, 10912676Seschrock * make sure that it matches the reservation, or add it if necessary. 10922676Seschrock */ 10932676Seschrock if (zhp != NULL && type == ZFS_TYPE_VOLUME && 10942676Seschrock nvlist_lookup_uint64(ret, zfs_prop_to_name(ZFS_PROP_VOLSIZE), 10952676Seschrock &intval) == 0) { 10962676Seschrock uint64_t old_volsize = zfs_prop_get_int(zhp, 10972676Seschrock ZFS_PROP_VOLSIZE); 10982676Seschrock uint64_t old_reservation = zfs_prop_get_int(zhp, 10992676Seschrock ZFS_PROP_RESERVATION); 11002676Seschrock uint64_t new_reservation; 11012676Seschrock 11022676Seschrock if (old_volsize == old_reservation && 11032676Seschrock nvlist_lookup_uint64(ret, 11042676Seschrock zfs_prop_to_name(ZFS_PROP_RESERVATION), 11052676Seschrock &new_reservation) != 0) { 11062676Seschrock if (nvlist_add_uint64(ret, 11072676Seschrock zfs_prop_to_name(ZFS_PROP_RESERVATION), 11082676Seschrock intval) != 0) { 11092676Seschrock (void) no_memory(hdl); 11102676Seschrock goto error; 11112676Seschrock } 11122676Seschrock } 11132676Seschrock } 11142676Seschrock 11152676Seschrock return (ret); 11162676Seschrock 11172676Seschrock error: 11182676Seschrock nvlist_free(ret); 11192676Seschrock return (NULL); 1120789Sahrens } 1121789Sahrens 1122789Sahrens /* 1123789Sahrens * Given a property name and value, set the property for the given dataset. 1124789Sahrens */ 1125789Sahrens int 11262676Seschrock zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) 1127789Sahrens { 1128789Sahrens zfs_cmd_t zc = { 0 }; 11292676Seschrock int ret = -1; 11302676Seschrock prop_changelist_t *cl = NULL; 11312082Seschrock char errbuf[1024]; 11322082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 11332676Seschrock nvlist_t *nvl = NULL, *realprops; 11342676Seschrock zfs_prop_t prop; 11352082Seschrock 11362082Seschrock (void) snprintf(errbuf, sizeof (errbuf), 11372676Seschrock dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 11382082Seschrock zhp->zfs_name); 11392082Seschrock 11402676Seschrock if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || 11412676Seschrock nvlist_add_string(nvl, propname, propval) != 0) { 11422676Seschrock (void) no_memory(hdl); 11432676Seschrock goto error; 1144789Sahrens } 1145789Sahrens 11463912Slling if ((realprops = zfs_validate_properties(hdl, zhp->zfs_type, NULL, nvl, 11472676Seschrock zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL) 11482676Seschrock goto error; 11492676Seschrock nvlist_free(nvl); 11502676Seschrock nvl = realprops; 11512676Seschrock 11522676Seschrock prop = zfs_name_to_prop(propname); 11532676Seschrock 1154789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 11552676Seschrock goto error; 1156789Sahrens 1157789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 11582082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11592082Seschrock "child dataset with inherited mountpoint is used " 11602082Seschrock "in a non-global zone")); 11612082Seschrock ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1162789Sahrens goto error; 1163789Sahrens } 1164789Sahrens 1165789Sahrens if ((ret = changelist_prefix(cl)) != 0) 1166789Sahrens goto error; 1167789Sahrens 1168789Sahrens /* 1169789Sahrens * Execute the corresponding ioctl() to set this property. 1170789Sahrens */ 1171789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1172789Sahrens 11732676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvl, NULL) != 0) 11742676Seschrock goto error; 11752676Seschrock 11762676Seschrock ret = ioctl(hdl->libzfs_fd, ZFS_IOC_SET_PROP, &zc); 1177789Sahrens 1178789Sahrens if (ret != 0) { 1179789Sahrens switch (errno) { 1180789Sahrens 1181789Sahrens case ENOSPC: 1182789Sahrens /* 1183789Sahrens * For quotas and reservations, ENOSPC indicates 1184789Sahrens * something different; setting a quota or reservation 1185789Sahrens * doesn't use any disk space. 1186789Sahrens */ 1187789Sahrens switch (prop) { 1188789Sahrens case ZFS_PROP_QUOTA: 11892082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11902082Seschrock "size is less than current used or " 11912082Seschrock "reserved space")); 11922082Seschrock (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1193789Sahrens break; 1194789Sahrens 1195789Sahrens case ZFS_PROP_RESERVATION: 11962082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11972082Seschrock "size is greater than available space")); 11982082Seschrock (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1199789Sahrens break; 1200789Sahrens 1201789Sahrens default: 12022082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 1203789Sahrens break; 1204789Sahrens } 1205789Sahrens break; 1206789Sahrens 1207789Sahrens case EBUSY: 12082082Seschrock if (prop == ZFS_PROP_VOLBLOCKSIZE) 12092082Seschrock (void) zfs_error(hdl, EZFS_VOLHASDATA, errbuf); 12102082Seschrock else 12112676Seschrock (void) zfs_standard_error(hdl, EBUSY, errbuf); 1212789Sahrens break; 1213789Sahrens 12141175Slling case EROFS: 12152082Seschrock (void) zfs_error(hdl, EZFS_DSREADONLY, errbuf); 12161175Slling break; 12171175Slling 12183886Sahl case ENOTSUP: 12193886Sahl zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12203886Sahl "pool must be upgraded to allow gzip compression")); 12213886Sahl (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 12223886Sahl break; 12233886Sahl 1224789Sahrens case EOVERFLOW: 1225789Sahrens /* 1226789Sahrens * This platform can't address a volume this big. 1227789Sahrens */ 1228789Sahrens #ifdef _ILP32 1229789Sahrens if (prop == ZFS_PROP_VOLSIZE) { 12302082Seschrock (void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf); 1231789Sahrens break; 1232789Sahrens } 1233789Sahrens #endif 12342082Seschrock /* FALLTHROUGH */ 1235789Sahrens default: 12362082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 1237789Sahrens } 1238789Sahrens } else { 1239789Sahrens /* 1240789Sahrens * Refresh the statistics so the new property value 1241789Sahrens * is reflected. 1242789Sahrens */ 12432676Seschrock if ((ret = changelist_postfix(cl)) == 0) 12442676Seschrock (void) get_stats(zhp); 1245789Sahrens } 1246789Sahrens 1247789Sahrens error: 12482676Seschrock nvlist_free(nvl); 12492676Seschrock zcmd_free_nvlists(&zc); 12502676Seschrock if (cl) 12512676Seschrock changelist_free(cl); 1252789Sahrens return (ret); 1253789Sahrens } 1254789Sahrens 1255789Sahrens /* 1256789Sahrens * Given a property, inherit the value from the parent dataset. 1257789Sahrens */ 1258789Sahrens int 12592676Seschrock zfs_prop_inherit(zfs_handle_t *zhp, const char *propname) 1260789Sahrens { 1261789Sahrens zfs_cmd_t zc = { 0 }; 1262789Sahrens int ret; 1263789Sahrens prop_changelist_t *cl; 12642082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 12652082Seschrock char errbuf[1024]; 12662676Seschrock zfs_prop_t prop; 12672082Seschrock 12682082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 12692082Seschrock "cannot inherit %s for '%s'"), propname, zhp->zfs_name); 1270789Sahrens 12712676Seschrock if ((prop = zfs_name_to_prop(propname)) == ZFS_PROP_INVAL) { 12722676Seschrock /* 12732676Seschrock * For user properties, the amount of work we have to do is very 12742676Seschrock * small, so just do it here. 12752676Seschrock */ 12762676Seschrock if (!zfs_prop_user(propname)) { 12772676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12782676Seschrock "invalid property")); 12792676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 12802676Seschrock } 12812676Seschrock 12822676Seschrock (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 12832676Seschrock (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 12842676Seschrock 12852676Seschrock if (ioctl(zhp->zfs_hdl->libzfs_fd, 12862676Seschrock ZFS_IOC_SET_PROP, &zc) != 0) 12872676Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 12882676Seschrock 12892676Seschrock return (0); 12902676Seschrock } 12912676Seschrock 1292789Sahrens /* 1293789Sahrens * Verify that this property is inheritable. 1294789Sahrens */ 12952082Seschrock if (zfs_prop_readonly(prop)) 12962082Seschrock return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf)); 12972082Seschrock 12982082Seschrock if (!zfs_prop_inheritable(prop)) 12992082Seschrock return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf)); 1300789Sahrens 1301789Sahrens /* 1302789Sahrens * Check to see if the value applies to this type 1303789Sahrens */ 13042082Seschrock if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 13052082Seschrock return (zfs_error(hdl, EZFS_PROPTYPE, errbuf)); 1306789Sahrens 13073443Srm160521 /* 13083443Srm160521 * Normalize the name, to get rid of shorthand abbrevations. 13093443Srm160521 */ 13103443Srm160521 propname = zfs_prop_to_name(prop); 1311789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 13122676Seschrock (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 1313789Sahrens 1314789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID && 1315789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 13162082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 13172082Seschrock "dataset is used in a non-global zone")); 13182082Seschrock return (zfs_error(hdl, EZFS_ZONED, errbuf)); 1319789Sahrens } 1320789Sahrens 1321789Sahrens /* 1322789Sahrens * Determine datasets which will be affected by this change, if any. 1323789Sahrens */ 1324789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 1325789Sahrens return (-1); 1326789Sahrens 1327789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 13282082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 13292082Seschrock "child dataset with inherited mountpoint is used " 13302082Seschrock "in a non-global zone")); 13312082Seschrock ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1332789Sahrens goto error; 1333789Sahrens } 1334789Sahrens 1335789Sahrens if ((ret = changelist_prefix(cl)) != 0) 1336789Sahrens goto error; 1337789Sahrens 13382082Seschrock if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, 13392082Seschrock ZFS_IOC_SET_PROP, &zc)) != 0) { 13402082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 1341789Sahrens } else { 1342789Sahrens 13432169Snd150628 if ((ret = changelist_postfix(cl)) != 0) 1344789Sahrens goto error; 1345789Sahrens 1346789Sahrens /* 1347789Sahrens * Refresh the statistics so the new property is reflected. 1348789Sahrens */ 1349789Sahrens (void) get_stats(zhp); 1350789Sahrens } 1351789Sahrens 1352789Sahrens error: 1353789Sahrens changelist_free(cl); 1354789Sahrens return (ret); 1355789Sahrens } 1356789Sahrens 13573912Slling void 1358789Sahrens nicebool(int value, char *buf, size_t buflen) 1359789Sahrens { 1360789Sahrens if (value) 1361789Sahrens (void) strlcpy(buf, "on", buflen); 1362789Sahrens else 1363789Sahrens (void) strlcpy(buf, "off", buflen); 1364789Sahrens } 1365789Sahrens 1366789Sahrens /* 13671356Seschrock * True DSL properties are stored in an nvlist. The following two functions 13681356Seschrock * extract them appropriately. 13691356Seschrock */ 13701356Seschrock static uint64_t 13711356Seschrock getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 13721356Seschrock { 13731356Seschrock nvlist_t *nv; 13741356Seschrock uint64_t value; 13751356Seschrock 13762885Sahrens *source = NULL; 13771356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 13781356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 13791356Seschrock verify(nvlist_lookup_uint64(nv, ZFS_PROP_VALUE, &value) == 0); 13802885Sahrens (void) nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source); 13811356Seschrock } else { 13821356Seschrock value = zfs_prop_default_numeric(prop); 13831356Seschrock *source = ""; 13841356Seschrock } 13851356Seschrock 13861356Seschrock return (value); 13871356Seschrock } 13881356Seschrock 13891356Seschrock static char * 13901356Seschrock getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 13911356Seschrock { 13921356Seschrock nvlist_t *nv; 13931356Seschrock char *value; 13941356Seschrock 13952885Sahrens *source = NULL; 13961356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 13971356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 13981356Seschrock verify(nvlist_lookup_string(nv, ZFS_PROP_VALUE, &value) == 0); 13992885Sahrens (void) nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source); 14001356Seschrock } else { 14011356Seschrock if ((value = (char *)zfs_prop_default_string(prop)) == NULL) 14021356Seschrock value = ""; 14031356Seschrock *source = ""; 14041356Seschrock } 14051356Seschrock 14061356Seschrock return (value); 14071356Seschrock } 14081356Seschrock 14091356Seschrock /* 1410789Sahrens * Internal function for getting a numeric property. Both zfs_prop_get() and 1411789Sahrens * zfs_prop_get_int() are built using this interface. 1412789Sahrens * 1413789Sahrens * Certain properties can be overridden using 'mount -o'. In this case, scan 1414789Sahrens * the contents of the /etc/mnttab entry, searching for the appropriate options. 1415789Sahrens * If they differ from the on-disk values, report the current values and mark 1416789Sahrens * the source "temporary". 1417789Sahrens */ 14182082Seschrock static int 1419789Sahrens get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zfs_source_t *src, 14202082Seschrock char **source, uint64_t *val) 1421789Sahrens { 1422789Sahrens struct mnttab mnt; 14233265Sahrens char *mntopt_on = NULL; 14243265Sahrens char *mntopt_off = NULL; 1425789Sahrens 1426789Sahrens *source = NULL; 1427789Sahrens 14283265Sahrens switch (prop) { 14293265Sahrens case ZFS_PROP_ATIME: 14303265Sahrens mntopt_on = MNTOPT_ATIME; 14313265Sahrens mntopt_off = MNTOPT_NOATIME; 14323265Sahrens break; 14333265Sahrens 14343265Sahrens case ZFS_PROP_DEVICES: 14353265Sahrens mntopt_on = MNTOPT_DEVICES; 14363265Sahrens mntopt_off = MNTOPT_NODEVICES; 14373265Sahrens break; 14383265Sahrens 14393265Sahrens case ZFS_PROP_EXEC: 14403265Sahrens mntopt_on = MNTOPT_EXEC; 14413265Sahrens mntopt_off = MNTOPT_NOEXEC; 14423265Sahrens break; 14433265Sahrens 14443265Sahrens case ZFS_PROP_READONLY: 14453265Sahrens mntopt_on = MNTOPT_RO; 14463265Sahrens mntopt_off = MNTOPT_RW; 14473265Sahrens break; 14483265Sahrens 14493265Sahrens case ZFS_PROP_SETUID: 14503265Sahrens mntopt_on = MNTOPT_SETUID; 14513265Sahrens mntopt_off = MNTOPT_NOSETUID; 14523265Sahrens break; 14533265Sahrens 14543265Sahrens case ZFS_PROP_XATTR: 14553265Sahrens mntopt_on = MNTOPT_XATTR; 14563265Sahrens mntopt_off = MNTOPT_NOXATTR; 14573265Sahrens break; 14583265Sahrens } 14593265Sahrens 14602474Seschrock /* 14612474Seschrock * Because looking up the mount options is potentially expensive 14622474Seschrock * (iterating over all of /etc/mnttab), we defer its calculation until 14632474Seschrock * we're looking up a property which requires its presence. 14642474Seschrock */ 14652474Seschrock if (!zhp->zfs_mntcheck && 14663265Sahrens (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { 14673265Sahrens struct mnttab entry, search = { 0 }; 14683265Sahrens FILE *mnttab = zhp->zfs_hdl->libzfs_mnttab; 14692474Seschrock 14702474Seschrock search.mnt_special = (char *)zhp->zfs_name; 14712474Seschrock search.mnt_fstype = MNTTYPE_ZFS; 14723265Sahrens rewind(mnttab); 14733265Sahrens 14743265Sahrens if (getmntany(mnttab, &entry, &search) == 0) { 14753265Sahrens zhp->zfs_mntopts = zfs_strdup(zhp->zfs_hdl, 14763265Sahrens entry.mnt_mntopts); 14773265Sahrens if (zhp->zfs_mntopts == NULL) 14783265Sahrens return (-1); 14793265Sahrens } 14802474Seschrock 14812474Seschrock zhp->zfs_mntcheck = B_TRUE; 14822474Seschrock } 14832474Seschrock 1484789Sahrens if (zhp->zfs_mntopts == NULL) 1485789Sahrens mnt.mnt_mntopts = ""; 1486789Sahrens else 1487789Sahrens mnt.mnt_mntopts = zhp->zfs_mntopts; 1488789Sahrens 1489789Sahrens switch (prop) { 1490789Sahrens case ZFS_PROP_ATIME: 14913265Sahrens case ZFS_PROP_DEVICES: 14923265Sahrens case ZFS_PROP_EXEC: 14933265Sahrens case ZFS_PROP_READONLY: 14943265Sahrens case ZFS_PROP_SETUID: 14953265Sahrens case ZFS_PROP_XATTR: 14962082Seschrock *val = getprop_uint64(zhp, prop, source); 14972082Seschrock 14983265Sahrens if (hasmntopt(&mnt, mntopt_on) && !*val) { 14992082Seschrock *val = B_TRUE; 1500789Sahrens if (src) 1501789Sahrens *src = ZFS_SRC_TEMPORARY; 15023265Sahrens } else if (hasmntopt(&mnt, mntopt_off) && *val) { 15032082Seschrock *val = B_FALSE; 1504789Sahrens if (src) 1505789Sahrens *src = ZFS_SRC_TEMPORARY; 1506789Sahrens } 15072082Seschrock break; 1508789Sahrens 1509789Sahrens case ZFS_PROP_RECORDSIZE: 1510789Sahrens case ZFS_PROP_COMPRESSION: 15111356Seschrock case ZFS_PROP_ZONED: 15122885Sahrens case ZFS_PROP_CREATION: 15132885Sahrens case ZFS_PROP_COMPRESSRATIO: 15142885Sahrens case ZFS_PROP_REFERENCED: 15152885Sahrens case ZFS_PROP_USED: 15162885Sahrens case ZFS_PROP_CREATETXG: 15172885Sahrens case ZFS_PROP_AVAILABLE: 15182885Sahrens case ZFS_PROP_VOLSIZE: 15192885Sahrens case ZFS_PROP_VOLBLOCKSIZE: 15203417Srm160521 *val = getprop_uint64(zhp, prop, source); 15213417Srm160521 break; 15223417Srm160521 15233265Sahrens case ZFS_PROP_CANMOUNT: 15242082Seschrock *val = getprop_uint64(zhp, prop, source); 15253417Srm160521 if (*val == 0) 15263417Srm160521 *source = zhp->zfs_name; 15273417Srm160521 else 15283417Srm160521 *source = ""; /* default */ 15292082Seschrock break; 1530789Sahrens 1531789Sahrens case ZFS_PROP_QUOTA: 1532789Sahrens case ZFS_PROP_RESERVATION: 15332885Sahrens *val = getprop_uint64(zhp, prop, source); 15342885Sahrens if (*val == 0) 1535789Sahrens *source = ""; /* default */ 1536789Sahrens else 1537789Sahrens *source = zhp->zfs_name; 15382082Seschrock break; 1539789Sahrens 1540789Sahrens case ZFS_PROP_MOUNTED: 15412082Seschrock *val = (zhp->zfs_mntopts != NULL); 15422082Seschrock break; 1543789Sahrens 15443377Seschrock case ZFS_PROP_NUMCLONES: 15453377Seschrock *val = zhp->zfs_dmustats.dds_num_clones; 15463377Seschrock break; 15473377Seschrock 1548789Sahrens default: 15492082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 15502082Seschrock "cannot get non-numeric property")); 15512082Seschrock return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP, 15522082Seschrock dgettext(TEXT_DOMAIN, "internal error"))); 1553789Sahrens } 1554789Sahrens 1555789Sahrens return (0); 1556789Sahrens } 1557789Sahrens 1558789Sahrens /* 1559789Sahrens * Calculate the source type, given the raw source string. 1560789Sahrens */ 1561789Sahrens static void 1562789Sahrens get_source(zfs_handle_t *zhp, zfs_source_t *srctype, char *source, 1563789Sahrens char *statbuf, size_t statlen) 1564789Sahrens { 1565789Sahrens if (statbuf == NULL || *srctype == ZFS_SRC_TEMPORARY) 1566789Sahrens return; 1567789Sahrens 1568789Sahrens if (source == NULL) { 1569789Sahrens *srctype = ZFS_SRC_NONE; 1570789Sahrens } else if (source[0] == '\0') { 1571789Sahrens *srctype = ZFS_SRC_DEFAULT; 1572789Sahrens } else { 1573789Sahrens if (strcmp(source, zhp->zfs_name) == 0) { 1574789Sahrens *srctype = ZFS_SRC_LOCAL; 1575789Sahrens } else { 1576789Sahrens (void) strlcpy(statbuf, source, statlen); 1577789Sahrens *srctype = ZFS_SRC_INHERITED; 1578789Sahrens } 1579789Sahrens } 1580789Sahrens 1581789Sahrens } 1582789Sahrens 1583789Sahrens /* 1584789Sahrens * Retrieve a property from the given object. If 'literal' is specified, then 1585789Sahrens * numbers are left as exact values. Otherwise, numbers are converted to a 1586789Sahrens * human-readable form. 1587789Sahrens * 1588789Sahrens * Returns 0 on success, or -1 on error. 1589789Sahrens */ 1590789Sahrens int 1591789Sahrens zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, 15922082Seschrock zfs_source_t *src, char *statbuf, size_t statlen, boolean_t literal) 1593789Sahrens { 1594789Sahrens char *source = NULL; 1595789Sahrens uint64_t val; 1596789Sahrens char *str; 1597789Sahrens const char *root; 15982676Seschrock const char *strval; 1599789Sahrens 1600789Sahrens /* 1601789Sahrens * Check to see if this property applies to our object 1602789Sahrens */ 1603789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1604789Sahrens return (-1); 1605789Sahrens 1606789Sahrens if (src) 1607789Sahrens *src = ZFS_SRC_NONE; 1608789Sahrens 1609789Sahrens switch (prop) { 1610789Sahrens case ZFS_PROP_ATIME: 1611789Sahrens case ZFS_PROP_READONLY: 1612789Sahrens case ZFS_PROP_SETUID: 1613789Sahrens case ZFS_PROP_ZONED: 1614789Sahrens case ZFS_PROP_DEVICES: 1615789Sahrens case ZFS_PROP_EXEC: 16162676Seschrock case ZFS_PROP_CANMOUNT: 16173234Sck153898 case ZFS_PROP_XATTR: 1618789Sahrens /* 1619789Sahrens * Basic boolean values are built on top of 1620789Sahrens * get_numeric_property(). 1621789Sahrens */ 16222082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 16232082Seschrock return (-1); 16242082Seschrock nicebool(val, propbuf, proplen); 1625789Sahrens 1626789Sahrens break; 1627789Sahrens 1628789Sahrens case ZFS_PROP_AVAILABLE: 1629789Sahrens case ZFS_PROP_RECORDSIZE: 1630789Sahrens case ZFS_PROP_CREATETXG: 1631789Sahrens case ZFS_PROP_REFERENCED: 1632789Sahrens case ZFS_PROP_USED: 1633789Sahrens case ZFS_PROP_VOLSIZE: 1634789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 16353377Seschrock case ZFS_PROP_NUMCLONES: 1636789Sahrens /* 1637789Sahrens * Basic numeric values are built on top of 1638789Sahrens * get_numeric_property(). 1639789Sahrens */ 16402082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 16412082Seschrock return (-1); 1642789Sahrens if (literal) 16432856Snd150628 (void) snprintf(propbuf, proplen, "%llu", 16443912Slling (u_longlong_t)val); 1645789Sahrens else 1646789Sahrens zfs_nicenum(val, propbuf, proplen); 1647789Sahrens break; 1648789Sahrens 1649789Sahrens case ZFS_PROP_COMPRESSION: 1650789Sahrens case ZFS_PROP_CHECKSUM: 1651789Sahrens case ZFS_PROP_SNAPDIR: 1652789Sahrens case ZFS_PROP_ACLMODE: 1653789Sahrens case ZFS_PROP_ACLINHERIT: 16543835Sahrens case ZFS_PROP_COPIES: 16551356Seschrock val = getprop_uint64(zhp, prop, &source); 16562676Seschrock verify(zfs_prop_index_to_string(prop, val, &strval) == 0); 16572676Seschrock (void) strlcpy(propbuf, strval, proplen); 1658789Sahrens break; 1659789Sahrens 1660789Sahrens case ZFS_PROP_CREATION: 1661789Sahrens /* 1662789Sahrens * 'creation' is a time_t stored in the statistics. We convert 1663789Sahrens * this into a string unless 'literal' is specified. 1664789Sahrens */ 1665789Sahrens { 16662885Sahrens val = getprop_uint64(zhp, prop, &source); 16672885Sahrens time_t time = (time_t)val; 1668789Sahrens struct tm t; 1669789Sahrens 1670789Sahrens if (literal || 1671789Sahrens localtime_r(&time, &t) == NULL || 1672789Sahrens strftime(propbuf, proplen, "%a %b %e %k:%M %Y", 1673789Sahrens &t) == 0) 16742885Sahrens (void) snprintf(propbuf, proplen, "%llu", val); 1675789Sahrens } 1676789Sahrens break; 1677789Sahrens 1678789Sahrens case ZFS_PROP_MOUNTPOINT: 1679789Sahrens /* 1680789Sahrens * Getting the precise mountpoint can be tricky. 1681789Sahrens * 1682789Sahrens * - for 'none' or 'legacy', return those values. 1683789Sahrens * - for default mountpoints, construct it as /zfs/<dataset> 1684789Sahrens * - for inherited mountpoints, we want to take everything 1685789Sahrens * after our ancestor and append it to the inherited value. 1686789Sahrens * 1687789Sahrens * If the pool has an alternate root, we want to prepend that 1688789Sahrens * root to any values we return. 1689789Sahrens */ 16901544Seschrock root = zhp->zfs_root; 16911356Seschrock str = getprop_string(zhp, prop, &source); 16921356Seschrock 16931356Seschrock if (str[0] == '\0') { 1694789Sahrens (void) snprintf(propbuf, proplen, "%s/zfs/%s", 1695789Sahrens root, zhp->zfs_name); 16961356Seschrock } else if (str[0] == '/') { 16971356Seschrock const char *relpath = zhp->zfs_name + strlen(source); 1698789Sahrens 1699789Sahrens if (relpath[0] == '/') 1700789Sahrens relpath++; 17011356Seschrock if (str[1] == '\0') 17021356Seschrock str++; 1703789Sahrens 1704789Sahrens if (relpath[0] == '\0') 1705789Sahrens (void) snprintf(propbuf, proplen, "%s%s", 17061356Seschrock root, str); 1707789Sahrens else 1708789Sahrens (void) snprintf(propbuf, proplen, "%s%s%s%s", 17091356Seschrock root, str, relpath[0] == '@' ? "" : "/", 1710789Sahrens relpath); 1711789Sahrens } else { 1712789Sahrens /* 'legacy' or 'none' */ 17131356Seschrock (void) strlcpy(propbuf, str, proplen); 1714789Sahrens } 1715789Sahrens 1716789Sahrens break; 1717789Sahrens 1718789Sahrens case ZFS_PROP_SHARENFS: 17193126Sahl case ZFS_PROP_SHAREISCSI: 17203126Sahl case ZFS_PROP_ISCSIOPTIONS: 17211356Seschrock (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 17221356Seschrock proplen); 1723789Sahrens break; 1724789Sahrens 1725789Sahrens case ZFS_PROP_ORIGIN: 17262885Sahrens (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 1727789Sahrens proplen); 1728789Sahrens /* 1729789Sahrens * If there is no parent at all, return failure to indicate that 1730789Sahrens * it doesn't apply to this dataset. 1731789Sahrens */ 1732789Sahrens if (propbuf[0] == '\0') 1733789Sahrens return (-1); 1734789Sahrens break; 1735789Sahrens 1736789Sahrens case ZFS_PROP_QUOTA: 1737789Sahrens case ZFS_PROP_RESERVATION: 17382082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 17392082Seschrock return (-1); 1740789Sahrens 1741789Sahrens /* 1742789Sahrens * If quota or reservation is 0, we translate this into 'none' 1743789Sahrens * (unless literal is set), and indicate that it's the default 1744789Sahrens * value. Otherwise, we print the number nicely and indicate 1745789Sahrens * that its set locally. 1746789Sahrens */ 1747789Sahrens if (val == 0) { 1748789Sahrens if (literal) 1749789Sahrens (void) strlcpy(propbuf, "0", proplen); 1750789Sahrens else 1751789Sahrens (void) strlcpy(propbuf, "none", proplen); 1752789Sahrens } else { 1753789Sahrens if (literal) 17542856Snd150628 (void) snprintf(propbuf, proplen, "%llu", 17553912Slling (u_longlong_t)val); 1756789Sahrens else 1757789Sahrens zfs_nicenum(val, propbuf, proplen); 1758789Sahrens } 1759789Sahrens break; 1760789Sahrens 1761789Sahrens case ZFS_PROP_COMPRESSRATIO: 17622082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 17632082Seschrock return (-1); 17642856Snd150628 (void) snprintf(propbuf, proplen, "%lld.%02lldx", (longlong_t) 17652856Snd150628 val / 100, (longlong_t)val % 100); 1766789Sahrens break; 1767789Sahrens 1768789Sahrens case ZFS_PROP_TYPE: 1769789Sahrens switch (zhp->zfs_type) { 1770789Sahrens case ZFS_TYPE_FILESYSTEM: 1771789Sahrens str = "filesystem"; 1772789Sahrens break; 1773789Sahrens case ZFS_TYPE_VOLUME: 1774789Sahrens str = "volume"; 1775789Sahrens break; 1776789Sahrens case ZFS_TYPE_SNAPSHOT: 1777789Sahrens str = "snapshot"; 1778789Sahrens break; 1779789Sahrens default: 17802082Seschrock abort(); 1781789Sahrens } 1782789Sahrens (void) snprintf(propbuf, proplen, "%s", str); 1783789Sahrens break; 1784789Sahrens 1785789Sahrens case ZFS_PROP_MOUNTED: 1786789Sahrens /* 1787789Sahrens * The 'mounted' property is a pseudo-property that described 1788789Sahrens * whether the filesystem is currently mounted. Even though 1789789Sahrens * it's a boolean value, the typical values of "on" and "off" 1790789Sahrens * don't make sense, so we translate to "yes" and "no". 1791789Sahrens */ 17922082Seschrock if (get_numeric_property(zhp, ZFS_PROP_MOUNTED, 17932082Seschrock src, &source, &val) != 0) 17942082Seschrock return (-1); 17952082Seschrock if (val) 1796789Sahrens (void) strlcpy(propbuf, "yes", proplen); 1797789Sahrens else 1798789Sahrens (void) strlcpy(propbuf, "no", proplen); 1799789Sahrens break; 1800789Sahrens 1801789Sahrens case ZFS_PROP_NAME: 1802789Sahrens /* 1803789Sahrens * The 'name' property is a pseudo-property derived from the 1804789Sahrens * dataset name. It is presented as a real property to simplify 1805789Sahrens * consumers. 1806789Sahrens */ 1807789Sahrens (void) strlcpy(propbuf, zhp->zfs_name, proplen); 1808789Sahrens break; 1809789Sahrens 1810789Sahrens default: 18112082Seschrock abort(); 1812789Sahrens } 1813789Sahrens 1814789Sahrens get_source(zhp, src, source, statbuf, statlen); 1815789Sahrens 1816789Sahrens return (0); 1817789Sahrens } 1818789Sahrens 1819789Sahrens /* 1820789Sahrens * Utility function to get the given numeric property. Does no validation that 1821789Sahrens * the given property is the appropriate type; should only be used with 1822789Sahrens * hard-coded property types. 1823789Sahrens */ 1824789Sahrens uint64_t 1825789Sahrens zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop) 1826789Sahrens { 1827789Sahrens char *source; 1828789Sahrens zfs_source_t sourcetype = ZFS_SRC_NONE; 18292082Seschrock uint64_t val; 18302082Seschrock 18312082Seschrock (void) get_numeric_property(zhp, prop, &sourcetype, &source, &val); 18322082Seschrock 18332082Seschrock return (val); 1834789Sahrens } 1835789Sahrens 1836789Sahrens /* 1837789Sahrens * Similar to zfs_prop_get(), but returns the value as an integer. 1838789Sahrens */ 1839789Sahrens int 1840789Sahrens zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, 1841789Sahrens zfs_source_t *src, char *statbuf, size_t statlen) 1842789Sahrens { 1843789Sahrens char *source; 1844789Sahrens 1845789Sahrens /* 1846789Sahrens * Check to see if this property applies to our object 1847789Sahrens */ 1848789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 18493237Slling return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE, 18502082Seschrock dgettext(TEXT_DOMAIN, "cannot get property '%s'"), 18512082Seschrock zfs_prop_to_name(prop))); 1852789Sahrens 1853789Sahrens if (src) 1854789Sahrens *src = ZFS_SRC_NONE; 1855789Sahrens 18562082Seschrock if (get_numeric_property(zhp, prop, src, &source, value) != 0) 18572082Seschrock return (-1); 1858789Sahrens 1859789Sahrens get_source(zhp, src, source, statbuf, statlen); 1860789Sahrens 1861789Sahrens return (0); 1862789Sahrens } 1863789Sahrens 1864789Sahrens /* 1865789Sahrens * Returns the name of the given zfs handle. 1866789Sahrens */ 1867789Sahrens const char * 1868789Sahrens zfs_get_name(const zfs_handle_t *zhp) 1869789Sahrens { 1870789Sahrens return (zhp->zfs_name); 1871789Sahrens } 1872789Sahrens 1873789Sahrens /* 1874789Sahrens * Returns the type of the given zfs handle. 1875789Sahrens */ 1876789Sahrens zfs_type_t 1877789Sahrens zfs_get_type(const zfs_handle_t *zhp) 1878789Sahrens { 1879789Sahrens return (zhp->zfs_type); 1880789Sahrens } 1881789Sahrens 1882789Sahrens /* 18831356Seschrock * Iterate over all child filesystems 1884789Sahrens */ 1885789Sahrens int 18861356Seschrock zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) 1887789Sahrens { 1888789Sahrens zfs_cmd_t zc = { 0 }; 1889789Sahrens zfs_handle_t *nzhp; 1890789Sahrens int ret; 1891789Sahrens 1892789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 18932082Seschrock ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; 1894789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1895789Sahrens /* 1896789Sahrens * Ignore private dataset names. 1897789Sahrens */ 1898789Sahrens if (dataset_name_hidden(zc.zc_name)) 1899789Sahrens continue; 1900789Sahrens 1901789Sahrens /* 1902789Sahrens * Silently ignore errors, as the only plausible explanation is 1903789Sahrens * that the pool has since been removed. 1904789Sahrens */ 19052082Seschrock if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 19062082Seschrock zc.zc_name)) == NULL) 1907789Sahrens continue; 1908789Sahrens 1909789Sahrens if ((ret = func(nzhp, data)) != 0) 1910789Sahrens return (ret); 1911789Sahrens } 1912789Sahrens 1913789Sahrens /* 1914789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1915789Sahrens * returned, then the underlying dataset has been removed since we 1916789Sahrens * obtained the handle. 1917789Sahrens */ 1918789Sahrens if (errno != ESRCH && errno != ENOENT) 19192082Seschrock return (zfs_standard_error(zhp->zfs_hdl, errno, 19202082Seschrock dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 1921789Sahrens 19221356Seschrock return (0); 19231356Seschrock } 19241356Seschrock 19251356Seschrock /* 19261356Seschrock * Iterate over all snapshots 19271356Seschrock */ 19281356Seschrock int 19291356Seschrock zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) 19301356Seschrock { 19311356Seschrock zfs_cmd_t zc = { 0 }; 19321356Seschrock zfs_handle_t *nzhp; 19331356Seschrock int ret; 1934789Sahrens 1935789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 19362082Seschrock ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, 19372082Seschrock &zc) == 0; 1938789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1939789Sahrens 19402082Seschrock if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 19412082Seschrock zc.zc_name)) == NULL) 1942789Sahrens continue; 1943789Sahrens 1944789Sahrens if ((ret = func(nzhp, data)) != 0) 1945789Sahrens return (ret); 1946789Sahrens } 1947789Sahrens 1948789Sahrens /* 1949789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1950789Sahrens * returned, then the underlying dataset has been removed since we 1951789Sahrens * obtained the handle. Silently ignore this case, and return success. 1952789Sahrens */ 1953789Sahrens if (errno != ESRCH && errno != ENOENT) 19542082Seschrock return (zfs_standard_error(zhp->zfs_hdl, errno, 19552082Seschrock dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 1956789Sahrens 1957789Sahrens return (0); 1958789Sahrens } 1959789Sahrens 1960789Sahrens /* 19611356Seschrock * Iterate over all children, snapshots and filesystems 19621356Seschrock */ 19631356Seschrock int 19641356Seschrock zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 19651356Seschrock { 19661356Seschrock int ret; 19671356Seschrock 19681356Seschrock if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0) 19691356Seschrock return (ret); 19701356Seschrock 19711356Seschrock return (zfs_iter_snapshots(zhp, func, data)); 19721356Seschrock } 19731356Seschrock 19741356Seschrock /* 1975789Sahrens * Given a complete name, return just the portion that refers to the parent. 1976789Sahrens * Can return NULL if this is a pool. 1977789Sahrens */ 1978789Sahrens static int 1979789Sahrens parent_name(const char *path, char *buf, size_t buflen) 1980789Sahrens { 1981789Sahrens char *loc; 1982789Sahrens 1983789Sahrens if ((loc = strrchr(path, '/')) == NULL) 1984789Sahrens return (-1); 1985789Sahrens 1986789Sahrens (void) strncpy(buf, path, MIN(buflen, loc - path)); 1987789Sahrens buf[loc - path] = '\0'; 1988789Sahrens 1989789Sahrens return (0); 1990789Sahrens } 1991789Sahrens 1992789Sahrens /* 19932676Seschrock * Checks to make sure that the given path has a parent, and that it exists. We 19942676Seschrock * also fetch the 'zoned' property, which is used to validate property settings 19952676Seschrock * when creating new datasets. 1996789Sahrens */ 1997789Sahrens static int 19982676Seschrock check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned) 1999789Sahrens { 2000789Sahrens zfs_cmd_t zc = { 0 }; 2001789Sahrens char parent[ZFS_MAXNAMELEN]; 2002789Sahrens char *slash; 20031356Seschrock zfs_handle_t *zhp; 20042082Seschrock char errbuf[1024]; 20052082Seschrock 20062082Seschrock (void) snprintf(errbuf, sizeof (errbuf), "cannot create '%s'", 20072082Seschrock path); 2008789Sahrens 2009789Sahrens /* get parent, and check to see if this is just a pool */ 2010789Sahrens if (parent_name(path, parent, sizeof (parent)) != 0) { 20112082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20122082Seschrock "missing dataset name")); 20132082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2014789Sahrens } 2015789Sahrens 2016789Sahrens /* check to see if the pool exists */ 2017789Sahrens if ((slash = strchr(parent, '/')) == NULL) 2018789Sahrens slash = parent + strlen(parent); 2019789Sahrens (void) strncpy(zc.zc_name, parent, slash - parent); 2020789Sahrens zc.zc_name[slash - parent] = '\0'; 20212082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 && 2022789Sahrens errno == ENOENT) { 20232082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20242082Seschrock "no such pool '%s'"), zc.zc_name); 20252082Seschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2026789Sahrens } 2027789Sahrens 2028789Sahrens /* check to see if the parent dataset exists */ 20292082Seschrock if ((zhp = make_dataset_handle(hdl, parent)) == NULL) { 2030789Sahrens switch (errno) { 2031789Sahrens case ENOENT: 20322082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20332082Seschrock "parent does not exist")); 20342082Seschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2035789Sahrens 2036789Sahrens default: 20372082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 2038789Sahrens } 2039789Sahrens } 2040789Sahrens 20412676Seschrock *zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); 2042789Sahrens /* we are in a non-global zone, but parent is in the global zone */ 20432676Seschrock if (getzoneid() != GLOBAL_ZONEID && !(*zoned)) { 20442082Seschrock (void) zfs_standard_error(hdl, EPERM, errbuf); 20451356Seschrock zfs_close(zhp); 2046789Sahrens return (-1); 2047789Sahrens } 2048789Sahrens 2049789Sahrens /* make sure parent is a filesystem */ 20501356Seschrock if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 20512082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20522082Seschrock "parent is not a filesystem")); 20532082Seschrock (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 20541356Seschrock zfs_close(zhp); 2055789Sahrens return (-1); 2056789Sahrens } 2057789Sahrens 20581356Seschrock zfs_close(zhp); 2059789Sahrens return (0); 2060789Sahrens } 2061789Sahrens 2062789Sahrens /* 20632676Seschrock * Create a new filesystem or volume. 2064789Sahrens */ 2065789Sahrens int 20662082Seschrock zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type, 20672676Seschrock nvlist_t *props) 2068789Sahrens { 2069789Sahrens zfs_cmd_t zc = { 0 }; 2070789Sahrens int ret; 2071789Sahrens uint64_t size = 0; 2072789Sahrens uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE); 20732082Seschrock char errbuf[1024]; 20742676Seschrock uint64_t zoned; 20752082Seschrock 20762082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 20772082Seschrock "cannot create '%s'"), path); 2078789Sahrens 2079789Sahrens /* validate the path, taking care to note the extended error message */ 20802082Seschrock if (!zfs_validate_name(hdl, path, type)) 20812082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2082789Sahrens 2083789Sahrens /* validate parents exist */ 20842676Seschrock if (check_parents(hdl, path, &zoned) != 0) 2085789Sahrens return (-1); 2086789Sahrens 2087789Sahrens /* 2088789Sahrens * The failure modes when creating a dataset of a different type over 2089789Sahrens * one that already exists is a little strange. In particular, if you 2090789Sahrens * try to create a dataset on top of an existing dataset, the ioctl() 2091789Sahrens * will return ENOENT, not EEXIST. To prevent this from happening, we 2092789Sahrens * first try to see if the dataset exists. 2093789Sahrens */ 2094789Sahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 20952082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) { 20962082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20972082Seschrock "dataset already exists")); 20982082Seschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2099789Sahrens } 2100789Sahrens 2101789Sahrens if (type == ZFS_TYPE_VOLUME) 2102789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2103789Sahrens else 2104789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2105789Sahrens 21063912Slling if (props && (props = zfs_validate_properties(hdl, type, NULL, props, 21073912Slling zoned, NULL, errbuf)) == 0) 21082676Seschrock return (-1); 21092676Seschrock 2110789Sahrens if (type == ZFS_TYPE_VOLUME) { 21111133Seschrock /* 21121133Seschrock * If we are creating a volume, the size and block size must 21131133Seschrock * satisfy a few restraints. First, the blocksize must be a 21141133Seschrock * valid block size between SPA_{MIN,MAX}BLOCKSIZE. Second, the 21151133Seschrock * volsize must be a multiple of the block size, and cannot be 21161133Seschrock * zero. 21171133Seschrock */ 21182676Seschrock if (props == NULL || nvlist_lookup_uint64(props, 21192676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) { 21202676Seschrock nvlist_free(props); 21212082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21222676Seschrock "missing volume size")); 21232676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2124789Sahrens } 2125789Sahrens 21262676Seschrock if ((ret = nvlist_lookup_uint64(props, 21272676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 21282676Seschrock &blocksize)) != 0) { 21292676Seschrock if (ret == ENOENT) { 21302676Seschrock blocksize = zfs_prop_default_numeric( 21312676Seschrock ZFS_PROP_VOLBLOCKSIZE); 21322676Seschrock } else { 21332676Seschrock nvlist_free(props); 21342676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21352676Seschrock "missing volume block size")); 21362676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 21372676Seschrock } 21382676Seschrock } 21392676Seschrock 21402676Seschrock if (size == 0) { 21412676Seschrock nvlist_free(props); 21422082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21432676Seschrock "volume size cannot be zero")); 21442676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 21451133Seschrock } 21461133Seschrock 21471133Seschrock if (size % blocksize != 0) { 21482676Seschrock nvlist_free(props); 21492082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21502676Seschrock "volume size must be a multiple of volume block " 21512676Seschrock "size")); 21522676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 21531133Seschrock } 2154789Sahrens } 2155789Sahrens 21562676Seschrock if (props && 21572676Seschrock zcmd_write_src_nvlist(hdl, &zc, props, NULL) != 0) 21582676Seschrock return (-1); 21592676Seschrock nvlist_free(props); 21602676Seschrock 2161789Sahrens /* create the dataset */ 21622082Seschrock ret = ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE, &zc); 2163789Sahrens 21643912Slling if (ret == 0 && type == ZFS_TYPE_VOLUME) { 21652082Seschrock ret = zvol_create_link(hdl, path); 21663912Slling if (ret) { 21673912Slling (void) zfs_standard_error(hdl, errno, 21683912Slling dgettext(TEXT_DOMAIN, 21693912Slling "Volume successfully created, but device links " 21703912Slling "were not created")); 21713912Slling zcmd_free_nvlists(&zc); 21723912Slling return (-1); 21733912Slling } 21743912Slling } 2175789Sahrens 21762676Seschrock zcmd_free_nvlists(&zc); 21772676Seschrock 2178789Sahrens /* check for failure */ 2179789Sahrens if (ret != 0) { 2180789Sahrens char parent[ZFS_MAXNAMELEN]; 2181789Sahrens (void) parent_name(path, parent, sizeof (parent)); 2182789Sahrens 2183789Sahrens switch (errno) { 2184789Sahrens case ENOENT: 21852082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21862082Seschrock "no such parent '%s'"), parent); 21872082Seschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2188789Sahrens 2189789Sahrens case EINVAL: 21902082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21913413Smmusante "parent '%s' is not a filesystem"), parent); 21922082Seschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 2193789Sahrens 2194789Sahrens case EDOM: 21952082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21962676Seschrock "volume block size must be power of 2 from " 21972676Seschrock "%u to %uk"), 2198789Sahrens (uint_t)SPA_MINBLOCKSIZE, 2199789Sahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 22002082Seschrock 22012676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 22022082Seschrock 2203789Sahrens #ifdef _ILP32 2204789Sahrens case EOVERFLOW: 2205789Sahrens /* 2206789Sahrens * This platform can't address a volume this big. 2207789Sahrens */ 22082082Seschrock if (type == ZFS_TYPE_VOLUME) 22092082Seschrock return (zfs_error(hdl, EZFS_VOLTOOBIG, 22102082Seschrock errbuf)); 2211789Sahrens #endif 22122082Seschrock /* FALLTHROUGH */ 2213789Sahrens default: 22142082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 2215789Sahrens } 2216789Sahrens } 2217789Sahrens 2218789Sahrens return (0); 2219789Sahrens } 2220789Sahrens 2221789Sahrens /* 2222789Sahrens * Destroys the given dataset. The caller must make sure that the filesystem 2223789Sahrens * isn't mounted, and that there are no active dependents. 2224789Sahrens */ 2225789Sahrens int 2226789Sahrens zfs_destroy(zfs_handle_t *zhp) 2227789Sahrens { 2228789Sahrens zfs_cmd_t zc = { 0 }; 2229789Sahrens 2230789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2231789Sahrens 22322676Seschrock if (ZFS_IS_VOLUME(zhp)) { 22333126Sahl /* 22343126Sahl * Unconditionally unshare this zvol ignoring failure as it 22353126Sahl * indicates only that the volume wasn't shared initially. 22363126Sahl */ 22373126Sahl (void) zfs_unshare_iscsi(zhp); 22383126Sahl 22392082Seschrock if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0) 2240789Sahrens return (-1); 2241789Sahrens 2242789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2243789Sahrens } else { 2244789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2245789Sahrens } 2246789Sahrens 22473126Sahl if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) != 0) { 22483237Slling return (zfs_standard_error_fmt(zhp->zfs_hdl, errno, 22492082Seschrock dgettext(TEXT_DOMAIN, "cannot destroy '%s'"), 22502082Seschrock zhp->zfs_name)); 22512199Sahrens } 2252789Sahrens 2253789Sahrens remove_mountpoint(zhp); 2254789Sahrens 2255789Sahrens return (0); 2256789Sahrens } 2257789Sahrens 22582199Sahrens struct destroydata { 22592199Sahrens char *snapname; 22602199Sahrens boolean_t gotone; 22613265Sahrens boolean_t closezhp; 22622199Sahrens }; 22632199Sahrens 22642199Sahrens static int 22652199Sahrens zfs_remove_link_cb(zfs_handle_t *zhp, void *arg) 22662199Sahrens { 22672199Sahrens struct destroydata *dd = arg; 22682199Sahrens zfs_handle_t *szhp; 22692199Sahrens char name[ZFS_MAXNAMELEN]; 22703265Sahrens boolean_t closezhp = dd->closezhp; 22713265Sahrens int rv; 22722199Sahrens 22732676Seschrock (void) strlcpy(name, zhp->zfs_name, sizeof (name)); 22742676Seschrock (void) strlcat(name, "@", sizeof (name)); 22752676Seschrock (void) strlcat(name, dd->snapname, sizeof (name)); 22762199Sahrens 22772199Sahrens szhp = make_dataset_handle(zhp->zfs_hdl, name); 22782199Sahrens if (szhp) { 22792199Sahrens dd->gotone = B_TRUE; 22802199Sahrens zfs_close(szhp); 22812199Sahrens } 22822199Sahrens 22832199Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 22842199Sahrens (void) zvol_remove_link(zhp->zfs_hdl, name); 22852199Sahrens /* 22862199Sahrens * NB: this is simply a best-effort. We don't want to 22872199Sahrens * return an error, because then we wouldn't visit all 22882199Sahrens * the volumes. 22892199Sahrens */ 22902199Sahrens } 22912199Sahrens 22923265Sahrens dd->closezhp = B_TRUE; 22933265Sahrens rv = zfs_iter_filesystems(zhp, zfs_remove_link_cb, arg); 22943265Sahrens if (closezhp) 22953265Sahrens zfs_close(zhp); 22963265Sahrens return (rv); 22972199Sahrens } 22982199Sahrens 22992199Sahrens /* 23002199Sahrens * Destroys all snapshots with the given name in zhp & descendants. 23012199Sahrens */ 23022199Sahrens int 23032199Sahrens zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname) 23042199Sahrens { 23052199Sahrens zfs_cmd_t zc = { 0 }; 23062199Sahrens int ret; 23072199Sahrens struct destroydata dd = { 0 }; 23082199Sahrens 23092199Sahrens dd.snapname = snapname; 23102199Sahrens (void) zfs_remove_link_cb(zhp, &dd); 23112199Sahrens 23122199Sahrens if (!dd.gotone) { 23133237Slling return (zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT, 23142199Sahrens dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"), 23152199Sahrens zhp->zfs_name, snapname)); 23162199Sahrens } 23172199Sahrens 23182199Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 23192676Seschrock (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); 23202199Sahrens 23212199Sahrens ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY_SNAPS, &zc); 23222199Sahrens if (ret != 0) { 23232199Sahrens char errbuf[1024]; 23242199Sahrens 23252199Sahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 23262199Sahrens "cannot destroy '%s@%s'"), zc.zc_name, snapname); 23272199Sahrens 23282199Sahrens switch (errno) { 23292199Sahrens case EEXIST: 23302199Sahrens zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 23312199Sahrens "snapshot is cloned")); 23322199Sahrens return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf)); 23332199Sahrens 23342199Sahrens default: 23352199Sahrens return (zfs_standard_error(zhp->zfs_hdl, errno, 23362199Sahrens errbuf)); 23372199Sahrens } 23382199Sahrens } 23392199Sahrens 23402199Sahrens return (0); 23412199Sahrens } 23422199Sahrens 2343789Sahrens /* 2344789Sahrens * Clones the given dataset. The target must be of the same type as the source. 2345789Sahrens */ 2346789Sahrens int 23472676Seschrock zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props) 2348789Sahrens { 2349789Sahrens zfs_cmd_t zc = { 0 }; 2350789Sahrens char parent[ZFS_MAXNAMELEN]; 2351789Sahrens int ret; 23522082Seschrock char errbuf[1024]; 23532082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 23542676Seschrock zfs_type_t type; 23552676Seschrock uint64_t zoned; 2356789Sahrens 2357789Sahrens assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 2358789Sahrens 23592082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 23602082Seschrock "cannot create '%s'"), target); 23612082Seschrock 2362789Sahrens /* validate the target name */ 23632082Seschrock if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM)) 23642082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2365789Sahrens 2366789Sahrens /* validate parents exist */ 23672676Seschrock if (check_parents(hdl, target, &zoned) != 0) 2368789Sahrens return (-1); 2369789Sahrens 2370789Sahrens (void) parent_name(target, parent, sizeof (parent)); 2371789Sahrens 2372789Sahrens /* do the clone */ 23732676Seschrock if (ZFS_IS_VOLUME(zhp)) { 2374789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 23752744Snn35248 type = ZFS_TYPE_VOLUME; 23762676Seschrock } else { 2377789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 23782744Snn35248 type = ZFS_TYPE_FILESYSTEM; 23792676Seschrock } 23802676Seschrock 23812676Seschrock if (props) { 23823912Slling if ((props = zfs_validate_properties(hdl, type, NULL, props, 23833912Slling zoned, zhp, errbuf)) == NULL) 23842676Seschrock return (-1); 23852676Seschrock 23862676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, props, NULL) != 0) { 23872676Seschrock nvlist_free(props); 23882676Seschrock return (-1); 23892676Seschrock } 23902676Seschrock 23912676Seschrock nvlist_free(props); 23922676Seschrock } 2393789Sahrens 2394789Sahrens (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name)); 23952676Seschrock (void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value)); 23962082Seschrock ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_CREATE, &zc); 2397789Sahrens 23982676Seschrock zcmd_free_nvlists(&zc); 23992676Seschrock 2400789Sahrens if (ret != 0) { 2401789Sahrens switch (errno) { 2402789Sahrens 2403789Sahrens case ENOENT: 2404789Sahrens /* 2405789Sahrens * The parent doesn't exist. We should have caught this 2406789Sahrens * above, but there may a race condition that has since 2407789Sahrens * destroyed the parent. 2408789Sahrens * 2409789Sahrens * At this point, we don't know whether it's the source 2410789Sahrens * that doesn't exist anymore, or whether the target 2411789Sahrens * dataset doesn't exist. 2412789Sahrens */ 24132082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 24142082Seschrock "no such parent '%s'"), parent); 24152082Seschrock return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf)); 24162082Seschrock 24172082Seschrock case EXDEV: 24182082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 24192082Seschrock "source and target pools differ")); 24202082Seschrock return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET, 24212082Seschrock errbuf)); 24222082Seschrock 24232082Seschrock default: 24242082Seschrock return (zfs_standard_error(zhp->zfs_hdl, errno, 24252082Seschrock errbuf)); 24262082Seschrock } 24272676Seschrock } else if (ZFS_IS_VOLUME(zhp)) { 24282082Seschrock ret = zvol_create_link(zhp->zfs_hdl, target); 24292082Seschrock } 24302082Seschrock 24312082Seschrock return (ret); 24322082Seschrock } 24332082Seschrock 24342082Seschrock typedef struct promote_data { 24352082Seschrock char cb_mountpoint[MAXPATHLEN]; 24362082Seschrock const char *cb_target; 24372082Seschrock const char *cb_errbuf; 24382082Seschrock uint64_t cb_pivot_txg; 24392082Seschrock } promote_data_t; 24402082Seschrock 24412082Seschrock static int 24422082Seschrock promote_snap_cb(zfs_handle_t *zhp, void *data) 24432082Seschrock { 24442082Seschrock promote_data_t *pd = data; 24452082Seschrock zfs_handle_t *szhp; 24462082Seschrock char snapname[MAXPATHLEN]; 24473265Sahrens int rv = 0; 24482082Seschrock 24492082Seschrock /* We don't care about snapshots after the pivot point */ 24503265Sahrens if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > pd->cb_pivot_txg) { 24513265Sahrens zfs_close(zhp); 24522082Seschrock return (0); 24533265Sahrens } 24542082Seschrock 24552417Sahrens /* Remove the device link if it's a zvol. */ 24562676Seschrock if (ZFS_IS_VOLUME(zhp)) 24572417Sahrens (void) zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name); 24582082Seschrock 24592082Seschrock /* Check for conflicting names */ 24602676Seschrock (void) strlcpy(snapname, pd->cb_target, sizeof (snapname)); 24612676Seschrock (void) strlcat(snapname, strchr(zhp->zfs_name, '@'), sizeof (snapname)); 24622082Seschrock szhp = make_dataset_handle(zhp->zfs_hdl, snapname); 24632082Seschrock if (szhp != NULL) { 24642082Seschrock zfs_close(szhp); 24652082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 24662082Seschrock "snapshot name '%s' from origin \n" 24672082Seschrock "conflicts with '%s' from target"), 24682082Seschrock zhp->zfs_name, snapname); 24693265Sahrens rv = zfs_error(zhp->zfs_hdl, EZFS_EXISTS, pd->cb_errbuf); 24702082Seschrock } 24713265Sahrens zfs_close(zhp); 24723265Sahrens return (rv); 24732082Seschrock } 24742082Seschrock 24752417Sahrens static int 24762417Sahrens promote_snap_done_cb(zfs_handle_t *zhp, void *data) 24772417Sahrens { 24782417Sahrens promote_data_t *pd = data; 24792417Sahrens 24802417Sahrens /* We don't care about snapshots after the pivot point */ 24813265Sahrens if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) <= pd->cb_pivot_txg) { 24823265Sahrens /* Create the device link if it's a zvol. */ 24833265Sahrens if (ZFS_IS_VOLUME(zhp)) 24843265Sahrens (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 24853265Sahrens } 24863265Sahrens 24873265Sahrens zfs_close(zhp); 24882417Sahrens return (0); 24892417Sahrens } 24902417Sahrens 24912082Seschrock /* 24922082Seschrock * Promotes the given clone fs to be the clone parent. 24932082Seschrock */ 24942082Seschrock int 24952082Seschrock zfs_promote(zfs_handle_t *zhp) 24962082Seschrock { 24972082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 24982082Seschrock zfs_cmd_t zc = { 0 }; 24992082Seschrock char parent[MAXPATHLEN]; 25002082Seschrock char *cp; 25012082Seschrock int ret; 25022082Seschrock zfs_handle_t *pzhp; 25032082Seschrock promote_data_t pd; 25042082Seschrock char errbuf[1024]; 25052082Seschrock 25062082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 25072082Seschrock "cannot promote '%s'"), zhp->zfs_name); 25082082Seschrock 25092082Seschrock if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 25102082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 25112082Seschrock "snapshots can not be promoted")); 25122082Seschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 25132082Seschrock } 25142082Seschrock 25152676Seschrock (void) strlcpy(parent, zhp->zfs_dmustats.dds_clone_of, sizeof (parent)); 25162082Seschrock if (parent[0] == '\0') { 25172082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 25182082Seschrock "not a cloned filesystem")); 25192082Seschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 25202082Seschrock } 25212082Seschrock cp = strchr(parent, '@'); 25222082Seschrock *cp = '\0'; 25232082Seschrock 25242082Seschrock /* Walk the snapshots we will be moving */ 25252082Seschrock pzhp = zfs_open(hdl, zhp->zfs_dmustats.dds_clone_of, ZFS_TYPE_SNAPSHOT); 25262082Seschrock if (pzhp == NULL) 25272082Seschrock return (-1); 25282082Seschrock pd.cb_pivot_txg = zfs_prop_get_int(pzhp, ZFS_PROP_CREATETXG); 25292082Seschrock zfs_close(pzhp); 25302082Seschrock pd.cb_target = zhp->zfs_name; 25312082Seschrock pd.cb_errbuf = errbuf; 25322082Seschrock pzhp = zfs_open(hdl, parent, ZFS_TYPE_ANY); 25332082Seschrock if (pzhp == NULL) 25342082Seschrock return (-1); 25352082Seschrock (void) zfs_prop_get(pzhp, ZFS_PROP_MOUNTPOINT, pd.cb_mountpoint, 25362082Seschrock sizeof (pd.cb_mountpoint), NULL, NULL, 0, FALSE); 25372082Seschrock ret = zfs_iter_snapshots(pzhp, promote_snap_cb, &pd); 25382417Sahrens if (ret != 0) { 25392417Sahrens zfs_close(pzhp); 25402082Seschrock return (-1); 25412417Sahrens } 25422082Seschrock 25432082Seschrock /* issue the ioctl */ 25442676Seschrock (void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_clone_of, 25452676Seschrock sizeof (zc.zc_value)); 25462082Seschrock (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 25472082Seschrock ret = ioctl(hdl->libzfs_fd, ZFS_IOC_PROMOTE, &zc); 25482082Seschrock 25492082Seschrock if (ret != 0) { 25502417Sahrens int save_errno = errno; 25512417Sahrens 25522417Sahrens (void) zfs_iter_snapshots(pzhp, promote_snap_done_cb, &pd); 25532417Sahrens zfs_close(pzhp); 25542417Sahrens 25552417Sahrens switch (save_errno) { 2556789Sahrens case EEXIST: 2557789Sahrens /* 25582082Seschrock * There is a conflicting snapshot name. We 25592082Seschrock * should have caught this above, but they could 25602082Seschrock * have renamed something in the mean time. 2561789Sahrens */ 25622082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 25632082Seschrock "conflicting snapshot name from parent '%s'"), 25642082Seschrock parent); 25652082Seschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2566789Sahrens 2567789Sahrens default: 25682417Sahrens return (zfs_standard_error(hdl, save_errno, errbuf)); 2569789Sahrens } 25702417Sahrens } else { 25712417Sahrens (void) zfs_iter_snapshots(zhp, promote_snap_done_cb, &pd); 2572789Sahrens } 2573789Sahrens 25742417Sahrens zfs_close(pzhp); 2575789Sahrens return (ret); 2576789Sahrens } 2577789Sahrens 25784007Smmusante struct createdata { 25794007Smmusante const char *cd_snapname; 25804007Smmusante int cd_ifexists; 25814007Smmusante }; 25824007Smmusante 25832199Sahrens static int 25842199Sahrens zfs_create_link_cb(zfs_handle_t *zhp, void *arg) 25852199Sahrens { 25864007Smmusante struct createdata *cd = arg; 25872676Seschrock int ret; 25882199Sahrens 25892199Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 25902199Sahrens char name[MAXPATHLEN]; 25912199Sahrens 25922676Seschrock (void) strlcpy(name, zhp->zfs_name, sizeof (name)); 25932676Seschrock (void) strlcat(name, "@", sizeof (name)); 25944007Smmusante (void) strlcat(name, cd->cd_snapname, sizeof (name)); 25954007Smmusante (void) zvol_create_link_common(zhp->zfs_hdl, name, 25964007Smmusante cd->cd_ifexists); 25972199Sahrens /* 25982199Sahrens * NB: this is simply a best-effort. We don't want to 25992199Sahrens * return an error, because then we wouldn't visit all 26002199Sahrens * the volumes. 26012199Sahrens */ 26022199Sahrens } 26032676Seschrock 26044007Smmusante ret = zfs_iter_filesystems(zhp, zfs_create_link_cb, cd); 26052676Seschrock 26062676Seschrock zfs_close(zhp); 26072676Seschrock 26082676Seschrock return (ret); 26092199Sahrens } 26102199Sahrens 2611789Sahrens /* 26123504Sahl * Takes a snapshot of the given dataset. 2613789Sahrens */ 2614789Sahrens int 26152199Sahrens zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive) 2616789Sahrens { 2617789Sahrens const char *delim; 2618789Sahrens char *parent; 2619789Sahrens zfs_handle_t *zhp; 2620789Sahrens zfs_cmd_t zc = { 0 }; 2621789Sahrens int ret; 26222082Seschrock char errbuf[1024]; 26232082Seschrock 26242082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 26252082Seschrock "cannot snapshot '%s'"), path); 26262082Seschrock 26272082Seschrock /* validate the target name */ 26282082Seschrock if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT)) 26292082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2630789Sahrens 2631789Sahrens /* make sure the parent exists and is of the appropriate type */ 26322199Sahrens delim = strchr(path, '@'); 26332082Seschrock if ((parent = zfs_alloc(hdl, delim - path + 1)) == NULL) 26342082Seschrock return (-1); 2635789Sahrens (void) strncpy(parent, path, delim - path); 2636789Sahrens parent[delim - path] = '\0'; 2637789Sahrens 26382082Seschrock if ((zhp = zfs_open(hdl, parent, ZFS_TYPE_FILESYSTEM | 2639789Sahrens ZFS_TYPE_VOLUME)) == NULL) { 2640789Sahrens free(parent); 2641789Sahrens return (-1); 2642789Sahrens } 2643789Sahrens 26442199Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 26452676Seschrock (void) strlcpy(zc.zc_value, delim+1, sizeof (zc.zc_value)); 26462199Sahrens zc.zc_cookie = recursive; 26472199Sahrens ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT, &zc); 26482199Sahrens 26492199Sahrens /* 26502199Sahrens * if it was recursive, the one that actually failed will be in 26512199Sahrens * zc.zc_name. 26522199Sahrens */ 26532199Sahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 26542676Seschrock "cannot create snapshot '%s@%s'"), zc.zc_name, zc.zc_value); 26552199Sahrens if (ret == 0 && recursive) { 26564007Smmusante struct createdata cd; 26574007Smmusante 26584007Smmusante cd.cd_snapname = delim + 1; 26594007Smmusante cd.cd_ifexists = B_FALSE; 26604007Smmusante (void) zfs_iter_filesystems(zhp, zfs_create_link_cb, &cd); 26612199Sahrens } 2662789Sahrens if (ret == 0 && zhp->zfs_type == ZFS_TYPE_VOLUME) { 26632082Seschrock ret = zvol_create_link(zhp->zfs_hdl, path); 26642199Sahrens if (ret != 0) { 26652082Seschrock (void) ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, 26662082Seschrock &zc); 26672199Sahrens } 2668789Sahrens } 2669789Sahrens 26702082Seschrock if (ret != 0) 26712082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 2672789Sahrens 2673789Sahrens free(parent); 2674789Sahrens zfs_close(zhp); 2675789Sahrens 2676789Sahrens return (ret); 2677789Sahrens } 2678789Sahrens 2679789Sahrens /* 26803504Sahl * Dumps a backup of the given snapshot (incremental from fromsnap if it's not 26813504Sahl * NULL) to the file descriptor specified by outfd. 2682789Sahrens */ 2683789Sahrens int 26843504Sahl zfs_send(zfs_handle_t *zhp, const char *fromsnap, int outfd) 2685789Sahrens { 2686789Sahrens zfs_cmd_t zc = { 0 }; 26872082Seschrock char errbuf[1024]; 26882885Sahrens libzfs_handle_t *hdl = zhp->zfs_hdl; 26892082Seschrock 26903504Sahl assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 26913504Sahl 26922885Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 26932885Sahrens if (fromsnap) 26942885Sahrens (void) strlcpy(zc.zc_value, fromsnap, sizeof (zc.zc_name)); 26953504Sahl zc.zc_cookie = outfd; 26963504Sahl 26973504Sahl if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SENDBACKUP, &zc) != 0) { 26983504Sahl (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 26993504Sahl "cannot send '%s'"), zhp->zfs_name); 27003504Sahl 2701789Sahrens switch (errno) { 2702789Sahrens 2703789Sahrens case EXDEV: 27042082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 27053413Smmusante "not an earlier snapshot from the same fs")); 27062082Seschrock return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); 2707789Sahrens 2708789Sahrens case EDQUOT: 2709789Sahrens case EFBIG: 2710789Sahrens case EIO: 2711789Sahrens case ENOLINK: 2712789Sahrens case ENOSPC: 2713789Sahrens case ENOSTR: 2714789Sahrens case ENXIO: 2715789Sahrens case EPIPE: 2716789Sahrens case ERANGE: 2717789Sahrens case EFAULT: 2718789Sahrens case EROFS: 27192082Seschrock zfs_error_aux(hdl, strerror(errno)); 27202082Seschrock return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); 2721789Sahrens 2722789Sahrens default: 27232082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 2724789Sahrens } 2725789Sahrens } 2726789Sahrens 27273504Sahl return (0); 2728789Sahrens } 2729789Sahrens 2730789Sahrens /* 27312885Sahrens * Create ancestors of 'target', but not target itself, and not 27322885Sahrens * ancestors whose names are shorter than prefixlen. Die if 27332885Sahrens * prefixlen-ancestor does not exist. 27342885Sahrens */ 27352885Sahrens static int 27362885Sahrens create_parents(libzfs_handle_t *hdl, char *target, int prefixlen) 27372885Sahrens { 27382885Sahrens zfs_handle_t *h; 27392885Sahrens char *cp; 27402885Sahrens 27412885Sahrens /* make sure prefix exists */ 27422885Sahrens cp = strchr(target + prefixlen, '/'); 27432885Sahrens *cp = '\0'; 27442885Sahrens h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 27452885Sahrens *cp = '/'; 27462885Sahrens if (h == NULL) 27472885Sahrens return (-1); 27482885Sahrens zfs_close(h); 27492885Sahrens 27502885Sahrens /* 27512885Sahrens * Attempt to create, mount, and share any ancestor filesystems, 27522885Sahrens * up to the prefixlen-long one. 27532885Sahrens */ 27542885Sahrens for (cp = target + prefixlen + 1; 27552885Sahrens cp = strchr(cp, '/'); *cp = '/', cp++) { 27562885Sahrens const char *opname; 27572885Sahrens 27582885Sahrens *cp = '\0'; 27592885Sahrens 27602885Sahrens h = make_dataset_handle(hdl, target); 27612885Sahrens if (h) { 27622885Sahrens /* it already exists, nothing to do here */ 27632885Sahrens zfs_close(h); 27642885Sahrens continue; 27652885Sahrens } 27662885Sahrens 27672885Sahrens opname = dgettext(TEXT_DOMAIN, "create"); 27682885Sahrens if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM, 27692885Sahrens NULL) != 0) 27702885Sahrens goto ancestorerr; 27712885Sahrens 27722885Sahrens opname = dgettext(TEXT_DOMAIN, "open"); 27732885Sahrens h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 27742885Sahrens if (h == NULL) 27752885Sahrens goto ancestorerr; 27762885Sahrens 27772885Sahrens opname = dgettext(TEXT_DOMAIN, "mount"); 27782885Sahrens if (zfs_mount(h, NULL, 0) != 0) 27792885Sahrens goto ancestorerr; 27802885Sahrens 27812885Sahrens opname = dgettext(TEXT_DOMAIN, "share"); 27822885Sahrens if (zfs_share(h) != 0) 27832885Sahrens goto ancestorerr; 27842885Sahrens 27852885Sahrens zfs_close(h); 27862885Sahrens 27872885Sahrens continue; 27882885Sahrens ancestorerr: 27892885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 27902885Sahrens "failed to %s ancestor '%s'"), opname, target); 27912885Sahrens return (-1); 27922885Sahrens } 27932885Sahrens 27942885Sahrens return (0); 27952885Sahrens } 27962885Sahrens 27972885Sahrens /* 27983504Sahl * Restores a backup of tosnap from the file descriptor specified by infd. 2799789Sahrens */ 2800789Sahrens int 28012082Seschrock zfs_receive(libzfs_handle_t *hdl, const char *tosnap, int isprefix, 28023504Sahl int verbose, int dryrun, boolean_t force, int infd) 2803789Sahrens { 2804789Sahrens zfs_cmd_t zc = { 0 }; 2805789Sahrens time_t begin_time; 28062885Sahrens int ioctl_err, err, bytes, size, choplen; 2807789Sahrens char *cp; 2808789Sahrens dmu_replay_record_t drr; 2809789Sahrens struct drr_begin *drrb = &zc.zc_begin_record; 28102082Seschrock char errbuf[1024]; 28112665Snd150628 prop_changelist_t *clp; 28122885Sahrens char chopprefix[ZFS_MAXNAMELEN]; 2813789Sahrens 2814789Sahrens begin_time = time(NULL); 2815789Sahrens 28162082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 28172082Seschrock "cannot receive")); 28182082Seschrock 2819789Sahrens /* read in the BEGIN record */ 2820789Sahrens cp = (char *)&drr; 2821789Sahrens bytes = 0; 2822789Sahrens do { 28233504Sahl size = read(infd, cp, sizeof (drr) - bytes); 2824868Sahrens cp += size; 2825868Sahrens bytes += size; 2826868Sahrens } while (size > 0); 2827868Sahrens 2828868Sahrens if (size < 0 || bytes != sizeof (drr)) { 28292082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 28302082Seschrock "stream (failed to read first record)")); 28312082Seschrock return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2832789Sahrens } 2833789Sahrens 2834789Sahrens zc.zc_begin_record = drr.drr_u.drr_begin; 2835789Sahrens 2836789Sahrens if (drrb->drr_magic != DMU_BACKUP_MAGIC && 2837789Sahrens drrb->drr_magic != BSWAP_64(DMU_BACKUP_MAGIC)) { 28382082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 28392082Seschrock "stream (bad magic number)")); 28402082Seschrock return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2841789Sahrens } 2842789Sahrens 2843789Sahrens if (drrb->drr_version != DMU_BACKUP_VERSION && 2844789Sahrens drrb->drr_version != BSWAP_64(DMU_BACKUP_VERSION)) { 28452082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only version " 28462082Seschrock "0x%llx is supported (stream is version 0x%llx)"), 2847789Sahrens DMU_BACKUP_VERSION, drrb->drr_version); 28482082Seschrock return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2849789Sahrens } 2850789Sahrens 28512885Sahrens if (strchr(drr.drr_u.drr_begin.drr_toname, '@') == NULL) { 28522885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 28533912Slling "stream (bad snapshot name)")); 28542885Sahrens return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 28552885Sahrens } 2856789Sahrens /* 28572885Sahrens * Determine how much of the snapshot name stored in the stream 28582885Sahrens * we are going to tack on to the name they specified on the 28592885Sahrens * command line, and how much we are going to chop off. 28602885Sahrens * 28612885Sahrens * If they specified a snapshot, chop the entire name stored in 28622885Sahrens * the stream. 2863789Sahrens */ 28642885Sahrens (void) strcpy(chopprefix, drr.drr_u.drr_begin.drr_toname); 2865789Sahrens if (isprefix) { 28662885Sahrens /* 28672885Sahrens * They specified a fs with -d, we want to tack on 28682885Sahrens * everything but the pool name stored in the stream 28692885Sahrens */ 28702885Sahrens if (strchr(tosnap, '@')) { 28712885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 28722885Sahrens "argument - snapshot not allowed with -d")); 28732885Sahrens return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2874789Sahrens } 28752885Sahrens cp = strchr(chopprefix, '/'); 2876789Sahrens if (cp == NULL) 28772885Sahrens cp = strchr(chopprefix, '@'); 28782885Sahrens *cp = '\0'; 2879789Sahrens } else if (strchr(tosnap, '@') == NULL) { 2880789Sahrens /* 28812885Sahrens * If they specified a filesystem without -d, we want to 28822885Sahrens * tack on everything after the fs specified in the 28832885Sahrens * first name from the stream. 2884789Sahrens */ 28852885Sahrens cp = strchr(chopprefix, '@'); 28862885Sahrens *cp = '\0'; 2887789Sahrens } 28882885Sahrens choplen = strlen(chopprefix); 28892885Sahrens 28902885Sahrens /* 28912885Sahrens * Determine name of destination snapshot, store in zc_value. 28922885Sahrens */ 28932885Sahrens (void) strcpy(zc.zc_value, tosnap); 28942885Sahrens (void) strncat(zc.zc_value, drr.drr_u.drr_begin.drr_toname+choplen, 28952885Sahrens sizeof (zc.zc_value)); 28963265Sahrens if (!zfs_validate_name(hdl, zc.zc_value, ZFS_TYPE_SNAPSHOT)) 28973265Sahrens return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 28982885Sahrens 28992885Sahrens (void) strcpy(zc.zc_name, zc.zc_value); 2900789Sahrens if (drrb->drr_fromguid) { 2901789Sahrens /* incremental backup stream */ 29022885Sahrens zfs_handle_t *h; 29032885Sahrens 29042885Sahrens /* do the recvbackup ioctl to the containing fs */ 29052885Sahrens *strchr(zc.zc_name, '@') = '\0'; 2906789Sahrens 2907789Sahrens /* make sure destination fs exists */ 29082082Seschrock h = zfs_open(hdl, zc.zc_name, 29092082Seschrock ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 29102082Seschrock if (h == NULL) 2911789Sahrens return (-1); 2912868Sahrens if (!dryrun) { 29132665Snd150628 /* 29142665Snd150628 * We need to unmount all the dependents of the dataset 29152665Snd150628 * and the dataset itself. If it's a volume 29162665Snd150628 * then remove device link. 29172665Snd150628 */ 2918868Sahrens if (h->zfs_type == ZFS_TYPE_FILESYSTEM) { 29192665Snd150628 clp = changelist_gather(h, ZFS_PROP_NAME, 0); 29202665Snd150628 if (clp == NULL) 29212665Snd150628 return (-1); 29222665Snd150628 if (changelist_prefix(clp) != 0) { 29232665Snd150628 changelist_free(clp); 29242665Snd150628 return (-1); 29252665Snd150628 } 2926868Sahrens } else { 29272082Seschrock (void) zvol_remove_link(hdl, h->zfs_name); 2928868Sahrens } 2929868Sahrens } 2930789Sahrens zfs_close(h); 2931789Sahrens } else { 2932789Sahrens /* full backup stream */ 2933789Sahrens 2934868Sahrens /* Make sure destination fs does not exist */ 29352885Sahrens *strchr(zc.zc_name, '@') = '\0'; 29362082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) { 29372082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29382082Seschrock "destination '%s' exists"), zc.zc_name); 29392082Seschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2940868Sahrens } 2941868Sahrens 29422885Sahrens if (strchr(zc.zc_name, '/') == NULL) { 29432885Sahrens /* 29442885Sahrens * they're trying to do a recv into a 29452885Sahrens * nonexistant topmost filesystem. 29462885Sahrens */ 29472885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29482885Sahrens "destination does not exist"), zc.zc_name); 29492885Sahrens return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 29502885Sahrens } 29512885Sahrens 2952868Sahrens /* Do the recvbackup ioctl to the fs's parent. */ 29532885Sahrens *strrchr(zc.zc_name, '/') = '\0'; 29542885Sahrens 29552885Sahrens if (isprefix && (err = create_parents(hdl, 29562885Sahrens zc.zc_value, strlen(tosnap))) != 0) { 29572885Sahrens return (zfs_error(hdl, EZFS_BADRESTORE, errbuf)); 29582885Sahrens } 29592885Sahrens 2960789Sahrens } 2961789Sahrens 29623504Sahl zc.zc_cookie = infd; 29632676Seschrock zc.zc_guid = force; 2964789Sahrens if (verbose) { 29651749Sahrens (void) printf("%s %s stream of %s into %s\n", 29661749Sahrens dryrun ? "would receive" : "receiving", 2967789Sahrens drrb->drr_fromguid ? "incremental" : "full", 2968789Sahrens drr.drr_u.drr_begin.drr_toname, 29692676Seschrock zc.zc_value); 2970789Sahrens (void) fflush(stdout); 2971789Sahrens } 2972789Sahrens if (dryrun) 2973789Sahrens return (0); 29742082Seschrock err = ioctl_err = ioctl(hdl->libzfs_fd, ZFS_IOC_RECVBACKUP, &zc); 2975868Sahrens if (ioctl_err != 0) { 2976789Sahrens switch (errno) { 2977789Sahrens case ENODEV: 29782082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29792082Seschrock "most recent snapshot does not match incremental " 29802082Seschrock "source")); 29812082Seschrock (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); 2982789Sahrens break; 2983789Sahrens case ETXTBSY: 29842082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29852082Seschrock "destination has been modified since most recent " 29862082Seschrock "snapshot")); 29872082Seschrock (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); 2988789Sahrens break; 2989789Sahrens case EEXIST: 2990789Sahrens if (drrb->drr_fromguid == 0) { 2991789Sahrens /* it's the containing fs that exists */ 29922676Seschrock cp = strchr(zc.zc_value, '@'); 2993789Sahrens *cp = '\0'; 2994789Sahrens } 29952082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29962082Seschrock "destination already exists")); 29973237Slling (void) zfs_error_fmt(hdl, EZFS_EXISTS, 29983237Slling dgettext(TEXT_DOMAIN, "cannot restore to %s"), 29993237Slling zc.zc_value); 3000789Sahrens break; 3001789Sahrens case EINVAL: 30022082Seschrock (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); 3003868Sahrens break; 30041544Seschrock case ECKSUM: 30052082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 30062082Seschrock "invalid stream (checksum mismatch)")); 30072082Seschrock (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); 3008789Sahrens break; 3009789Sahrens default: 30102082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 3011789Sahrens } 3012789Sahrens } 3013789Sahrens 3014789Sahrens /* 3015868Sahrens * Mount or recreate the /dev links for the target filesystem 3016868Sahrens * (if created, or if we tore them down to do an incremental 3017868Sahrens * restore), and the /dev links for the new snapshot (if 30182665Snd150628 * created). Also mount any children of the target filesystem 30192665Snd150628 * if we did an incremental receive. 3020789Sahrens */ 30212676Seschrock cp = strchr(zc.zc_value, '@'); 3022868Sahrens if (cp && (ioctl_err == 0 || drrb->drr_fromguid)) { 3023789Sahrens zfs_handle_t *h; 3024789Sahrens 3025789Sahrens *cp = '\0'; 30262676Seschrock h = zfs_open(hdl, zc.zc_value, 3027789Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 3028868Sahrens *cp = '@'; 3029789Sahrens if (h) { 30302665Snd150628 if (h->zfs_type == ZFS_TYPE_VOLUME) { 30312082Seschrock err = zvol_create_link(hdl, h->zfs_name); 30321544Seschrock if (err == 0 && ioctl_err == 0) 30332082Seschrock err = zvol_create_link(hdl, 30342676Seschrock zc.zc_value); 30352665Snd150628 } else { 30362665Snd150628 if (drrb->drr_fromguid) { 30372665Snd150628 err = changelist_postfix(clp); 30382665Snd150628 changelist_free(clp); 30392665Snd150628 } else { 30402665Snd150628 err = zfs_mount(h, NULL, 0); 30412665Snd150628 } 3042868Sahrens } 30432665Snd150628 zfs_close(h); 3044789Sahrens } 3045789Sahrens } 3046789Sahrens 3047868Sahrens if (err || ioctl_err) 3048868Sahrens return (-1); 3049789Sahrens 3050789Sahrens if (verbose) { 3051789Sahrens char buf1[64]; 3052789Sahrens char buf2[64]; 3053789Sahrens uint64_t bytes = zc.zc_cookie; 3054789Sahrens time_t delta = time(NULL) - begin_time; 3055789Sahrens if (delta == 0) 3056789Sahrens delta = 1; 3057789Sahrens zfs_nicenum(bytes, buf1, sizeof (buf1)); 3058789Sahrens zfs_nicenum(bytes/delta, buf2, sizeof (buf1)); 3059789Sahrens 30601749Sahrens (void) printf("received %sb stream in %lu seconds (%sb/sec)\n", 3061789Sahrens buf1, delta, buf2); 3062789Sahrens } 30632665Snd150628 3064789Sahrens return (0); 3065789Sahrens } 3066789Sahrens 3067789Sahrens /* 30681294Slling * Destroy any more recent snapshots. We invoke this callback on any dependents 30691294Slling * of the snapshot first. If the 'cb_dependent' member is non-zero, then this 30701294Slling * is a dependent and we should just destroy it without checking the transaction 30711294Slling * group. 3072789Sahrens */ 30731294Slling typedef struct rollback_data { 30741294Slling const char *cb_target; /* the snapshot */ 30751294Slling uint64_t cb_create; /* creation time reference */ 30761294Slling prop_changelist_t *cb_clp; /* changelist pointer */ 30771294Slling int cb_error; 30782082Seschrock boolean_t cb_dependent; 30791294Slling } rollback_data_t; 30801294Slling 30811294Slling static int 30821294Slling rollback_destroy(zfs_handle_t *zhp, void *data) 30831294Slling { 30841294Slling rollback_data_t *cbp = data; 30851294Slling 30861294Slling if (!cbp->cb_dependent) { 30871294Slling if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 && 30881294Slling zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && 30891294Slling zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > 30901294Slling cbp->cb_create) { 30911294Slling 30922082Seschrock cbp->cb_dependent = B_TRUE; 30932474Seschrock if (zfs_iter_dependents(zhp, B_FALSE, rollback_destroy, 30942474Seschrock cbp) != 0) 30952474Seschrock cbp->cb_error = 1; 30962082Seschrock cbp->cb_dependent = B_FALSE; 30971294Slling 30981294Slling if (zfs_destroy(zhp) != 0) 30991294Slling cbp->cb_error = 1; 31001294Slling else 31011294Slling changelist_remove(zhp, cbp->cb_clp); 31021294Slling } 31031294Slling } else { 31041294Slling if (zfs_destroy(zhp) != 0) 31051294Slling cbp->cb_error = 1; 31061294Slling else 31071294Slling changelist_remove(zhp, cbp->cb_clp); 31081294Slling } 31091294Slling 31101294Slling zfs_close(zhp); 31111294Slling return (0); 31121294Slling } 31131294Slling 31141294Slling /* 31151294Slling * Rollback the dataset to its latest snapshot. 31161294Slling */ 31171294Slling static int 31181294Slling do_rollback(zfs_handle_t *zhp) 3119789Sahrens { 3120789Sahrens int ret; 3121789Sahrens zfs_cmd_t zc = { 0 }; 3122789Sahrens 3123789Sahrens assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM || 3124789Sahrens zhp->zfs_type == ZFS_TYPE_VOLUME); 3125789Sahrens 3126789Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME && 31272082Seschrock zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0) 3128789Sahrens return (-1); 3129789Sahrens 3130789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3131789Sahrens 31322676Seschrock if (ZFS_IS_VOLUME(zhp)) 3133789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3134789Sahrens else 3135789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3136789Sahrens 3137789Sahrens /* 3138789Sahrens * We rely on the consumer to verify that there are no newer snapshots 3139789Sahrens * for the given dataset. Given these constraints, we can simply pass 3140789Sahrens * the name on to the ioctl() call. There is still an unlikely race 3141789Sahrens * condition where the user has taken a snapshot since we verified that 3142789Sahrens * this was the most recent. 3143789Sahrens */ 31442082Seschrock if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_ROLLBACK, 31452082Seschrock &zc)) != 0) { 31463237Slling (void) zfs_standard_error_fmt(zhp->zfs_hdl, errno, 31472082Seschrock dgettext(TEXT_DOMAIN, "cannot rollback '%s'"), 31482082Seschrock zhp->zfs_name); 3149789Sahrens } else if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 31502082Seschrock ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 3151789Sahrens } 3152789Sahrens 3153789Sahrens return (ret); 3154789Sahrens } 3155789Sahrens 3156789Sahrens /* 31571294Slling * Given a dataset, rollback to a specific snapshot, discarding any 31581294Slling * data changes since then and making it the active dataset. 31591294Slling * 31601294Slling * Any snapshots more recent than the target are destroyed, along with 31611294Slling * their dependents. 31621294Slling */ 31631294Slling int 31641294Slling zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, int flag) 31651294Slling { 31661294Slling int ret; 31671294Slling rollback_data_t cb = { 0 }; 31681294Slling prop_changelist_t *clp; 31691294Slling 31701294Slling /* 31711294Slling * Unmount all dependendents of the dataset and the dataset itself. 31721294Slling * The list we need to gather is the same as for doing rename 31731294Slling */ 31741294Slling clp = changelist_gather(zhp, ZFS_PROP_NAME, flag ? MS_FORCE: 0); 31751294Slling if (clp == NULL) 31761294Slling return (-1); 31771294Slling 31781294Slling if ((ret = changelist_prefix(clp)) != 0) 31791294Slling goto out; 31801294Slling 31811294Slling /* 31821294Slling * Destroy all recent snapshots and its dependends. 31831294Slling */ 31841294Slling cb.cb_target = snap->zfs_name; 31851294Slling cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG); 31861294Slling cb.cb_clp = clp; 31871294Slling (void) zfs_iter_children(zhp, rollback_destroy, &cb); 31881294Slling 31891294Slling if ((ret = cb.cb_error) != 0) { 31901294Slling (void) changelist_postfix(clp); 31911294Slling goto out; 31921294Slling } 31931294Slling 31941294Slling /* 31951294Slling * Now that we have verified that the snapshot is the latest, 31961294Slling * rollback to the given snapshot. 31971294Slling */ 31981294Slling ret = do_rollback(zhp); 31991294Slling 32001294Slling if (ret != 0) { 32011294Slling (void) changelist_postfix(clp); 32021294Slling goto out; 32031294Slling } 32041294Slling 32051294Slling /* 32061294Slling * We only want to re-mount the filesystem if it was mounted in the 32071294Slling * first place. 32081294Slling */ 32091294Slling ret = changelist_postfix(clp); 32101294Slling 32111294Slling out: 32121294Slling changelist_free(clp); 32131294Slling return (ret); 32141294Slling } 32151294Slling 32161294Slling /* 3217789Sahrens * Iterate over all dependents for a given dataset. This includes both 3218789Sahrens * hierarchical dependents (children) and data dependents (snapshots and 3219789Sahrens * clones). The bulk of the processing occurs in get_dependents() in 3220789Sahrens * libzfs_graph.c. 3221789Sahrens */ 3222789Sahrens int 32232474Seschrock zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion, 32242474Seschrock zfs_iter_f func, void *data) 3225789Sahrens { 3226789Sahrens char **dependents; 3227789Sahrens size_t count; 3228789Sahrens int i; 3229789Sahrens zfs_handle_t *child; 3230789Sahrens int ret = 0; 3231789Sahrens 32322474Seschrock if (get_dependents(zhp->zfs_hdl, allowrecursion, zhp->zfs_name, 32332474Seschrock &dependents, &count) != 0) 32342474Seschrock return (-1); 32352474Seschrock 3236789Sahrens for (i = 0; i < count; i++) { 32372082Seschrock if ((child = make_dataset_handle(zhp->zfs_hdl, 32382082Seschrock dependents[i])) == NULL) 3239789Sahrens continue; 3240789Sahrens 3241789Sahrens if ((ret = func(child, data)) != 0) 3242789Sahrens break; 3243789Sahrens } 3244789Sahrens 3245789Sahrens for (i = 0; i < count; i++) 3246789Sahrens free(dependents[i]); 3247789Sahrens free(dependents); 3248789Sahrens 3249789Sahrens return (ret); 3250789Sahrens } 3251789Sahrens 3252789Sahrens /* 3253789Sahrens * Renames the given dataset. 3254789Sahrens */ 3255789Sahrens int 32564007Smmusante zfs_rename(zfs_handle_t *zhp, const char *target, int recursive) 3257789Sahrens { 3258789Sahrens int ret; 3259789Sahrens zfs_cmd_t zc = { 0 }; 3260789Sahrens char *delim; 32614007Smmusante prop_changelist_t *cl = NULL; 32624007Smmusante zfs_handle_t *zhrp = NULL; 32634007Smmusante char *parentname = NULL; 3264789Sahrens char parent[ZFS_MAXNAMELEN]; 32652082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 32662082Seschrock char errbuf[1024]; 3267789Sahrens 3268789Sahrens /* if we have the same exact name, just return success */ 3269789Sahrens if (strcmp(zhp->zfs_name, target) == 0) 3270789Sahrens return (0); 3271789Sahrens 32722082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 32732082Seschrock "cannot rename to '%s'"), target); 32742082Seschrock 3275789Sahrens /* 3276789Sahrens * Make sure the target name is valid 3277789Sahrens */ 3278789Sahrens if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 32792665Snd150628 if ((strchr(target, '@') == NULL) || 32802665Snd150628 *target == '@') { 32812665Snd150628 /* 32822665Snd150628 * Snapshot target name is abbreviated, 32832665Snd150628 * reconstruct full dataset name 32842665Snd150628 */ 32852665Snd150628 (void) strlcpy(parent, zhp->zfs_name, 32862665Snd150628 sizeof (parent)); 32872665Snd150628 delim = strchr(parent, '@'); 32882665Snd150628 if (strchr(target, '@') == NULL) 32892665Snd150628 *(++delim) = '\0'; 32902665Snd150628 else 32912665Snd150628 *delim = '\0'; 32922665Snd150628 (void) strlcat(parent, target, sizeof (parent)); 32932665Snd150628 target = parent; 32942665Snd150628 } else { 32952665Snd150628 /* 32962665Snd150628 * Make sure we're renaming within the same dataset. 32972665Snd150628 */ 32982665Snd150628 delim = strchr(target, '@'); 32992665Snd150628 if (strncmp(zhp->zfs_name, target, delim - target) 33002665Snd150628 != 0 || zhp->zfs_name[delim - target] != '@') { 33012665Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33022665Snd150628 "snapshots must be part of same " 33032665Snd150628 "dataset")); 33042665Snd150628 return (zfs_error(hdl, EZFS_CROSSTARGET, 33053912Slling errbuf)); 33062665Snd150628 } 3307789Sahrens } 33082665Snd150628 if (!zfs_validate_name(hdl, target, zhp->zfs_type)) 33092665Snd150628 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 3310789Sahrens } else { 33114007Smmusante if (recursive) { 33124007Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33134007Smmusante "recursive rename must be a snapshot")); 33144007Smmusante return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 33154007Smmusante } 33164007Smmusante 33172665Snd150628 if (!zfs_validate_name(hdl, target, zhp->zfs_type)) 33182665Snd150628 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 33192676Seschrock uint64_t unused; 33202676Seschrock 3321789Sahrens /* validate parents */ 33222676Seschrock if (check_parents(hdl, target, &unused) != 0) 3323789Sahrens return (-1); 3324789Sahrens 3325789Sahrens (void) parent_name(target, parent, sizeof (parent)); 3326789Sahrens 3327789Sahrens /* make sure we're in the same pool */ 3328789Sahrens verify((delim = strchr(target, '/')) != NULL); 3329789Sahrens if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 3330789Sahrens zhp->zfs_name[delim - target] != '/') { 33312082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33322082Seschrock "datasets must be within same pool")); 33332082Seschrock return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); 3334789Sahrens } 33352440Snd150628 33362440Snd150628 /* new name cannot be a child of the current dataset name */ 33372440Snd150628 if (strncmp(parent, zhp->zfs_name, 33383912Slling strlen(zhp->zfs_name)) == 0) { 33392440Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33402440Snd150628 "New dataset name cannot be a descendent of " 33412440Snd150628 "current dataset name")); 33422440Snd150628 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 33432440Snd150628 } 3344789Sahrens } 3345789Sahrens 33462082Seschrock (void) snprintf(errbuf, sizeof (errbuf), 33472082Seschrock dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name); 33482082Seschrock 3349789Sahrens if (getzoneid() == GLOBAL_ZONEID && 3350789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 33512082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33522082Seschrock "dataset is used in a non-global zone")); 33532082Seschrock return (zfs_error(hdl, EZFS_ZONED, errbuf)); 3354789Sahrens } 3355789Sahrens 33564007Smmusante if (recursive) { 33574007Smmusante struct destroydata dd; 33584007Smmusante 33594183Smmusante parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name); 33604183Smmusante if (parentname == NULL) { 33614183Smmusante ret = -1; 33624183Smmusante goto error; 33634183Smmusante } 33644007Smmusante delim = strchr(parentname, '@'); 33654007Smmusante *delim = '\0'; 33664007Smmusante zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_ANY); 33674007Smmusante if (zhrp == NULL) { 33684183Smmusante ret = -1; 33694183Smmusante goto error; 33704007Smmusante } 33714007Smmusante 33724007Smmusante dd.snapname = delim + 1; 33734007Smmusante dd.gotone = B_FALSE; 33744183Smmusante dd.closezhp = B_TRUE; 33754007Smmusante 33764007Smmusante /* We remove any zvol links prior to renaming them */ 33774007Smmusante ret = zfs_iter_filesystems(zhrp, zfs_remove_link_cb, &dd); 33784007Smmusante if (ret) { 33794007Smmusante goto error; 33804007Smmusante } 33814007Smmusante } else { 33824007Smmusante if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0)) == NULL) 33834007Smmusante return (-1); 33844007Smmusante 33854007Smmusante if (changelist_haszonedchild(cl)) { 33864007Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33874007Smmusante "child dataset with inherited mountpoint is used " 33884007Smmusante "in a non-global zone")); 33894007Smmusante (void) zfs_error(hdl, EZFS_ZONED, errbuf); 33904007Smmusante goto error; 33914007Smmusante } 33924007Smmusante 33934007Smmusante if ((ret = changelist_prefix(cl)) != 0) 33944007Smmusante goto error; 3395789Sahrens } 3396789Sahrens 33972676Seschrock if (ZFS_IS_VOLUME(zhp)) 3398789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3399789Sahrens else 3400789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3401789Sahrens 34022665Snd150628 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 34032676Seschrock (void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value)); 34042665Snd150628 34054007Smmusante zc.zc_cookie = recursive; 34064007Smmusante 34072082Seschrock if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_RENAME, &zc)) != 0) { 34084007Smmusante /* 34094007Smmusante * if it was recursive, the one that actually failed will 34104007Smmusante * be in zc.zc_name 34114007Smmusante */ 34124007Smmusante (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 34134007Smmusante "cannot rename to '%s'"), zc.zc_name); 34144007Smmusante 34154007Smmusante if (recursive && errno == EEXIST) { 34164007Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 34174007Smmusante "a child dataset already has a snapshot " 34184007Smmusante "with the new name")); 34194007Smmusante (void) zfs_error(hdl, EZFS_CROSSTARGET, errbuf); 34204007Smmusante } else { 34214007Smmusante (void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf); 34224007Smmusante } 3423789Sahrens 3424789Sahrens /* 3425789Sahrens * On failure, we still want to remount any filesystems that 3426789Sahrens * were previously mounted, so we don't alter the system state. 3427789Sahrens */ 34284007Smmusante if (recursive) { 34294007Smmusante struct createdata cd; 34304007Smmusante 34314007Smmusante /* only create links for datasets that had existed */ 34324007Smmusante cd.cd_snapname = delim + 1; 34334007Smmusante cd.cd_ifexists = B_TRUE; 34344007Smmusante (void) zfs_iter_filesystems(zhrp, zfs_create_link_cb, 34354007Smmusante &cd); 34364007Smmusante } else { 34374007Smmusante (void) changelist_postfix(cl); 34384007Smmusante } 3439789Sahrens } else { 34404007Smmusante if (recursive) { 34414007Smmusante struct createdata cd; 34424007Smmusante 34434007Smmusante /* only create links for datasets that had existed */ 34444007Smmusante cd.cd_snapname = strchr(target, '@') + 1; 34454007Smmusante cd.cd_ifexists = B_TRUE; 34464007Smmusante ret = zfs_iter_filesystems(zhrp, zfs_create_link_cb, 34474007Smmusante &cd); 34484007Smmusante } else { 34494007Smmusante changelist_rename(cl, zfs_get_name(zhp), target); 34504007Smmusante ret = changelist_postfix(cl); 34514007Smmusante } 3452789Sahrens } 3453789Sahrens 3454789Sahrens error: 34554007Smmusante if (parentname) { 34564007Smmusante free(parentname); 34574007Smmusante } 34584007Smmusante if (zhrp) { 34594007Smmusante zfs_close(zhrp); 34604007Smmusante } 34614007Smmusante if (cl) { 34624007Smmusante changelist_free(cl); 34634007Smmusante } 3464789Sahrens return (ret); 3465789Sahrens } 3466789Sahrens 3467789Sahrens /* 3468789Sahrens * Given a zvol dataset, issue the ioctl to create the appropriate minor node, 3469789Sahrens * poke devfsadm to create the /dev link, and then wait for the link to appear. 3470789Sahrens */ 3471789Sahrens int 34722082Seschrock zvol_create_link(libzfs_handle_t *hdl, const char *dataset) 3473789Sahrens { 34744007Smmusante return (zvol_create_link_common(hdl, dataset, B_FALSE)); 34754007Smmusante } 34764007Smmusante 34774007Smmusante static int 34784007Smmusante zvol_create_link_common(libzfs_handle_t *hdl, const char *dataset, int ifexists) 34794007Smmusante { 3480789Sahrens zfs_cmd_t zc = { 0 }; 34812082Seschrock di_devlink_handle_t dhdl; 3482789Sahrens 3483789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3484789Sahrens 3485789Sahrens /* 3486789Sahrens * Issue the appropriate ioctl. 3487789Sahrens */ 34882082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE_MINOR, &zc) != 0) { 3489789Sahrens switch (errno) { 3490789Sahrens case EEXIST: 3491789Sahrens /* 3492789Sahrens * Silently ignore the case where the link already 3493789Sahrens * exists. This allows 'zfs volinit' to be run multiple 3494789Sahrens * times without errors. 3495789Sahrens */ 3496789Sahrens return (0); 3497789Sahrens 34984007Smmusante case ENOENT: 34994007Smmusante /* 35004007Smmusante * Dataset does not exist in the kernel. If we 35014007Smmusante * don't care (see zfs_rename), then ignore the 35024007Smmusante * error quietly. 35034007Smmusante */ 35044007Smmusante if (ifexists) { 35054007Smmusante return (0); 35064007Smmusante } 35074007Smmusante 35084007Smmusante /* FALLTHROUGH */ 35094007Smmusante 3510789Sahrens default: 35113237Slling return (zfs_standard_error_fmt(hdl, errno, 35122082Seschrock dgettext(TEXT_DOMAIN, "cannot create device links " 35132082Seschrock "for '%s'"), dataset)); 3514789Sahrens } 3515789Sahrens } 3516789Sahrens 3517789Sahrens /* 3518789Sahrens * Call devfsadm and wait for the links to magically appear. 3519789Sahrens */ 35202082Seschrock if ((dhdl = di_devlink_init(ZFS_DRIVER, DI_MAKE_LINK)) == NULL) { 35212082Seschrock zfs_error_aux(hdl, strerror(errno)); 35223237Slling (void) zfs_error_fmt(hdl, EZFS_DEVLINKS, 35232082Seschrock dgettext(TEXT_DOMAIN, "cannot create device links " 35242082Seschrock "for '%s'"), dataset); 35252082Seschrock (void) ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc); 3526789Sahrens return (-1); 3527789Sahrens } else { 35282082Seschrock (void) di_devlink_fini(&dhdl); 3529789Sahrens } 3530789Sahrens 3531789Sahrens return (0); 3532789Sahrens } 3533789Sahrens 3534789Sahrens /* 3535789Sahrens * Remove a minor node for the given zvol and the associated /dev links. 3536789Sahrens */ 3537789Sahrens int 35382082Seschrock zvol_remove_link(libzfs_handle_t *hdl, const char *dataset) 3539789Sahrens { 3540789Sahrens zfs_cmd_t zc = { 0 }; 3541789Sahrens 3542789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3543789Sahrens 35442082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc) != 0) { 3545789Sahrens switch (errno) { 3546789Sahrens case ENXIO: 3547789Sahrens /* 3548789Sahrens * Silently ignore the case where the link no longer 3549789Sahrens * exists, so that 'zfs volfini' can be run multiple 3550789Sahrens * times without errors. 3551789Sahrens */ 3552789Sahrens return (0); 3553789Sahrens 3554789Sahrens default: 35553237Slling return (zfs_standard_error_fmt(hdl, errno, 35562082Seschrock dgettext(TEXT_DOMAIN, "cannot remove device " 35572082Seschrock "links for '%s'"), dataset)); 3558789Sahrens } 3559789Sahrens } 3560789Sahrens 3561789Sahrens return (0); 3562789Sahrens } 35632676Seschrock 35642676Seschrock nvlist_t * 35652676Seschrock zfs_get_user_props(zfs_handle_t *zhp) 35662676Seschrock { 35672676Seschrock return (zhp->zfs_user_props); 35682676Seschrock } 35692676Seschrock 35702676Seschrock /* 3571*4451Seschrock * Given a comma-separated list of properties, construct a property list 35722676Seschrock * containing both user-defined and native properties. This function will 35732676Seschrock * return a NULL list if 'all' is specified, which can later be expanded on a 35742676Seschrock * per-dataset basis by zfs_expand_proplist(). 35752676Seschrock */ 35762676Seschrock int 35773912Slling zfs_get_proplist_common(libzfs_handle_t *hdl, char *fields, 35783912Slling zfs_proplist_t **listp, zfs_type_t type) 35792676Seschrock { 35802676Seschrock size_t len; 35812676Seschrock char *s, *p; 35822676Seschrock char c; 35832676Seschrock zfs_prop_t prop; 35842676Seschrock zfs_proplist_t *entry; 35852676Seschrock zfs_proplist_t **last; 35862676Seschrock 35872676Seschrock *listp = NULL; 35882676Seschrock last = listp; 35892676Seschrock 35902676Seschrock /* 35912676Seschrock * If 'all' is specified, return a NULL list. 35922676Seschrock */ 35932676Seschrock if (strcmp(fields, "all") == 0) 35942676Seschrock return (0); 35952676Seschrock 35962676Seschrock /* 35972676Seschrock * If no fields were specified, return an error. 35982676Seschrock */ 35992676Seschrock if (fields[0] == '\0') { 36002676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 36012676Seschrock "no properties specified")); 36022676Seschrock return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, 36032676Seschrock "bad property list"))); 36042676Seschrock } 36052676Seschrock 36062676Seschrock /* 36072676Seschrock * It would be nice to use getsubopt() here, but the inclusion of column 36082676Seschrock * aliases makes this more effort than it's worth. 36092676Seschrock */ 36102676Seschrock s = fields; 36112676Seschrock while (*s != '\0') { 36122676Seschrock if ((p = strchr(s, ',')) == NULL) { 36132676Seschrock len = strlen(s); 36142676Seschrock p = s + len; 36152676Seschrock } else { 36162676Seschrock len = p - s; 36172676Seschrock } 36182676Seschrock 36192676Seschrock /* 36202676Seschrock * Check for empty options. 36212676Seschrock */ 36222676Seschrock if (len == 0) { 36232676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 36242676Seschrock "empty property name")); 36252676Seschrock return (zfs_error(hdl, EZFS_BADPROP, 36262676Seschrock dgettext(TEXT_DOMAIN, "bad property list"))); 36272676Seschrock } 36282676Seschrock 36292676Seschrock /* 36302676Seschrock * Check all regular property names. 36312676Seschrock */ 36322676Seschrock c = s[len]; 36332676Seschrock s[len] = '\0'; 3634*4451Seschrock prop = type == ZFS_TYPE_POOL ? zpool_name_to_prop(s) : 3635*4451Seschrock zfs_name_to_prop(s); 36363912Slling 36373912Slling if (prop != ZFS_PROP_INVAL && 36383912Slling !zfs_prop_valid_for_type(prop, type)) 36393912Slling prop = ZFS_PROP_INVAL; 36402676Seschrock 36412676Seschrock /* 36423912Slling * When no property table entry can be found, return failure if 36433912Slling * this is a pool property or if this isn't a user-defined 36443912Slling * dataset property, 36452676Seschrock */ 36463912Slling if (prop == ZFS_PROP_INVAL && 36473912Slling (type & ZFS_TYPE_POOL || !zfs_prop_user(s))) { 36482676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 36492676Seschrock "invalid property '%s'"), s); 36502676Seschrock return (zfs_error(hdl, EZFS_BADPROP, 36512676Seschrock dgettext(TEXT_DOMAIN, "bad property list"))); 36522676Seschrock } 36532676Seschrock 36542676Seschrock if ((entry = zfs_alloc(hdl, sizeof (zfs_proplist_t))) == NULL) 36552676Seschrock return (-1); 36562676Seschrock 36572676Seschrock entry->pl_prop = prop; 36582676Seschrock if (prop == ZFS_PROP_INVAL) { 36592676Seschrock if ((entry->pl_user_prop = 36602676Seschrock zfs_strdup(hdl, s)) == NULL) { 36612676Seschrock free(entry); 36622676Seschrock return (-1); 36632676Seschrock } 36642676Seschrock entry->pl_width = strlen(s); 36652676Seschrock } else { 36662676Seschrock entry->pl_width = zfs_prop_width(prop, 36672676Seschrock &entry->pl_fixed); 36682676Seschrock } 36692676Seschrock 36702676Seschrock *last = entry; 36712676Seschrock last = &entry->pl_next; 36722676Seschrock 36732676Seschrock s = p; 36742676Seschrock if (c == ',') 36752676Seschrock s++; 36762676Seschrock } 36772676Seschrock 36782676Seschrock return (0); 36792676Seschrock } 36802676Seschrock 36813912Slling int 36823912Slling zfs_get_proplist(libzfs_handle_t *hdl, char *fields, zfs_proplist_t **listp) 36833912Slling { 36843912Slling return (zfs_get_proplist_common(hdl, fields, listp, ZFS_TYPE_ANY)); 36853912Slling } 36863912Slling 36872676Seschrock void 36882676Seschrock zfs_free_proplist(zfs_proplist_t *pl) 36892676Seschrock { 36902676Seschrock zfs_proplist_t *next; 36912676Seschrock 36922676Seschrock while (pl != NULL) { 36932676Seschrock next = pl->pl_next; 36942676Seschrock free(pl->pl_user_prop); 36952676Seschrock free(pl); 36962676Seschrock pl = next; 36972676Seschrock } 36982676Seschrock } 36992676Seschrock 37003654Sgw25295 typedef struct expand_data { 37013654Sgw25295 zfs_proplist_t **last; 37023654Sgw25295 libzfs_handle_t *hdl; 37033654Sgw25295 } expand_data_t; 37043654Sgw25295 37053654Sgw25295 static zfs_prop_t 37063654Sgw25295 zfs_expand_proplist_cb(zfs_prop_t prop, void *cb) 37073654Sgw25295 { 37083654Sgw25295 zfs_proplist_t *entry; 37093654Sgw25295 expand_data_t *edp = cb; 37103654Sgw25295 37113654Sgw25295 if ((entry = zfs_alloc(edp->hdl, sizeof (zfs_proplist_t))) == NULL) 37123654Sgw25295 return (ZFS_PROP_INVAL); 37133654Sgw25295 37143654Sgw25295 entry->pl_prop = prop; 37153654Sgw25295 entry->pl_width = zfs_prop_width(prop, &entry->pl_fixed); 37163654Sgw25295 entry->pl_all = B_TRUE; 37173654Sgw25295 37183654Sgw25295 *(edp->last) = entry; 37193654Sgw25295 edp->last = &entry->pl_next; 37203654Sgw25295 37213654Sgw25295 return (ZFS_PROP_CONT); 37223654Sgw25295 } 37233654Sgw25295 37242676Seschrock int 37253912Slling zfs_expand_proplist_common(libzfs_handle_t *hdl, zfs_proplist_t **plp, 37263912Slling zfs_type_t type) 37272676Seschrock { 37282676Seschrock zfs_proplist_t *entry; 37293912Slling zfs_proplist_t **last; 37303654Sgw25295 expand_data_t exp; 37312676Seschrock 37322676Seschrock if (*plp == NULL) { 37332676Seschrock /* 37342676Seschrock * If this is the very first time we've been called for an 'all' 37352676Seschrock * specification, expand the list to include all native 37362676Seschrock * properties. 37372676Seschrock */ 37382676Seschrock last = plp; 37393654Sgw25295 37403654Sgw25295 exp.last = last; 37413654Sgw25295 exp.hdl = hdl; 37423654Sgw25295 37433912Slling if (zfs_prop_iter_common(zfs_expand_proplist_cb, &exp, type, 37443654Sgw25295 B_FALSE) == ZFS_PROP_INVAL) 37453654Sgw25295 return (-1); 37462676Seschrock 37472676Seschrock /* 37482676Seschrock * Add 'name' to the beginning of the list, which is handled 37492676Seschrock * specially. 37502676Seschrock */ 37512676Seschrock if ((entry = zfs_alloc(hdl, 37522676Seschrock sizeof (zfs_proplist_t))) == NULL) 37532676Seschrock return (-1); 37542676Seschrock 37552676Seschrock entry->pl_prop = ZFS_PROP_NAME; 37562676Seschrock entry->pl_width = zfs_prop_width(ZFS_PROP_NAME, 37572676Seschrock &entry->pl_fixed); 37582676Seschrock entry->pl_all = B_TRUE; 37592676Seschrock entry->pl_next = *plp; 37602676Seschrock *plp = entry; 37612676Seschrock } 37623912Slling return (0); 37633912Slling } 37643912Slling 37653912Slling /* 37663912Slling * This function is used by 'zfs list' to determine the exact set of columns to 37673912Slling * display, and their maximum widths. This does two main things: 37683912Slling * 37693912Slling * - If this is a list of all properties, then expand the list to include 37703912Slling * all native properties, and set a flag so that for each dataset we look 37713912Slling * for new unique user properties and add them to the list. 37723912Slling * 37733912Slling * - For non fixed-width properties, keep track of the maximum width seen 37743912Slling * so that we can size the column appropriately. 37753912Slling */ 37763912Slling int 37773912Slling zfs_expand_proplist(zfs_handle_t *zhp, zfs_proplist_t **plp) 37783912Slling { 37793912Slling libzfs_handle_t *hdl = zhp->zfs_hdl; 37803912Slling zfs_proplist_t *entry; 37813912Slling zfs_proplist_t **last, **start; 37823912Slling nvlist_t *userprops, *propval; 37833912Slling nvpair_t *elem; 37843912Slling char *strval; 37853912Slling char buf[ZFS_MAXPROPLEN]; 37863912Slling 37873912Slling if (zfs_expand_proplist_common(hdl, plp, ZFS_TYPE_ANY) != 0) 37883912Slling return (-1); 37892676Seschrock 37902676Seschrock userprops = zfs_get_user_props(zhp); 37912676Seschrock 37922676Seschrock entry = *plp; 37932676Seschrock if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) { 37942676Seschrock /* 37952676Seschrock * Go through and add any user properties as necessary. We 37962676Seschrock * start by incrementing our list pointer to the first 37972676Seschrock * non-native property. 37982676Seschrock */ 37992676Seschrock start = plp; 38002676Seschrock while (*start != NULL) { 38012676Seschrock if ((*start)->pl_prop == ZFS_PROP_INVAL) 38022676Seschrock break; 38032676Seschrock start = &(*start)->pl_next; 38042676Seschrock } 38052676Seschrock 38062676Seschrock elem = NULL; 38072676Seschrock while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) { 38082676Seschrock /* 38092676Seschrock * See if we've already found this property in our list. 38102676Seschrock */ 38112676Seschrock for (last = start; *last != NULL; 38122676Seschrock last = &(*last)->pl_next) { 38132676Seschrock if (strcmp((*last)->pl_user_prop, 38142676Seschrock nvpair_name(elem)) == 0) 38152676Seschrock break; 38162676Seschrock } 38172676Seschrock 38182676Seschrock if (*last == NULL) { 38192676Seschrock if ((entry = zfs_alloc(hdl, 38202676Seschrock sizeof (zfs_proplist_t))) == NULL || 38212676Seschrock ((entry->pl_user_prop = zfs_strdup(hdl, 38222676Seschrock nvpair_name(elem)))) == NULL) { 38232676Seschrock free(entry); 38242676Seschrock return (-1); 38252676Seschrock } 38262676Seschrock 38272676Seschrock entry->pl_prop = ZFS_PROP_INVAL; 38282676Seschrock entry->pl_width = strlen(nvpair_name(elem)); 38292676Seschrock entry->pl_all = B_TRUE; 38302676Seschrock *last = entry; 38312676Seschrock } 38322676Seschrock } 38332676Seschrock } 38342676Seschrock 38352676Seschrock /* 38362676Seschrock * Now go through and check the width of any non-fixed columns 38372676Seschrock */ 38382676Seschrock for (entry = *plp; entry != NULL; entry = entry->pl_next) { 38392676Seschrock if (entry->pl_fixed) 38402676Seschrock continue; 38412676Seschrock 38422676Seschrock if (entry->pl_prop != ZFS_PROP_INVAL) { 38432676Seschrock if (zfs_prop_get(zhp, entry->pl_prop, 38442676Seschrock buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0) { 38452676Seschrock if (strlen(buf) > entry->pl_width) 38462676Seschrock entry->pl_width = strlen(buf); 38472676Seschrock } 38482676Seschrock } else if (nvlist_lookup_nvlist(userprops, 38492676Seschrock entry->pl_user_prop, &propval) == 0) { 38502676Seschrock verify(nvlist_lookup_string(propval, 38512676Seschrock ZFS_PROP_VALUE, &strval) == 0); 38522676Seschrock if (strlen(strval) > entry->pl_width) 38532676Seschrock entry->pl_width = strlen(strval); 38542676Seschrock } 38552676Seschrock } 38562676Seschrock 38572676Seschrock return (0); 38582676Seschrock } 3859