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 54*4490Svb160487 static int create_parents(libzfs_handle_t *, char *, int); 554007Smmusante static int zvol_create_link_common(libzfs_handle_t *, const char *, int); 564007Smmusante 57789Sahrens /* 58789Sahrens * Given a single type (not a mask of types), return the type in a human 59789Sahrens * readable form. 60789Sahrens */ 61789Sahrens const char * 62789Sahrens zfs_type_to_name(zfs_type_t type) 63789Sahrens { 64789Sahrens switch (type) { 65789Sahrens case ZFS_TYPE_FILESYSTEM: 66789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 67789Sahrens case ZFS_TYPE_SNAPSHOT: 68789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 69789Sahrens case ZFS_TYPE_VOLUME: 70789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 71789Sahrens } 72789Sahrens 73789Sahrens return (NULL); 74789Sahrens } 75789Sahrens 76789Sahrens /* 77789Sahrens * Given a path and mask of ZFS types, return a string describing this dataset. 78789Sahrens * This is used when we fail to open a dataset and we cannot get an exact type. 79789Sahrens * We guess what the type would have been based on the path and the mask of 80789Sahrens * acceptable types. 81789Sahrens */ 82789Sahrens static const char * 83789Sahrens path_to_str(const char *path, int types) 84789Sahrens { 85789Sahrens /* 86789Sahrens * When given a single type, always report the exact type. 87789Sahrens */ 88789Sahrens if (types == ZFS_TYPE_SNAPSHOT) 89789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 90789Sahrens if (types == ZFS_TYPE_FILESYSTEM) 91789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 92789Sahrens if (types == ZFS_TYPE_VOLUME) 93789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 94789Sahrens 95789Sahrens /* 96789Sahrens * The user is requesting more than one type of dataset. If this is the 97789Sahrens * case, consult the path itself. If we're looking for a snapshot, and 98789Sahrens * a '@' is found, then report it as "snapshot". Otherwise, remove the 99789Sahrens * snapshot attribute and try again. 100789Sahrens */ 101789Sahrens if (types & ZFS_TYPE_SNAPSHOT) { 102789Sahrens if (strchr(path, '@') != NULL) 103789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 104789Sahrens return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 105789Sahrens } 106789Sahrens 107789Sahrens 108789Sahrens /* 109789Sahrens * The user has requested either filesystems or volumes. 110789Sahrens * We have no way of knowing a priori what type this would be, so always 111789Sahrens * report it as "filesystem" or "volume", our two primitive types. 112789Sahrens */ 113789Sahrens if (types & ZFS_TYPE_FILESYSTEM) 114789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 115789Sahrens 116789Sahrens assert(types & ZFS_TYPE_VOLUME); 117789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 118789Sahrens } 119789Sahrens 120789Sahrens /* 121789Sahrens * Validate a ZFS path. This is used even before trying to open the dataset, to 122789Sahrens * provide a more meaningful error message. We place a more useful message in 123789Sahrens * 'buf' detailing exactly why the name was not valid. 124789Sahrens */ 125789Sahrens static int 1262082Seschrock zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type) 127789Sahrens { 128789Sahrens namecheck_err_t why; 129789Sahrens char what; 130789Sahrens 131789Sahrens if (dataset_namecheck(path, &why, &what) != 0) { 1322082Seschrock if (hdl != NULL) { 133789Sahrens switch (why) { 1341003Slling case NAME_ERR_TOOLONG: 1352082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1362082Seschrock "name is too long")); 1371003Slling break; 1381003Slling 139789Sahrens case NAME_ERR_LEADING_SLASH: 1402082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1412082Seschrock "leading slash in name")); 142789Sahrens break; 143789Sahrens 144789Sahrens case NAME_ERR_EMPTY_COMPONENT: 1452082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1462082Seschrock "empty component in name")); 147789Sahrens break; 148789Sahrens 149789Sahrens case NAME_ERR_TRAILING_SLASH: 1502082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1512082Seschrock "trailing slash in name")); 152789Sahrens break; 153789Sahrens 154789Sahrens case NAME_ERR_INVALCHAR: 1552082Seschrock zfs_error_aux(hdl, 156789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 1572082Seschrock "'%c' in name"), what); 158789Sahrens break; 159789Sahrens 160789Sahrens case NAME_ERR_MULTIPLE_AT: 1612082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1622082Seschrock "multiple '@' delimiters in name")); 163789Sahrens break; 1642856Snd150628 1652856Snd150628 case NAME_ERR_NOLETTER: 1662856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1672856Snd150628 "pool doesn't begin with a letter")); 1682856Snd150628 break; 1692856Snd150628 1702856Snd150628 case NAME_ERR_RESERVED: 1712856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1722856Snd150628 "name is reserved")); 1732856Snd150628 break; 1742856Snd150628 1752856Snd150628 case NAME_ERR_DISKLIKE: 1762856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1772856Snd150628 "reserved disk name")); 1782856Snd150628 break; 179789Sahrens } 180789Sahrens } 181789Sahrens 182789Sahrens return (0); 183789Sahrens } 184789Sahrens 185789Sahrens if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) { 1862082Seschrock if (hdl != NULL) 1872082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1882082Seschrock "snapshot delimiter '@' in filesystem name")); 189789Sahrens return (0); 190789Sahrens } 191789Sahrens 1922199Sahrens if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) { 1932199Sahrens if (hdl != NULL) 1942199Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1953413Smmusante "missing '@' delimiter in snapshot name")); 1962199Sahrens return (0); 1972199Sahrens } 1982199Sahrens 1992082Seschrock return (-1); 200789Sahrens } 201789Sahrens 202789Sahrens int 203789Sahrens zfs_name_valid(const char *name, zfs_type_t type) 204789Sahrens { 2052082Seschrock return (zfs_validate_name(NULL, name, type)); 206789Sahrens } 207789Sahrens 208789Sahrens /* 2092676Seschrock * This function takes the raw DSL properties, and filters out the user-defined 2102676Seschrock * properties into a separate nvlist. 2112676Seschrock */ 2124217Seschrock static nvlist_t * 2134217Seschrock process_user_props(zfs_handle_t *zhp, nvlist_t *props) 2142676Seschrock { 2152676Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 2162676Seschrock nvpair_t *elem; 2172676Seschrock nvlist_t *propval; 2184217Seschrock nvlist_t *nvl; 2194217Seschrock 2204217Seschrock if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 2214217Seschrock (void) no_memory(hdl); 2224217Seschrock return (NULL); 2234217Seschrock } 2242676Seschrock 2252676Seschrock elem = NULL; 2264217Seschrock while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 2272676Seschrock if (!zfs_prop_user(nvpair_name(elem))) 2282676Seschrock continue; 2292676Seschrock 2302676Seschrock verify(nvpair_value_nvlist(elem, &propval) == 0); 2314217Seschrock if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) { 2324217Seschrock nvlist_free(nvl); 2334217Seschrock (void) no_memory(hdl); 2344217Seschrock return (NULL); 2354217Seschrock } 2362676Seschrock } 2372676Seschrock 2384217Seschrock return (nvl); 2392676Seschrock } 2402676Seschrock 2412676Seschrock /* 242789Sahrens * Utility function to gather stats (objset and zpl) for the given object. 243789Sahrens */ 244789Sahrens static int 245789Sahrens get_stats(zfs_handle_t *zhp) 246789Sahrens { 247789Sahrens zfs_cmd_t zc = { 0 }; 2482676Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 2494217Seschrock nvlist_t *allprops, *userprops; 250789Sahrens 251789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 252789Sahrens 2532676Seschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 2542082Seschrock return (-1); 2551356Seschrock 2562082Seschrock while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) { 2571356Seschrock if (errno == ENOMEM) { 2582676Seschrock if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 2592676Seschrock zcmd_free_nvlists(&zc); 2602082Seschrock return (-1); 2612676Seschrock } 2621356Seschrock } else { 2632676Seschrock zcmd_free_nvlists(&zc); 2641356Seschrock return (-1); 2651356Seschrock } 2661356Seschrock } 267789Sahrens 2682885Sahrens zhp->zfs_dmustats = zc.zc_objset_stats; /* structure assignment */ 269789Sahrens 2702676Seschrock (void) strlcpy(zhp->zfs_root, zc.zc_value, sizeof (zhp->zfs_root)); 2711544Seschrock 2724217Seschrock if (zcmd_read_dst_nvlist(hdl, &zc, &allprops) != 0) { 2732676Seschrock zcmd_free_nvlists(&zc); 2742082Seschrock return (-1); 2752082Seschrock } 276789Sahrens 2772676Seschrock zcmd_free_nvlists(&zc); 2782676Seschrock 2794217Seschrock if ((userprops = process_user_props(zhp, allprops)) == NULL) { 2804217Seschrock nvlist_free(allprops); 2812676Seschrock return (-1); 2824217Seschrock } 2834217Seschrock 2844217Seschrock nvlist_free(zhp->zfs_props); 2854217Seschrock nvlist_free(zhp->zfs_user_props); 2864217Seschrock 2874217Seschrock zhp->zfs_props = allprops; 2884217Seschrock zhp->zfs_user_props = userprops; 2892082Seschrock 290789Sahrens return (0); 291789Sahrens } 292789Sahrens 293789Sahrens /* 294789Sahrens * Refresh the properties currently stored in the handle. 295789Sahrens */ 296789Sahrens void 297789Sahrens zfs_refresh_properties(zfs_handle_t *zhp) 298789Sahrens { 299789Sahrens (void) get_stats(zhp); 300789Sahrens } 301789Sahrens 302789Sahrens /* 303789Sahrens * Makes a handle from the given dataset name. Used by zfs_open() and 304789Sahrens * zfs_iter_* to create child handles on the fly. 305789Sahrens */ 306789Sahrens zfs_handle_t * 3072082Seschrock make_dataset_handle(libzfs_handle_t *hdl, const char *path) 308789Sahrens { 3092082Seschrock zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1); 3102082Seschrock 3112082Seschrock if (zhp == NULL) 3122082Seschrock return (NULL); 3132082Seschrock 3142082Seschrock zhp->zfs_hdl = hdl; 315789Sahrens 3161758Sahrens top: 317789Sahrens (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); 318789Sahrens 319789Sahrens if (get_stats(zhp) != 0) { 320789Sahrens free(zhp); 321789Sahrens return (NULL); 322789Sahrens } 323789Sahrens 3241758Sahrens if (zhp->zfs_dmustats.dds_inconsistent) { 3251758Sahrens zfs_cmd_t zc = { 0 }; 3261758Sahrens 3271758Sahrens /* 3281758Sahrens * If it is dds_inconsistent, then we've caught it in 3291758Sahrens * the middle of a 'zfs receive' or 'zfs destroy', and 3301758Sahrens * it is inconsistent from the ZPL's point of view, so 3311758Sahrens * can't be mounted. However, it could also be that we 3321758Sahrens * have crashed in the middle of one of those 3331758Sahrens * operations, in which case we need to get rid of the 3341758Sahrens * inconsistent state. We do that by either rolling 3351758Sahrens * back to the previous snapshot (which will fail if 3361758Sahrens * there is none), or destroying the filesystem. Note 3371758Sahrens * that if we are still in the middle of an active 3381758Sahrens * 'receive' or 'destroy', then the rollback and destroy 3391758Sahrens * will fail with EBUSY and we will drive on as usual. 3401758Sahrens */ 3411758Sahrens 3421758Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3431758Sahrens 3442885Sahrens if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) { 3452082Seschrock (void) zvol_remove_link(hdl, zhp->zfs_name); 3461758Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3471758Sahrens } else { 3481758Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3491758Sahrens } 3501758Sahrens 3511758Sahrens /* If we can successfully roll it back, reget the stats */ 3522082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_ROLLBACK, &zc) == 0) 3531758Sahrens goto top; 3541758Sahrens /* 3551758Sahrens * If we can sucessfully destroy it, pretend that it 3561758Sahrens * never existed. 3571758Sahrens */ 3582082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) == 0) { 3591758Sahrens free(zhp); 3601758Sahrens errno = ENOENT; 3611758Sahrens return (NULL); 3621758Sahrens } 3631758Sahrens } 3641758Sahrens 365789Sahrens /* 366789Sahrens * We've managed to open the dataset and gather statistics. Determine 367789Sahrens * the high-level type. 368789Sahrens */ 3692885Sahrens if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 3702885Sahrens zhp->zfs_head_type = ZFS_TYPE_VOLUME; 3712885Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 3722885Sahrens zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM; 3732885Sahrens else 3742885Sahrens abort(); 3752885Sahrens 376789Sahrens if (zhp->zfs_dmustats.dds_is_snapshot) 377789Sahrens zhp->zfs_type = ZFS_TYPE_SNAPSHOT; 378789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 379789Sahrens zhp->zfs_type = ZFS_TYPE_VOLUME; 380789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 381789Sahrens zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 382789Sahrens else 3832082Seschrock abort(); /* we should never see any other types */ 384789Sahrens 385789Sahrens return (zhp); 386789Sahrens } 387789Sahrens 388789Sahrens /* 389789Sahrens * Opens the given snapshot, filesystem, or volume. The 'types' 390789Sahrens * argument is a mask of acceptable types. The function will print an 391789Sahrens * appropriate error message and return NULL if it can't be opened. 392789Sahrens */ 393789Sahrens zfs_handle_t * 3942082Seschrock zfs_open(libzfs_handle_t *hdl, const char *path, int types) 395789Sahrens { 396789Sahrens zfs_handle_t *zhp; 3972082Seschrock char errbuf[1024]; 3982082Seschrock 3992082Seschrock (void) snprintf(errbuf, sizeof (errbuf), 4002082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), path); 401789Sahrens 402789Sahrens /* 4032082Seschrock * Validate the name before we even try to open it. 404789Sahrens */ 4052082Seschrock if (!zfs_validate_name(hdl, path, ZFS_TYPE_ANY)) { 4062082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4072082Seschrock "invalid dataset name")); 4082082Seschrock (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 409789Sahrens return (NULL); 410789Sahrens } 411789Sahrens 412789Sahrens /* 413789Sahrens * Try to get stats for the dataset, which will tell us if it exists. 414789Sahrens */ 415789Sahrens errno = 0; 4162082Seschrock if ((zhp = make_dataset_handle(hdl, path)) == NULL) { 4173237Slling (void) zfs_standard_error(hdl, errno, errbuf); 418789Sahrens return (NULL); 419789Sahrens } 420789Sahrens 421789Sahrens if (!(types & zhp->zfs_type)) { 4222082Seschrock (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 4232142Seschrock zfs_close(zhp); 424789Sahrens return (NULL); 425789Sahrens } 426789Sahrens 427789Sahrens return (zhp); 428789Sahrens } 429789Sahrens 430789Sahrens /* 431789Sahrens * Release a ZFS handle. Nothing to do but free the associated memory. 432789Sahrens */ 433789Sahrens void 434789Sahrens zfs_close(zfs_handle_t *zhp) 435789Sahrens { 436789Sahrens if (zhp->zfs_mntopts) 437789Sahrens free(zhp->zfs_mntopts); 4382676Seschrock nvlist_free(zhp->zfs_props); 4392676Seschrock nvlist_free(zhp->zfs_user_props); 440789Sahrens free(zhp); 441789Sahrens } 442789Sahrens 443789Sahrens /* 444789Sahrens * Given a numeric suffix, convert the value into a number of bits that the 445789Sahrens * resulting value must be shifted. 446789Sahrens */ 447789Sahrens static int 4482082Seschrock str2shift(libzfs_handle_t *hdl, const char *buf) 449789Sahrens { 450789Sahrens const char *ends = "BKMGTPEZ"; 451789Sahrens int i; 452789Sahrens 453789Sahrens if (buf[0] == '\0') 454789Sahrens return (0); 455789Sahrens for (i = 0; i < strlen(ends); i++) { 456789Sahrens if (toupper(buf[0]) == ends[i]) 457789Sahrens break; 458789Sahrens } 459789Sahrens if (i == strlen(ends)) { 4602082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4612082Seschrock "invalid numeric suffix '%s'"), buf); 462789Sahrens return (-1); 463789Sahrens } 464789Sahrens 465789Sahrens /* 466789Sahrens * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 467789Sahrens * allow 'BB' - that's just weird. 468789Sahrens */ 469789Sahrens if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 4702082Seschrock toupper(buf[0]) != 'B')) 471789Sahrens return (10*i); 4722082Seschrock 4732082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4742082Seschrock "invalid numeric suffix '%s'"), buf); 475789Sahrens return (-1); 476789Sahrens } 477789Sahrens 478789Sahrens /* 479789Sahrens * Convert a string of the form '100G' into a real number. Used when setting 480789Sahrens * properties or creating a volume. 'buf' is used to place an extended error 481789Sahrens * message for the caller to use. 482789Sahrens */ 483789Sahrens static int 4842082Seschrock nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) 485789Sahrens { 486789Sahrens char *end; 487789Sahrens int shift; 488789Sahrens 489789Sahrens *num = 0; 490789Sahrens 491789Sahrens /* Check to see if this looks like a number. */ 492789Sahrens if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 4932082Seschrock if (hdl) 4942082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4952082Seschrock "bad numeric value '%s'"), value); 496789Sahrens return (-1); 497789Sahrens } 498789Sahrens 499789Sahrens /* Rely on stroll() to process the numeric portion. */ 500789Sahrens errno = 0; 501789Sahrens *num = strtoll(value, &end, 10); 502789Sahrens 503789Sahrens /* 504789Sahrens * Check for ERANGE, which indicates that the value is too large to fit 505789Sahrens * in a 64-bit value. 506789Sahrens */ 507789Sahrens if (errno == ERANGE) { 5082082Seschrock if (hdl) 5092082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5102082Seschrock "numeric value is too large")); 511789Sahrens return (-1); 512789Sahrens } 513789Sahrens 514789Sahrens /* 515789Sahrens * If we have a decimal value, then do the computation with floating 516789Sahrens * point arithmetic. Otherwise, use standard arithmetic. 517789Sahrens */ 518789Sahrens if (*end == '.') { 519789Sahrens double fval = strtod(value, &end); 520789Sahrens 5212082Seschrock if ((shift = str2shift(hdl, end)) == -1) 522789Sahrens return (-1); 523789Sahrens 524789Sahrens fval *= pow(2, shift); 525789Sahrens 526789Sahrens if (fval > UINT64_MAX) { 5272082Seschrock if (hdl) 5282082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5292082Seschrock "numeric value is too large")); 530789Sahrens return (-1); 531789Sahrens } 532789Sahrens 533789Sahrens *num = (uint64_t)fval; 534789Sahrens } else { 5352082Seschrock if ((shift = str2shift(hdl, end)) == -1) 536789Sahrens return (-1); 537789Sahrens 538789Sahrens /* Check for overflow */ 539789Sahrens if (shift >= 64 || (*num << shift) >> shift != *num) { 5402082Seschrock if (hdl) 5412082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5422082Seschrock "numeric value is too large")); 543789Sahrens return (-1); 544789Sahrens } 545789Sahrens 546789Sahrens *num <<= shift; 547789Sahrens } 548789Sahrens 549789Sahrens return (0); 550789Sahrens } 551789Sahrens 552789Sahrens int 5532676Seschrock zfs_nicestrtonum(libzfs_handle_t *hdl, const char *str, uint64_t *val) 5542676Seschrock { 5552676Seschrock return (nicestrtonum(hdl, str, val)); 5562676Seschrock } 5572676Seschrock 5582676Seschrock /* 5592676Seschrock * The prop_parse_*() functions are designed to allow flexibility in callers 5602676Seschrock * when setting properties. At the DSL layer, all properties are either 64-bit 5612676Seschrock * numbers or strings. We want the user to be able to ignore this fact and 5622676Seschrock * specify properties as native values (boolean, for example) or as strings (to 5632676Seschrock * simplify command line utilities). This also handles converting index types 5642676Seschrock * (compression, checksum, etc) from strings to their on-disk index. 5652676Seschrock */ 5662676Seschrock 5672676Seschrock static int 5682676Seschrock prop_parse_boolean(libzfs_handle_t *hdl, nvpair_t *elem, uint64_t *val) 569789Sahrens { 5702676Seschrock uint64_t ret; 5712676Seschrock 5722676Seschrock switch (nvpair_type(elem)) { 5732676Seschrock case DATA_TYPE_STRING: 5742676Seschrock { 5752676Seschrock char *value; 5763363Sgw25295 verify(nvpair_value_string(elem, &value) == 0); 5772676Seschrock 5782676Seschrock if (strcmp(value, "on") == 0) { 5792676Seschrock ret = 1; 5802676Seschrock } else if (strcmp(value, "off") == 0) { 5812676Seschrock ret = 0; 5822676Seschrock } else { 5832676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5842676Seschrock "property '%s' must be 'on' or 'off'"), 5852676Seschrock nvpair_name(elem)); 5862676Seschrock return (-1); 5872676Seschrock } 5882676Seschrock break; 5892676Seschrock } 5902676Seschrock 5912676Seschrock case DATA_TYPE_UINT64: 5922676Seschrock { 5933363Sgw25295 verify(nvpair_value_uint64(elem, &ret) == 0); 5942676Seschrock if (ret > 1) { 5952676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5962676Seschrock "'%s' must be a boolean value"), 5972676Seschrock nvpair_name(elem)); 5982676Seschrock return (-1); 5992676Seschrock } 6002676Seschrock break; 6012676Seschrock } 6022676Seschrock 6032676Seschrock case DATA_TYPE_BOOLEAN_VALUE: 6042676Seschrock { 6052676Seschrock boolean_t value; 6063363Sgw25295 verify(nvpair_value_boolean_value(elem, &value) == 0); 6072676Seschrock ret = value; 6082676Seschrock break; 6092676Seschrock } 6102676Seschrock 6112676Seschrock default: 6122676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6132676Seschrock "'%s' must be a boolean value"), 6142676Seschrock nvpair_name(elem)); 6152676Seschrock return (-1); 6162676Seschrock } 6172676Seschrock 6182676Seschrock *val = ret; 6192676Seschrock return (0); 6202676Seschrock } 6212676Seschrock 6222676Seschrock static int 6232676Seschrock prop_parse_number(libzfs_handle_t *hdl, nvpair_t *elem, zfs_prop_t prop, 6242676Seschrock uint64_t *val) 6252676Seschrock { 6262676Seschrock uint64_t ret; 6272676Seschrock boolean_t isnone = B_FALSE; 6282676Seschrock 6292676Seschrock switch (nvpair_type(elem)) { 6302676Seschrock case DATA_TYPE_STRING: 6312676Seschrock { 6322676Seschrock char *value; 6332676Seschrock (void) nvpair_value_string(elem, &value); 6342676Seschrock if (strcmp(value, "none") == 0) { 6352676Seschrock isnone = B_TRUE; 6362676Seschrock ret = 0; 6372676Seschrock } else if (nicestrtonum(hdl, value, &ret) != 0) { 6382676Seschrock return (-1); 6392676Seschrock } 6402676Seschrock break; 6412676Seschrock } 6422676Seschrock 6432676Seschrock case DATA_TYPE_UINT64: 6442676Seschrock (void) nvpair_value_uint64(elem, &ret); 6452676Seschrock break; 6462676Seschrock 6472676Seschrock default: 6482676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6492676Seschrock "'%s' must be a number"), 6502676Seschrock nvpair_name(elem)); 6512676Seschrock return (-1); 6522676Seschrock } 6532676Seschrock 6542676Seschrock /* 6552676Seschrock * Quota special: force 'none' and don't allow 0. 6562676Seschrock */ 6572676Seschrock if (ret == 0 && !isnone && prop == ZFS_PROP_QUOTA) { 6582676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6592676Seschrock "use 'none' to disable quota")); 6602676Seschrock return (-1); 6612676Seschrock } 6622676Seschrock 6632676Seschrock *val = ret; 6642676Seschrock return (0); 6652676Seschrock } 6662676Seschrock 6672676Seschrock static int 6682676Seschrock prop_parse_index(libzfs_handle_t *hdl, nvpair_t *elem, zfs_prop_t prop, 6692676Seschrock uint64_t *val) 6702676Seschrock { 6712676Seschrock char *propname = nvpair_name(elem); 6722676Seschrock char *value; 6732676Seschrock 6742676Seschrock if (nvpair_type(elem) != DATA_TYPE_STRING) { 6752676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6762676Seschrock "'%s' must be a string"), propname); 6772676Seschrock return (-1); 6782676Seschrock } 6792676Seschrock 6802676Seschrock (void) nvpair_value_string(elem, &value); 6812676Seschrock 6822676Seschrock if (zfs_prop_string_to_index(prop, value, val) != 0) { 6832676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6842676Seschrock "'%s' must be one of '%s'"), propname, 6852676Seschrock zfs_prop_values(prop)); 6862676Seschrock return (-1); 6872676Seschrock } 6882676Seschrock 6892676Seschrock return (0); 690789Sahrens } 691789Sahrens 692789Sahrens /* 6933912Slling * Check if the bootfs name has the same pool name as it is set to. 6943912Slling * Assuming bootfs is a valid dataset name. 6953912Slling */ 6963912Slling static boolean_t 6973912Slling bootfs_poolname_valid(char *pool, char *bootfs) 6983912Slling { 6993912Slling char ch, *pname; 7003912Slling 7013912Slling /* get the pool name from the bootfs name */ 7023912Slling pname = bootfs; 7033912Slling while (*bootfs && !isspace(*bootfs) && *bootfs != '/') 7043912Slling bootfs++; 7053912Slling 7063912Slling ch = *bootfs; 7073912Slling *bootfs = 0; 7083912Slling 7093912Slling if (strcmp(pool, pname) == 0) { 7103912Slling *bootfs = ch; 7113912Slling return (B_TRUE); 7123912Slling } 7133912Slling 7143912Slling *bootfs = ch; 7153912Slling return (B_FALSE); 7163912Slling } 7173912Slling 7183912Slling /* 7192676Seschrock * Given an nvlist of properties to set, validates that they are correct, and 7202676Seschrock * parses any numeric properties (index, boolean, etc) if they are specified as 7212676Seschrock * strings. 722789Sahrens */ 7233912Slling nvlist_t * 7243912Slling zfs_validate_properties(libzfs_handle_t *hdl, zfs_type_t type, char *pool_name, 7253912Slling nvlist_t *nvl, uint64_t zoned, zfs_handle_t *zhp, const char *errbuf) 726789Sahrens { 7272676Seschrock nvpair_t *elem; 7282676Seschrock const char *propname; 7292676Seschrock zfs_prop_t prop; 7302676Seschrock uint64_t intval; 7312676Seschrock char *strval; 7322676Seschrock nvlist_t *ret; 7333912Slling int isuser; 7342676Seschrock 7352676Seschrock if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) { 7362676Seschrock (void) no_memory(hdl); 7372676Seschrock return (NULL); 7382676Seschrock } 7392676Seschrock 7402676Seschrock if (type == ZFS_TYPE_SNAPSHOT) { 7412676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7423413Smmusante "snapshot properties cannot be modified")); 7432676Seschrock (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 7442676Seschrock goto error; 745789Sahrens } 746789Sahrens 7472676Seschrock elem = NULL; 7482676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 7492676Seschrock propname = nvpair_name(elem); 7502676Seschrock 7512676Seschrock /* 7522676Seschrock * Make sure this property is valid and applies to this type. 7532676Seschrock */ 7543912Slling if ((prop = zfs_name_to_prop_common(propname, type)) 7553912Slling == ZFS_PROP_INVAL) { 7563912Slling isuser = zfs_prop_user(propname); 7573912Slling if (!isuser || (isuser && (type & ZFS_TYPE_POOL))) { 7582676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7592676Seschrock "invalid property '%s'"), 7602676Seschrock propname); 7612676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 7622676Seschrock goto error; 7632676Seschrock } else { 7642676Seschrock /* 7652676Seschrock * If this is a user property, make sure it's a 7662676Seschrock * string, and that it's less than 7672676Seschrock * ZAP_MAXNAMELEN. 7682676Seschrock */ 7692676Seschrock if (nvpair_type(elem) != DATA_TYPE_STRING) { 7702676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7712676Seschrock "'%s' must be a string"), 7722676Seschrock propname); 7732676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 7742676Seschrock errbuf); 7752676Seschrock goto error; 7762676Seschrock } 7772676Seschrock 7782676Seschrock if (strlen(nvpair_name(elem)) >= 7792676Seschrock ZAP_MAXNAMELEN) { 7802676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7812676Seschrock "property name '%s' is too long"), 7822676Seschrock propname); 7832676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 7842676Seschrock errbuf); 7852676Seschrock goto error; 7862676Seschrock } 7872676Seschrock } 7882676Seschrock 7892676Seschrock (void) nvpair_value_string(elem, &strval); 7902676Seschrock if (nvlist_add_string(ret, propname, strval) != 0) { 7912676Seschrock (void) no_memory(hdl); 7922676Seschrock goto error; 7932676Seschrock } 7942676Seschrock continue; 795789Sahrens } 7962676Seschrock 7972676Seschrock /* 7982676Seschrock * Normalize the name, to get rid of shorthand abbrevations. 7992676Seschrock */ 8002676Seschrock propname = zfs_prop_to_name(prop); 8012676Seschrock 8022676Seschrock if (!zfs_prop_valid_for_type(prop, type)) { 8032676Seschrock zfs_error_aux(hdl, 8042676Seschrock dgettext(TEXT_DOMAIN, "'%s' does not " 8052676Seschrock "apply to datasets of this type"), propname); 8062676Seschrock (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 8072676Seschrock goto error; 8082676Seschrock } 8092676Seschrock 8102676Seschrock if (zfs_prop_readonly(prop) && 8112676Seschrock (prop != ZFS_PROP_VOLBLOCKSIZE || zhp != NULL)) { 8122676Seschrock zfs_error_aux(hdl, 8132676Seschrock dgettext(TEXT_DOMAIN, "'%s' is readonly"), 8142676Seschrock propname); 8152676Seschrock (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); 8162676Seschrock goto error; 8172676Seschrock } 8182676Seschrock 8192676Seschrock /* 8202676Seschrock * Convert any properties to the internal DSL value types. 8212676Seschrock */ 8222676Seschrock strval = NULL; 8232676Seschrock switch (zfs_prop_get_type(prop)) { 8242676Seschrock case prop_type_boolean: 8252676Seschrock if (prop_parse_boolean(hdl, elem, &intval) != 0) { 8262676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8272676Seschrock goto error; 8282676Seschrock } 829789Sahrens break; 8302676Seschrock 8312676Seschrock case prop_type_string: 8322676Seschrock if (nvpair_type(elem) != DATA_TYPE_STRING) { 8332082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8342676Seschrock "'%s' must be a string"), 8352676Seschrock propname); 8362676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8372676Seschrock goto error; 838789Sahrens } 8392676Seschrock (void) nvpair_value_string(elem, &strval); 8402676Seschrock if (strlen(strval) >= ZFS_MAXPROPLEN) { 8412082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8422676Seschrock "'%s' is too long"), propname); 8432676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8442676Seschrock goto error; 8452676Seschrock } 8462676Seschrock break; 8472676Seschrock 8482676Seschrock case prop_type_number: 8492676Seschrock if (prop_parse_number(hdl, elem, prop, &intval) != 0) { 8502676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8512676Seschrock goto error; 8522676Seschrock } 8532676Seschrock break; 8542676Seschrock 8552676Seschrock case prop_type_index: 8562676Seschrock if (prop_parse_index(hdl, elem, prop, &intval) != 0) { 8572676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8582676Seschrock goto error; 859789Sahrens } 860789Sahrens break; 861789Sahrens 8622676Seschrock default: 8632676Seschrock abort(); 8642676Seschrock } 8652676Seschrock 8662676Seschrock /* 8672676Seschrock * Add the result to our return set of properties. 8682676Seschrock */ 8692676Seschrock if (strval) { 8702676Seschrock if (nvlist_add_string(ret, propname, strval) != 0) { 8712676Seschrock (void) no_memory(hdl); 8722676Seschrock goto error; 873789Sahrens } 8742676Seschrock } else if (nvlist_add_uint64(ret, propname, intval) != 0) { 8752676Seschrock (void) no_memory(hdl); 8762676Seschrock goto error; 8772676Seschrock } 8782676Seschrock 8792676Seschrock /* 8802676Seschrock * Perform some additional checks for specific properties. 8812676Seschrock */ 8822676Seschrock switch (prop) { 8832676Seschrock case ZFS_PROP_RECORDSIZE: 8842676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 8852676Seschrock /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */ 8862676Seschrock if (intval < SPA_MINBLOCKSIZE || 8872676Seschrock intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) { 8882082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8892676Seschrock "'%s' must be power of 2 from %u " 8902676Seschrock "to %uk"), propname, 8912676Seschrock (uint_t)SPA_MINBLOCKSIZE, 8922676Seschrock (uint_t)SPA_MAXBLOCKSIZE >> 10); 8932676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8942676Seschrock goto error; 895789Sahrens } 896789Sahrens break; 897789Sahrens 8983126Sahl case ZFS_PROP_SHAREISCSI: 8993126Sahl if (strcmp(strval, "off") != 0 && 9003126Sahl strcmp(strval, "on") != 0 && 9013126Sahl strcmp(strval, "type=disk") != 0) { 9023126Sahl zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9033126Sahl "'%s' must be 'on', 'off', or 'type=disk'"), 9043126Sahl propname); 9053126Sahl (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 9063126Sahl goto error; 9073126Sahl } 9083126Sahl 9093126Sahl break; 9103126Sahl 9112676Seschrock case ZFS_PROP_MOUNTPOINT: 9122676Seschrock if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 || 9132676Seschrock strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0) 9142676Seschrock break; 9152676Seschrock 9162676Seschrock if (strval[0] != '/') { 9172082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9182676Seschrock "'%s' must be an absolute path, " 9192676Seschrock "'none', or 'legacy'"), propname); 9202676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 9212676Seschrock goto error; 922789Sahrens } 9233126Sahl /*FALLTHRU*/ 9243126Sahl 9253126Sahl case ZFS_PROP_SHARENFS: 9263126Sahl /* 9273126Sahl * For the mountpoint and sharenfs properties, check if 9283126Sahl * it can be set in a global/non-global zone based on 9293126Sahl * the zoned property value: 9303126Sahl * 9313126Sahl * global zone non-global zone 9323126Sahl * -------------------------------------------------- 9333126Sahl * zoned=on mountpoint (no) mountpoint (yes) 9343126Sahl * sharenfs (no) sharenfs (no) 9353126Sahl * 9363126Sahl * zoned=off mountpoint (yes) N/A 9373126Sahl * sharenfs (yes) 9383126Sahl */ 9392676Seschrock if (zoned) { 9402676Seschrock if (getzoneid() == GLOBAL_ZONEID) { 9412676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9422676Seschrock "'%s' cannot be set on " 9432676Seschrock "dataset in a non-global zone"), 9442676Seschrock propname); 9452676Seschrock (void) zfs_error(hdl, EZFS_ZONED, 9462676Seschrock errbuf); 9472676Seschrock goto error; 9482676Seschrock } else if (prop == ZFS_PROP_SHARENFS) { 9492676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9502676Seschrock "'%s' cannot be set in " 9512676Seschrock "a non-global zone"), propname); 9522676Seschrock (void) zfs_error(hdl, EZFS_ZONED, 9532676Seschrock errbuf); 9542676Seschrock goto error; 9552676Seschrock } 9562676Seschrock } else if (getzoneid() != GLOBAL_ZONEID) { 9572676Seschrock /* 9582676Seschrock * If zoned property is 'off', this must be in 9592676Seschrock * a globle zone. If not, something is wrong. 9602676Seschrock */ 9612676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9622676Seschrock "'%s' cannot be set while dataset " 9632676Seschrock "'zoned' property is set"), propname); 9642676Seschrock (void) zfs_error(hdl, EZFS_ZONED, errbuf); 9652676Seschrock goto error; 9662676Seschrock } 9673126Sahl 9684180Sdougm /* 9694180Sdougm * At this point, it is legitimate to set the 9704180Sdougm * property. Now we want to make sure that the 9714180Sdougm * property value is valid if it is sharenfs. 9724180Sdougm */ 9734180Sdougm if (prop == ZFS_PROP_SHARENFS && 9744217Seschrock strcmp(strval, "on") != 0 && 9754217Seschrock strcmp(strval, "off") != 0) { 9764180Sdougm 9774180Sdougm /* 9784180Sdougm * Must be an NFS option string so 9794180Sdougm * init the libshare in order to 9804180Sdougm * enable the parser and then parse 9814180Sdougm * the options. We use the control API 9824180Sdougm * since we don't care about the 9834180Sdougm * current configuration and don't 9844180Sdougm * want the overhead of loading it 9854180Sdougm * until we actually do something. 9864180Sdougm */ 9874180Sdougm 9884217Seschrock if (zfs_init_libshare(hdl, 9894217Seschrock SA_INIT_CONTROL_API) != SA_OK) { 9904217Seschrock /* 9914217Seschrock * An error occurred so we can't do 9924217Seschrock * anything 9934217Seschrock */ 9944217Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9954217Seschrock "'%s' cannot be set: problem " 9964217Seschrock "in share initialization"), 9974217Seschrock propname); 9984217Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 9994217Seschrock errbuf); 10004217Seschrock goto error; 10014217Seschrock } 10024217Seschrock 10034217Seschrock if (zfs_parse_options(strval, "nfs") != SA_OK) { 10044217Seschrock /* 10054217Seschrock * There was an error in parsing so 10064217Seschrock * deal with it by issuing an error 10074217Seschrock * message and leaving after 10084217Seschrock * uninitializing the the libshare 10094217Seschrock * interface. 10104217Seschrock */ 10114217Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10124217Seschrock "'%s' cannot be set to invalid " 10134217Seschrock "options"), propname); 10144217Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10154217Seschrock errbuf); 10164217Seschrock zfs_uninit_libshare(hdl); 10174217Seschrock goto error; 10184217Seschrock } 10194180Sdougm zfs_uninit_libshare(hdl); 10204180Sdougm } 10214180Sdougm 10223126Sahl break; 10233912Slling 10244451Seschrock case ZPOOL_PROP_BOOTFS: 10253912Slling /* 10263912Slling * bootfs property value has to be a dataset name and 10273912Slling * the dataset has to be in the same pool as it sets to. 10283912Slling */ 10293912Slling if (strval[0] != '\0' && (!zfs_name_valid(strval, 10303912Slling ZFS_TYPE_FILESYSTEM) || !bootfs_poolname_valid( 10313912Slling pool_name, strval))) { 10323912Slling 10333912Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 10343912Slling "is an invalid name"), strval); 10353912Slling (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 10363912Slling goto error; 10373912Slling } 10383912Slling break; 10392676Seschrock } 10402676Seschrock 10412676Seschrock /* 10422676Seschrock * For changes to existing volumes, we have some additional 10432676Seschrock * checks to enforce. 10442676Seschrock */ 10452676Seschrock if (type == ZFS_TYPE_VOLUME && zhp != NULL) { 10462676Seschrock uint64_t volsize = zfs_prop_get_int(zhp, 10472676Seschrock ZFS_PROP_VOLSIZE); 10482676Seschrock uint64_t blocksize = zfs_prop_get_int(zhp, 10492676Seschrock ZFS_PROP_VOLBLOCKSIZE); 10502676Seschrock char buf[64]; 10512676Seschrock 10522676Seschrock switch (prop) { 10532676Seschrock case ZFS_PROP_RESERVATION: 10542676Seschrock if (intval > volsize) { 10552676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10562676Seschrock "'%s' is greater than current " 10572676Seschrock "volume size"), propname); 10582676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10592676Seschrock errbuf); 10602676Seschrock goto error; 10612676Seschrock } 10622676Seschrock break; 10632676Seschrock 10642676Seschrock case ZFS_PROP_VOLSIZE: 10652676Seschrock if (intval % blocksize != 0) { 10662676Seschrock zfs_nicenum(blocksize, buf, 10672676Seschrock sizeof (buf)); 10682676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10692676Seschrock "'%s' must be a multiple of " 10702676Seschrock "volume block size (%s)"), 10712676Seschrock propname, buf); 10722676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10732676Seschrock errbuf); 10742676Seschrock goto error; 10752676Seschrock } 10762676Seschrock 10772676Seschrock if (intval == 0) { 10782676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10792676Seschrock "'%s' cannot be zero"), 10802676Seschrock propname); 10812676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10822676Seschrock errbuf); 10832676Seschrock goto error; 1084789Sahrens } 10853126Sahl break; 1086789Sahrens } 1087789Sahrens } 1088789Sahrens } 1089789Sahrens 10902676Seschrock /* 10912676Seschrock * If this is an existing volume, and someone is setting the volsize, 10922676Seschrock * make sure that it matches the reservation, or add it if necessary. 10932676Seschrock */ 10942676Seschrock if (zhp != NULL && type == ZFS_TYPE_VOLUME && 10952676Seschrock nvlist_lookup_uint64(ret, zfs_prop_to_name(ZFS_PROP_VOLSIZE), 10962676Seschrock &intval) == 0) { 10972676Seschrock uint64_t old_volsize = zfs_prop_get_int(zhp, 10982676Seschrock ZFS_PROP_VOLSIZE); 10992676Seschrock uint64_t old_reservation = zfs_prop_get_int(zhp, 11002676Seschrock ZFS_PROP_RESERVATION); 11012676Seschrock uint64_t new_reservation; 11022676Seschrock 11032676Seschrock if (old_volsize == old_reservation && 11042676Seschrock nvlist_lookup_uint64(ret, 11052676Seschrock zfs_prop_to_name(ZFS_PROP_RESERVATION), 11062676Seschrock &new_reservation) != 0) { 11072676Seschrock if (nvlist_add_uint64(ret, 11082676Seschrock zfs_prop_to_name(ZFS_PROP_RESERVATION), 11092676Seschrock intval) != 0) { 11102676Seschrock (void) no_memory(hdl); 11112676Seschrock goto error; 11122676Seschrock } 11132676Seschrock } 11142676Seschrock } 11152676Seschrock 11162676Seschrock return (ret); 11172676Seschrock 11182676Seschrock error: 11192676Seschrock nvlist_free(ret); 11202676Seschrock return (NULL); 1121789Sahrens } 1122789Sahrens 1123789Sahrens /* 1124789Sahrens * Given a property name and value, set the property for the given dataset. 1125789Sahrens */ 1126789Sahrens int 11272676Seschrock zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) 1128789Sahrens { 1129789Sahrens zfs_cmd_t zc = { 0 }; 11302676Seschrock int ret = -1; 11312676Seschrock prop_changelist_t *cl = NULL; 11322082Seschrock char errbuf[1024]; 11332082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 11342676Seschrock nvlist_t *nvl = NULL, *realprops; 11352676Seschrock zfs_prop_t prop; 11362082Seschrock 11372082Seschrock (void) snprintf(errbuf, sizeof (errbuf), 11382676Seschrock dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 11392082Seschrock zhp->zfs_name); 11402082Seschrock 11412676Seschrock if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || 11422676Seschrock nvlist_add_string(nvl, propname, propval) != 0) { 11432676Seschrock (void) no_memory(hdl); 11442676Seschrock goto error; 1145789Sahrens } 1146789Sahrens 11473912Slling if ((realprops = zfs_validate_properties(hdl, zhp->zfs_type, NULL, nvl, 11482676Seschrock zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL) 11492676Seschrock goto error; 11502676Seschrock nvlist_free(nvl); 11512676Seschrock nvl = realprops; 11522676Seschrock 11532676Seschrock prop = zfs_name_to_prop(propname); 11542676Seschrock 1155789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 11562676Seschrock goto error; 1157789Sahrens 1158789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 11592082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11602082Seschrock "child dataset with inherited mountpoint is used " 11612082Seschrock "in a non-global zone")); 11622082Seschrock ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1163789Sahrens goto error; 1164789Sahrens } 1165789Sahrens 1166789Sahrens if ((ret = changelist_prefix(cl)) != 0) 1167789Sahrens goto error; 1168789Sahrens 1169789Sahrens /* 1170789Sahrens * Execute the corresponding ioctl() to set this property. 1171789Sahrens */ 1172789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1173789Sahrens 11742676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvl, NULL) != 0) 11752676Seschrock goto error; 11762676Seschrock 11772676Seschrock ret = ioctl(hdl->libzfs_fd, ZFS_IOC_SET_PROP, &zc); 1178789Sahrens 1179789Sahrens if (ret != 0) { 1180789Sahrens switch (errno) { 1181789Sahrens 1182789Sahrens case ENOSPC: 1183789Sahrens /* 1184789Sahrens * For quotas and reservations, ENOSPC indicates 1185789Sahrens * something different; setting a quota or reservation 1186789Sahrens * doesn't use any disk space. 1187789Sahrens */ 1188789Sahrens switch (prop) { 1189789Sahrens case ZFS_PROP_QUOTA: 11902082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11912082Seschrock "size is less than current used or " 11922082Seschrock "reserved space")); 11932082Seschrock (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1194789Sahrens break; 1195789Sahrens 1196789Sahrens case ZFS_PROP_RESERVATION: 11972082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11982082Seschrock "size is greater than available space")); 11992082Seschrock (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1200789Sahrens break; 1201789Sahrens 1202789Sahrens default: 12032082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 1204789Sahrens break; 1205789Sahrens } 1206789Sahrens break; 1207789Sahrens 1208789Sahrens case EBUSY: 12092082Seschrock if (prop == ZFS_PROP_VOLBLOCKSIZE) 12102082Seschrock (void) zfs_error(hdl, EZFS_VOLHASDATA, errbuf); 12112082Seschrock else 12122676Seschrock (void) zfs_standard_error(hdl, EBUSY, errbuf); 1213789Sahrens break; 1214789Sahrens 12151175Slling case EROFS: 12162082Seschrock (void) zfs_error(hdl, EZFS_DSREADONLY, errbuf); 12171175Slling break; 12181175Slling 12193886Sahl case ENOTSUP: 12203886Sahl zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12213886Sahl "pool must be upgraded to allow gzip compression")); 12223886Sahl (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 12233886Sahl break; 12243886Sahl 1225789Sahrens case EOVERFLOW: 1226789Sahrens /* 1227789Sahrens * This platform can't address a volume this big. 1228789Sahrens */ 1229789Sahrens #ifdef _ILP32 1230789Sahrens if (prop == ZFS_PROP_VOLSIZE) { 12312082Seschrock (void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf); 1232789Sahrens break; 1233789Sahrens } 1234789Sahrens #endif 12352082Seschrock /* FALLTHROUGH */ 1236789Sahrens default: 12372082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 1238789Sahrens } 1239789Sahrens } else { 1240789Sahrens /* 1241789Sahrens * Refresh the statistics so the new property value 1242789Sahrens * is reflected. 1243789Sahrens */ 12442676Seschrock if ((ret = changelist_postfix(cl)) == 0) 12452676Seschrock (void) get_stats(zhp); 1246789Sahrens } 1247789Sahrens 1248789Sahrens error: 12492676Seschrock nvlist_free(nvl); 12502676Seschrock zcmd_free_nvlists(&zc); 12512676Seschrock if (cl) 12522676Seschrock changelist_free(cl); 1253789Sahrens return (ret); 1254789Sahrens } 1255789Sahrens 1256789Sahrens /* 1257789Sahrens * Given a property, inherit the value from the parent dataset. 1258789Sahrens */ 1259789Sahrens int 12602676Seschrock zfs_prop_inherit(zfs_handle_t *zhp, const char *propname) 1261789Sahrens { 1262789Sahrens zfs_cmd_t zc = { 0 }; 1263789Sahrens int ret; 1264789Sahrens prop_changelist_t *cl; 12652082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 12662082Seschrock char errbuf[1024]; 12672676Seschrock zfs_prop_t prop; 12682082Seschrock 12692082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 12702082Seschrock "cannot inherit %s for '%s'"), propname, zhp->zfs_name); 1271789Sahrens 12722676Seschrock if ((prop = zfs_name_to_prop(propname)) == ZFS_PROP_INVAL) { 12732676Seschrock /* 12742676Seschrock * For user properties, the amount of work we have to do is very 12752676Seschrock * small, so just do it here. 12762676Seschrock */ 12772676Seschrock if (!zfs_prop_user(propname)) { 12782676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12792676Seschrock "invalid property")); 12802676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 12812676Seschrock } 12822676Seschrock 12832676Seschrock (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 12842676Seschrock (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 12852676Seschrock 12862676Seschrock if (ioctl(zhp->zfs_hdl->libzfs_fd, 12872676Seschrock ZFS_IOC_SET_PROP, &zc) != 0) 12882676Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 12892676Seschrock 12902676Seschrock return (0); 12912676Seschrock } 12922676Seschrock 1293789Sahrens /* 1294789Sahrens * Verify that this property is inheritable. 1295789Sahrens */ 12962082Seschrock if (zfs_prop_readonly(prop)) 12972082Seschrock return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf)); 12982082Seschrock 12992082Seschrock if (!zfs_prop_inheritable(prop)) 13002082Seschrock return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf)); 1301789Sahrens 1302789Sahrens /* 1303789Sahrens * Check to see if the value applies to this type 1304789Sahrens */ 13052082Seschrock if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 13062082Seschrock return (zfs_error(hdl, EZFS_PROPTYPE, errbuf)); 1307789Sahrens 13083443Srm160521 /* 13093443Srm160521 * Normalize the name, to get rid of shorthand abbrevations. 13103443Srm160521 */ 13113443Srm160521 propname = zfs_prop_to_name(prop); 1312789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 13132676Seschrock (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 1314789Sahrens 1315789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID && 1316789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 13172082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 13182082Seschrock "dataset is used in a non-global zone")); 13192082Seschrock return (zfs_error(hdl, EZFS_ZONED, errbuf)); 1320789Sahrens } 1321789Sahrens 1322789Sahrens /* 1323789Sahrens * Determine datasets which will be affected by this change, if any. 1324789Sahrens */ 1325789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 1326789Sahrens return (-1); 1327789Sahrens 1328789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 13292082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 13302082Seschrock "child dataset with inherited mountpoint is used " 13312082Seschrock "in a non-global zone")); 13322082Seschrock ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1333789Sahrens goto error; 1334789Sahrens } 1335789Sahrens 1336789Sahrens if ((ret = changelist_prefix(cl)) != 0) 1337789Sahrens goto error; 1338789Sahrens 13392082Seschrock if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, 13402082Seschrock ZFS_IOC_SET_PROP, &zc)) != 0) { 13412082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 1342789Sahrens } else { 1343789Sahrens 13442169Snd150628 if ((ret = changelist_postfix(cl)) != 0) 1345789Sahrens goto error; 1346789Sahrens 1347789Sahrens /* 1348789Sahrens * Refresh the statistics so the new property is reflected. 1349789Sahrens */ 1350789Sahrens (void) get_stats(zhp); 1351789Sahrens } 1352789Sahrens 1353789Sahrens error: 1354789Sahrens changelist_free(cl); 1355789Sahrens return (ret); 1356789Sahrens } 1357789Sahrens 13583912Slling void 1359789Sahrens nicebool(int value, char *buf, size_t buflen) 1360789Sahrens { 1361789Sahrens if (value) 1362789Sahrens (void) strlcpy(buf, "on", buflen); 1363789Sahrens else 1364789Sahrens (void) strlcpy(buf, "off", buflen); 1365789Sahrens } 1366789Sahrens 1367789Sahrens /* 13681356Seschrock * True DSL properties are stored in an nvlist. The following two functions 13691356Seschrock * extract them appropriately. 13701356Seschrock */ 13711356Seschrock static uint64_t 13721356Seschrock getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 13731356Seschrock { 13741356Seschrock nvlist_t *nv; 13751356Seschrock uint64_t value; 13761356Seschrock 13772885Sahrens *source = NULL; 13781356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 13791356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 13801356Seschrock verify(nvlist_lookup_uint64(nv, ZFS_PROP_VALUE, &value) == 0); 13812885Sahrens (void) nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source); 13821356Seschrock } else { 13831356Seschrock value = zfs_prop_default_numeric(prop); 13841356Seschrock *source = ""; 13851356Seschrock } 13861356Seschrock 13871356Seschrock return (value); 13881356Seschrock } 13891356Seschrock 13901356Seschrock static char * 13911356Seschrock getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 13921356Seschrock { 13931356Seschrock nvlist_t *nv; 13941356Seschrock char *value; 13951356Seschrock 13962885Sahrens *source = NULL; 13971356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 13981356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 13991356Seschrock verify(nvlist_lookup_string(nv, ZFS_PROP_VALUE, &value) == 0); 14002885Sahrens (void) nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source); 14011356Seschrock } else { 14021356Seschrock if ((value = (char *)zfs_prop_default_string(prop)) == NULL) 14031356Seschrock value = ""; 14041356Seschrock *source = ""; 14051356Seschrock } 14061356Seschrock 14071356Seschrock return (value); 14081356Seschrock } 14091356Seschrock 14101356Seschrock /* 1411789Sahrens * Internal function for getting a numeric property. Both zfs_prop_get() and 1412789Sahrens * zfs_prop_get_int() are built using this interface. 1413789Sahrens * 1414789Sahrens * Certain properties can be overridden using 'mount -o'. In this case, scan 1415789Sahrens * the contents of the /etc/mnttab entry, searching for the appropriate options. 1416789Sahrens * If they differ from the on-disk values, report the current values and mark 1417789Sahrens * the source "temporary". 1418789Sahrens */ 14192082Seschrock static int 1420789Sahrens get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zfs_source_t *src, 14212082Seschrock char **source, uint64_t *val) 1422789Sahrens { 1423789Sahrens struct mnttab mnt; 14243265Sahrens char *mntopt_on = NULL; 14253265Sahrens char *mntopt_off = NULL; 1426789Sahrens 1427789Sahrens *source = NULL; 1428789Sahrens 14293265Sahrens switch (prop) { 14303265Sahrens case ZFS_PROP_ATIME: 14313265Sahrens mntopt_on = MNTOPT_ATIME; 14323265Sahrens mntopt_off = MNTOPT_NOATIME; 14333265Sahrens break; 14343265Sahrens 14353265Sahrens case ZFS_PROP_DEVICES: 14363265Sahrens mntopt_on = MNTOPT_DEVICES; 14373265Sahrens mntopt_off = MNTOPT_NODEVICES; 14383265Sahrens break; 14393265Sahrens 14403265Sahrens case ZFS_PROP_EXEC: 14413265Sahrens mntopt_on = MNTOPT_EXEC; 14423265Sahrens mntopt_off = MNTOPT_NOEXEC; 14433265Sahrens break; 14443265Sahrens 14453265Sahrens case ZFS_PROP_READONLY: 14463265Sahrens mntopt_on = MNTOPT_RO; 14473265Sahrens mntopt_off = MNTOPT_RW; 14483265Sahrens break; 14493265Sahrens 14503265Sahrens case ZFS_PROP_SETUID: 14513265Sahrens mntopt_on = MNTOPT_SETUID; 14523265Sahrens mntopt_off = MNTOPT_NOSETUID; 14533265Sahrens break; 14543265Sahrens 14553265Sahrens case ZFS_PROP_XATTR: 14563265Sahrens mntopt_on = MNTOPT_XATTR; 14573265Sahrens mntopt_off = MNTOPT_NOXATTR; 14583265Sahrens break; 14593265Sahrens } 14603265Sahrens 14612474Seschrock /* 14622474Seschrock * Because looking up the mount options is potentially expensive 14632474Seschrock * (iterating over all of /etc/mnttab), we defer its calculation until 14642474Seschrock * we're looking up a property which requires its presence. 14652474Seschrock */ 14662474Seschrock if (!zhp->zfs_mntcheck && 14673265Sahrens (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { 14683265Sahrens struct mnttab entry, search = { 0 }; 14693265Sahrens FILE *mnttab = zhp->zfs_hdl->libzfs_mnttab; 14702474Seschrock 14712474Seschrock search.mnt_special = (char *)zhp->zfs_name; 14722474Seschrock search.mnt_fstype = MNTTYPE_ZFS; 14733265Sahrens rewind(mnttab); 14743265Sahrens 14753265Sahrens if (getmntany(mnttab, &entry, &search) == 0) { 14763265Sahrens zhp->zfs_mntopts = zfs_strdup(zhp->zfs_hdl, 14773265Sahrens entry.mnt_mntopts); 14783265Sahrens if (zhp->zfs_mntopts == NULL) 14793265Sahrens return (-1); 14803265Sahrens } 14812474Seschrock 14822474Seschrock zhp->zfs_mntcheck = B_TRUE; 14832474Seschrock } 14842474Seschrock 1485789Sahrens if (zhp->zfs_mntopts == NULL) 1486789Sahrens mnt.mnt_mntopts = ""; 1487789Sahrens else 1488789Sahrens mnt.mnt_mntopts = zhp->zfs_mntopts; 1489789Sahrens 1490789Sahrens switch (prop) { 1491789Sahrens case ZFS_PROP_ATIME: 14923265Sahrens case ZFS_PROP_DEVICES: 14933265Sahrens case ZFS_PROP_EXEC: 14943265Sahrens case ZFS_PROP_READONLY: 14953265Sahrens case ZFS_PROP_SETUID: 14963265Sahrens case ZFS_PROP_XATTR: 14972082Seschrock *val = getprop_uint64(zhp, prop, source); 14982082Seschrock 14993265Sahrens if (hasmntopt(&mnt, mntopt_on) && !*val) { 15002082Seschrock *val = B_TRUE; 1501789Sahrens if (src) 1502789Sahrens *src = ZFS_SRC_TEMPORARY; 15033265Sahrens } else if (hasmntopt(&mnt, mntopt_off) && *val) { 15042082Seschrock *val = B_FALSE; 1505789Sahrens if (src) 1506789Sahrens *src = ZFS_SRC_TEMPORARY; 1507789Sahrens } 15082082Seschrock break; 1509789Sahrens 1510789Sahrens case ZFS_PROP_RECORDSIZE: 1511789Sahrens case ZFS_PROP_COMPRESSION: 15121356Seschrock case ZFS_PROP_ZONED: 15132885Sahrens case ZFS_PROP_CREATION: 15142885Sahrens case ZFS_PROP_COMPRESSRATIO: 15152885Sahrens case ZFS_PROP_REFERENCED: 15162885Sahrens case ZFS_PROP_USED: 15172885Sahrens case ZFS_PROP_CREATETXG: 15182885Sahrens case ZFS_PROP_AVAILABLE: 15192885Sahrens case ZFS_PROP_VOLSIZE: 15202885Sahrens case ZFS_PROP_VOLBLOCKSIZE: 15213417Srm160521 *val = getprop_uint64(zhp, prop, source); 15223417Srm160521 break; 15233417Srm160521 15243265Sahrens case ZFS_PROP_CANMOUNT: 15252082Seschrock *val = getprop_uint64(zhp, prop, source); 15263417Srm160521 if (*val == 0) 15273417Srm160521 *source = zhp->zfs_name; 15283417Srm160521 else 15293417Srm160521 *source = ""; /* default */ 15302082Seschrock break; 1531789Sahrens 1532789Sahrens case ZFS_PROP_QUOTA: 1533789Sahrens case ZFS_PROP_RESERVATION: 15342885Sahrens *val = getprop_uint64(zhp, prop, source); 15352885Sahrens if (*val == 0) 1536789Sahrens *source = ""; /* default */ 1537789Sahrens else 1538789Sahrens *source = zhp->zfs_name; 15392082Seschrock break; 1540789Sahrens 1541789Sahrens case ZFS_PROP_MOUNTED: 15422082Seschrock *val = (zhp->zfs_mntopts != NULL); 15432082Seschrock break; 1544789Sahrens 15453377Seschrock case ZFS_PROP_NUMCLONES: 15463377Seschrock *val = zhp->zfs_dmustats.dds_num_clones; 15473377Seschrock break; 15483377Seschrock 1549789Sahrens default: 15502082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 15512082Seschrock "cannot get non-numeric property")); 15522082Seschrock return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP, 15532082Seschrock dgettext(TEXT_DOMAIN, "internal error"))); 1554789Sahrens } 1555789Sahrens 1556789Sahrens return (0); 1557789Sahrens } 1558789Sahrens 1559789Sahrens /* 1560789Sahrens * Calculate the source type, given the raw source string. 1561789Sahrens */ 1562789Sahrens static void 1563789Sahrens get_source(zfs_handle_t *zhp, zfs_source_t *srctype, char *source, 1564789Sahrens char *statbuf, size_t statlen) 1565789Sahrens { 1566789Sahrens if (statbuf == NULL || *srctype == ZFS_SRC_TEMPORARY) 1567789Sahrens return; 1568789Sahrens 1569789Sahrens if (source == NULL) { 1570789Sahrens *srctype = ZFS_SRC_NONE; 1571789Sahrens } else if (source[0] == '\0') { 1572789Sahrens *srctype = ZFS_SRC_DEFAULT; 1573789Sahrens } else { 1574789Sahrens if (strcmp(source, zhp->zfs_name) == 0) { 1575789Sahrens *srctype = ZFS_SRC_LOCAL; 1576789Sahrens } else { 1577789Sahrens (void) strlcpy(statbuf, source, statlen); 1578789Sahrens *srctype = ZFS_SRC_INHERITED; 1579789Sahrens } 1580789Sahrens } 1581789Sahrens 1582789Sahrens } 1583789Sahrens 1584789Sahrens /* 1585789Sahrens * Retrieve a property from the given object. If 'literal' is specified, then 1586789Sahrens * numbers are left as exact values. Otherwise, numbers are converted to a 1587789Sahrens * human-readable form. 1588789Sahrens * 1589789Sahrens * Returns 0 on success, or -1 on error. 1590789Sahrens */ 1591789Sahrens int 1592789Sahrens zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, 15932082Seschrock zfs_source_t *src, char *statbuf, size_t statlen, boolean_t literal) 1594789Sahrens { 1595789Sahrens char *source = NULL; 1596789Sahrens uint64_t val; 1597789Sahrens char *str; 1598789Sahrens const char *root; 15992676Seschrock const char *strval; 1600789Sahrens 1601789Sahrens /* 1602789Sahrens * Check to see if this property applies to our object 1603789Sahrens */ 1604789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1605789Sahrens return (-1); 1606789Sahrens 1607789Sahrens if (src) 1608789Sahrens *src = ZFS_SRC_NONE; 1609789Sahrens 1610789Sahrens switch (prop) { 1611789Sahrens case ZFS_PROP_ATIME: 1612789Sahrens case ZFS_PROP_READONLY: 1613789Sahrens case ZFS_PROP_SETUID: 1614789Sahrens case ZFS_PROP_ZONED: 1615789Sahrens case ZFS_PROP_DEVICES: 1616789Sahrens case ZFS_PROP_EXEC: 16172676Seschrock case ZFS_PROP_CANMOUNT: 16183234Sck153898 case ZFS_PROP_XATTR: 1619789Sahrens /* 1620789Sahrens * Basic boolean values are built on top of 1621789Sahrens * get_numeric_property(). 1622789Sahrens */ 16232082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 16242082Seschrock return (-1); 16252082Seschrock nicebool(val, propbuf, proplen); 1626789Sahrens 1627789Sahrens break; 1628789Sahrens 1629789Sahrens case ZFS_PROP_AVAILABLE: 1630789Sahrens case ZFS_PROP_RECORDSIZE: 1631789Sahrens case ZFS_PROP_CREATETXG: 1632789Sahrens case ZFS_PROP_REFERENCED: 1633789Sahrens case ZFS_PROP_USED: 1634789Sahrens case ZFS_PROP_VOLSIZE: 1635789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 16363377Seschrock case ZFS_PROP_NUMCLONES: 1637789Sahrens /* 1638789Sahrens * Basic numeric values are built on top of 1639789Sahrens * get_numeric_property(). 1640789Sahrens */ 16412082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 16422082Seschrock return (-1); 1643789Sahrens if (literal) 16442856Snd150628 (void) snprintf(propbuf, proplen, "%llu", 16453912Slling (u_longlong_t)val); 1646789Sahrens else 1647789Sahrens zfs_nicenum(val, propbuf, proplen); 1648789Sahrens break; 1649789Sahrens 1650789Sahrens case ZFS_PROP_COMPRESSION: 1651789Sahrens case ZFS_PROP_CHECKSUM: 1652789Sahrens case ZFS_PROP_SNAPDIR: 1653789Sahrens case ZFS_PROP_ACLMODE: 1654789Sahrens case ZFS_PROP_ACLINHERIT: 16553835Sahrens case ZFS_PROP_COPIES: 16561356Seschrock val = getprop_uint64(zhp, prop, &source); 16572676Seschrock verify(zfs_prop_index_to_string(prop, val, &strval) == 0); 16582676Seschrock (void) strlcpy(propbuf, strval, proplen); 1659789Sahrens break; 1660789Sahrens 1661789Sahrens case ZFS_PROP_CREATION: 1662789Sahrens /* 1663789Sahrens * 'creation' is a time_t stored in the statistics. We convert 1664789Sahrens * this into a string unless 'literal' is specified. 1665789Sahrens */ 1666789Sahrens { 16672885Sahrens val = getprop_uint64(zhp, prop, &source); 16682885Sahrens time_t time = (time_t)val; 1669789Sahrens struct tm t; 1670789Sahrens 1671789Sahrens if (literal || 1672789Sahrens localtime_r(&time, &t) == NULL || 1673789Sahrens strftime(propbuf, proplen, "%a %b %e %k:%M %Y", 1674789Sahrens &t) == 0) 16752885Sahrens (void) snprintf(propbuf, proplen, "%llu", val); 1676789Sahrens } 1677789Sahrens break; 1678789Sahrens 1679789Sahrens case ZFS_PROP_MOUNTPOINT: 1680789Sahrens /* 1681789Sahrens * Getting the precise mountpoint can be tricky. 1682789Sahrens * 1683789Sahrens * - for 'none' or 'legacy', return those values. 1684789Sahrens * - for default mountpoints, construct it as /zfs/<dataset> 1685789Sahrens * - for inherited mountpoints, we want to take everything 1686789Sahrens * after our ancestor and append it to the inherited value. 1687789Sahrens * 1688789Sahrens * If the pool has an alternate root, we want to prepend that 1689789Sahrens * root to any values we return. 1690789Sahrens */ 16911544Seschrock root = zhp->zfs_root; 16921356Seschrock str = getprop_string(zhp, prop, &source); 16931356Seschrock 16941356Seschrock if (str[0] == '\0') { 1695789Sahrens (void) snprintf(propbuf, proplen, "%s/zfs/%s", 1696789Sahrens root, zhp->zfs_name); 16971356Seschrock } else if (str[0] == '/') { 16981356Seschrock const char *relpath = zhp->zfs_name + strlen(source); 1699789Sahrens 1700789Sahrens if (relpath[0] == '/') 1701789Sahrens relpath++; 17021356Seschrock if (str[1] == '\0') 17031356Seschrock str++; 1704789Sahrens 1705789Sahrens if (relpath[0] == '\0') 1706789Sahrens (void) snprintf(propbuf, proplen, "%s%s", 17071356Seschrock root, str); 1708789Sahrens else 1709789Sahrens (void) snprintf(propbuf, proplen, "%s%s%s%s", 17101356Seschrock root, str, relpath[0] == '@' ? "" : "/", 1711789Sahrens relpath); 1712789Sahrens } else { 1713789Sahrens /* 'legacy' or 'none' */ 17141356Seschrock (void) strlcpy(propbuf, str, proplen); 1715789Sahrens } 1716789Sahrens 1717789Sahrens break; 1718789Sahrens 1719789Sahrens case ZFS_PROP_SHARENFS: 17203126Sahl case ZFS_PROP_SHAREISCSI: 17213126Sahl case ZFS_PROP_ISCSIOPTIONS: 17221356Seschrock (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 17231356Seschrock proplen); 1724789Sahrens break; 1725789Sahrens 1726789Sahrens case ZFS_PROP_ORIGIN: 17272885Sahrens (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 1728789Sahrens proplen); 1729789Sahrens /* 1730789Sahrens * If there is no parent at all, return failure to indicate that 1731789Sahrens * it doesn't apply to this dataset. 1732789Sahrens */ 1733789Sahrens if (propbuf[0] == '\0') 1734789Sahrens return (-1); 1735789Sahrens break; 1736789Sahrens 1737789Sahrens case ZFS_PROP_QUOTA: 1738789Sahrens case ZFS_PROP_RESERVATION: 17392082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 17402082Seschrock return (-1); 1741789Sahrens 1742789Sahrens /* 1743789Sahrens * If quota or reservation is 0, we translate this into 'none' 1744789Sahrens * (unless literal is set), and indicate that it's the default 1745789Sahrens * value. Otherwise, we print the number nicely and indicate 1746789Sahrens * that its set locally. 1747789Sahrens */ 1748789Sahrens if (val == 0) { 1749789Sahrens if (literal) 1750789Sahrens (void) strlcpy(propbuf, "0", proplen); 1751789Sahrens else 1752789Sahrens (void) strlcpy(propbuf, "none", proplen); 1753789Sahrens } else { 1754789Sahrens if (literal) 17552856Snd150628 (void) snprintf(propbuf, proplen, "%llu", 17563912Slling (u_longlong_t)val); 1757789Sahrens else 1758789Sahrens zfs_nicenum(val, propbuf, proplen); 1759789Sahrens } 1760789Sahrens break; 1761789Sahrens 1762789Sahrens case ZFS_PROP_COMPRESSRATIO: 17632082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 17642082Seschrock return (-1); 17652856Snd150628 (void) snprintf(propbuf, proplen, "%lld.%02lldx", (longlong_t) 17662856Snd150628 val / 100, (longlong_t)val % 100); 1767789Sahrens break; 1768789Sahrens 1769789Sahrens case ZFS_PROP_TYPE: 1770789Sahrens switch (zhp->zfs_type) { 1771789Sahrens case ZFS_TYPE_FILESYSTEM: 1772789Sahrens str = "filesystem"; 1773789Sahrens break; 1774789Sahrens case ZFS_TYPE_VOLUME: 1775789Sahrens str = "volume"; 1776789Sahrens break; 1777789Sahrens case ZFS_TYPE_SNAPSHOT: 1778789Sahrens str = "snapshot"; 1779789Sahrens break; 1780789Sahrens default: 17812082Seschrock abort(); 1782789Sahrens } 1783789Sahrens (void) snprintf(propbuf, proplen, "%s", str); 1784789Sahrens break; 1785789Sahrens 1786789Sahrens case ZFS_PROP_MOUNTED: 1787789Sahrens /* 1788789Sahrens * The 'mounted' property is a pseudo-property that described 1789789Sahrens * whether the filesystem is currently mounted. Even though 1790789Sahrens * it's a boolean value, the typical values of "on" and "off" 1791789Sahrens * don't make sense, so we translate to "yes" and "no". 1792789Sahrens */ 17932082Seschrock if (get_numeric_property(zhp, ZFS_PROP_MOUNTED, 17942082Seschrock src, &source, &val) != 0) 17952082Seschrock return (-1); 17962082Seschrock if (val) 1797789Sahrens (void) strlcpy(propbuf, "yes", proplen); 1798789Sahrens else 1799789Sahrens (void) strlcpy(propbuf, "no", proplen); 1800789Sahrens break; 1801789Sahrens 1802789Sahrens case ZFS_PROP_NAME: 1803789Sahrens /* 1804789Sahrens * The 'name' property is a pseudo-property derived from the 1805789Sahrens * dataset name. It is presented as a real property to simplify 1806789Sahrens * consumers. 1807789Sahrens */ 1808789Sahrens (void) strlcpy(propbuf, zhp->zfs_name, proplen); 1809789Sahrens break; 1810789Sahrens 1811789Sahrens default: 18122082Seschrock abort(); 1813789Sahrens } 1814789Sahrens 1815789Sahrens get_source(zhp, src, source, statbuf, statlen); 1816789Sahrens 1817789Sahrens return (0); 1818789Sahrens } 1819789Sahrens 1820789Sahrens /* 1821789Sahrens * Utility function to get the given numeric property. Does no validation that 1822789Sahrens * the given property is the appropriate type; should only be used with 1823789Sahrens * hard-coded property types. 1824789Sahrens */ 1825789Sahrens uint64_t 1826789Sahrens zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop) 1827789Sahrens { 1828789Sahrens char *source; 1829789Sahrens zfs_source_t sourcetype = ZFS_SRC_NONE; 18302082Seschrock uint64_t val; 18312082Seschrock 18322082Seschrock (void) get_numeric_property(zhp, prop, &sourcetype, &source, &val); 18332082Seschrock 18342082Seschrock return (val); 1835789Sahrens } 1836789Sahrens 1837789Sahrens /* 1838789Sahrens * Similar to zfs_prop_get(), but returns the value as an integer. 1839789Sahrens */ 1840789Sahrens int 1841789Sahrens zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, 1842789Sahrens zfs_source_t *src, char *statbuf, size_t statlen) 1843789Sahrens { 1844789Sahrens char *source; 1845789Sahrens 1846789Sahrens /* 1847789Sahrens * Check to see if this property applies to our object 1848789Sahrens */ 1849789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 18503237Slling return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE, 18512082Seschrock dgettext(TEXT_DOMAIN, "cannot get property '%s'"), 18522082Seschrock zfs_prop_to_name(prop))); 1853789Sahrens 1854789Sahrens if (src) 1855789Sahrens *src = ZFS_SRC_NONE; 1856789Sahrens 18572082Seschrock if (get_numeric_property(zhp, prop, src, &source, value) != 0) 18582082Seschrock return (-1); 1859789Sahrens 1860789Sahrens get_source(zhp, src, source, statbuf, statlen); 1861789Sahrens 1862789Sahrens return (0); 1863789Sahrens } 1864789Sahrens 1865789Sahrens /* 1866789Sahrens * Returns the name of the given zfs handle. 1867789Sahrens */ 1868789Sahrens const char * 1869789Sahrens zfs_get_name(const zfs_handle_t *zhp) 1870789Sahrens { 1871789Sahrens return (zhp->zfs_name); 1872789Sahrens } 1873789Sahrens 1874789Sahrens /* 1875789Sahrens * Returns the type of the given zfs handle. 1876789Sahrens */ 1877789Sahrens zfs_type_t 1878789Sahrens zfs_get_type(const zfs_handle_t *zhp) 1879789Sahrens { 1880789Sahrens return (zhp->zfs_type); 1881789Sahrens } 1882789Sahrens 1883789Sahrens /* 18841356Seschrock * Iterate over all child filesystems 1885789Sahrens */ 1886789Sahrens int 18871356Seschrock zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) 1888789Sahrens { 1889789Sahrens zfs_cmd_t zc = { 0 }; 1890789Sahrens zfs_handle_t *nzhp; 1891789Sahrens int ret; 1892789Sahrens 1893789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 18942082Seschrock ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; 1895789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1896789Sahrens /* 1897789Sahrens * Ignore private dataset names. 1898789Sahrens */ 1899789Sahrens if (dataset_name_hidden(zc.zc_name)) 1900789Sahrens continue; 1901789Sahrens 1902789Sahrens /* 1903789Sahrens * Silently ignore errors, as the only plausible explanation is 1904789Sahrens * that the pool has since been removed. 1905789Sahrens */ 19062082Seschrock if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 19072082Seschrock zc.zc_name)) == NULL) 1908789Sahrens continue; 1909789Sahrens 1910789Sahrens if ((ret = func(nzhp, data)) != 0) 1911789Sahrens return (ret); 1912789Sahrens } 1913789Sahrens 1914789Sahrens /* 1915789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1916789Sahrens * returned, then the underlying dataset has been removed since we 1917789Sahrens * obtained the handle. 1918789Sahrens */ 1919789Sahrens if (errno != ESRCH && errno != ENOENT) 19202082Seschrock return (zfs_standard_error(zhp->zfs_hdl, errno, 19212082Seschrock dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 1922789Sahrens 19231356Seschrock return (0); 19241356Seschrock } 19251356Seschrock 19261356Seschrock /* 19271356Seschrock * Iterate over all snapshots 19281356Seschrock */ 19291356Seschrock int 19301356Seschrock zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) 19311356Seschrock { 19321356Seschrock zfs_cmd_t zc = { 0 }; 19331356Seschrock zfs_handle_t *nzhp; 19341356Seschrock int ret; 1935789Sahrens 1936789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 19372082Seschrock ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, 19382082Seschrock &zc) == 0; 1939789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1940789Sahrens 19412082Seschrock if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 19422082Seschrock zc.zc_name)) == NULL) 1943789Sahrens continue; 1944789Sahrens 1945789Sahrens if ((ret = func(nzhp, data)) != 0) 1946789Sahrens return (ret); 1947789Sahrens } 1948789Sahrens 1949789Sahrens /* 1950789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1951789Sahrens * returned, then the underlying dataset has been removed since we 1952789Sahrens * obtained the handle. Silently ignore this case, and return success. 1953789Sahrens */ 1954789Sahrens if (errno != ESRCH && errno != ENOENT) 19552082Seschrock return (zfs_standard_error(zhp->zfs_hdl, errno, 19562082Seschrock dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 1957789Sahrens 1958789Sahrens return (0); 1959789Sahrens } 1960789Sahrens 1961789Sahrens /* 19621356Seschrock * Iterate over all children, snapshots and filesystems 19631356Seschrock */ 19641356Seschrock int 19651356Seschrock zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 19661356Seschrock { 19671356Seschrock int ret; 19681356Seschrock 19691356Seschrock if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0) 19701356Seschrock return (ret); 19711356Seschrock 19721356Seschrock return (zfs_iter_snapshots(zhp, func, data)); 19731356Seschrock } 19741356Seschrock 19751356Seschrock /* 1976789Sahrens * Given a complete name, return just the portion that refers to the parent. 1977789Sahrens * Can return NULL if this is a pool. 1978789Sahrens */ 1979789Sahrens static int 1980789Sahrens parent_name(const char *path, char *buf, size_t buflen) 1981789Sahrens { 1982789Sahrens char *loc; 1983789Sahrens 1984789Sahrens if ((loc = strrchr(path, '/')) == NULL) 1985789Sahrens return (-1); 1986789Sahrens 1987789Sahrens (void) strncpy(buf, path, MIN(buflen, loc - path)); 1988789Sahrens buf[loc - path] = '\0'; 1989789Sahrens 1990789Sahrens return (0); 1991789Sahrens } 1992789Sahrens 1993789Sahrens /* 1994*4490Svb160487 * If accept_ancestor is false, then check to make sure that the given path has 1995*4490Svb160487 * a parent, and that it exists. If accept_ancestor is true, then find the 1996*4490Svb160487 * closest existing ancestor for the given path. In prefixlen return the 1997*4490Svb160487 * length of already existing prefix of the given path. We also fetch the 1998*4490Svb160487 * 'zoned' property, which is used to validate property settings when creating 1999*4490Svb160487 * new datasets. 2000789Sahrens */ 2001789Sahrens static int 2002*4490Svb160487 check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned, 2003*4490Svb160487 boolean_t accept_ancestor, int *prefixlen) 2004789Sahrens { 2005789Sahrens zfs_cmd_t zc = { 0 }; 2006789Sahrens char parent[ZFS_MAXNAMELEN]; 2007789Sahrens char *slash; 20081356Seschrock zfs_handle_t *zhp; 20092082Seschrock char errbuf[1024]; 20102082Seschrock 20112082Seschrock (void) snprintf(errbuf, sizeof (errbuf), "cannot create '%s'", 20122082Seschrock path); 2013789Sahrens 2014789Sahrens /* get parent, and check to see if this is just a pool */ 2015789Sahrens if (parent_name(path, parent, sizeof (parent)) != 0) { 20162082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20172082Seschrock "missing dataset name")); 20182082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2019789Sahrens } 2020789Sahrens 2021789Sahrens /* check to see if the pool exists */ 2022789Sahrens if ((slash = strchr(parent, '/')) == NULL) 2023789Sahrens slash = parent + strlen(parent); 2024789Sahrens (void) strncpy(zc.zc_name, parent, slash - parent); 2025789Sahrens zc.zc_name[slash - parent] = '\0'; 20262082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 && 2027789Sahrens errno == ENOENT) { 20282082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20292082Seschrock "no such pool '%s'"), zc.zc_name); 20302082Seschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2031789Sahrens } 2032789Sahrens 2033789Sahrens /* check to see if the parent dataset exists */ 2034*4490Svb160487 while ((zhp = make_dataset_handle(hdl, parent)) == NULL) { 2035*4490Svb160487 if (errno == ENOENT && accept_ancestor) { 2036*4490Svb160487 /* 2037*4490Svb160487 * Go deeper to find an ancestor, give up on top level. 2038*4490Svb160487 */ 2039*4490Svb160487 if (parent_name(parent, parent, sizeof (parent)) != 0) { 2040*4490Svb160487 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2041*4490Svb160487 "no such pool '%s'"), zc.zc_name); 2042*4490Svb160487 return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2043*4490Svb160487 } 2044*4490Svb160487 } else if (errno == ENOENT) { 20452082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20462082Seschrock "parent does not exist")); 20472082Seschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2048*4490Svb160487 } else 20492082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 2050789Sahrens } 2051789Sahrens 20522676Seschrock *zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); 2053789Sahrens /* we are in a non-global zone, but parent is in the global zone */ 20542676Seschrock if (getzoneid() != GLOBAL_ZONEID && !(*zoned)) { 20552082Seschrock (void) zfs_standard_error(hdl, EPERM, errbuf); 20561356Seschrock zfs_close(zhp); 2057789Sahrens return (-1); 2058789Sahrens } 2059789Sahrens 2060789Sahrens /* make sure parent is a filesystem */ 20611356Seschrock if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 20622082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20632082Seschrock "parent is not a filesystem")); 20642082Seschrock (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 20651356Seschrock zfs_close(zhp); 2066789Sahrens return (-1); 2067789Sahrens } 2068789Sahrens 20691356Seschrock zfs_close(zhp); 2070*4490Svb160487 if (prefixlen != NULL) 2071*4490Svb160487 *prefixlen = strlen(parent); 2072*4490Svb160487 return (0); 2073*4490Svb160487 } 2074*4490Svb160487 2075*4490Svb160487 /* 2076*4490Svb160487 * Finds whether the dataset of the given type(s) exists. 2077*4490Svb160487 */ 2078*4490Svb160487 boolean_t 2079*4490Svb160487 zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types) 2080*4490Svb160487 { 2081*4490Svb160487 zfs_handle_t *zhp; 2082*4490Svb160487 2083*4490Svb160487 if (!zfs_validate_name(hdl, path, types)) 2084*4490Svb160487 return (B_FALSE); 2085*4490Svb160487 2086*4490Svb160487 /* 2087*4490Svb160487 * Try to get stats for the dataset, which will tell us if it exists. 2088*4490Svb160487 */ 2089*4490Svb160487 if ((zhp = make_dataset_handle(hdl, path)) != NULL) { 2090*4490Svb160487 int ds_type = zhp->zfs_type; 2091*4490Svb160487 2092*4490Svb160487 zfs_close(zhp); 2093*4490Svb160487 if (types & ds_type) 2094*4490Svb160487 return (B_TRUE); 2095*4490Svb160487 } 2096*4490Svb160487 return (B_FALSE); 2097*4490Svb160487 } 2098*4490Svb160487 2099*4490Svb160487 /* 2100*4490Svb160487 * Creates non-existing ancestors of the given path. 2101*4490Svb160487 */ 2102*4490Svb160487 int 2103*4490Svb160487 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path) 2104*4490Svb160487 { 2105*4490Svb160487 int prefix; 2106*4490Svb160487 uint64_t zoned; 2107*4490Svb160487 char *path_copy; 2108*4490Svb160487 int rc; 2109*4490Svb160487 2110*4490Svb160487 if (check_parents(hdl, path, &zoned, B_TRUE, &prefix) != 0) 2111*4490Svb160487 return (-1); 2112*4490Svb160487 2113*4490Svb160487 if ((path_copy = strdup(path)) != NULL) { 2114*4490Svb160487 rc = create_parents(hdl, path_copy, prefix); 2115*4490Svb160487 free(path_copy); 2116*4490Svb160487 } 2117*4490Svb160487 if (path_copy == NULL || rc != 0) 2118*4490Svb160487 return (-1); 2119*4490Svb160487 2120789Sahrens return (0); 2121789Sahrens } 2122789Sahrens 2123789Sahrens /* 21242676Seschrock * Create a new filesystem or volume. 2125789Sahrens */ 2126789Sahrens int 21272082Seschrock zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type, 21282676Seschrock nvlist_t *props) 2129789Sahrens { 2130789Sahrens zfs_cmd_t zc = { 0 }; 2131789Sahrens int ret; 2132789Sahrens uint64_t size = 0; 2133789Sahrens uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE); 21342082Seschrock char errbuf[1024]; 21352676Seschrock uint64_t zoned; 21362082Seschrock 21372082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 21382082Seschrock "cannot create '%s'"), path); 2139789Sahrens 2140789Sahrens /* validate the path, taking care to note the extended error message */ 21412082Seschrock if (!zfs_validate_name(hdl, path, type)) 21422082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2143789Sahrens 2144789Sahrens /* validate parents exist */ 2145*4490Svb160487 if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0) 2146789Sahrens return (-1); 2147789Sahrens 2148789Sahrens /* 2149789Sahrens * The failure modes when creating a dataset of a different type over 2150789Sahrens * one that already exists is a little strange. In particular, if you 2151789Sahrens * try to create a dataset on top of an existing dataset, the ioctl() 2152789Sahrens * will return ENOENT, not EEXIST. To prevent this from happening, we 2153789Sahrens * first try to see if the dataset exists. 2154789Sahrens */ 2155789Sahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 2156*4490Svb160487 if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_ANY)) { 21572082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21582082Seschrock "dataset already exists")); 21592082Seschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2160789Sahrens } 2161789Sahrens 2162789Sahrens if (type == ZFS_TYPE_VOLUME) 2163789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2164789Sahrens else 2165789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2166789Sahrens 21673912Slling if (props && (props = zfs_validate_properties(hdl, type, NULL, props, 21683912Slling zoned, NULL, errbuf)) == 0) 21692676Seschrock return (-1); 21702676Seschrock 2171789Sahrens if (type == ZFS_TYPE_VOLUME) { 21721133Seschrock /* 21731133Seschrock * If we are creating a volume, the size and block size must 21741133Seschrock * satisfy a few restraints. First, the blocksize must be a 21751133Seschrock * valid block size between SPA_{MIN,MAX}BLOCKSIZE. Second, the 21761133Seschrock * volsize must be a multiple of the block size, and cannot be 21771133Seschrock * zero. 21781133Seschrock */ 21792676Seschrock if (props == NULL || nvlist_lookup_uint64(props, 21802676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) { 21812676Seschrock nvlist_free(props); 21822082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21832676Seschrock "missing volume size")); 21842676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2185789Sahrens } 2186789Sahrens 21872676Seschrock if ((ret = nvlist_lookup_uint64(props, 21882676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 21892676Seschrock &blocksize)) != 0) { 21902676Seschrock if (ret == ENOENT) { 21912676Seschrock blocksize = zfs_prop_default_numeric( 21922676Seschrock ZFS_PROP_VOLBLOCKSIZE); 21932676Seschrock } else { 21942676Seschrock nvlist_free(props); 21952676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21962676Seschrock "missing volume block size")); 21972676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 21982676Seschrock } 21992676Seschrock } 22002676Seschrock 22012676Seschrock if (size == 0) { 22022676Seschrock nvlist_free(props); 22032082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 22042676Seschrock "volume size cannot be zero")); 22052676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 22061133Seschrock } 22071133Seschrock 22081133Seschrock if (size % blocksize != 0) { 22092676Seschrock nvlist_free(props); 22102082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 22112676Seschrock "volume size must be a multiple of volume block " 22122676Seschrock "size")); 22132676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 22141133Seschrock } 2215789Sahrens } 2216789Sahrens 22172676Seschrock if (props && 22182676Seschrock zcmd_write_src_nvlist(hdl, &zc, props, NULL) != 0) 22192676Seschrock return (-1); 22202676Seschrock nvlist_free(props); 22212676Seschrock 2222789Sahrens /* create the dataset */ 22232082Seschrock ret = ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE, &zc); 2224789Sahrens 22253912Slling if (ret == 0 && type == ZFS_TYPE_VOLUME) { 22262082Seschrock ret = zvol_create_link(hdl, path); 22273912Slling if (ret) { 22283912Slling (void) zfs_standard_error(hdl, errno, 22293912Slling dgettext(TEXT_DOMAIN, 22303912Slling "Volume successfully created, but device links " 22313912Slling "were not created")); 22323912Slling zcmd_free_nvlists(&zc); 22333912Slling return (-1); 22343912Slling } 22353912Slling } 2236789Sahrens 22372676Seschrock zcmd_free_nvlists(&zc); 22382676Seschrock 2239789Sahrens /* check for failure */ 2240789Sahrens if (ret != 0) { 2241789Sahrens char parent[ZFS_MAXNAMELEN]; 2242789Sahrens (void) parent_name(path, parent, sizeof (parent)); 2243789Sahrens 2244789Sahrens switch (errno) { 2245789Sahrens case ENOENT: 22462082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 22472082Seschrock "no such parent '%s'"), parent); 22482082Seschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2249789Sahrens 2250789Sahrens case EINVAL: 22512082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 22523413Smmusante "parent '%s' is not a filesystem"), parent); 22532082Seschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 2254789Sahrens 2255789Sahrens case EDOM: 22562082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 22572676Seschrock "volume block size must be power of 2 from " 22582676Seschrock "%u to %uk"), 2259789Sahrens (uint_t)SPA_MINBLOCKSIZE, 2260789Sahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 22612082Seschrock 22622676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 22632082Seschrock 2264789Sahrens #ifdef _ILP32 2265789Sahrens case EOVERFLOW: 2266789Sahrens /* 2267789Sahrens * This platform can't address a volume this big. 2268789Sahrens */ 22692082Seschrock if (type == ZFS_TYPE_VOLUME) 22702082Seschrock return (zfs_error(hdl, EZFS_VOLTOOBIG, 22712082Seschrock errbuf)); 2272789Sahrens #endif 22732082Seschrock /* FALLTHROUGH */ 2274789Sahrens default: 22752082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 2276789Sahrens } 2277789Sahrens } 2278789Sahrens 2279789Sahrens return (0); 2280789Sahrens } 2281789Sahrens 2282789Sahrens /* 2283789Sahrens * Destroys the given dataset. The caller must make sure that the filesystem 2284789Sahrens * isn't mounted, and that there are no active dependents. 2285789Sahrens */ 2286789Sahrens int 2287789Sahrens zfs_destroy(zfs_handle_t *zhp) 2288789Sahrens { 2289789Sahrens zfs_cmd_t zc = { 0 }; 2290789Sahrens 2291789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2292789Sahrens 22932676Seschrock if (ZFS_IS_VOLUME(zhp)) { 22943126Sahl /* 22953126Sahl * Unconditionally unshare this zvol ignoring failure as it 22963126Sahl * indicates only that the volume wasn't shared initially. 22973126Sahl */ 22983126Sahl (void) zfs_unshare_iscsi(zhp); 22993126Sahl 23002082Seschrock if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0) 2301789Sahrens return (-1); 2302789Sahrens 2303789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2304789Sahrens } else { 2305789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2306789Sahrens } 2307789Sahrens 23083126Sahl if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) != 0) { 23093237Slling return (zfs_standard_error_fmt(zhp->zfs_hdl, errno, 23102082Seschrock dgettext(TEXT_DOMAIN, "cannot destroy '%s'"), 23112082Seschrock zhp->zfs_name)); 23122199Sahrens } 2313789Sahrens 2314789Sahrens remove_mountpoint(zhp); 2315789Sahrens 2316789Sahrens return (0); 2317789Sahrens } 2318789Sahrens 23192199Sahrens struct destroydata { 23202199Sahrens char *snapname; 23212199Sahrens boolean_t gotone; 23223265Sahrens boolean_t closezhp; 23232199Sahrens }; 23242199Sahrens 23252199Sahrens static int 23262199Sahrens zfs_remove_link_cb(zfs_handle_t *zhp, void *arg) 23272199Sahrens { 23282199Sahrens struct destroydata *dd = arg; 23292199Sahrens zfs_handle_t *szhp; 23302199Sahrens char name[ZFS_MAXNAMELEN]; 23313265Sahrens boolean_t closezhp = dd->closezhp; 23323265Sahrens int rv; 23332199Sahrens 23342676Seschrock (void) strlcpy(name, zhp->zfs_name, sizeof (name)); 23352676Seschrock (void) strlcat(name, "@", sizeof (name)); 23362676Seschrock (void) strlcat(name, dd->snapname, sizeof (name)); 23372199Sahrens 23382199Sahrens szhp = make_dataset_handle(zhp->zfs_hdl, name); 23392199Sahrens if (szhp) { 23402199Sahrens dd->gotone = B_TRUE; 23412199Sahrens zfs_close(szhp); 23422199Sahrens } 23432199Sahrens 23442199Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 23452199Sahrens (void) zvol_remove_link(zhp->zfs_hdl, name); 23462199Sahrens /* 23472199Sahrens * NB: this is simply a best-effort. We don't want to 23482199Sahrens * return an error, because then we wouldn't visit all 23492199Sahrens * the volumes. 23502199Sahrens */ 23512199Sahrens } 23522199Sahrens 23533265Sahrens dd->closezhp = B_TRUE; 23543265Sahrens rv = zfs_iter_filesystems(zhp, zfs_remove_link_cb, arg); 23553265Sahrens if (closezhp) 23563265Sahrens zfs_close(zhp); 23573265Sahrens return (rv); 23582199Sahrens } 23592199Sahrens 23602199Sahrens /* 23612199Sahrens * Destroys all snapshots with the given name in zhp & descendants. 23622199Sahrens */ 23632199Sahrens int 23642199Sahrens zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname) 23652199Sahrens { 23662199Sahrens zfs_cmd_t zc = { 0 }; 23672199Sahrens int ret; 23682199Sahrens struct destroydata dd = { 0 }; 23692199Sahrens 23702199Sahrens dd.snapname = snapname; 23712199Sahrens (void) zfs_remove_link_cb(zhp, &dd); 23722199Sahrens 23732199Sahrens if (!dd.gotone) { 23743237Slling return (zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT, 23752199Sahrens dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"), 23762199Sahrens zhp->zfs_name, snapname)); 23772199Sahrens } 23782199Sahrens 23792199Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 23802676Seschrock (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); 23812199Sahrens 23822199Sahrens ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY_SNAPS, &zc); 23832199Sahrens if (ret != 0) { 23842199Sahrens char errbuf[1024]; 23852199Sahrens 23862199Sahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 23872199Sahrens "cannot destroy '%s@%s'"), zc.zc_name, snapname); 23882199Sahrens 23892199Sahrens switch (errno) { 23902199Sahrens case EEXIST: 23912199Sahrens zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 23922199Sahrens "snapshot is cloned")); 23932199Sahrens return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf)); 23942199Sahrens 23952199Sahrens default: 23962199Sahrens return (zfs_standard_error(zhp->zfs_hdl, errno, 23972199Sahrens errbuf)); 23982199Sahrens } 23992199Sahrens } 24002199Sahrens 24012199Sahrens return (0); 24022199Sahrens } 24032199Sahrens 2404789Sahrens /* 2405789Sahrens * Clones the given dataset. The target must be of the same type as the source. 2406789Sahrens */ 2407789Sahrens int 24082676Seschrock zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props) 2409789Sahrens { 2410789Sahrens zfs_cmd_t zc = { 0 }; 2411789Sahrens char parent[ZFS_MAXNAMELEN]; 2412789Sahrens int ret; 24132082Seschrock char errbuf[1024]; 24142082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 24152676Seschrock zfs_type_t type; 24162676Seschrock uint64_t zoned; 2417789Sahrens 2418789Sahrens assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 2419789Sahrens 24202082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 24212082Seschrock "cannot create '%s'"), target); 24222082Seschrock 2423789Sahrens /* validate the target name */ 24242082Seschrock if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM)) 24252082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2426789Sahrens 2427789Sahrens /* validate parents exist */ 2428*4490Svb160487 if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0) 2429789Sahrens return (-1); 2430789Sahrens 2431789Sahrens (void) parent_name(target, parent, sizeof (parent)); 2432789Sahrens 2433789Sahrens /* do the clone */ 24342676Seschrock if (ZFS_IS_VOLUME(zhp)) { 2435789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 24362744Snn35248 type = ZFS_TYPE_VOLUME; 24372676Seschrock } else { 2438789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 24392744Snn35248 type = ZFS_TYPE_FILESYSTEM; 24402676Seschrock } 24412676Seschrock 24422676Seschrock if (props) { 24433912Slling if ((props = zfs_validate_properties(hdl, type, NULL, props, 24443912Slling zoned, zhp, errbuf)) == NULL) 24452676Seschrock return (-1); 24462676Seschrock 24472676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, props, NULL) != 0) { 24482676Seschrock nvlist_free(props); 24492676Seschrock return (-1); 24502676Seschrock } 24512676Seschrock 24522676Seschrock nvlist_free(props); 24532676Seschrock } 2454789Sahrens 2455789Sahrens (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name)); 24562676Seschrock (void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value)); 24572082Seschrock ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_CREATE, &zc); 2458789Sahrens 24592676Seschrock zcmd_free_nvlists(&zc); 24602676Seschrock 2461789Sahrens if (ret != 0) { 2462789Sahrens switch (errno) { 2463789Sahrens 2464789Sahrens case ENOENT: 2465789Sahrens /* 2466789Sahrens * The parent doesn't exist. We should have caught this 2467789Sahrens * above, but there may a race condition that has since 2468789Sahrens * destroyed the parent. 2469789Sahrens * 2470789Sahrens * At this point, we don't know whether it's the source 2471789Sahrens * that doesn't exist anymore, or whether the target 2472789Sahrens * dataset doesn't exist. 2473789Sahrens */ 24742082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 24752082Seschrock "no such parent '%s'"), parent); 24762082Seschrock return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf)); 24772082Seschrock 24782082Seschrock case EXDEV: 24792082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 24802082Seschrock "source and target pools differ")); 24812082Seschrock return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET, 24822082Seschrock errbuf)); 24832082Seschrock 24842082Seschrock default: 24852082Seschrock return (zfs_standard_error(zhp->zfs_hdl, errno, 24862082Seschrock errbuf)); 24872082Seschrock } 24882676Seschrock } else if (ZFS_IS_VOLUME(zhp)) { 24892082Seschrock ret = zvol_create_link(zhp->zfs_hdl, target); 24902082Seschrock } 24912082Seschrock 24922082Seschrock return (ret); 24932082Seschrock } 24942082Seschrock 24952082Seschrock typedef struct promote_data { 24962082Seschrock char cb_mountpoint[MAXPATHLEN]; 24972082Seschrock const char *cb_target; 24982082Seschrock const char *cb_errbuf; 24992082Seschrock uint64_t cb_pivot_txg; 25002082Seschrock } promote_data_t; 25012082Seschrock 25022082Seschrock static int 25032082Seschrock promote_snap_cb(zfs_handle_t *zhp, void *data) 25042082Seschrock { 25052082Seschrock promote_data_t *pd = data; 25062082Seschrock zfs_handle_t *szhp; 25072082Seschrock char snapname[MAXPATHLEN]; 25083265Sahrens int rv = 0; 25092082Seschrock 25102082Seschrock /* We don't care about snapshots after the pivot point */ 25113265Sahrens if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > pd->cb_pivot_txg) { 25123265Sahrens zfs_close(zhp); 25132082Seschrock return (0); 25143265Sahrens } 25152082Seschrock 25162417Sahrens /* Remove the device link if it's a zvol. */ 25172676Seschrock if (ZFS_IS_VOLUME(zhp)) 25182417Sahrens (void) zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name); 25192082Seschrock 25202082Seschrock /* Check for conflicting names */ 25212676Seschrock (void) strlcpy(snapname, pd->cb_target, sizeof (snapname)); 25222676Seschrock (void) strlcat(snapname, strchr(zhp->zfs_name, '@'), sizeof (snapname)); 25232082Seschrock szhp = make_dataset_handle(zhp->zfs_hdl, snapname); 25242082Seschrock if (szhp != NULL) { 25252082Seschrock zfs_close(szhp); 25262082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 25272082Seschrock "snapshot name '%s' from origin \n" 25282082Seschrock "conflicts with '%s' from target"), 25292082Seschrock zhp->zfs_name, snapname); 25303265Sahrens rv = zfs_error(zhp->zfs_hdl, EZFS_EXISTS, pd->cb_errbuf); 25312082Seschrock } 25323265Sahrens zfs_close(zhp); 25333265Sahrens return (rv); 25342082Seschrock } 25352082Seschrock 25362417Sahrens static int 25372417Sahrens promote_snap_done_cb(zfs_handle_t *zhp, void *data) 25382417Sahrens { 25392417Sahrens promote_data_t *pd = data; 25402417Sahrens 25412417Sahrens /* We don't care about snapshots after the pivot point */ 25423265Sahrens if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) <= pd->cb_pivot_txg) { 25433265Sahrens /* Create the device link if it's a zvol. */ 25443265Sahrens if (ZFS_IS_VOLUME(zhp)) 25453265Sahrens (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 25463265Sahrens } 25473265Sahrens 25483265Sahrens zfs_close(zhp); 25492417Sahrens return (0); 25502417Sahrens } 25512417Sahrens 25522082Seschrock /* 25532082Seschrock * Promotes the given clone fs to be the clone parent. 25542082Seschrock */ 25552082Seschrock int 25562082Seschrock zfs_promote(zfs_handle_t *zhp) 25572082Seschrock { 25582082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 25592082Seschrock zfs_cmd_t zc = { 0 }; 25602082Seschrock char parent[MAXPATHLEN]; 25612082Seschrock char *cp; 25622082Seschrock int ret; 25632082Seschrock zfs_handle_t *pzhp; 25642082Seschrock promote_data_t pd; 25652082Seschrock char errbuf[1024]; 25662082Seschrock 25672082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 25682082Seschrock "cannot promote '%s'"), zhp->zfs_name); 25692082Seschrock 25702082Seschrock if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 25712082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 25722082Seschrock "snapshots can not be promoted")); 25732082Seschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 25742082Seschrock } 25752082Seschrock 25762676Seschrock (void) strlcpy(parent, zhp->zfs_dmustats.dds_clone_of, sizeof (parent)); 25772082Seschrock if (parent[0] == '\0') { 25782082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 25792082Seschrock "not a cloned filesystem")); 25802082Seschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 25812082Seschrock } 25822082Seschrock cp = strchr(parent, '@'); 25832082Seschrock *cp = '\0'; 25842082Seschrock 25852082Seschrock /* Walk the snapshots we will be moving */ 25862082Seschrock pzhp = zfs_open(hdl, zhp->zfs_dmustats.dds_clone_of, ZFS_TYPE_SNAPSHOT); 25872082Seschrock if (pzhp == NULL) 25882082Seschrock return (-1); 25892082Seschrock pd.cb_pivot_txg = zfs_prop_get_int(pzhp, ZFS_PROP_CREATETXG); 25902082Seschrock zfs_close(pzhp); 25912082Seschrock pd.cb_target = zhp->zfs_name; 25922082Seschrock pd.cb_errbuf = errbuf; 25932082Seschrock pzhp = zfs_open(hdl, parent, ZFS_TYPE_ANY); 25942082Seschrock if (pzhp == NULL) 25952082Seschrock return (-1); 25962082Seschrock (void) zfs_prop_get(pzhp, ZFS_PROP_MOUNTPOINT, pd.cb_mountpoint, 25972082Seschrock sizeof (pd.cb_mountpoint), NULL, NULL, 0, FALSE); 25982082Seschrock ret = zfs_iter_snapshots(pzhp, promote_snap_cb, &pd); 25992417Sahrens if (ret != 0) { 26002417Sahrens zfs_close(pzhp); 26012082Seschrock return (-1); 26022417Sahrens } 26032082Seschrock 26042082Seschrock /* issue the ioctl */ 26052676Seschrock (void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_clone_of, 26062676Seschrock sizeof (zc.zc_value)); 26072082Seschrock (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 26082082Seschrock ret = ioctl(hdl->libzfs_fd, ZFS_IOC_PROMOTE, &zc); 26092082Seschrock 26102082Seschrock if (ret != 0) { 26112417Sahrens int save_errno = errno; 26122417Sahrens 26132417Sahrens (void) zfs_iter_snapshots(pzhp, promote_snap_done_cb, &pd); 26142417Sahrens zfs_close(pzhp); 26152417Sahrens 26162417Sahrens switch (save_errno) { 2617789Sahrens case EEXIST: 2618789Sahrens /* 26192082Seschrock * There is a conflicting snapshot name. We 26202082Seschrock * should have caught this above, but they could 26212082Seschrock * have renamed something in the mean time. 2622789Sahrens */ 26232082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 26242082Seschrock "conflicting snapshot name from parent '%s'"), 26252082Seschrock parent); 26262082Seschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2627789Sahrens 2628789Sahrens default: 26292417Sahrens return (zfs_standard_error(hdl, save_errno, errbuf)); 2630789Sahrens } 26312417Sahrens } else { 26322417Sahrens (void) zfs_iter_snapshots(zhp, promote_snap_done_cb, &pd); 2633789Sahrens } 2634789Sahrens 26352417Sahrens zfs_close(pzhp); 2636789Sahrens return (ret); 2637789Sahrens } 2638789Sahrens 26394007Smmusante struct createdata { 26404007Smmusante const char *cd_snapname; 26414007Smmusante int cd_ifexists; 26424007Smmusante }; 26434007Smmusante 26442199Sahrens static int 26452199Sahrens zfs_create_link_cb(zfs_handle_t *zhp, void *arg) 26462199Sahrens { 26474007Smmusante struct createdata *cd = arg; 26482676Seschrock int ret; 26492199Sahrens 26502199Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 26512199Sahrens char name[MAXPATHLEN]; 26522199Sahrens 26532676Seschrock (void) strlcpy(name, zhp->zfs_name, sizeof (name)); 26542676Seschrock (void) strlcat(name, "@", sizeof (name)); 26554007Smmusante (void) strlcat(name, cd->cd_snapname, sizeof (name)); 26564007Smmusante (void) zvol_create_link_common(zhp->zfs_hdl, name, 26574007Smmusante cd->cd_ifexists); 26582199Sahrens /* 26592199Sahrens * NB: this is simply a best-effort. We don't want to 26602199Sahrens * return an error, because then we wouldn't visit all 26612199Sahrens * the volumes. 26622199Sahrens */ 26632199Sahrens } 26642676Seschrock 26654007Smmusante ret = zfs_iter_filesystems(zhp, zfs_create_link_cb, cd); 26662676Seschrock 26672676Seschrock zfs_close(zhp); 26682676Seschrock 26692676Seschrock return (ret); 26702199Sahrens } 26712199Sahrens 2672789Sahrens /* 26733504Sahl * Takes a snapshot of the given dataset. 2674789Sahrens */ 2675789Sahrens int 26762199Sahrens zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive) 2677789Sahrens { 2678789Sahrens const char *delim; 2679789Sahrens char *parent; 2680789Sahrens zfs_handle_t *zhp; 2681789Sahrens zfs_cmd_t zc = { 0 }; 2682789Sahrens int ret; 26832082Seschrock char errbuf[1024]; 26842082Seschrock 26852082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 26862082Seschrock "cannot snapshot '%s'"), path); 26872082Seschrock 26882082Seschrock /* validate the target name */ 26892082Seschrock if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT)) 26902082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2691789Sahrens 2692789Sahrens /* make sure the parent exists and is of the appropriate type */ 26932199Sahrens delim = strchr(path, '@'); 26942082Seschrock if ((parent = zfs_alloc(hdl, delim - path + 1)) == NULL) 26952082Seschrock return (-1); 2696789Sahrens (void) strncpy(parent, path, delim - path); 2697789Sahrens parent[delim - path] = '\0'; 2698789Sahrens 26992082Seschrock if ((zhp = zfs_open(hdl, parent, ZFS_TYPE_FILESYSTEM | 2700789Sahrens ZFS_TYPE_VOLUME)) == NULL) { 2701789Sahrens free(parent); 2702789Sahrens return (-1); 2703789Sahrens } 2704789Sahrens 27052199Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 27062676Seschrock (void) strlcpy(zc.zc_value, delim+1, sizeof (zc.zc_value)); 27072199Sahrens zc.zc_cookie = recursive; 27082199Sahrens ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT, &zc); 27092199Sahrens 27102199Sahrens /* 27112199Sahrens * if it was recursive, the one that actually failed will be in 27122199Sahrens * zc.zc_name. 27132199Sahrens */ 27142199Sahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 27152676Seschrock "cannot create snapshot '%s@%s'"), zc.zc_name, zc.zc_value); 27162199Sahrens if (ret == 0 && recursive) { 27174007Smmusante struct createdata cd; 27184007Smmusante 27194007Smmusante cd.cd_snapname = delim + 1; 27204007Smmusante cd.cd_ifexists = B_FALSE; 27214007Smmusante (void) zfs_iter_filesystems(zhp, zfs_create_link_cb, &cd); 27222199Sahrens } 2723789Sahrens if (ret == 0 && zhp->zfs_type == ZFS_TYPE_VOLUME) { 27242082Seschrock ret = zvol_create_link(zhp->zfs_hdl, path); 27252199Sahrens if (ret != 0) { 27262082Seschrock (void) ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, 27272082Seschrock &zc); 27282199Sahrens } 2729789Sahrens } 2730789Sahrens 27312082Seschrock if (ret != 0) 27322082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 2733789Sahrens 2734789Sahrens free(parent); 2735789Sahrens zfs_close(zhp); 2736789Sahrens 2737789Sahrens return (ret); 2738789Sahrens } 2739789Sahrens 2740789Sahrens /* 27413504Sahl * Dumps a backup of the given snapshot (incremental from fromsnap if it's not 27423504Sahl * NULL) to the file descriptor specified by outfd. 2743789Sahrens */ 2744789Sahrens int 27453504Sahl zfs_send(zfs_handle_t *zhp, const char *fromsnap, int outfd) 2746789Sahrens { 2747789Sahrens zfs_cmd_t zc = { 0 }; 27482082Seschrock char errbuf[1024]; 27492885Sahrens libzfs_handle_t *hdl = zhp->zfs_hdl; 27502082Seschrock 27513504Sahl assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 27523504Sahl 27532885Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 27542885Sahrens if (fromsnap) 27552885Sahrens (void) strlcpy(zc.zc_value, fromsnap, sizeof (zc.zc_name)); 27563504Sahl zc.zc_cookie = outfd; 27573504Sahl 27583504Sahl if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SENDBACKUP, &zc) != 0) { 27593504Sahl (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 27603504Sahl "cannot send '%s'"), zhp->zfs_name); 27613504Sahl 2762789Sahrens switch (errno) { 2763789Sahrens 2764789Sahrens case EXDEV: 27652082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 27663413Smmusante "not an earlier snapshot from the same fs")); 27672082Seschrock return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); 2768789Sahrens 2769789Sahrens case EDQUOT: 2770789Sahrens case EFBIG: 2771789Sahrens case EIO: 2772789Sahrens case ENOLINK: 2773789Sahrens case ENOSPC: 2774789Sahrens case ENOSTR: 2775789Sahrens case ENXIO: 2776789Sahrens case EPIPE: 2777789Sahrens case ERANGE: 2778789Sahrens case EFAULT: 2779789Sahrens case EROFS: 27802082Seschrock zfs_error_aux(hdl, strerror(errno)); 27812082Seschrock return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); 2782789Sahrens 2783789Sahrens default: 27842082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 2785789Sahrens } 2786789Sahrens } 2787789Sahrens 27883504Sahl return (0); 2789789Sahrens } 2790789Sahrens 2791789Sahrens /* 27922885Sahrens * Create ancestors of 'target', but not target itself, and not 27932885Sahrens * ancestors whose names are shorter than prefixlen. Die if 27942885Sahrens * prefixlen-ancestor does not exist. 27952885Sahrens */ 27962885Sahrens static int 27972885Sahrens create_parents(libzfs_handle_t *hdl, char *target, int prefixlen) 27982885Sahrens { 27992885Sahrens zfs_handle_t *h; 28002885Sahrens char *cp; 28012885Sahrens 28022885Sahrens /* make sure prefix exists */ 28032885Sahrens cp = strchr(target + prefixlen, '/'); 28042885Sahrens *cp = '\0'; 28052885Sahrens h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 28062885Sahrens *cp = '/'; 28072885Sahrens if (h == NULL) 28082885Sahrens return (-1); 28092885Sahrens zfs_close(h); 28102885Sahrens 28112885Sahrens /* 28122885Sahrens * Attempt to create, mount, and share any ancestor filesystems, 28132885Sahrens * up to the prefixlen-long one. 28142885Sahrens */ 28152885Sahrens for (cp = target + prefixlen + 1; 28162885Sahrens cp = strchr(cp, '/'); *cp = '/', cp++) { 28172885Sahrens const char *opname; 28182885Sahrens 28192885Sahrens *cp = '\0'; 28202885Sahrens 28212885Sahrens h = make_dataset_handle(hdl, target); 28222885Sahrens if (h) { 28232885Sahrens /* it already exists, nothing to do here */ 28242885Sahrens zfs_close(h); 28252885Sahrens continue; 28262885Sahrens } 28272885Sahrens 28282885Sahrens opname = dgettext(TEXT_DOMAIN, "create"); 28292885Sahrens if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM, 28302885Sahrens NULL) != 0) 28312885Sahrens goto ancestorerr; 28322885Sahrens 28332885Sahrens opname = dgettext(TEXT_DOMAIN, "open"); 28342885Sahrens h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 28352885Sahrens if (h == NULL) 28362885Sahrens goto ancestorerr; 28372885Sahrens 28382885Sahrens opname = dgettext(TEXT_DOMAIN, "mount"); 28392885Sahrens if (zfs_mount(h, NULL, 0) != 0) 28402885Sahrens goto ancestorerr; 28412885Sahrens 28422885Sahrens opname = dgettext(TEXT_DOMAIN, "share"); 28432885Sahrens if (zfs_share(h) != 0) 28442885Sahrens goto ancestorerr; 28452885Sahrens 28462885Sahrens zfs_close(h); 28472885Sahrens 28482885Sahrens continue; 28492885Sahrens ancestorerr: 28502885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 28512885Sahrens "failed to %s ancestor '%s'"), opname, target); 28522885Sahrens return (-1); 28532885Sahrens } 28542885Sahrens 28552885Sahrens return (0); 28562885Sahrens } 28572885Sahrens 28582885Sahrens /* 28593504Sahl * Restores a backup of tosnap from the file descriptor specified by infd. 2860789Sahrens */ 2861789Sahrens int 28622082Seschrock zfs_receive(libzfs_handle_t *hdl, const char *tosnap, int isprefix, 28633504Sahl int verbose, int dryrun, boolean_t force, int infd) 2864789Sahrens { 2865789Sahrens zfs_cmd_t zc = { 0 }; 2866789Sahrens time_t begin_time; 28672885Sahrens int ioctl_err, err, bytes, size, choplen; 2868789Sahrens char *cp; 2869789Sahrens dmu_replay_record_t drr; 2870789Sahrens struct drr_begin *drrb = &zc.zc_begin_record; 28712082Seschrock char errbuf[1024]; 28722665Snd150628 prop_changelist_t *clp; 28732885Sahrens char chopprefix[ZFS_MAXNAMELEN]; 2874789Sahrens 2875789Sahrens begin_time = time(NULL); 2876789Sahrens 28772082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 28782082Seschrock "cannot receive")); 28792082Seschrock 2880789Sahrens /* read in the BEGIN record */ 2881789Sahrens cp = (char *)&drr; 2882789Sahrens bytes = 0; 2883789Sahrens do { 28843504Sahl size = read(infd, cp, sizeof (drr) - bytes); 2885868Sahrens cp += size; 2886868Sahrens bytes += size; 2887868Sahrens } while (size > 0); 2888868Sahrens 2889868Sahrens if (size < 0 || bytes != sizeof (drr)) { 28902082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 28912082Seschrock "stream (failed to read first record)")); 28922082Seschrock return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2893789Sahrens } 2894789Sahrens 2895789Sahrens zc.zc_begin_record = drr.drr_u.drr_begin; 2896789Sahrens 2897789Sahrens if (drrb->drr_magic != DMU_BACKUP_MAGIC && 2898789Sahrens drrb->drr_magic != BSWAP_64(DMU_BACKUP_MAGIC)) { 28992082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 29002082Seschrock "stream (bad magic number)")); 29012082Seschrock return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2902789Sahrens } 2903789Sahrens 2904789Sahrens if (drrb->drr_version != DMU_BACKUP_VERSION && 2905789Sahrens drrb->drr_version != BSWAP_64(DMU_BACKUP_VERSION)) { 29062082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only version " 29072082Seschrock "0x%llx is supported (stream is version 0x%llx)"), 2908789Sahrens DMU_BACKUP_VERSION, drrb->drr_version); 29092082Seschrock return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2910789Sahrens } 2911789Sahrens 29122885Sahrens if (strchr(drr.drr_u.drr_begin.drr_toname, '@') == NULL) { 29132885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 29143912Slling "stream (bad snapshot name)")); 29152885Sahrens return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 29162885Sahrens } 2917789Sahrens /* 29182885Sahrens * Determine how much of the snapshot name stored in the stream 29192885Sahrens * we are going to tack on to the name they specified on the 29202885Sahrens * command line, and how much we are going to chop off. 29212885Sahrens * 29222885Sahrens * If they specified a snapshot, chop the entire name stored in 29232885Sahrens * the stream. 2924789Sahrens */ 29252885Sahrens (void) strcpy(chopprefix, drr.drr_u.drr_begin.drr_toname); 2926789Sahrens if (isprefix) { 29272885Sahrens /* 29282885Sahrens * They specified a fs with -d, we want to tack on 29292885Sahrens * everything but the pool name stored in the stream 29302885Sahrens */ 29312885Sahrens if (strchr(tosnap, '@')) { 29322885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 29332885Sahrens "argument - snapshot not allowed with -d")); 29342885Sahrens return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2935789Sahrens } 29362885Sahrens cp = strchr(chopprefix, '/'); 2937789Sahrens if (cp == NULL) 29382885Sahrens cp = strchr(chopprefix, '@'); 29392885Sahrens *cp = '\0'; 2940789Sahrens } else if (strchr(tosnap, '@') == NULL) { 2941789Sahrens /* 29422885Sahrens * If they specified a filesystem without -d, we want to 29432885Sahrens * tack on everything after the fs specified in the 29442885Sahrens * first name from the stream. 2945789Sahrens */ 29462885Sahrens cp = strchr(chopprefix, '@'); 29472885Sahrens *cp = '\0'; 2948789Sahrens } 29492885Sahrens choplen = strlen(chopprefix); 29502885Sahrens 29512885Sahrens /* 29522885Sahrens * Determine name of destination snapshot, store in zc_value. 29532885Sahrens */ 29542885Sahrens (void) strcpy(zc.zc_value, tosnap); 29552885Sahrens (void) strncat(zc.zc_value, drr.drr_u.drr_begin.drr_toname+choplen, 29562885Sahrens sizeof (zc.zc_value)); 29573265Sahrens if (!zfs_validate_name(hdl, zc.zc_value, ZFS_TYPE_SNAPSHOT)) 29583265Sahrens return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 29592885Sahrens 29602885Sahrens (void) strcpy(zc.zc_name, zc.zc_value); 2961789Sahrens if (drrb->drr_fromguid) { 2962789Sahrens /* incremental backup stream */ 29632885Sahrens zfs_handle_t *h; 29642885Sahrens 29652885Sahrens /* do the recvbackup ioctl to the containing fs */ 29662885Sahrens *strchr(zc.zc_name, '@') = '\0'; 2967789Sahrens 2968789Sahrens /* make sure destination fs exists */ 29692082Seschrock h = zfs_open(hdl, zc.zc_name, 29702082Seschrock ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 29712082Seschrock if (h == NULL) 2972789Sahrens return (-1); 2973868Sahrens if (!dryrun) { 29742665Snd150628 /* 29752665Snd150628 * We need to unmount all the dependents of the dataset 29762665Snd150628 * and the dataset itself. If it's a volume 29772665Snd150628 * then remove device link. 29782665Snd150628 */ 2979868Sahrens if (h->zfs_type == ZFS_TYPE_FILESYSTEM) { 29802665Snd150628 clp = changelist_gather(h, ZFS_PROP_NAME, 0); 29812665Snd150628 if (clp == NULL) 29822665Snd150628 return (-1); 29832665Snd150628 if (changelist_prefix(clp) != 0) { 29842665Snd150628 changelist_free(clp); 29852665Snd150628 return (-1); 29862665Snd150628 } 2987868Sahrens } else { 29882082Seschrock (void) zvol_remove_link(hdl, h->zfs_name); 2989868Sahrens } 2990868Sahrens } 2991789Sahrens zfs_close(h); 2992789Sahrens } else { 2993789Sahrens /* full backup stream */ 2994789Sahrens 2995868Sahrens /* Make sure destination fs does not exist */ 29962885Sahrens *strchr(zc.zc_name, '@') = '\0'; 2997*4490Svb160487 if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_ANY)) { 29982082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29992082Seschrock "destination '%s' exists"), zc.zc_name); 30002082Seschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 3001868Sahrens } 3002868Sahrens 30032885Sahrens if (strchr(zc.zc_name, '/') == NULL) { 30042885Sahrens /* 30052885Sahrens * they're trying to do a recv into a 30062885Sahrens * nonexistant topmost filesystem. 30072885Sahrens */ 30082885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 30092885Sahrens "destination does not exist"), zc.zc_name); 30102885Sahrens return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 30112885Sahrens } 30122885Sahrens 3013868Sahrens /* Do the recvbackup ioctl to the fs's parent. */ 30142885Sahrens *strrchr(zc.zc_name, '/') = '\0'; 30152885Sahrens 30162885Sahrens if (isprefix && (err = create_parents(hdl, 30172885Sahrens zc.zc_value, strlen(tosnap))) != 0) { 30182885Sahrens return (zfs_error(hdl, EZFS_BADRESTORE, errbuf)); 30192885Sahrens } 30202885Sahrens 3021789Sahrens } 3022789Sahrens 30233504Sahl zc.zc_cookie = infd; 30242676Seschrock zc.zc_guid = force; 3025789Sahrens if (verbose) { 30261749Sahrens (void) printf("%s %s stream of %s into %s\n", 30271749Sahrens dryrun ? "would receive" : "receiving", 3028789Sahrens drrb->drr_fromguid ? "incremental" : "full", 3029789Sahrens drr.drr_u.drr_begin.drr_toname, 30302676Seschrock zc.zc_value); 3031789Sahrens (void) fflush(stdout); 3032789Sahrens } 3033789Sahrens if (dryrun) 3034789Sahrens return (0); 30352082Seschrock err = ioctl_err = ioctl(hdl->libzfs_fd, ZFS_IOC_RECVBACKUP, &zc); 3036868Sahrens if (ioctl_err != 0) { 3037789Sahrens switch (errno) { 3038789Sahrens case ENODEV: 30392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 30402082Seschrock "most recent snapshot does not match incremental " 30412082Seschrock "source")); 30422082Seschrock (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); 3043789Sahrens break; 3044789Sahrens case ETXTBSY: 30452082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 30462082Seschrock "destination has been modified since most recent " 30472082Seschrock "snapshot")); 30482082Seschrock (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); 3049789Sahrens break; 3050789Sahrens case EEXIST: 3051789Sahrens if (drrb->drr_fromguid == 0) { 3052789Sahrens /* it's the containing fs that exists */ 30532676Seschrock cp = strchr(zc.zc_value, '@'); 3054789Sahrens *cp = '\0'; 3055789Sahrens } 30562082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 30572082Seschrock "destination already exists")); 30583237Slling (void) zfs_error_fmt(hdl, EZFS_EXISTS, 30593237Slling dgettext(TEXT_DOMAIN, "cannot restore to %s"), 30603237Slling zc.zc_value); 3061789Sahrens break; 3062789Sahrens case EINVAL: 30632082Seschrock (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); 3064868Sahrens break; 30651544Seschrock case ECKSUM: 30662082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 30672082Seschrock "invalid stream (checksum mismatch)")); 30682082Seschrock (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); 3069789Sahrens break; 3070789Sahrens default: 30712082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 3072789Sahrens } 3073789Sahrens } 3074789Sahrens 3075789Sahrens /* 3076868Sahrens * Mount or recreate the /dev links for the target filesystem 3077868Sahrens * (if created, or if we tore them down to do an incremental 3078868Sahrens * restore), and the /dev links for the new snapshot (if 30792665Snd150628 * created). Also mount any children of the target filesystem 30802665Snd150628 * if we did an incremental receive. 3081789Sahrens */ 30822676Seschrock cp = strchr(zc.zc_value, '@'); 3083868Sahrens if (cp && (ioctl_err == 0 || drrb->drr_fromguid)) { 3084789Sahrens zfs_handle_t *h; 3085789Sahrens 3086789Sahrens *cp = '\0'; 30872676Seschrock h = zfs_open(hdl, zc.zc_value, 3088789Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 3089868Sahrens *cp = '@'; 3090789Sahrens if (h) { 30912665Snd150628 if (h->zfs_type == ZFS_TYPE_VOLUME) { 30922082Seschrock err = zvol_create_link(hdl, h->zfs_name); 30931544Seschrock if (err == 0 && ioctl_err == 0) 30942082Seschrock err = zvol_create_link(hdl, 30952676Seschrock zc.zc_value); 30962665Snd150628 } else { 30972665Snd150628 if (drrb->drr_fromguid) { 30982665Snd150628 err = changelist_postfix(clp); 30992665Snd150628 changelist_free(clp); 31002665Snd150628 } else { 31012665Snd150628 err = zfs_mount(h, NULL, 0); 31022665Snd150628 } 3103868Sahrens } 31042665Snd150628 zfs_close(h); 3105789Sahrens } 3106789Sahrens } 3107789Sahrens 3108868Sahrens if (err || ioctl_err) 3109868Sahrens return (-1); 3110789Sahrens 3111789Sahrens if (verbose) { 3112789Sahrens char buf1[64]; 3113789Sahrens char buf2[64]; 3114789Sahrens uint64_t bytes = zc.zc_cookie; 3115789Sahrens time_t delta = time(NULL) - begin_time; 3116789Sahrens if (delta == 0) 3117789Sahrens delta = 1; 3118789Sahrens zfs_nicenum(bytes, buf1, sizeof (buf1)); 3119789Sahrens zfs_nicenum(bytes/delta, buf2, sizeof (buf1)); 3120789Sahrens 31211749Sahrens (void) printf("received %sb stream in %lu seconds (%sb/sec)\n", 3122789Sahrens buf1, delta, buf2); 3123789Sahrens } 31242665Snd150628 3125789Sahrens return (0); 3126789Sahrens } 3127789Sahrens 3128789Sahrens /* 31291294Slling * Destroy any more recent snapshots. We invoke this callback on any dependents 31301294Slling * of the snapshot first. If the 'cb_dependent' member is non-zero, then this 31311294Slling * is a dependent and we should just destroy it without checking the transaction 31321294Slling * group. 3133789Sahrens */ 31341294Slling typedef struct rollback_data { 31351294Slling const char *cb_target; /* the snapshot */ 31361294Slling uint64_t cb_create; /* creation time reference */ 31371294Slling prop_changelist_t *cb_clp; /* changelist pointer */ 31381294Slling int cb_error; 31392082Seschrock boolean_t cb_dependent; 31401294Slling } rollback_data_t; 31411294Slling 31421294Slling static int 31431294Slling rollback_destroy(zfs_handle_t *zhp, void *data) 31441294Slling { 31451294Slling rollback_data_t *cbp = data; 31461294Slling 31471294Slling if (!cbp->cb_dependent) { 31481294Slling if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 && 31491294Slling zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && 31501294Slling zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > 31511294Slling cbp->cb_create) { 31521294Slling 31532082Seschrock cbp->cb_dependent = B_TRUE; 31542474Seschrock if (zfs_iter_dependents(zhp, B_FALSE, rollback_destroy, 31552474Seschrock cbp) != 0) 31562474Seschrock cbp->cb_error = 1; 31572082Seschrock cbp->cb_dependent = B_FALSE; 31581294Slling 31591294Slling if (zfs_destroy(zhp) != 0) 31601294Slling cbp->cb_error = 1; 31611294Slling else 31621294Slling changelist_remove(zhp, cbp->cb_clp); 31631294Slling } 31641294Slling } else { 31651294Slling if (zfs_destroy(zhp) != 0) 31661294Slling cbp->cb_error = 1; 31671294Slling else 31681294Slling changelist_remove(zhp, cbp->cb_clp); 31691294Slling } 31701294Slling 31711294Slling zfs_close(zhp); 31721294Slling return (0); 31731294Slling } 31741294Slling 31751294Slling /* 31761294Slling * Rollback the dataset to its latest snapshot. 31771294Slling */ 31781294Slling static int 31791294Slling do_rollback(zfs_handle_t *zhp) 3180789Sahrens { 3181789Sahrens int ret; 3182789Sahrens zfs_cmd_t zc = { 0 }; 3183789Sahrens 3184789Sahrens assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM || 3185789Sahrens zhp->zfs_type == ZFS_TYPE_VOLUME); 3186789Sahrens 3187789Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME && 31882082Seschrock zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0) 3189789Sahrens return (-1); 3190789Sahrens 3191789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3192789Sahrens 31932676Seschrock if (ZFS_IS_VOLUME(zhp)) 3194789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3195789Sahrens else 3196789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3197789Sahrens 3198789Sahrens /* 3199789Sahrens * We rely on the consumer to verify that there are no newer snapshots 3200789Sahrens * for the given dataset. Given these constraints, we can simply pass 3201789Sahrens * the name on to the ioctl() call. There is still an unlikely race 3202789Sahrens * condition where the user has taken a snapshot since we verified that 3203789Sahrens * this was the most recent. 3204789Sahrens */ 32052082Seschrock if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_ROLLBACK, 32062082Seschrock &zc)) != 0) { 32073237Slling (void) zfs_standard_error_fmt(zhp->zfs_hdl, errno, 32082082Seschrock dgettext(TEXT_DOMAIN, "cannot rollback '%s'"), 32092082Seschrock zhp->zfs_name); 3210789Sahrens } else if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 32112082Seschrock ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 3212789Sahrens } 3213789Sahrens 3214789Sahrens return (ret); 3215789Sahrens } 3216789Sahrens 3217789Sahrens /* 32181294Slling * Given a dataset, rollback to a specific snapshot, discarding any 32191294Slling * data changes since then and making it the active dataset. 32201294Slling * 32211294Slling * Any snapshots more recent than the target are destroyed, along with 32221294Slling * their dependents. 32231294Slling */ 32241294Slling int 32251294Slling zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, int flag) 32261294Slling { 32271294Slling int ret; 32281294Slling rollback_data_t cb = { 0 }; 32291294Slling prop_changelist_t *clp; 32301294Slling 32311294Slling /* 32321294Slling * Unmount all dependendents of the dataset and the dataset itself. 32331294Slling * The list we need to gather is the same as for doing rename 32341294Slling */ 32351294Slling clp = changelist_gather(zhp, ZFS_PROP_NAME, flag ? MS_FORCE: 0); 32361294Slling if (clp == NULL) 32371294Slling return (-1); 32381294Slling 32391294Slling if ((ret = changelist_prefix(clp)) != 0) 32401294Slling goto out; 32411294Slling 32421294Slling /* 32431294Slling * Destroy all recent snapshots and its dependends. 32441294Slling */ 32451294Slling cb.cb_target = snap->zfs_name; 32461294Slling cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG); 32471294Slling cb.cb_clp = clp; 32481294Slling (void) zfs_iter_children(zhp, rollback_destroy, &cb); 32491294Slling 32501294Slling if ((ret = cb.cb_error) != 0) { 32511294Slling (void) changelist_postfix(clp); 32521294Slling goto out; 32531294Slling } 32541294Slling 32551294Slling /* 32561294Slling * Now that we have verified that the snapshot is the latest, 32571294Slling * rollback to the given snapshot. 32581294Slling */ 32591294Slling ret = do_rollback(zhp); 32601294Slling 32611294Slling if (ret != 0) { 32621294Slling (void) changelist_postfix(clp); 32631294Slling goto out; 32641294Slling } 32651294Slling 32661294Slling /* 32671294Slling * We only want to re-mount the filesystem if it was mounted in the 32681294Slling * first place. 32691294Slling */ 32701294Slling ret = changelist_postfix(clp); 32711294Slling 32721294Slling out: 32731294Slling changelist_free(clp); 32741294Slling return (ret); 32751294Slling } 32761294Slling 32771294Slling /* 3278789Sahrens * Iterate over all dependents for a given dataset. This includes both 3279789Sahrens * hierarchical dependents (children) and data dependents (snapshots and 3280789Sahrens * clones). The bulk of the processing occurs in get_dependents() in 3281789Sahrens * libzfs_graph.c. 3282789Sahrens */ 3283789Sahrens int 32842474Seschrock zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion, 32852474Seschrock zfs_iter_f func, void *data) 3286789Sahrens { 3287789Sahrens char **dependents; 3288789Sahrens size_t count; 3289789Sahrens int i; 3290789Sahrens zfs_handle_t *child; 3291789Sahrens int ret = 0; 3292789Sahrens 32932474Seschrock if (get_dependents(zhp->zfs_hdl, allowrecursion, zhp->zfs_name, 32942474Seschrock &dependents, &count) != 0) 32952474Seschrock return (-1); 32962474Seschrock 3297789Sahrens for (i = 0; i < count; i++) { 32982082Seschrock if ((child = make_dataset_handle(zhp->zfs_hdl, 32992082Seschrock dependents[i])) == NULL) 3300789Sahrens continue; 3301789Sahrens 3302789Sahrens if ((ret = func(child, data)) != 0) 3303789Sahrens break; 3304789Sahrens } 3305789Sahrens 3306789Sahrens for (i = 0; i < count; i++) 3307789Sahrens free(dependents[i]); 3308789Sahrens free(dependents); 3309789Sahrens 3310789Sahrens return (ret); 3311789Sahrens } 3312789Sahrens 3313789Sahrens /* 3314789Sahrens * Renames the given dataset. 3315789Sahrens */ 3316789Sahrens int 3317*4490Svb160487 zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive) 3318789Sahrens { 3319789Sahrens int ret; 3320789Sahrens zfs_cmd_t zc = { 0 }; 3321789Sahrens char *delim; 33224007Smmusante prop_changelist_t *cl = NULL; 33234007Smmusante zfs_handle_t *zhrp = NULL; 33244007Smmusante char *parentname = NULL; 3325789Sahrens char parent[ZFS_MAXNAMELEN]; 33262082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 33272082Seschrock char errbuf[1024]; 3328789Sahrens 3329789Sahrens /* if we have the same exact name, just return success */ 3330789Sahrens if (strcmp(zhp->zfs_name, target) == 0) 3331789Sahrens return (0); 3332789Sahrens 33332082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 33342082Seschrock "cannot rename to '%s'"), target); 33352082Seschrock 3336789Sahrens /* 3337789Sahrens * Make sure the target name is valid 3338789Sahrens */ 3339789Sahrens if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 33402665Snd150628 if ((strchr(target, '@') == NULL) || 33412665Snd150628 *target == '@') { 33422665Snd150628 /* 33432665Snd150628 * Snapshot target name is abbreviated, 33442665Snd150628 * reconstruct full dataset name 33452665Snd150628 */ 33462665Snd150628 (void) strlcpy(parent, zhp->zfs_name, 33472665Snd150628 sizeof (parent)); 33482665Snd150628 delim = strchr(parent, '@'); 33492665Snd150628 if (strchr(target, '@') == NULL) 33502665Snd150628 *(++delim) = '\0'; 33512665Snd150628 else 33522665Snd150628 *delim = '\0'; 33532665Snd150628 (void) strlcat(parent, target, sizeof (parent)); 33542665Snd150628 target = parent; 33552665Snd150628 } else { 33562665Snd150628 /* 33572665Snd150628 * Make sure we're renaming within the same dataset. 33582665Snd150628 */ 33592665Snd150628 delim = strchr(target, '@'); 33602665Snd150628 if (strncmp(zhp->zfs_name, target, delim - target) 33612665Snd150628 != 0 || zhp->zfs_name[delim - target] != '@') { 33622665Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33632665Snd150628 "snapshots must be part of same " 33642665Snd150628 "dataset")); 33652665Snd150628 return (zfs_error(hdl, EZFS_CROSSTARGET, 33663912Slling errbuf)); 33672665Snd150628 } 3368789Sahrens } 33692665Snd150628 if (!zfs_validate_name(hdl, target, zhp->zfs_type)) 33702665Snd150628 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 3371789Sahrens } else { 33724007Smmusante if (recursive) { 33734007Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33744007Smmusante "recursive rename must be a snapshot")); 33754007Smmusante return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 33764007Smmusante } 33774007Smmusante 33782665Snd150628 if (!zfs_validate_name(hdl, target, zhp->zfs_type)) 33792665Snd150628 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 33802676Seschrock uint64_t unused; 33812676Seschrock 3382789Sahrens /* validate parents */ 3383*4490Svb160487 if (check_parents(hdl, target, &unused, B_FALSE, NULL) != 0) 3384789Sahrens return (-1); 3385789Sahrens 3386789Sahrens (void) parent_name(target, parent, sizeof (parent)); 3387789Sahrens 3388789Sahrens /* make sure we're in the same pool */ 3389789Sahrens verify((delim = strchr(target, '/')) != NULL); 3390789Sahrens if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 3391789Sahrens zhp->zfs_name[delim - target] != '/') { 33922082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33932082Seschrock "datasets must be within same pool")); 33942082Seschrock return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); 3395789Sahrens } 33962440Snd150628 33972440Snd150628 /* new name cannot be a child of the current dataset name */ 33982440Snd150628 if (strncmp(parent, zhp->zfs_name, 33993912Slling strlen(zhp->zfs_name)) == 0) { 34002440Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 34012440Snd150628 "New dataset name cannot be a descendent of " 34022440Snd150628 "current dataset name")); 34032440Snd150628 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 34042440Snd150628 } 3405789Sahrens } 3406789Sahrens 34072082Seschrock (void) snprintf(errbuf, sizeof (errbuf), 34082082Seschrock dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name); 34092082Seschrock 3410789Sahrens if (getzoneid() == GLOBAL_ZONEID && 3411789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 34122082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 34132082Seschrock "dataset is used in a non-global zone")); 34142082Seschrock return (zfs_error(hdl, EZFS_ZONED, errbuf)); 3415789Sahrens } 3416789Sahrens 34174007Smmusante if (recursive) { 34184007Smmusante struct destroydata dd; 34194007Smmusante 34204183Smmusante parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name); 34214183Smmusante if (parentname == NULL) { 34224183Smmusante ret = -1; 34234183Smmusante goto error; 34244183Smmusante } 34254007Smmusante delim = strchr(parentname, '@'); 34264007Smmusante *delim = '\0'; 34274007Smmusante zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_ANY); 34284007Smmusante if (zhrp == NULL) { 34294183Smmusante ret = -1; 34304183Smmusante goto error; 34314007Smmusante } 34324007Smmusante 34334007Smmusante dd.snapname = delim + 1; 34344007Smmusante dd.gotone = B_FALSE; 34354183Smmusante dd.closezhp = B_TRUE; 34364007Smmusante 34374007Smmusante /* We remove any zvol links prior to renaming them */ 34384007Smmusante ret = zfs_iter_filesystems(zhrp, zfs_remove_link_cb, &dd); 34394007Smmusante if (ret) { 34404007Smmusante goto error; 34414007Smmusante } 34424007Smmusante } else { 34434007Smmusante if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0)) == NULL) 34444007Smmusante return (-1); 34454007Smmusante 34464007Smmusante if (changelist_haszonedchild(cl)) { 34474007Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 34484007Smmusante "child dataset with inherited mountpoint is used " 34494007Smmusante "in a non-global zone")); 34504007Smmusante (void) zfs_error(hdl, EZFS_ZONED, errbuf); 34514007Smmusante goto error; 34524007Smmusante } 34534007Smmusante 34544007Smmusante if ((ret = changelist_prefix(cl)) != 0) 34554007Smmusante goto error; 3456789Sahrens } 3457789Sahrens 34582676Seschrock if (ZFS_IS_VOLUME(zhp)) 3459789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3460789Sahrens else 3461789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3462789Sahrens 34632665Snd150628 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 34642676Seschrock (void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value)); 34652665Snd150628 34664007Smmusante zc.zc_cookie = recursive; 34674007Smmusante 34682082Seschrock if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_RENAME, &zc)) != 0) { 34694007Smmusante /* 34704007Smmusante * if it was recursive, the one that actually failed will 34714007Smmusante * be in zc.zc_name 34724007Smmusante */ 34734007Smmusante (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 34744007Smmusante "cannot rename to '%s'"), zc.zc_name); 34754007Smmusante 34764007Smmusante if (recursive && errno == EEXIST) { 34774007Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 34784007Smmusante "a child dataset already has a snapshot " 34794007Smmusante "with the new name")); 34804007Smmusante (void) zfs_error(hdl, EZFS_CROSSTARGET, errbuf); 34814007Smmusante } else { 34824007Smmusante (void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf); 34834007Smmusante } 3484789Sahrens 3485789Sahrens /* 3486789Sahrens * On failure, we still want to remount any filesystems that 3487789Sahrens * were previously mounted, so we don't alter the system state. 3488789Sahrens */ 34894007Smmusante if (recursive) { 34904007Smmusante struct createdata cd; 34914007Smmusante 34924007Smmusante /* only create links for datasets that had existed */ 34934007Smmusante cd.cd_snapname = delim + 1; 34944007Smmusante cd.cd_ifexists = B_TRUE; 34954007Smmusante (void) zfs_iter_filesystems(zhrp, zfs_create_link_cb, 34964007Smmusante &cd); 34974007Smmusante } else { 34984007Smmusante (void) changelist_postfix(cl); 34994007Smmusante } 3500789Sahrens } else { 35014007Smmusante if (recursive) { 35024007Smmusante struct createdata cd; 35034007Smmusante 35044007Smmusante /* only create links for datasets that had existed */ 35054007Smmusante cd.cd_snapname = strchr(target, '@') + 1; 35064007Smmusante cd.cd_ifexists = B_TRUE; 35074007Smmusante ret = zfs_iter_filesystems(zhrp, zfs_create_link_cb, 35084007Smmusante &cd); 35094007Smmusante } else { 35104007Smmusante changelist_rename(cl, zfs_get_name(zhp), target); 35114007Smmusante ret = changelist_postfix(cl); 35124007Smmusante } 3513789Sahrens } 3514789Sahrens 3515789Sahrens error: 35164007Smmusante if (parentname) { 35174007Smmusante free(parentname); 35184007Smmusante } 35194007Smmusante if (zhrp) { 35204007Smmusante zfs_close(zhrp); 35214007Smmusante } 35224007Smmusante if (cl) { 35234007Smmusante changelist_free(cl); 35244007Smmusante } 3525789Sahrens return (ret); 3526789Sahrens } 3527789Sahrens 3528789Sahrens /* 3529789Sahrens * Given a zvol dataset, issue the ioctl to create the appropriate minor node, 3530789Sahrens * poke devfsadm to create the /dev link, and then wait for the link to appear. 3531789Sahrens */ 3532789Sahrens int 35332082Seschrock zvol_create_link(libzfs_handle_t *hdl, const char *dataset) 3534789Sahrens { 35354007Smmusante return (zvol_create_link_common(hdl, dataset, B_FALSE)); 35364007Smmusante } 35374007Smmusante 35384007Smmusante static int 35394007Smmusante zvol_create_link_common(libzfs_handle_t *hdl, const char *dataset, int ifexists) 35404007Smmusante { 3541789Sahrens zfs_cmd_t zc = { 0 }; 35422082Seschrock di_devlink_handle_t dhdl; 3543789Sahrens 3544789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3545789Sahrens 3546789Sahrens /* 3547789Sahrens * Issue the appropriate ioctl. 3548789Sahrens */ 35492082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE_MINOR, &zc) != 0) { 3550789Sahrens switch (errno) { 3551789Sahrens case EEXIST: 3552789Sahrens /* 3553789Sahrens * Silently ignore the case where the link already 3554789Sahrens * exists. This allows 'zfs volinit' to be run multiple 3555789Sahrens * times without errors. 3556789Sahrens */ 3557789Sahrens return (0); 3558789Sahrens 35594007Smmusante case ENOENT: 35604007Smmusante /* 35614007Smmusante * Dataset does not exist in the kernel. If we 35624007Smmusante * don't care (see zfs_rename), then ignore the 35634007Smmusante * error quietly. 35644007Smmusante */ 35654007Smmusante if (ifexists) { 35664007Smmusante return (0); 35674007Smmusante } 35684007Smmusante 35694007Smmusante /* FALLTHROUGH */ 35704007Smmusante 3571789Sahrens default: 35723237Slling return (zfs_standard_error_fmt(hdl, errno, 35732082Seschrock dgettext(TEXT_DOMAIN, "cannot create device links " 35742082Seschrock "for '%s'"), dataset)); 3575789Sahrens } 3576789Sahrens } 3577789Sahrens 3578789Sahrens /* 3579789Sahrens * Call devfsadm and wait for the links to magically appear. 3580789Sahrens */ 35812082Seschrock if ((dhdl = di_devlink_init(ZFS_DRIVER, DI_MAKE_LINK)) == NULL) { 35822082Seschrock zfs_error_aux(hdl, strerror(errno)); 35833237Slling (void) zfs_error_fmt(hdl, EZFS_DEVLINKS, 35842082Seschrock dgettext(TEXT_DOMAIN, "cannot create device links " 35852082Seschrock "for '%s'"), dataset); 35862082Seschrock (void) ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc); 3587789Sahrens return (-1); 3588789Sahrens } else { 35892082Seschrock (void) di_devlink_fini(&dhdl); 3590789Sahrens } 3591789Sahrens 3592789Sahrens return (0); 3593789Sahrens } 3594789Sahrens 3595789Sahrens /* 3596789Sahrens * Remove a minor node for the given zvol and the associated /dev links. 3597789Sahrens */ 3598789Sahrens int 35992082Seschrock zvol_remove_link(libzfs_handle_t *hdl, const char *dataset) 3600789Sahrens { 3601789Sahrens zfs_cmd_t zc = { 0 }; 3602789Sahrens 3603789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3604789Sahrens 36052082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc) != 0) { 3606789Sahrens switch (errno) { 3607789Sahrens case ENXIO: 3608789Sahrens /* 3609789Sahrens * Silently ignore the case where the link no longer 3610789Sahrens * exists, so that 'zfs volfini' can be run multiple 3611789Sahrens * times without errors. 3612789Sahrens */ 3613789Sahrens return (0); 3614789Sahrens 3615789Sahrens default: 36163237Slling return (zfs_standard_error_fmt(hdl, errno, 36172082Seschrock dgettext(TEXT_DOMAIN, "cannot remove device " 36182082Seschrock "links for '%s'"), dataset)); 3619789Sahrens } 3620789Sahrens } 3621789Sahrens 3622789Sahrens return (0); 3623789Sahrens } 36242676Seschrock 36252676Seschrock nvlist_t * 36262676Seschrock zfs_get_user_props(zfs_handle_t *zhp) 36272676Seschrock { 36282676Seschrock return (zhp->zfs_user_props); 36292676Seschrock } 36302676Seschrock 36312676Seschrock /* 36324451Seschrock * Given a comma-separated list of properties, construct a property list 36332676Seschrock * containing both user-defined and native properties. This function will 36342676Seschrock * return a NULL list if 'all' is specified, which can later be expanded on a 36352676Seschrock * per-dataset basis by zfs_expand_proplist(). 36362676Seschrock */ 36372676Seschrock int 36383912Slling zfs_get_proplist_common(libzfs_handle_t *hdl, char *fields, 36393912Slling zfs_proplist_t **listp, zfs_type_t type) 36402676Seschrock { 36412676Seschrock size_t len; 36422676Seschrock char *s, *p; 36432676Seschrock char c; 36442676Seschrock zfs_prop_t prop; 36452676Seschrock zfs_proplist_t *entry; 36462676Seschrock zfs_proplist_t **last; 36472676Seschrock 36482676Seschrock *listp = NULL; 36492676Seschrock last = listp; 36502676Seschrock 36512676Seschrock /* 36522676Seschrock * If 'all' is specified, return a NULL list. 36532676Seschrock */ 36542676Seschrock if (strcmp(fields, "all") == 0) 36552676Seschrock return (0); 36562676Seschrock 36572676Seschrock /* 36582676Seschrock * If no fields were specified, return an error. 36592676Seschrock */ 36602676Seschrock if (fields[0] == '\0') { 36612676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 36622676Seschrock "no properties specified")); 36632676Seschrock return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, 36642676Seschrock "bad property list"))); 36652676Seschrock } 36662676Seschrock 36672676Seschrock /* 36682676Seschrock * It would be nice to use getsubopt() here, but the inclusion of column 36692676Seschrock * aliases makes this more effort than it's worth. 36702676Seschrock */ 36712676Seschrock s = fields; 36722676Seschrock while (*s != '\0') { 36732676Seschrock if ((p = strchr(s, ',')) == NULL) { 36742676Seschrock len = strlen(s); 36752676Seschrock p = s + len; 36762676Seschrock } else { 36772676Seschrock len = p - s; 36782676Seschrock } 36792676Seschrock 36802676Seschrock /* 36812676Seschrock * Check for empty options. 36822676Seschrock */ 36832676Seschrock if (len == 0) { 36842676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 36852676Seschrock "empty property name")); 36862676Seschrock return (zfs_error(hdl, EZFS_BADPROP, 36872676Seschrock dgettext(TEXT_DOMAIN, "bad property list"))); 36882676Seschrock } 36892676Seschrock 36902676Seschrock /* 36912676Seschrock * Check all regular property names. 36922676Seschrock */ 36932676Seschrock c = s[len]; 36942676Seschrock s[len] = '\0'; 36954451Seschrock prop = type == ZFS_TYPE_POOL ? zpool_name_to_prop(s) : 36964451Seschrock zfs_name_to_prop(s); 36973912Slling 36983912Slling if (prop != ZFS_PROP_INVAL && 36993912Slling !zfs_prop_valid_for_type(prop, type)) 37003912Slling prop = ZFS_PROP_INVAL; 37012676Seschrock 37022676Seschrock /* 37033912Slling * When no property table entry can be found, return failure if 37043912Slling * this is a pool property or if this isn't a user-defined 37053912Slling * dataset property, 37062676Seschrock */ 37073912Slling if (prop == ZFS_PROP_INVAL && 37083912Slling (type & ZFS_TYPE_POOL || !zfs_prop_user(s))) { 37092676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 37102676Seschrock "invalid property '%s'"), s); 37112676Seschrock return (zfs_error(hdl, EZFS_BADPROP, 37122676Seschrock dgettext(TEXT_DOMAIN, "bad property list"))); 37132676Seschrock } 37142676Seschrock 37152676Seschrock if ((entry = zfs_alloc(hdl, sizeof (zfs_proplist_t))) == NULL) 37162676Seschrock return (-1); 37172676Seschrock 37182676Seschrock entry->pl_prop = prop; 37192676Seschrock if (prop == ZFS_PROP_INVAL) { 37202676Seschrock if ((entry->pl_user_prop = 37212676Seschrock zfs_strdup(hdl, s)) == NULL) { 37222676Seschrock free(entry); 37232676Seschrock return (-1); 37242676Seschrock } 37252676Seschrock entry->pl_width = strlen(s); 37262676Seschrock } else { 37272676Seschrock entry->pl_width = zfs_prop_width(prop, 37282676Seschrock &entry->pl_fixed); 37292676Seschrock } 37302676Seschrock 37312676Seschrock *last = entry; 37322676Seschrock last = &entry->pl_next; 37332676Seschrock 37342676Seschrock s = p; 37352676Seschrock if (c == ',') 37362676Seschrock s++; 37372676Seschrock } 37382676Seschrock 37392676Seschrock return (0); 37402676Seschrock } 37412676Seschrock 37423912Slling int 37433912Slling zfs_get_proplist(libzfs_handle_t *hdl, char *fields, zfs_proplist_t **listp) 37443912Slling { 37453912Slling return (zfs_get_proplist_common(hdl, fields, listp, ZFS_TYPE_ANY)); 37463912Slling } 37473912Slling 37482676Seschrock void 37492676Seschrock zfs_free_proplist(zfs_proplist_t *pl) 37502676Seschrock { 37512676Seschrock zfs_proplist_t *next; 37522676Seschrock 37532676Seschrock while (pl != NULL) { 37542676Seschrock next = pl->pl_next; 37552676Seschrock free(pl->pl_user_prop); 37562676Seschrock free(pl); 37572676Seschrock pl = next; 37582676Seschrock } 37592676Seschrock } 37602676Seschrock 37613654Sgw25295 typedef struct expand_data { 37623654Sgw25295 zfs_proplist_t **last; 37633654Sgw25295 libzfs_handle_t *hdl; 37643654Sgw25295 } expand_data_t; 37653654Sgw25295 37663654Sgw25295 static zfs_prop_t 37673654Sgw25295 zfs_expand_proplist_cb(zfs_prop_t prop, void *cb) 37683654Sgw25295 { 37693654Sgw25295 zfs_proplist_t *entry; 37703654Sgw25295 expand_data_t *edp = cb; 37713654Sgw25295 37723654Sgw25295 if ((entry = zfs_alloc(edp->hdl, sizeof (zfs_proplist_t))) == NULL) 37733654Sgw25295 return (ZFS_PROP_INVAL); 37743654Sgw25295 37753654Sgw25295 entry->pl_prop = prop; 37763654Sgw25295 entry->pl_width = zfs_prop_width(prop, &entry->pl_fixed); 37773654Sgw25295 entry->pl_all = B_TRUE; 37783654Sgw25295 37793654Sgw25295 *(edp->last) = entry; 37803654Sgw25295 edp->last = &entry->pl_next; 37813654Sgw25295 37823654Sgw25295 return (ZFS_PROP_CONT); 37833654Sgw25295 } 37843654Sgw25295 37852676Seschrock int 37863912Slling zfs_expand_proplist_common(libzfs_handle_t *hdl, zfs_proplist_t **plp, 37873912Slling zfs_type_t type) 37882676Seschrock { 37892676Seschrock zfs_proplist_t *entry; 37903912Slling zfs_proplist_t **last; 37913654Sgw25295 expand_data_t exp; 37922676Seschrock 37932676Seschrock if (*plp == NULL) { 37942676Seschrock /* 37952676Seschrock * If this is the very first time we've been called for an 'all' 37962676Seschrock * specification, expand the list to include all native 37972676Seschrock * properties. 37982676Seschrock */ 37992676Seschrock last = plp; 38003654Sgw25295 38013654Sgw25295 exp.last = last; 38023654Sgw25295 exp.hdl = hdl; 38033654Sgw25295 38043912Slling if (zfs_prop_iter_common(zfs_expand_proplist_cb, &exp, type, 38053654Sgw25295 B_FALSE) == ZFS_PROP_INVAL) 38063654Sgw25295 return (-1); 38072676Seschrock 38082676Seschrock /* 38092676Seschrock * Add 'name' to the beginning of the list, which is handled 38102676Seschrock * specially. 38112676Seschrock */ 38122676Seschrock if ((entry = zfs_alloc(hdl, 38132676Seschrock sizeof (zfs_proplist_t))) == NULL) 38142676Seschrock return (-1); 38152676Seschrock 38162676Seschrock entry->pl_prop = ZFS_PROP_NAME; 38172676Seschrock entry->pl_width = zfs_prop_width(ZFS_PROP_NAME, 38182676Seschrock &entry->pl_fixed); 38192676Seschrock entry->pl_all = B_TRUE; 38202676Seschrock entry->pl_next = *plp; 38212676Seschrock *plp = entry; 38222676Seschrock } 38233912Slling return (0); 38243912Slling } 38253912Slling 38263912Slling /* 38273912Slling * This function is used by 'zfs list' to determine the exact set of columns to 38283912Slling * display, and their maximum widths. This does two main things: 38293912Slling * 38303912Slling * - If this is a list of all properties, then expand the list to include 38313912Slling * all native properties, and set a flag so that for each dataset we look 38323912Slling * for new unique user properties and add them to the list. 38333912Slling * 38343912Slling * - For non fixed-width properties, keep track of the maximum width seen 38353912Slling * so that we can size the column appropriately. 38363912Slling */ 38373912Slling int 38383912Slling zfs_expand_proplist(zfs_handle_t *zhp, zfs_proplist_t **plp) 38393912Slling { 38403912Slling libzfs_handle_t *hdl = zhp->zfs_hdl; 38413912Slling zfs_proplist_t *entry; 38423912Slling zfs_proplist_t **last, **start; 38433912Slling nvlist_t *userprops, *propval; 38443912Slling nvpair_t *elem; 38453912Slling char *strval; 38463912Slling char buf[ZFS_MAXPROPLEN]; 38473912Slling 38483912Slling if (zfs_expand_proplist_common(hdl, plp, ZFS_TYPE_ANY) != 0) 38493912Slling return (-1); 38502676Seschrock 38512676Seschrock userprops = zfs_get_user_props(zhp); 38522676Seschrock 38532676Seschrock entry = *plp; 38542676Seschrock if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) { 38552676Seschrock /* 38562676Seschrock * Go through and add any user properties as necessary. We 38572676Seschrock * start by incrementing our list pointer to the first 38582676Seschrock * non-native property. 38592676Seschrock */ 38602676Seschrock start = plp; 38612676Seschrock while (*start != NULL) { 38622676Seschrock if ((*start)->pl_prop == ZFS_PROP_INVAL) 38632676Seschrock break; 38642676Seschrock start = &(*start)->pl_next; 38652676Seschrock } 38662676Seschrock 38672676Seschrock elem = NULL; 38682676Seschrock while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) { 38692676Seschrock /* 38702676Seschrock * See if we've already found this property in our list. 38712676Seschrock */ 38722676Seschrock for (last = start; *last != NULL; 38732676Seschrock last = &(*last)->pl_next) { 38742676Seschrock if (strcmp((*last)->pl_user_prop, 38752676Seschrock nvpair_name(elem)) == 0) 38762676Seschrock break; 38772676Seschrock } 38782676Seschrock 38792676Seschrock if (*last == NULL) { 38802676Seschrock if ((entry = zfs_alloc(hdl, 38812676Seschrock sizeof (zfs_proplist_t))) == NULL || 38822676Seschrock ((entry->pl_user_prop = zfs_strdup(hdl, 38832676Seschrock nvpair_name(elem)))) == NULL) { 38842676Seschrock free(entry); 38852676Seschrock return (-1); 38862676Seschrock } 38872676Seschrock 38882676Seschrock entry->pl_prop = ZFS_PROP_INVAL; 38892676Seschrock entry->pl_width = strlen(nvpair_name(elem)); 38902676Seschrock entry->pl_all = B_TRUE; 38912676Seschrock *last = entry; 38922676Seschrock } 38932676Seschrock } 38942676Seschrock } 38952676Seschrock 38962676Seschrock /* 38972676Seschrock * Now go through and check the width of any non-fixed columns 38982676Seschrock */ 38992676Seschrock for (entry = *plp; entry != NULL; entry = entry->pl_next) { 39002676Seschrock if (entry->pl_fixed) 39012676Seschrock continue; 39022676Seschrock 39032676Seschrock if (entry->pl_prop != ZFS_PROP_INVAL) { 39042676Seschrock if (zfs_prop_get(zhp, entry->pl_prop, 39052676Seschrock buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0) { 39062676Seschrock if (strlen(buf) > entry->pl_width) 39072676Seschrock entry->pl_width = strlen(buf); 39082676Seschrock } 39092676Seschrock } else if (nvlist_lookup_nvlist(userprops, 39102676Seschrock entry->pl_user_prop, &propval) == 0) { 39112676Seschrock verify(nvlist_lookup_string(propval, 39122676Seschrock ZFS_PROP_VALUE, &strval) == 0); 39132676Seschrock if (strlen(strval) > entry->pl_width) 39142676Seschrock entry->pl_width = strlen(strval); 39152676Seschrock } 39162676Seschrock } 39172676Seschrock 39182676Seschrock return (0); 39192676Seschrock } 3920