1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 213126Sahl 22789Sahrens /* 233363Sgw25295 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24789Sahrens * Use is subject to license terms. 25789Sahrens */ 26789Sahrens 27789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28789Sahrens 29789Sahrens #include <assert.h> 30789Sahrens #include <ctype.h> 31789Sahrens #include <errno.h> 32789Sahrens #include <libdevinfo.h> 33789Sahrens #include <libintl.h> 34789Sahrens #include <math.h> 35789Sahrens #include <stdio.h> 36789Sahrens #include <stdlib.h> 37789Sahrens #include <strings.h> 38789Sahrens #include <unistd.h> 39789Sahrens #include <zone.h> 402082Seschrock #include <fcntl.h> 41789Sahrens #include <sys/mntent.h> 42789Sahrens #include <sys/mnttab.h> 431294Slling #include <sys/mount.h> 44789Sahrens 45789Sahrens #include <sys/spa.h> 46789Sahrens #include <sys/zio.h> 472676Seschrock #include <sys/zap.h> 48789Sahrens #include <libzfs.h> 49789Sahrens 50789Sahrens #include "zfs_namecheck.h" 51789Sahrens #include "zfs_prop.h" 52789Sahrens #include "libzfs_impl.h" 53789Sahrens 544007Smmusante static int zvol_create_link_common(libzfs_handle_t *, const char *, int); 554007Smmusante 56789Sahrens /* 57789Sahrens * Given a single type (not a mask of types), return the type in a human 58789Sahrens * readable form. 59789Sahrens */ 60789Sahrens const char * 61789Sahrens zfs_type_to_name(zfs_type_t type) 62789Sahrens { 63789Sahrens switch (type) { 64789Sahrens case ZFS_TYPE_FILESYSTEM: 65789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 66789Sahrens case ZFS_TYPE_SNAPSHOT: 67789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 68789Sahrens case ZFS_TYPE_VOLUME: 69789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 70789Sahrens } 71789Sahrens 72789Sahrens return (NULL); 73789Sahrens } 74789Sahrens 75789Sahrens /* 76789Sahrens * Given a path and mask of ZFS types, return a string describing this dataset. 77789Sahrens * This is used when we fail to open a dataset and we cannot get an exact type. 78789Sahrens * We guess what the type would have been based on the path and the mask of 79789Sahrens * acceptable types. 80789Sahrens */ 81789Sahrens static const char * 82789Sahrens path_to_str(const char *path, int types) 83789Sahrens { 84789Sahrens /* 85789Sahrens * When given a single type, always report the exact type. 86789Sahrens */ 87789Sahrens if (types == ZFS_TYPE_SNAPSHOT) 88789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 89789Sahrens if (types == ZFS_TYPE_FILESYSTEM) 90789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 91789Sahrens if (types == ZFS_TYPE_VOLUME) 92789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 93789Sahrens 94789Sahrens /* 95789Sahrens * The user is requesting more than one type of dataset. If this is the 96789Sahrens * case, consult the path itself. If we're looking for a snapshot, and 97789Sahrens * a '@' is found, then report it as "snapshot". Otherwise, remove the 98789Sahrens * snapshot attribute and try again. 99789Sahrens */ 100789Sahrens if (types & ZFS_TYPE_SNAPSHOT) { 101789Sahrens if (strchr(path, '@') != NULL) 102789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 103789Sahrens return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 104789Sahrens } 105789Sahrens 106789Sahrens 107789Sahrens /* 108789Sahrens * The user has requested either filesystems or volumes. 109789Sahrens * We have no way of knowing a priori what type this would be, so always 110789Sahrens * report it as "filesystem" or "volume", our two primitive types. 111789Sahrens */ 112789Sahrens if (types & ZFS_TYPE_FILESYSTEM) 113789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 114789Sahrens 115789Sahrens assert(types & ZFS_TYPE_VOLUME); 116789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 117789Sahrens } 118789Sahrens 119789Sahrens /* 120789Sahrens * Validate a ZFS path. This is used even before trying to open the dataset, to 121789Sahrens * provide a more meaningful error message. We place a more useful message in 122789Sahrens * 'buf' detailing exactly why the name was not valid. 123789Sahrens */ 124789Sahrens static int 1252082Seschrock zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type) 126789Sahrens { 127789Sahrens namecheck_err_t why; 128789Sahrens char what; 129789Sahrens 130789Sahrens if (dataset_namecheck(path, &why, &what) != 0) { 1312082Seschrock if (hdl != NULL) { 132789Sahrens switch (why) { 1331003Slling case NAME_ERR_TOOLONG: 1342082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1352082Seschrock "name is too long")); 1361003Slling break; 1371003Slling 138789Sahrens case NAME_ERR_LEADING_SLASH: 1392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1402082Seschrock "leading slash in name")); 141789Sahrens break; 142789Sahrens 143789Sahrens case NAME_ERR_EMPTY_COMPONENT: 1442082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1452082Seschrock "empty component in name")); 146789Sahrens break; 147789Sahrens 148789Sahrens case NAME_ERR_TRAILING_SLASH: 1492082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1502082Seschrock "trailing slash in name")); 151789Sahrens break; 152789Sahrens 153789Sahrens case NAME_ERR_INVALCHAR: 1542082Seschrock zfs_error_aux(hdl, 155789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 1562082Seschrock "'%c' in name"), what); 157789Sahrens break; 158789Sahrens 159789Sahrens case NAME_ERR_MULTIPLE_AT: 1602082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1612082Seschrock "multiple '@' delimiters in name")); 162789Sahrens break; 1632856Snd150628 1642856Snd150628 case NAME_ERR_NOLETTER: 1652856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1662856Snd150628 "pool doesn't begin with a letter")); 1672856Snd150628 break; 1682856Snd150628 1692856Snd150628 case NAME_ERR_RESERVED: 1702856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1712856Snd150628 "name is reserved")); 1722856Snd150628 break; 1732856Snd150628 1742856Snd150628 case NAME_ERR_DISKLIKE: 1752856Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1762856Snd150628 "reserved disk name")); 1772856Snd150628 break; 178789Sahrens } 179789Sahrens } 180789Sahrens 181789Sahrens return (0); 182789Sahrens } 183789Sahrens 184789Sahrens if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) { 1852082Seschrock if (hdl != NULL) 1862082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1872082Seschrock "snapshot delimiter '@' in filesystem name")); 188789Sahrens return (0); 189789Sahrens } 190789Sahrens 1912199Sahrens if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) { 1922199Sahrens if (hdl != NULL) 1932199Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1943413Smmusante "missing '@' delimiter in snapshot name")); 1952199Sahrens return (0); 1962199Sahrens } 1972199Sahrens 1982082Seschrock return (-1); 199789Sahrens } 200789Sahrens 201789Sahrens int 202789Sahrens zfs_name_valid(const char *name, zfs_type_t type) 203789Sahrens { 2042082Seschrock return (zfs_validate_name(NULL, name, type)); 205789Sahrens } 206789Sahrens 207789Sahrens /* 2082676Seschrock * This function takes the raw DSL properties, and filters out the user-defined 2092676Seschrock * properties into a separate nvlist. 2102676Seschrock */ 2112676Seschrock static int 2122676Seschrock process_user_props(zfs_handle_t *zhp) 2132676Seschrock { 2142676Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 2152676Seschrock nvpair_t *elem; 2162676Seschrock nvlist_t *propval; 2172676Seschrock 2182676Seschrock nvlist_free(zhp->zfs_user_props); 2192676Seschrock 2202676Seschrock if (nvlist_alloc(&zhp->zfs_user_props, NV_UNIQUE_NAME, 0) != 0) 2212676Seschrock return (no_memory(hdl)); 2222676Seschrock 2232676Seschrock elem = NULL; 2242676Seschrock while ((elem = nvlist_next_nvpair(zhp->zfs_props, elem)) != NULL) { 2252676Seschrock if (!zfs_prop_user(nvpair_name(elem))) 2262676Seschrock continue; 2272676Seschrock 2282676Seschrock verify(nvpair_value_nvlist(elem, &propval) == 0); 2292676Seschrock if (nvlist_add_nvlist(zhp->zfs_user_props, 2302676Seschrock nvpair_name(elem), propval) != 0) 2312676Seschrock return (no_memory(hdl)); 2322676Seschrock } 2332676Seschrock 2342676Seschrock return (0); 2352676Seschrock } 2362676Seschrock 2372676Seschrock /* 238789Sahrens * Utility function to gather stats (objset and zpl) for the given object. 239789Sahrens */ 240789Sahrens static int 241789Sahrens get_stats(zfs_handle_t *zhp) 242789Sahrens { 243789Sahrens zfs_cmd_t zc = { 0 }; 2442676Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 245789Sahrens 246789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 247789Sahrens 2482676Seschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 2492082Seschrock return (-1); 2501356Seschrock 2512082Seschrock while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) { 2521356Seschrock if (errno == ENOMEM) { 2532676Seschrock if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 2542676Seschrock zcmd_free_nvlists(&zc); 2552082Seschrock return (-1); 2562676Seschrock } 2571356Seschrock } else { 2582676Seschrock zcmd_free_nvlists(&zc); 2591356Seschrock return (-1); 2601356Seschrock } 2611356Seschrock } 262789Sahrens 2632885Sahrens zhp->zfs_dmustats = zc.zc_objset_stats; /* structure assignment */ 264789Sahrens 2652676Seschrock (void) strlcpy(zhp->zfs_root, zc.zc_value, sizeof (zhp->zfs_root)); 2661544Seschrock 2672082Seschrock if (zhp->zfs_props) { 2682082Seschrock nvlist_free(zhp->zfs_props); 2692082Seschrock zhp->zfs_props = NULL; 2702082Seschrock } 2712082Seschrock 2722676Seschrock if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zfs_props) != 0) { 2732676Seschrock zcmd_free_nvlists(&zc); 2742082Seschrock return (-1); 2752082Seschrock } 276789Sahrens 2772676Seschrock zcmd_free_nvlists(&zc); 2782676Seschrock 2792676Seschrock if (process_user_props(zhp) != 0) 2802676Seschrock return (-1); 2812082Seschrock 282789Sahrens return (0); 283789Sahrens } 284789Sahrens 285789Sahrens /* 286789Sahrens * Refresh the properties currently stored in the handle. 287789Sahrens */ 288789Sahrens void 289789Sahrens zfs_refresh_properties(zfs_handle_t *zhp) 290789Sahrens { 291789Sahrens (void) get_stats(zhp); 292789Sahrens } 293789Sahrens 294789Sahrens /* 295789Sahrens * Makes a handle from the given dataset name. Used by zfs_open() and 296789Sahrens * zfs_iter_* to create child handles on the fly. 297789Sahrens */ 298789Sahrens zfs_handle_t * 2992082Seschrock make_dataset_handle(libzfs_handle_t *hdl, const char *path) 300789Sahrens { 3012082Seschrock zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1); 3022082Seschrock 3032082Seschrock if (zhp == NULL) 3042082Seschrock return (NULL); 3052082Seschrock 3062082Seschrock zhp->zfs_hdl = hdl; 307789Sahrens 3081758Sahrens top: 309789Sahrens (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); 310789Sahrens 311789Sahrens if (get_stats(zhp) != 0) { 312789Sahrens free(zhp); 313789Sahrens return (NULL); 314789Sahrens } 315789Sahrens 3161758Sahrens if (zhp->zfs_dmustats.dds_inconsistent) { 3171758Sahrens zfs_cmd_t zc = { 0 }; 3181758Sahrens 3191758Sahrens /* 3201758Sahrens * If it is dds_inconsistent, then we've caught it in 3211758Sahrens * the middle of a 'zfs receive' or 'zfs destroy', and 3221758Sahrens * it is inconsistent from the ZPL's point of view, so 3231758Sahrens * can't be mounted. However, it could also be that we 3241758Sahrens * have crashed in the middle of one of those 3251758Sahrens * operations, in which case we need to get rid of the 3261758Sahrens * inconsistent state. We do that by either rolling 3271758Sahrens * back to the previous snapshot (which will fail if 3281758Sahrens * there is none), or destroying the filesystem. Note 3291758Sahrens * that if we are still in the middle of an active 3301758Sahrens * 'receive' or 'destroy', then the rollback and destroy 3311758Sahrens * will fail with EBUSY and we will drive on as usual. 3321758Sahrens */ 3331758Sahrens 3341758Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3351758Sahrens 3362885Sahrens if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) { 3372082Seschrock (void) zvol_remove_link(hdl, zhp->zfs_name); 3381758Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3391758Sahrens } else { 3401758Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3411758Sahrens } 3421758Sahrens 3431758Sahrens /* If we can successfully roll it back, reget the stats */ 3442082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_ROLLBACK, &zc) == 0) 3451758Sahrens goto top; 3461758Sahrens /* 3471758Sahrens * If we can sucessfully destroy it, pretend that it 3481758Sahrens * never existed. 3491758Sahrens */ 3502082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) == 0) { 3511758Sahrens free(zhp); 3521758Sahrens errno = ENOENT; 3531758Sahrens return (NULL); 3541758Sahrens } 3551758Sahrens } 3561758Sahrens 357789Sahrens /* 358789Sahrens * We've managed to open the dataset and gather statistics. Determine 359789Sahrens * the high-level type. 360789Sahrens */ 3612885Sahrens if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 3622885Sahrens zhp->zfs_head_type = ZFS_TYPE_VOLUME; 3632885Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 3642885Sahrens zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM; 3652885Sahrens else 3662885Sahrens abort(); 3672885Sahrens 368789Sahrens if (zhp->zfs_dmustats.dds_is_snapshot) 369789Sahrens zhp->zfs_type = ZFS_TYPE_SNAPSHOT; 370789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 371789Sahrens zhp->zfs_type = ZFS_TYPE_VOLUME; 372789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 373789Sahrens zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 374789Sahrens else 3752082Seschrock abort(); /* we should never see any other types */ 376789Sahrens 377789Sahrens return (zhp); 378789Sahrens } 379789Sahrens 380789Sahrens /* 381789Sahrens * Opens the given snapshot, filesystem, or volume. The 'types' 382789Sahrens * argument is a mask of acceptable types. The function will print an 383789Sahrens * appropriate error message and return NULL if it can't be opened. 384789Sahrens */ 385789Sahrens zfs_handle_t * 3862082Seschrock zfs_open(libzfs_handle_t *hdl, const char *path, int types) 387789Sahrens { 388789Sahrens zfs_handle_t *zhp; 3892082Seschrock char errbuf[1024]; 3902082Seschrock 3912082Seschrock (void) snprintf(errbuf, sizeof (errbuf), 3922082Seschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), path); 393789Sahrens 394789Sahrens /* 3952082Seschrock * Validate the name before we even try to open it. 396789Sahrens */ 3972082Seschrock if (!zfs_validate_name(hdl, path, ZFS_TYPE_ANY)) { 3982082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3992082Seschrock "invalid dataset name")); 4002082Seschrock (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 401789Sahrens return (NULL); 402789Sahrens } 403789Sahrens 404789Sahrens /* 405789Sahrens * Try to get stats for the dataset, which will tell us if it exists. 406789Sahrens */ 407789Sahrens errno = 0; 4082082Seschrock if ((zhp = make_dataset_handle(hdl, path)) == NULL) { 4093237Slling (void) zfs_standard_error(hdl, errno, errbuf); 410789Sahrens return (NULL); 411789Sahrens } 412789Sahrens 413789Sahrens if (!(types & zhp->zfs_type)) { 4142082Seschrock (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 4152142Seschrock zfs_close(zhp); 416789Sahrens return (NULL); 417789Sahrens } 418789Sahrens 419789Sahrens return (zhp); 420789Sahrens } 421789Sahrens 422789Sahrens /* 423789Sahrens * Release a ZFS handle. Nothing to do but free the associated memory. 424789Sahrens */ 425789Sahrens void 426789Sahrens zfs_close(zfs_handle_t *zhp) 427789Sahrens { 428789Sahrens if (zhp->zfs_mntopts) 429789Sahrens free(zhp->zfs_mntopts); 4302676Seschrock nvlist_free(zhp->zfs_props); 4312676Seschrock nvlist_free(zhp->zfs_user_props); 432789Sahrens free(zhp); 433789Sahrens } 434789Sahrens 435789Sahrens /* 436789Sahrens * Given a numeric suffix, convert the value into a number of bits that the 437789Sahrens * resulting value must be shifted. 438789Sahrens */ 439789Sahrens static int 4402082Seschrock str2shift(libzfs_handle_t *hdl, const char *buf) 441789Sahrens { 442789Sahrens const char *ends = "BKMGTPEZ"; 443789Sahrens int i; 444789Sahrens 445789Sahrens if (buf[0] == '\0') 446789Sahrens return (0); 447789Sahrens for (i = 0; i < strlen(ends); i++) { 448789Sahrens if (toupper(buf[0]) == ends[i]) 449789Sahrens break; 450789Sahrens } 451789Sahrens if (i == strlen(ends)) { 4522082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4532082Seschrock "invalid numeric suffix '%s'"), buf); 454789Sahrens return (-1); 455789Sahrens } 456789Sahrens 457789Sahrens /* 458789Sahrens * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 459789Sahrens * allow 'BB' - that's just weird. 460789Sahrens */ 461789Sahrens if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 4622082Seschrock toupper(buf[0]) != 'B')) 463789Sahrens return (10*i); 4642082Seschrock 4652082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4662082Seschrock "invalid numeric suffix '%s'"), buf); 467789Sahrens return (-1); 468789Sahrens } 469789Sahrens 470789Sahrens /* 471789Sahrens * Convert a string of the form '100G' into a real number. Used when setting 472789Sahrens * properties or creating a volume. 'buf' is used to place an extended error 473789Sahrens * message for the caller to use. 474789Sahrens */ 475789Sahrens static int 4762082Seschrock nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) 477789Sahrens { 478789Sahrens char *end; 479789Sahrens int shift; 480789Sahrens 481789Sahrens *num = 0; 482789Sahrens 483789Sahrens /* Check to see if this looks like a number. */ 484789Sahrens if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 4852082Seschrock if (hdl) 4862082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4872082Seschrock "bad numeric value '%s'"), value); 488789Sahrens return (-1); 489789Sahrens } 490789Sahrens 491789Sahrens /* Rely on stroll() to process the numeric portion. */ 492789Sahrens errno = 0; 493789Sahrens *num = strtoll(value, &end, 10); 494789Sahrens 495789Sahrens /* 496789Sahrens * Check for ERANGE, which indicates that the value is too large to fit 497789Sahrens * in a 64-bit value. 498789Sahrens */ 499789Sahrens if (errno == ERANGE) { 5002082Seschrock if (hdl) 5012082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5022082Seschrock "numeric value is too large")); 503789Sahrens return (-1); 504789Sahrens } 505789Sahrens 506789Sahrens /* 507789Sahrens * If we have a decimal value, then do the computation with floating 508789Sahrens * point arithmetic. Otherwise, use standard arithmetic. 509789Sahrens */ 510789Sahrens if (*end == '.') { 511789Sahrens double fval = strtod(value, &end); 512789Sahrens 5132082Seschrock if ((shift = str2shift(hdl, end)) == -1) 514789Sahrens return (-1); 515789Sahrens 516789Sahrens fval *= pow(2, shift); 517789Sahrens 518789Sahrens if (fval > UINT64_MAX) { 5192082Seschrock if (hdl) 5202082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5212082Seschrock "numeric value is too large")); 522789Sahrens return (-1); 523789Sahrens } 524789Sahrens 525789Sahrens *num = (uint64_t)fval; 526789Sahrens } else { 5272082Seschrock if ((shift = str2shift(hdl, end)) == -1) 528789Sahrens return (-1); 529789Sahrens 530789Sahrens /* Check for overflow */ 531789Sahrens if (shift >= 64 || (*num << shift) >> shift != *num) { 5322082Seschrock if (hdl) 5332082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5342082Seschrock "numeric value is too large")); 535789Sahrens return (-1); 536789Sahrens } 537789Sahrens 538789Sahrens *num <<= shift; 539789Sahrens } 540789Sahrens 541789Sahrens return (0); 542789Sahrens } 543789Sahrens 544789Sahrens int 5452676Seschrock zfs_nicestrtonum(libzfs_handle_t *hdl, const char *str, uint64_t *val) 5462676Seschrock { 5472676Seschrock return (nicestrtonum(hdl, str, val)); 5482676Seschrock } 5492676Seschrock 5502676Seschrock /* 5512676Seschrock * The prop_parse_*() functions are designed to allow flexibility in callers 5522676Seschrock * when setting properties. At the DSL layer, all properties are either 64-bit 5532676Seschrock * numbers or strings. We want the user to be able to ignore this fact and 5542676Seschrock * specify properties as native values (boolean, for example) or as strings (to 5552676Seschrock * simplify command line utilities). This also handles converting index types 5562676Seschrock * (compression, checksum, etc) from strings to their on-disk index. 5572676Seschrock */ 5582676Seschrock 5592676Seschrock static int 5602676Seschrock prop_parse_boolean(libzfs_handle_t *hdl, nvpair_t *elem, uint64_t *val) 561789Sahrens { 5622676Seschrock uint64_t ret; 5632676Seschrock 5642676Seschrock switch (nvpair_type(elem)) { 5652676Seschrock case DATA_TYPE_STRING: 5662676Seschrock { 5672676Seschrock char *value; 5683363Sgw25295 verify(nvpair_value_string(elem, &value) == 0); 5692676Seschrock 5702676Seschrock if (strcmp(value, "on") == 0) { 5712676Seschrock ret = 1; 5722676Seschrock } else if (strcmp(value, "off") == 0) { 5732676Seschrock ret = 0; 5742676Seschrock } else { 5752676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5762676Seschrock "property '%s' must be 'on' or 'off'"), 5772676Seschrock nvpair_name(elem)); 5782676Seschrock return (-1); 5792676Seschrock } 5802676Seschrock break; 5812676Seschrock } 5822676Seschrock 5832676Seschrock case DATA_TYPE_UINT64: 5842676Seschrock { 5853363Sgw25295 verify(nvpair_value_uint64(elem, &ret) == 0); 5862676Seschrock if (ret > 1) { 5872676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 5882676Seschrock "'%s' must be a boolean value"), 5892676Seschrock nvpair_name(elem)); 5902676Seschrock return (-1); 5912676Seschrock } 5922676Seschrock break; 5932676Seschrock } 5942676Seschrock 5952676Seschrock case DATA_TYPE_BOOLEAN_VALUE: 5962676Seschrock { 5972676Seschrock boolean_t value; 5983363Sgw25295 verify(nvpair_value_boolean_value(elem, &value) == 0); 5992676Seschrock ret = value; 6002676Seschrock break; 6012676Seschrock } 6022676Seschrock 6032676Seschrock default: 6042676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6052676Seschrock "'%s' must be a boolean value"), 6062676Seschrock nvpair_name(elem)); 6072676Seschrock return (-1); 6082676Seschrock } 6092676Seschrock 6102676Seschrock *val = ret; 6112676Seschrock return (0); 6122676Seschrock } 6132676Seschrock 6142676Seschrock static int 6152676Seschrock prop_parse_number(libzfs_handle_t *hdl, nvpair_t *elem, zfs_prop_t prop, 6162676Seschrock uint64_t *val) 6172676Seschrock { 6182676Seschrock uint64_t ret; 6192676Seschrock boolean_t isnone = B_FALSE; 6202676Seschrock 6212676Seschrock switch (nvpair_type(elem)) { 6222676Seschrock case DATA_TYPE_STRING: 6232676Seschrock { 6242676Seschrock char *value; 6252676Seschrock (void) nvpair_value_string(elem, &value); 6262676Seschrock if (strcmp(value, "none") == 0) { 6272676Seschrock isnone = B_TRUE; 6282676Seschrock ret = 0; 6292676Seschrock } else if (nicestrtonum(hdl, value, &ret) != 0) { 6302676Seschrock return (-1); 6312676Seschrock } 6322676Seschrock break; 6332676Seschrock } 6342676Seschrock 6352676Seschrock case DATA_TYPE_UINT64: 6362676Seschrock (void) nvpair_value_uint64(elem, &ret); 6372676Seschrock break; 6382676Seschrock 6392676Seschrock default: 6402676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6412676Seschrock "'%s' must be a number"), 6422676Seschrock nvpair_name(elem)); 6432676Seschrock return (-1); 6442676Seschrock } 6452676Seschrock 6462676Seschrock /* 6472676Seschrock * Quota special: force 'none' and don't allow 0. 6482676Seschrock */ 6492676Seschrock if (ret == 0 && !isnone && prop == ZFS_PROP_QUOTA) { 6502676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6512676Seschrock "use 'none' to disable quota")); 6522676Seschrock return (-1); 6532676Seschrock } 6542676Seschrock 6552676Seschrock *val = ret; 6562676Seschrock return (0); 6572676Seschrock } 6582676Seschrock 6592676Seschrock static int 6602676Seschrock prop_parse_index(libzfs_handle_t *hdl, nvpair_t *elem, zfs_prop_t prop, 6612676Seschrock uint64_t *val) 6622676Seschrock { 6632676Seschrock char *propname = nvpair_name(elem); 6642676Seschrock char *value; 6652676Seschrock 6662676Seschrock if (nvpair_type(elem) != DATA_TYPE_STRING) { 6672676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6682676Seschrock "'%s' must be a string"), propname); 6692676Seschrock return (-1); 6702676Seschrock } 6712676Seschrock 6722676Seschrock (void) nvpair_value_string(elem, &value); 6732676Seschrock 6742676Seschrock if (zfs_prop_string_to_index(prop, value, val) != 0) { 6752676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 6762676Seschrock "'%s' must be one of '%s'"), propname, 6772676Seschrock zfs_prop_values(prop)); 6782676Seschrock return (-1); 6792676Seschrock } 6802676Seschrock 6812676Seschrock return (0); 682789Sahrens } 683789Sahrens 684789Sahrens /* 6853912Slling * Check if the bootfs name has the same pool name as it is set to. 6863912Slling * Assuming bootfs is a valid dataset name. 6873912Slling */ 6883912Slling static boolean_t 6893912Slling bootfs_poolname_valid(char *pool, char *bootfs) 6903912Slling { 6913912Slling char ch, *pname; 6923912Slling 6933912Slling /* get the pool name from the bootfs name */ 6943912Slling pname = bootfs; 6953912Slling while (*bootfs && !isspace(*bootfs) && *bootfs != '/') 6963912Slling bootfs++; 6973912Slling 6983912Slling ch = *bootfs; 6993912Slling *bootfs = 0; 7003912Slling 7013912Slling if (strcmp(pool, pname) == 0) { 7023912Slling *bootfs = ch; 7033912Slling return (B_TRUE); 7043912Slling } 7053912Slling 7063912Slling *bootfs = ch; 7073912Slling return (B_FALSE); 7083912Slling } 7093912Slling 7103912Slling /* 7112676Seschrock * Given an nvlist of properties to set, validates that they are correct, and 7122676Seschrock * parses any numeric properties (index, boolean, etc) if they are specified as 7132676Seschrock * strings. 714789Sahrens */ 7153912Slling nvlist_t * 7163912Slling zfs_validate_properties(libzfs_handle_t *hdl, zfs_type_t type, char *pool_name, 7173912Slling nvlist_t *nvl, uint64_t zoned, zfs_handle_t *zhp, const char *errbuf) 718789Sahrens { 7192676Seschrock nvpair_t *elem; 7202676Seschrock const char *propname; 7212676Seschrock zfs_prop_t prop; 7222676Seschrock uint64_t intval; 7232676Seschrock char *strval; 7242676Seschrock nvlist_t *ret; 7253912Slling int isuser; 7262676Seschrock 7272676Seschrock if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) { 7282676Seschrock (void) no_memory(hdl); 7292676Seschrock return (NULL); 7302676Seschrock } 7312676Seschrock 7322676Seschrock if (type == ZFS_TYPE_SNAPSHOT) { 7332676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7343413Smmusante "snapshot properties cannot be modified")); 7352676Seschrock (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 7362676Seschrock goto error; 737789Sahrens } 738789Sahrens 7392676Seschrock elem = NULL; 7402676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 7412676Seschrock propname = nvpair_name(elem); 7422676Seschrock 7432676Seschrock /* 7442676Seschrock * Make sure this property is valid and applies to this type. 7452676Seschrock */ 7463912Slling if ((prop = zfs_name_to_prop_common(propname, type)) 7473912Slling == ZFS_PROP_INVAL) { 7483912Slling isuser = zfs_prop_user(propname); 7493912Slling if (!isuser || (isuser && (type & ZFS_TYPE_POOL))) { 7502676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7512676Seschrock "invalid property '%s'"), 7522676Seschrock propname); 7532676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 7542676Seschrock goto error; 7552676Seschrock } else { 7562676Seschrock /* 7572676Seschrock * If this is a user property, make sure it's a 7582676Seschrock * string, and that it's less than 7592676Seschrock * ZAP_MAXNAMELEN. 7602676Seschrock */ 7612676Seschrock if (nvpair_type(elem) != DATA_TYPE_STRING) { 7622676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7632676Seschrock "'%s' must be a string"), 7642676Seschrock propname); 7652676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 7662676Seschrock errbuf); 7672676Seschrock goto error; 7682676Seschrock } 7692676Seschrock 7702676Seschrock if (strlen(nvpair_name(elem)) >= 7712676Seschrock ZAP_MAXNAMELEN) { 7722676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 7732676Seschrock "property name '%s' is too long"), 7742676Seschrock propname); 7752676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 7762676Seschrock errbuf); 7772676Seschrock goto error; 7782676Seschrock } 7792676Seschrock } 7802676Seschrock 7812676Seschrock (void) nvpair_value_string(elem, &strval); 7822676Seschrock if (nvlist_add_string(ret, propname, strval) != 0) { 7832676Seschrock (void) no_memory(hdl); 7842676Seschrock goto error; 7852676Seschrock } 7862676Seschrock continue; 787789Sahrens } 7882676Seschrock 7892676Seschrock /* 7902676Seschrock * Normalize the name, to get rid of shorthand abbrevations. 7912676Seschrock */ 7922676Seschrock propname = zfs_prop_to_name(prop); 7932676Seschrock 7942676Seschrock if (!zfs_prop_valid_for_type(prop, type)) { 7952676Seschrock zfs_error_aux(hdl, 7962676Seschrock dgettext(TEXT_DOMAIN, "'%s' does not " 7972676Seschrock "apply to datasets of this type"), propname); 7982676Seschrock (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 7992676Seschrock goto error; 8002676Seschrock } 8012676Seschrock 8022676Seschrock if (zfs_prop_readonly(prop) && 8032676Seschrock (prop != ZFS_PROP_VOLBLOCKSIZE || zhp != NULL)) { 8042676Seschrock zfs_error_aux(hdl, 8052676Seschrock dgettext(TEXT_DOMAIN, "'%s' is readonly"), 8062676Seschrock propname); 8072676Seschrock (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); 8082676Seschrock goto error; 8092676Seschrock } 8102676Seschrock 8112676Seschrock /* 8122676Seschrock * Convert any properties to the internal DSL value types. 8132676Seschrock */ 8142676Seschrock strval = NULL; 8152676Seschrock switch (zfs_prop_get_type(prop)) { 8162676Seschrock case prop_type_boolean: 8172676Seschrock if (prop_parse_boolean(hdl, elem, &intval) != 0) { 8182676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8192676Seschrock goto error; 8202676Seschrock } 821789Sahrens break; 8222676Seschrock 8232676Seschrock case prop_type_string: 8242676Seschrock if (nvpair_type(elem) != DATA_TYPE_STRING) { 8252082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8262676Seschrock "'%s' must be a string"), 8272676Seschrock propname); 8282676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8292676Seschrock goto error; 830789Sahrens } 8312676Seschrock (void) nvpair_value_string(elem, &strval); 8322676Seschrock if (strlen(strval) >= ZFS_MAXPROPLEN) { 8332082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8342676Seschrock "'%s' is too long"), propname); 8352676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8362676Seschrock goto error; 8372676Seschrock } 8382676Seschrock break; 8392676Seschrock 8402676Seschrock case prop_type_number: 8412676Seschrock if (prop_parse_number(hdl, elem, prop, &intval) != 0) { 8422676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8432676Seschrock goto error; 8442676Seschrock } 8452676Seschrock break; 8462676Seschrock 8472676Seschrock case prop_type_index: 8482676Seschrock if (prop_parse_index(hdl, elem, prop, &intval) != 0) { 8492676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8502676Seschrock goto error; 851789Sahrens } 852789Sahrens break; 853789Sahrens 8542676Seschrock default: 8552676Seschrock abort(); 8562676Seschrock } 8572676Seschrock 8582676Seschrock /* 8592676Seschrock * Add the result to our return set of properties. 8602676Seschrock */ 8612676Seschrock if (strval) { 8622676Seschrock if (nvlist_add_string(ret, propname, strval) != 0) { 8632676Seschrock (void) no_memory(hdl); 8642676Seschrock goto error; 865789Sahrens } 8662676Seschrock } else if (nvlist_add_uint64(ret, propname, intval) != 0) { 8672676Seschrock (void) no_memory(hdl); 8682676Seschrock goto error; 8692676Seschrock } 8702676Seschrock 8712676Seschrock /* 8722676Seschrock * Perform some additional checks for specific properties. 8732676Seschrock */ 8742676Seschrock switch (prop) { 8752676Seschrock case ZFS_PROP_RECORDSIZE: 8762676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 8772676Seschrock /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */ 8782676Seschrock if (intval < SPA_MINBLOCKSIZE || 8792676Seschrock intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) { 8802082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8812676Seschrock "'%s' must be power of 2 from %u " 8822676Seschrock "to %uk"), propname, 8832676Seschrock (uint_t)SPA_MINBLOCKSIZE, 8842676Seschrock (uint_t)SPA_MAXBLOCKSIZE >> 10); 8852676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8862676Seschrock goto error; 887789Sahrens } 888789Sahrens break; 889789Sahrens 8903126Sahl case ZFS_PROP_SHAREISCSI: 8913126Sahl if (strcmp(strval, "off") != 0 && 8923126Sahl strcmp(strval, "on") != 0 && 8933126Sahl strcmp(strval, "type=disk") != 0) { 8943126Sahl zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 8953126Sahl "'%s' must be 'on', 'off', or 'type=disk'"), 8963126Sahl propname); 8973126Sahl (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 8983126Sahl goto error; 8993126Sahl } 9003126Sahl 9013126Sahl break; 9023126Sahl 9032676Seschrock case ZFS_PROP_MOUNTPOINT: 9042676Seschrock if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 || 9052676Seschrock strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0) 9062676Seschrock break; 9072676Seschrock 9082676Seschrock if (strval[0] != '/') { 9092082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9102676Seschrock "'%s' must be an absolute path, " 9112676Seschrock "'none', or 'legacy'"), propname); 9122676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 9132676Seschrock goto error; 914789Sahrens } 9153126Sahl /*FALLTHRU*/ 9163126Sahl 9173126Sahl case ZFS_PROP_SHARENFS: 9183126Sahl /* 9193126Sahl * For the mountpoint and sharenfs properties, check if 9203126Sahl * it can be set in a global/non-global zone based on 9213126Sahl * the zoned property value: 9223126Sahl * 9233126Sahl * global zone non-global zone 9243126Sahl * -------------------------------------------------- 9253126Sahl * zoned=on mountpoint (no) mountpoint (yes) 9263126Sahl * sharenfs (no) sharenfs (no) 9273126Sahl * 9283126Sahl * zoned=off mountpoint (yes) N/A 9293126Sahl * sharenfs (yes) 9303126Sahl */ 9312676Seschrock if (zoned) { 9322676Seschrock if (getzoneid() == GLOBAL_ZONEID) { 9332676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9342676Seschrock "'%s' cannot be set on " 9352676Seschrock "dataset in a non-global zone"), 9362676Seschrock propname); 9372676Seschrock (void) zfs_error(hdl, EZFS_ZONED, 9382676Seschrock errbuf); 9392676Seschrock goto error; 9402676Seschrock } else if (prop == ZFS_PROP_SHARENFS) { 9412676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9422676Seschrock "'%s' cannot be set in " 9432676Seschrock "a non-global zone"), propname); 9442676Seschrock (void) zfs_error(hdl, EZFS_ZONED, 9452676Seschrock errbuf); 9462676Seschrock goto error; 9472676Seschrock } 9482676Seschrock } else if (getzoneid() != GLOBAL_ZONEID) { 9492676Seschrock /* 9502676Seschrock * If zoned property is 'off', this must be in 9512676Seschrock * a globle zone. If not, something is wrong. 9522676Seschrock */ 9532676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9542676Seschrock "'%s' cannot be set while dataset " 9552676Seschrock "'zoned' property is set"), propname); 9562676Seschrock (void) zfs_error(hdl, EZFS_ZONED, errbuf); 9572676Seschrock goto error; 9582676Seschrock } 9593126Sahl 960*4180Sdougm /* 961*4180Sdougm * At this point, it is legitimate to set the 962*4180Sdougm * property. Now we want to make sure that the 963*4180Sdougm * property value is valid if it is sharenfs. 964*4180Sdougm */ 965*4180Sdougm if (prop == ZFS_PROP_SHARENFS && 966*4180Sdougm strcmp(strval, "on") != 0 && 967*4180Sdougm strcmp(strval, "off") != 0) { 968*4180Sdougm 969*4180Sdougm /* 970*4180Sdougm * Must be an NFS option string so 971*4180Sdougm * init the libshare in order to 972*4180Sdougm * enable the parser and then parse 973*4180Sdougm * the options. We use the control API 974*4180Sdougm * since we don't care about the 975*4180Sdougm * current configuration and don't 976*4180Sdougm * want the overhead of loading it 977*4180Sdougm * until we actually do something. 978*4180Sdougm */ 979*4180Sdougm 980*4180Sdougm if (zfs_init_libshare(hdl, 981*4180Sdougm SA_INIT_CONTROL_API) != SA_OK) { 982*4180Sdougm /* An error occurred so we can't do anything */ 983*4180Sdougm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 984*4180Sdougm "'%s' cannot be set: problem " 985*4180Sdougm "in share initialization"), 986*4180Sdougm propname); 987*4180Sdougm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 988*4180Sdougm goto error; 989*4180Sdougm } 990*4180Sdougm 991*4180Sdougm if (zfs_parse_options(strval, "nfs") != SA_OK) { 992*4180Sdougm /* 993*4180Sdougm * There was an error in parsing so 994*4180Sdougm * deal with it by issuing an error 995*4180Sdougm * message and leaving after 996*4180Sdougm * uninitializing the the libshare 997*4180Sdougm * interface. 998*4180Sdougm */ 999*4180Sdougm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1000*4180Sdougm "'%s' cannot be set to invalid " 1001*4180Sdougm "options"), propname); 1002*4180Sdougm (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 1003*4180Sdougm zfs_uninit_libshare(hdl); 1004*4180Sdougm goto error; 1005*4180Sdougm } 1006*4180Sdougm zfs_uninit_libshare(hdl); 1007*4180Sdougm } 1008*4180Sdougm 10093126Sahl break; 10103912Slling 10113912Slling case ZFS_PROP_BOOTFS: 10123912Slling /* 10133912Slling * bootfs property value has to be a dataset name and 10143912Slling * the dataset has to be in the same pool as it sets to. 10153912Slling */ 10163912Slling if (strval[0] != '\0' && (!zfs_name_valid(strval, 10173912Slling ZFS_TYPE_FILESYSTEM) || !bootfs_poolname_valid( 10183912Slling pool_name, strval))) { 10193912Slling 10203912Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' " 10213912Slling "is an invalid name"), strval); 10223912Slling (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 10233912Slling goto error; 10243912Slling } 10253912Slling break; 10262676Seschrock } 10272676Seschrock 10282676Seschrock /* 10292676Seschrock * For changes to existing volumes, we have some additional 10302676Seschrock * checks to enforce. 10312676Seschrock */ 10322676Seschrock if (type == ZFS_TYPE_VOLUME && zhp != NULL) { 10332676Seschrock uint64_t volsize = zfs_prop_get_int(zhp, 10342676Seschrock ZFS_PROP_VOLSIZE); 10352676Seschrock uint64_t blocksize = zfs_prop_get_int(zhp, 10362676Seschrock ZFS_PROP_VOLBLOCKSIZE); 10372676Seschrock char buf[64]; 10382676Seschrock 10392676Seschrock switch (prop) { 10402676Seschrock case ZFS_PROP_RESERVATION: 10412676Seschrock if (intval > volsize) { 10422676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10432676Seschrock "'%s' is greater than current " 10442676Seschrock "volume size"), propname); 10452676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10462676Seschrock errbuf); 10472676Seschrock goto error; 10482676Seschrock } 10492676Seschrock break; 10502676Seschrock 10512676Seschrock case ZFS_PROP_VOLSIZE: 10522676Seschrock if (intval % blocksize != 0) { 10532676Seschrock zfs_nicenum(blocksize, buf, 10542676Seschrock sizeof (buf)); 10552676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10562676Seschrock "'%s' must be a multiple of " 10572676Seschrock "volume block size (%s)"), 10582676Seschrock propname, buf); 10592676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10602676Seschrock errbuf); 10612676Seschrock goto error; 10622676Seschrock } 10632676Seschrock 10642676Seschrock if (intval == 0) { 10652676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10662676Seschrock "'%s' cannot be zero"), 10672676Seschrock propname); 10682676Seschrock (void) zfs_error(hdl, EZFS_BADPROP, 10692676Seschrock errbuf); 10702676Seschrock goto error; 1071789Sahrens } 10723126Sahl break; 1073789Sahrens } 1074789Sahrens } 1075789Sahrens } 1076789Sahrens 10772676Seschrock /* 10782676Seschrock * If this is an existing volume, and someone is setting the volsize, 10792676Seschrock * make sure that it matches the reservation, or add it if necessary. 10802676Seschrock */ 10812676Seschrock if (zhp != NULL && type == ZFS_TYPE_VOLUME && 10822676Seschrock nvlist_lookup_uint64(ret, zfs_prop_to_name(ZFS_PROP_VOLSIZE), 10832676Seschrock &intval) == 0) { 10842676Seschrock uint64_t old_volsize = zfs_prop_get_int(zhp, 10852676Seschrock ZFS_PROP_VOLSIZE); 10862676Seschrock uint64_t old_reservation = zfs_prop_get_int(zhp, 10872676Seschrock ZFS_PROP_RESERVATION); 10882676Seschrock uint64_t new_reservation; 10892676Seschrock 10902676Seschrock if (old_volsize == old_reservation && 10912676Seschrock nvlist_lookup_uint64(ret, 10922676Seschrock zfs_prop_to_name(ZFS_PROP_RESERVATION), 10932676Seschrock &new_reservation) != 0) { 10942676Seschrock if (nvlist_add_uint64(ret, 10952676Seschrock zfs_prop_to_name(ZFS_PROP_RESERVATION), 10962676Seschrock intval) != 0) { 10972676Seschrock (void) no_memory(hdl); 10982676Seschrock goto error; 10992676Seschrock } 11002676Seschrock } 11012676Seschrock } 11022676Seschrock 11032676Seschrock return (ret); 11042676Seschrock 11052676Seschrock error: 11062676Seschrock nvlist_free(ret); 11072676Seschrock return (NULL); 1108789Sahrens } 1109789Sahrens 1110789Sahrens /* 1111789Sahrens * Given a property name and value, set the property for the given dataset. 1112789Sahrens */ 1113789Sahrens int 11142676Seschrock zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) 1115789Sahrens { 1116789Sahrens zfs_cmd_t zc = { 0 }; 11172676Seschrock int ret = -1; 11182676Seschrock prop_changelist_t *cl = NULL; 11192082Seschrock char errbuf[1024]; 11202082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 11212676Seschrock nvlist_t *nvl = NULL, *realprops; 11222676Seschrock zfs_prop_t prop; 11232082Seschrock 11242082Seschrock (void) snprintf(errbuf, sizeof (errbuf), 11252676Seschrock dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 11262082Seschrock zhp->zfs_name); 11272082Seschrock 11282676Seschrock if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || 11292676Seschrock nvlist_add_string(nvl, propname, propval) != 0) { 11302676Seschrock (void) no_memory(hdl); 11312676Seschrock goto error; 1132789Sahrens } 1133789Sahrens 11343912Slling if ((realprops = zfs_validate_properties(hdl, zhp->zfs_type, NULL, nvl, 11352676Seschrock zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL) 11362676Seschrock goto error; 11372676Seschrock nvlist_free(nvl); 11382676Seschrock nvl = realprops; 11392676Seschrock 11402676Seschrock prop = zfs_name_to_prop(propname); 11412676Seschrock 1142789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 11432676Seschrock goto error; 1144789Sahrens 1145789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 11462082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11472082Seschrock "child dataset with inherited mountpoint is used " 11482082Seschrock "in a non-global zone")); 11492082Seschrock ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1150789Sahrens goto error; 1151789Sahrens } 1152789Sahrens 1153789Sahrens if ((ret = changelist_prefix(cl)) != 0) 1154789Sahrens goto error; 1155789Sahrens 1156789Sahrens /* 1157789Sahrens * Execute the corresponding ioctl() to set this property. 1158789Sahrens */ 1159789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1160789Sahrens 11612676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, nvl, NULL) != 0) 11622676Seschrock goto error; 11632676Seschrock 11642676Seschrock ret = ioctl(hdl->libzfs_fd, ZFS_IOC_SET_PROP, &zc); 1165789Sahrens 1166789Sahrens if (ret != 0) { 1167789Sahrens switch (errno) { 1168789Sahrens 1169789Sahrens case ENOSPC: 1170789Sahrens /* 1171789Sahrens * For quotas and reservations, ENOSPC indicates 1172789Sahrens * something different; setting a quota or reservation 1173789Sahrens * doesn't use any disk space. 1174789Sahrens */ 1175789Sahrens switch (prop) { 1176789Sahrens case ZFS_PROP_QUOTA: 11772082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11782082Seschrock "size is less than current used or " 11792082Seschrock "reserved space")); 11802082Seschrock (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1181789Sahrens break; 1182789Sahrens 1183789Sahrens case ZFS_PROP_RESERVATION: 11842082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11852082Seschrock "size is greater than available space")); 11862082Seschrock (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1187789Sahrens break; 1188789Sahrens 1189789Sahrens default: 11902082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 1191789Sahrens break; 1192789Sahrens } 1193789Sahrens break; 1194789Sahrens 1195789Sahrens case EBUSY: 11962082Seschrock if (prop == ZFS_PROP_VOLBLOCKSIZE) 11972082Seschrock (void) zfs_error(hdl, EZFS_VOLHASDATA, errbuf); 11982082Seschrock else 11992676Seschrock (void) zfs_standard_error(hdl, EBUSY, errbuf); 1200789Sahrens break; 1201789Sahrens 12021175Slling case EROFS: 12032082Seschrock (void) zfs_error(hdl, EZFS_DSREADONLY, errbuf); 12041175Slling break; 12051175Slling 12063886Sahl case ENOTSUP: 12073886Sahl zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12083886Sahl "pool must be upgraded to allow gzip compression")); 12093886Sahl (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 12103886Sahl break; 12113886Sahl 1212789Sahrens case EOVERFLOW: 1213789Sahrens /* 1214789Sahrens * This platform can't address a volume this big. 1215789Sahrens */ 1216789Sahrens #ifdef _ILP32 1217789Sahrens if (prop == ZFS_PROP_VOLSIZE) { 12182082Seschrock (void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf); 1219789Sahrens break; 1220789Sahrens } 1221789Sahrens #endif 12222082Seschrock /* FALLTHROUGH */ 1223789Sahrens default: 12242082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 1225789Sahrens } 1226789Sahrens } else { 1227789Sahrens /* 1228789Sahrens * Refresh the statistics so the new property value 1229789Sahrens * is reflected. 1230789Sahrens */ 12312676Seschrock if ((ret = changelist_postfix(cl)) == 0) 12322676Seschrock (void) get_stats(zhp); 1233789Sahrens } 1234789Sahrens 1235789Sahrens error: 12362676Seschrock nvlist_free(nvl); 12372676Seschrock zcmd_free_nvlists(&zc); 12382676Seschrock if (cl) 12392676Seschrock changelist_free(cl); 1240789Sahrens return (ret); 1241789Sahrens } 1242789Sahrens 1243789Sahrens /* 1244789Sahrens * Given a property, inherit the value from the parent dataset. 1245789Sahrens */ 1246789Sahrens int 12472676Seschrock zfs_prop_inherit(zfs_handle_t *zhp, const char *propname) 1248789Sahrens { 1249789Sahrens zfs_cmd_t zc = { 0 }; 1250789Sahrens int ret; 1251789Sahrens prop_changelist_t *cl; 12522082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 12532082Seschrock char errbuf[1024]; 12542676Seschrock zfs_prop_t prop; 12552082Seschrock 12562082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 12572082Seschrock "cannot inherit %s for '%s'"), propname, zhp->zfs_name); 1258789Sahrens 12592676Seschrock if ((prop = zfs_name_to_prop(propname)) == ZFS_PROP_INVAL) { 12602676Seschrock /* 12612676Seschrock * For user properties, the amount of work we have to do is very 12622676Seschrock * small, so just do it here. 12632676Seschrock */ 12642676Seschrock if (!zfs_prop_user(propname)) { 12652676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12662676Seschrock "invalid property")); 12672676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 12682676Seschrock } 12692676Seschrock 12702676Seschrock (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 12712676Seschrock (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 12722676Seschrock 12732676Seschrock if (ioctl(zhp->zfs_hdl->libzfs_fd, 12742676Seschrock ZFS_IOC_SET_PROP, &zc) != 0) 12752676Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 12762676Seschrock 12772676Seschrock return (0); 12782676Seschrock } 12792676Seschrock 1280789Sahrens /* 1281789Sahrens * Verify that this property is inheritable. 1282789Sahrens */ 12832082Seschrock if (zfs_prop_readonly(prop)) 12842082Seschrock return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf)); 12852082Seschrock 12862082Seschrock if (!zfs_prop_inheritable(prop)) 12872082Seschrock return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf)); 1288789Sahrens 1289789Sahrens /* 1290789Sahrens * Check to see if the value applies to this type 1291789Sahrens */ 12922082Seschrock if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 12932082Seschrock return (zfs_error(hdl, EZFS_PROPTYPE, errbuf)); 1294789Sahrens 12953443Srm160521 /* 12963443Srm160521 * Normalize the name, to get rid of shorthand abbrevations. 12973443Srm160521 */ 12983443Srm160521 propname = zfs_prop_to_name(prop); 1299789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 13002676Seschrock (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 1301789Sahrens 1302789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID && 1303789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 13042082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 13052082Seschrock "dataset is used in a non-global zone")); 13062082Seschrock return (zfs_error(hdl, EZFS_ZONED, errbuf)); 1307789Sahrens } 1308789Sahrens 1309789Sahrens /* 1310789Sahrens * Determine datasets which will be affected by this change, if any. 1311789Sahrens */ 1312789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 1313789Sahrens return (-1); 1314789Sahrens 1315789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 13162082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 13172082Seschrock "child dataset with inherited mountpoint is used " 13182082Seschrock "in a non-global zone")); 13192082Seschrock ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1320789Sahrens goto error; 1321789Sahrens } 1322789Sahrens 1323789Sahrens if ((ret = changelist_prefix(cl)) != 0) 1324789Sahrens goto error; 1325789Sahrens 13262082Seschrock if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, 13272082Seschrock ZFS_IOC_SET_PROP, &zc)) != 0) { 13282082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 1329789Sahrens } else { 1330789Sahrens 13312169Snd150628 if ((ret = changelist_postfix(cl)) != 0) 1332789Sahrens goto error; 1333789Sahrens 1334789Sahrens /* 1335789Sahrens * Refresh the statistics so the new property is reflected. 1336789Sahrens */ 1337789Sahrens (void) get_stats(zhp); 1338789Sahrens } 1339789Sahrens 1340789Sahrens error: 1341789Sahrens changelist_free(cl); 1342789Sahrens return (ret); 1343789Sahrens } 1344789Sahrens 13453912Slling void 1346789Sahrens nicebool(int value, char *buf, size_t buflen) 1347789Sahrens { 1348789Sahrens if (value) 1349789Sahrens (void) strlcpy(buf, "on", buflen); 1350789Sahrens else 1351789Sahrens (void) strlcpy(buf, "off", buflen); 1352789Sahrens } 1353789Sahrens 1354789Sahrens /* 13551356Seschrock * True DSL properties are stored in an nvlist. The following two functions 13561356Seschrock * extract them appropriately. 13571356Seschrock */ 13581356Seschrock static uint64_t 13591356Seschrock getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 13601356Seschrock { 13611356Seschrock nvlist_t *nv; 13621356Seschrock uint64_t value; 13631356Seschrock 13642885Sahrens *source = NULL; 13651356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 13661356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 13671356Seschrock verify(nvlist_lookup_uint64(nv, ZFS_PROP_VALUE, &value) == 0); 13682885Sahrens (void) nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source); 13691356Seschrock } else { 13701356Seschrock value = zfs_prop_default_numeric(prop); 13711356Seschrock *source = ""; 13721356Seschrock } 13731356Seschrock 13741356Seschrock return (value); 13751356Seschrock } 13761356Seschrock 13771356Seschrock static char * 13781356Seschrock getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 13791356Seschrock { 13801356Seschrock nvlist_t *nv; 13811356Seschrock char *value; 13821356Seschrock 13832885Sahrens *source = NULL; 13841356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 13851356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 13861356Seschrock verify(nvlist_lookup_string(nv, ZFS_PROP_VALUE, &value) == 0); 13872885Sahrens (void) nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source); 13881356Seschrock } else { 13891356Seschrock if ((value = (char *)zfs_prop_default_string(prop)) == NULL) 13901356Seschrock value = ""; 13911356Seschrock *source = ""; 13921356Seschrock } 13931356Seschrock 13941356Seschrock return (value); 13951356Seschrock } 13961356Seschrock 13971356Seschrock /* 1398789Sahrens * Internal function for getting a numeric property. Both zfs_prop_get() and 1399789Sahrens * zfs_prop_get_int() are built using this interface. 1400789Sahrens * 1401789Sahrens * Certain properties can be overridden using 'mount -o'. In this case, scan 1402789Sahrens * the contents of the /etc/mnttab entry, searching for the appropriate options. 1403789Sahrens * If they differ from the on-disk values, report the current values and mark 1404789Sahrens * the source "temporary". 1405789Sahrens */ 14062082Seschrock static int 1407789Sahrens get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zfs_source_t *src, 14082082Seschrock char **source, uint64_t *val) 1409789Sahrens { 1410789Sahrens struct mnttab mnt; 14113265Sahrens char *mntopt_on = NULL; 14123265Sahrens char *mntopt_off = NULL; 1413789Sahrens 1414789Sahrens *source = NULL; 1415789Sahrens 14163265Sahrens switch (prop) { 14173265Sahrens case ZFS_PROP_ATIME: 14183265Sahrens mntopt_on = MNTOPT_ATIME; 14193265Sahrens mntopt_off = MNTOPT_NOATIME; 14203265Sahrens break; 14213265Sahrens 14223265Sahrens case ZFS_PROP_DEVICES: 14233265Sahrens mntopt_on = MNTOPT_DEVICES; 14243265Sahrens mntopt_off = MNTOPT_NODEVICES; 14253265Sahrens break; 14263265Sahrens 14273265Sahrens case ZFS_PROP_EXEC: 14283265Sahrens mntopt_on = MNTOPT_EXEC; 14293265Sahrens mntopt_off = MNTOPT_NOEXEC; 14303265Sahrens break; 14313265Sahrens 14323265Sahrens case ZFS_PROP_READONLY: 14333265Sahrens mntopt_on = MNTOPT_RO; 14343265Sahrens mntopt_off = MNTOPT_RW; 14353265Sahrens break; 14363265Sahrens 14373265Sahrens case ZFS_PROP_SETUID: 14383265Sahrens mntopt_on = MNTOPT_SETUID; 14393265Sahrens mntopt_off = MNTOPT_NOSETUID; 14403265Sahrens break; 14413265Sahrens 14423265Sahrens case ZFS_PROP_XATTR: 14433265Sahrens mntopt_on = MNTOPT_XATTR; 14443265Sahrens mntopt_off = MNTOPT_NOXATTR; 14453265Sahrens break; 14463265Sahrens } 14473265Sahrens 14482474Seschrock /* 14492474Seschrock * Because looking up the mount options is potentially expensive 14502474Seschrock * (iterating over all of /etc/mnttab), we defer its calculation until 14512474Seschrock * we're looking up a property which requires its presence. 14522474Seschrock */ 14532474Seschrock if (!zhp->zfs_mntcheck && 14543265Sahrens (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { 14553265Sahrens struct mnttab entry, search = { 0 }; 14563265Sahrens FILE *mnttab = zhp->zfs_hdl->libzfs_mnttab; 14572474Seschrock 14582474Seschrock search.mnt_special = (char *)zhp->zfs_name; 14592474Seschrock search.mnt_fstype = MNTTYPE_ZFS; 14603265Sahrens rewind(mnttab); 14613265Sahrens 14623265Sahrens if (getmntany(mnttab, &entry, &search) == 0) { 14633265Sahrens zhp->zfs_mntopts = zfs_strdup(zhp->zfs_hdl, 14643265Sahrens entry.mnt_mntopts); 14653265Sahrens if (zhp->zfs_mntopts == NULL) 14663265Sahrens return (-1); 14673265Sahrens } 14682474Seschrock 14692474Seschrock zhp->zfs_mntcheck = B_TRUE; 14702474Seschrock } 14712474Seschrock 1472789Sahrens if (zhp->zfs_mntopts == NULL) 1473789Sahrens mnt.mnt_mntopts = ""; 1474789Sahrens else 1475789Sahrens mnt.mnt_mntopts = zhp->zfs_mntopts; 1476789Sahrens 1477789Sahrens switch (prop) { 1478789Sahrens case ZFS_PROP_ATIME: 14793265Sahrens case ZFS_PROP_DEVICES: 14803265Sahrens case ZFS_PROP_EXEC: 14813265Sahrens case ZFS_PROP_READONLY: 14823265Sahrens case ZFS_PROP_SETUID: 14833265Sahrens case ZFS_PROP_XATTR: 14842082Seschrock *val = getprop_uint64(zhp, prop, source); 14852082Seschrock 14863265Sahrens if (hasmntopt(&mnt, mntopt_on) && !*val) { 14872082Seschrock *val = B_TRUE; 1488789Sahrens if (src) 1489789Sahrens *src = ZFS_SRC_TEMPORARY; 14903265Sahrens } else if (hasmntopt(&mnt, mntopt_off) && *val) { 14912082Seschrock *val = B_FALSE; 1492789Sahrens if (src) 1493789Sahrens *src = ZFS_SRC_TEMPORARY; 1494789Sahrens } 14952082Seschrock break; 1496789Sahrens 1497789Sahrens case ZFS_PROP_RECORDSIZE: 1498789Sahrens case ZFS_PROP_COMPRESSION: 14991356Seschrock case ZFS_PROP_ZONED: 15002885Sahrens case ZFS_PROP_CREATION: 15012885Sahrens case ZFS_PROP_COMPRESSRATIO: 15022885Sahrens case ZFS_PROP_REFERENCED: 15032885Sahrens case ZFS_PROP_USED: 15042885Sahrens case ZFS_PROP_CREATETXG: 15052885Sahrens case ZFS_PROP_AVAILABLE: 15062885Sahrens case ZFS_PROP_VOLSIZE: 15072885Sahrens case ZFS_PROP_VOLBLOCKSIZE: 15083417Srm160521 *val = getprop_uint64(zhp, prop, source); 15093417Srm160521 break; 15103417Srm160521 15113265Sahrens case ZFS_PROP_CANMOUNT: 15122082Seschrock *val = getprop_uint64(zhp, prop, source); 15133417Srm160521 if (*val == 0) 15143417Srm160521 *source = zhp->zfs_name; 15153417Srm160521 else 15163417Srm160521 *source = ""; /* default */ 15172082Seschrock break; 1518789Sahrens 1519789Sahrens case ZFS_PROP_QUOTA: 1520789Sahrens case ZFS_PROP_RESERVATION: 15212885Sahrens *val = getprop_uint64(zhp, prop, source); 15222885Sahrens if (*val == 0) 1523789Sahrens *source = ""; /* default */ 1524789Sahrens else 1525789Sahrens *source = zhp->zfs_name; 15262082Seschrock break; 1527789Sahrens 1528789Sahrens case ZFS_PROP_MOUNTED: 15292082Seschrock *val = (zhp->zfs_mntopts != NULL); 15302082Seschrock break; 1531789Sahrens 15323377Seschrock case ZFS_PROP_NUMCLONES: 15333377Seschrock *val = zhp->zfs_dmustats.dds_num_clones; 15343377Seschrock break; 15353377Seschrock 1536789Sahrens default: 15372082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 15382082Seschrock "cannot get non-numeric property")); 15392082Seschrock return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP, 15402082Seschrock dgettext(TEXT_DOMAIN, "internal error"))); 1541789Sahrens } 1542789Sahrens 1543789Sahrens return (0); 1544789Sahrens } 1545789Sahrens 1546789Sahrens /* 1547789Sahrens * Calculate the source type, given the raw source string. 1548789Sahrens */ 1549789Sahrens static void 1550789Sahrens get_source(zfs_handle_t *zhp, zfs_source_t *srctype, char *source, 1551789Sahrens char *statbuf, size_t statlen) 1552789Sahrens { 1553789Sahrens if (statbuf == NULL || *srctype == ZFS_SRC_TEMPORARY) 1554789Sahrens return; 1555789Sahrens 1556789Sahrens if (source == NULL) { 1557789Sahrens *srctype = ZFS_SRC_NONE; 1558789Sahrens } else if (source[0] == '\0') { 1559789Sahrens *srctype = ZFS_SRC_DEFAULT; 1560789Sahrens } else { 1561789Sahrens if (strcmp(source, zhp->zfs_name) == 0) { 1562789Sahrens *srctype = ZFS_SRC_LOCAL; 1563789Sahrens } else { 1564789Sahrens (void) strlcpy(statbuf, source, statlen); 1565789Sahrens *srctype = ZFS_SRC_INHERITED; 1566789Sahrens } 1567789Sahrens } 1568789Sahrens 1569789Sahrens } 1570789Sahrens 1571789Sahrens /* 1572789Sahrens * Retrieve a property from the given object. If 'literal' is specified, then 1573789Sahrens * numbers are left as exact values. Otherwise, numbers are converted to a 1574789Sahrens * human-readable form. 1575789Sahrens * 1576789Sahrens * Returns 0 on success, or -1 on error. 1577789Sahrens */ 1578789Sahrens int 1579789Sahrens zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, 15802082Seschrock zfs_source_t *src, char *statbuf, size_t statlen, boolean_t literal) 1581789Sahrens { 1582789Sahrens char *source = NULL; 1583789Sahrens uint64_t val; 1584789Sahrens char *str; 1585789Sahrens const char *root; 15862676Seschrock const char *strval; 1587789Sahrens 1588789Sahrens /* 1589789Sahrens * Check to see if this property applies to our object 1590789Sahrens */ 1591789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1592789Sahrens return (-1); 1593789Sahrens 1594789Sahrens if (src) 1595789Sahrens *src = ZFS_SRC_NONE; 1596789Sahrens 1597789Sahrens switch (prop) { 1598789Sahrens case ZFS_PROP_ATIME: 1599789Sahrens case ZFS_PROP_READONLY: 1600789Sahrens case ZFS_PROP_SETUID: 1601789Sahrens case ZFS_PROP_ZONED: 1602789Sahrens case ZFS_PROP_DEVICES: 1603789Sahrens case ZFS_PROP_EXEC: 16042676Seschrock case ZFS_PROP_CANMOUNT: 16053234Sck153898 case ZFS_PROP_XATTR: 1606789Sahrens /* 1607789Sahrens * Basic boolean values are built on top of 1608789Sahrens * get_numeric_property(). 1609789Sahrens */ 16102082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 16112082Seschrock return (-1); 16122082Seschrock nicebool(val, propbuf, proplen); 1613789Sahrens 1614789Sahrens break; 1615789Sahrens 1616789Sahrens case ZFS_PROP_AVAILABLE: 1617789Sahrens case ZFS_PROP_RECORDSIZE: 1618789Sahrens case ZFS_PROP_CREATETXG: 1619789Sahrens case ZFS_PROP_REFERENCED: 1620789Sahrens case ZFS_PROP_USED: 1621789Sahrens case ZFS_PROP_VOLSIZE: 1622789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 16233377Seschrock case ZFS_PROP_NUMCLONES: 1624789Sahrens /* 1625789Sahrens * Basic numeric values are built on top of 1626789Sahrens * get_numeric_property(). 1627789Sahrens */ 16282082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 16292082Seschrock return (-1); 1630789Sahrens if (literal) 16312856Snd150628 (void) snprintf(propbuf, proplen, "%llu", 16323912Slling (u_longlong_t)val); 1633789Sahrens else 1634789Sahrens zfs_nicenum(val, propbuf, proplen); 1635789Sahrens break; 1636789Sahrens 1637789Sahrens case ZFS_PROP_COMPRESSION: 1638789Sahrens case ZFS_PROP_CHECKSUM: 1639789Sahrens case ZFS_PROP_SNAPDIR: 1640789Sahrens case ZFS_PROP_ACLMODE: 1641789Sahrens case ZFS_PROP_ACLINHERIT: 16423835Sahrens case ZFS_PROP_COPIES: 16431356Seschrock val = getprop_uint64(zhp, prop, &source); 16442676Seschrock verify(zfs_prop_index_to_string(prop, val, &strval) == 0); 16452676Seschrock (void) strlcpy(propbuf, strval, proplen); 1646789Sahrens break; 1647789Sahrens 1648789Sahrens case ZFS_PROP_CREATION: 1649789Sahrens /* 1650789Sahrens * 'creation' is a time_t stored in the statistics. We convert 1651789Sahrens * this into a string unless 'literal' is specified. 1652789Sahrens */ 1653789Sahrens { 16542885Sahrens val = getprop_uint64(zhp, prop, &source); 16552885Sahrens time_t time = (time_t)val; 1656789Sahrens struct tm t; 1657789Sahrens 1658789Sahrens if (literal || 1659789Sahrens localtime_r(&time, &t) == NULL || 1660789Sahrens strftime(propbuf, proplen, "%a %b %e %k:%M %Y", 1661789Sahrens &t) == 0) 16622885Sahrens (void) snprintf(propbuf, proplen, "%llu", val); 1663789Sahrens } 1664789Sahrens break; 1665789Sahrens 1666789Sahrens case ZFS_PROP_MOUNTPOINT: 1667789Sahrens /* 1668789Sahrens * Getting the precise mountpoint can be tricky. 1669789Sahrens * 1670789Sahrens * - for 'none' or 'legacy', return those values. 1671789Sahrens * - for default mountpoints, construct it as /zfs/<dataset> 1672789Sahrens * - for inherited mountpoints, we want to take everything 1673789Sahrens * after our ancestor and append it to the inherited value. 1674789Sahrens * 1675789Sahrens * If the pool has an alternate root, we want to prepend that 1676789Sahrens * root to any values we return. 1677789Sahrens */ 16781544Seschrock root = zhp->zfs_root; 16791356Seschrock str = getprop_string(zhp, prop, &source); 16801356Seschrock 16811356Seschrock if (str[0] == '\0') { 1682789Sahrens (void) snprintf(propbuf, proplen, "%s/zfs/%s", 1683789Sahrens root, zhp->zfs_name); 16841356Seschrock } else if (str[0] == '/') { 16851356Seschrock const char *relpath = zhp->zfs_name + strlen(source); 1686789Sahrens 1687789Sahrens if (relpath[0] == '/') 1688789Sahrens relpath++; 16891356Seschrock if (str[1] == '\0') 16901356Seschrock str++; 1691789Sahrens 1692789Sahrens if (relpath[0] == '\0') 1693789Sahrens (void) snprintf(propbuf, proplen, "%s%s", 16941356Seschrock root, str); 1695789Sahrens else 1696789Sahrens (void) snprintf(propbuf, proplen, "%s%s%s%s", 16971356Seschrock root, str, relpath[0] == '@' ? "" : "/", 1698789Sahrens relpath); 1699789Sahrens } else { 1700789Sahrens /* 'legacy' or 'none' */ 17011356Seschrock (void) strlcpy(propbuf, str, proplen); 1702789Sahrens } 1703789Sahrens 1704789Sahrens break; 1705789Sahrens 1706789Sahrens case ZFS_PROP_SHARENFS: 17073126Sahl case ZFS_PROP_SHAREISCSI: 17083126Sahl case ZFS_PROP_ISCSIOPTIONS: 17091356Seschrock (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 17101356Seschrock proplen); 1711789Sahrens break; 1712789Sahrens 1713789Sahrens case ZFS_PROP_ORIGIN: 17142885Sahrens (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 1715789Sahrens proplen); 1716789Sahrens /* 1717789Sahrens * If there is no parent at all, return failure to indicate that 1718789Sahrens * it doesn't apply to this dataset. 1719789Sahrens */ 1720789Sahrens if (propbuf[0] == '\0') 1721789Sahrens return (-1); 1722789Sahrens break; 1723789Sahrens 1724789Sahrens case ZFS_PROP_QUOTA: 1725789Sahrens case ZFS_PROP_RESERVATION: 17262082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 17272082Seschrock return (-1); 1728789Sahrens 1729789Sahrens /* 1730789Sahrens * If quota or reservation is 0, we translate this into 'none' 1731789Sahrens * (unless literal is set), and indicate that it's the default 1732789Sahrens * value. Otherwise, we print the number nicely and indicate 1733789Sahrens * that its set locally. 1734789Sahrens */ 1735789Sahrens if (val == 0) { 1736789Sahrens if (literal) 1737789Sahrens (void) strlcpy(propbuf, "0", proplen); 1738789Sahrens else 1739789Sahrens (void) strlcpy(propbuf, "none", proplen); 1740789Sahrens } else { 1741789Sahrens if (literal) 17422856Snd150628 (void) snprintf(propbuf, proplen, "%llu", 17433912Slling (u_longlong_t)val); 1744789Sahrens else 1745789Sahrens zfs_nicenum(val, propbuf, proplen); 1746789Sahrens } 1747789Sahrens break; 1748789Sahrens 1749789Sahrens case ZFS_PROP_COMPRESSRATIO: 17502082Seschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 17512082Seschrock return (-1); 17522856Snd150628 (void) snprintf(propbuf, proplen, "%lld.%02lldx", (longlong_t) 17532856Snd150628 val / 100, (longlong_t)val % 100); 1754789Sahrens break; 1755789Sahrens 1756789Sahrens case ZFS_PROP_TYPE: 1757789Sahrens switch (zhp->zfs_type) { 1758789Sahrens case ZFS_TYPE_FILESYSTEM: 1759789Sahrens str = "filesystem"; 1760789Sahrens break; 1761789Sahrens case ZFS_TYPE_VOLUME: 1762789Sahrens str = "volume"; 1763789Sahrens break; 1764789Sahrens case ZFS_TYPE_SNAPSHOT: 1765789Sahrens str = "snapshot"; 1766789Sahrens break; 1767789Sahrens default: 17682082Seschrock abort(); 1769789Sahrens } 1770789Sahrens (void) snprintf(propbuf, proplen, "%s", str); 1771789Sahrens break; 1772789Sahrens 1773789Sahrens case ZFS_PROP_MOUNTED: 1774789Sahrens /* 1775789Sahrens * The 'mounted' property is a pseudo-property that described 1776789Sahrens * whether the filesystem is currently mounted. Even though 1777789Sahrens * it's a boolean value, the typical values of "on" and "off" 1778789Sahrens * don't make sense, so we translate to "yes" and "no". 1779789Sahrens */ 17802082Seschrock if (get_numeric_property(zhp, ZFS_PROP_MOUNTED, 17812082Seschrock src, &source, &val) != 0) 17822082Seschrock return (-1); 17832082Seschrock if (val) 1784789Sahrens (void) strlcpy(propbuf, "yes", proplen); 1785789Sahrens else 1786789Sahrens (void) strlcpy(propbuf, "no", proplen); 1787789Sahrens break; 1788789Sahrens 1789789Sahrens case ZFS_PROP_NAME: 1790789Sahrens /* 1791789Sahrens * The 'name' property is a pseudo-property derived from the 1792789Sahrens * dataset name. It is presented as a real property to simplify 1793789Sahrens * consumers. 1794789Sahrens */ 1795789Sahrens (void) strlcpy(propbuf, zhp->zfs_name, proplen); 1796789Sahrens break; 1797789Sahrens 1798789Sahrens default: 17992082Seschrock abort(); 1800789Sahrens } 1801789Sahrens 1802789Sahrens get_source(zhp, src, source, statbuf, statlen); 1803789Sahrens 1804789Sahrens return (0); 1805789Sahrens } 1806789Sahrens 1807789Sahrens /* 1808789Sahrens * Utility function to get the given numeric property. Does no validation that 1809789Sahrens * the given property is the appropriate type; should only be used with 1810789Sahrens * hard-coded property types. 1811789Sahrens */ 1812789Sahrens uint64_t 1813789Sahrens zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop) 1814789Sahrens { 1815789Sahrens char *source; 1816789Sahrens zfs_source_t sourcetype = ZFS_SRC_NONE; 18172082Seschrock uint64_t val; 18182082Seschrock 18192082Seschrock (void) get_numeric_property(zhp, prop, &sourcetype, &source, &val); 18202082Seschrock 18212082Seschrock return (val); 1822789Sahrens } 1823789Sahrens 1824789Sahrens /* 1825789Sahrens * Similar to zfs_prop_get(), but returns the value as an integer. 1826789Sahrens */ 1827789Sahrens int 1828789Sahrens zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, 1829789Sahrens zfs_source_t *src, char *statbuf, size_t statlen) 1830789Sahrens { 1831789Sahrens char *source; 1832789Sahrens 1833789Sahrens /* 1834789Sahrens * Check to see if this property applies to our object 1835789Sahrens */ 1836789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 18373237Slling return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE, 18382082Seschrock dgettext(TEXT_DOMAIN, "cannot get property '%s'"), 18392082Seschrock zfs_prop_to_name(prop))); 1840789Sahrens 1841789Sahrens if (src) 1842789Sahrens *src = ZFS_SRC_NONE; 1843789Sahrens 18442082Seschrock if (get_numeric_property(zhp, prop, src, &source, value) != 0) 18452082Seschrock return (-1); 1846789Sahrens 1847789Sahrens get_source(zhp, src, source, statbuf, statlen); 1848789Sahrens 1849789Sahrens return (0); 1850789Sahrens } 1851789Sahrens 1852789Sahrens /* 1853789Sahrens * Returns the name of the given zfs handle. 1854789Sahrens */ 1855789Sahrens const char * 1856789Sahrens zfs_get_name(const zfs_handle_t *zhp) 1857789Sahrens { 1858789Sahrens return (zhp->zfs_name); 1859789Sahrens } 1860789Sahrens 1861789Sahrens /* 1862789Sahrens * Returns the type of the given zfs handle. 1863789Sahrens */ 1864789Sahrens zfs_type_t 1865789Sahrens zfs_get_type(const zfs_handle_t *zhp) 1866789Sahrens { 1867789Sahrens return (zhp->zfs_type); 1868789Sahrens } 1869789Sahrens 1870789Sahrens /* 18711356Seschrock * Iterate over all child filesystems 1872789Sahrens */ 1873789Sahrens int 18741356Seschrock zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) 1875789Sahrens { 1876789Sahrens zfs_cmd_t zc = { 0 }; 1877789Sahrens zfs_handle_t *nzhp; 1878789Sahrens int ret; 1879789Sahrens 1880789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 18812082Seschrock ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; 1882789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1883789Sahrens /* 1884789Sahrens * Ignore private dataset names. 1885789Sahrens */ 1886789Sahrens if (dataset_name_hidden(zc.zc_name)) 1887789Sahrens continue; 1888789Sahrens 1889789Sahrens /* 1890789Sahrens * Silently ignore errors, as the only plausible explanation is 1891789Sahrens * that the pool has since been removed. 1892789Sahrens */ 18932082Seschrock if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 18942082Seschrock zc.zc_name)) == NULL) 1895789Sahrens continue; 1896789Sahrens 1897789Sahrens if ((ret = func(nzhp, data)) != 0) 1898789Sahrens return (ret); 1899789Sahrens } 1900789Sahrens 1901789Sahrens /* 1902789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1903789Sahrens * returned, then the underlying dataset has been removed since we 1904789Sahrens * obtained the handle. 1905789Sahrens */ 1906789Sahrens if (errno != ESRCH && errno != ENOENT) 19072082Seschrock return (zfs_standard_error(zhp->zfs_hdl, errno, 19082082Seschrock dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 1909789Sahrens 19101356Seschrock return (0); 19111356Seschrock } 19121356Seschrock 19131356Seschrock /* 19141356Seschrock * Iterate over all snapshots 19151356Seschrock */ 19161356Seschrock int 19171356Seschrock zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) 19181356Seschrock { 19191356Seschrock zfs_cmd_t zc = { 0 }; 19201356Seschrock zfs_handle_t *nzhp; 19211356Seschrock int ret; 1922789Sahrens 1923789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 19242082Seschrock ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, 19252082Seschrock &zc) == 0; 1926789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1927789Sahrens 19282082Seschrock if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 19292082Seschrock zc.zc_name)) == NULL) 1930789Sahrens continue; 1931789Sahrens 1932789Sahrens if ((ret = func(nzhp, data)) != 0) 1933789Sahrens return (ret); 1934789Sahrens } 1935789Sahrens 1936789Sahrens /* 1937789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1938789Sahrens * returned, then the underlying dataset has been removed since we 1939789Sahrens * obtained the handle. Silently ignore this case, and return success. 1940789Sahrens */ 1941789Sahrens if (errno != ESRCH && errno != ENOENT) 19422082Seschrock return (zfs_standard_error(zhp->zfs_hdl, errno, 19432082Seschrock dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 1944789Sahrens 1945789Sahrens return (0); 1946789Sahrens } 1947789Sahrens 1948789Sahrens /* 19491356Seschrock * Iterate over all children, snapshots and filesystems 19501356Seschrock */ 19511356Seschrock int 19521356Seschrock zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 19531356Seschrock { 19541356Seschrock int ret; 19551356Seschrock 19561356Seschrock if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0) 19571356Seschrock return (ret); 19581356Seschrock 19591356Seschrock return (zfs_iter_snapshots(zhp, func, data)); 19601356Seschrock } 19611356Seschrock 19621356Seschrock /* 1963789Sahrens * Given a complete name, return just the portion that refers to the parent. 1964789Sahrens * Can return NULL if this is a pool. 1965789Sahrens */ 1966789Sahrens static int 1967789Sahrens parent_name(const char *path, char *buf, size_t buflen) 1968789Sahrens { 1969789Sahrens char *loc; 1970789Sahrens 1971789Sahrens if ((loc = strrchr(path, '/')) == NULL) 1972789Sahrens return (-1); 1973789Sahrens 1974789Sahrens (void) strncpy(buf, path, MIN(buflen, loc - path)); 1975789Sahrens buf[loc - path] = '\0'; 1976789Sahrens 1977789Sahrens return (0); 1978789Sahrens } 1979789Sahrens 1980789Sahrens /* 19812676Seschrock * Checks to make sure that the given path has a parent, and that it exists. We 19822676Seschrock * also fetch the 'zoned' property, which is used to validate property settings 19832676Seschrock * when creating new datasets. 1984789Sahrens */ 1985789Sahrens static int 19862676Seschrock check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned) 1987789Sahrens { 1988789Sahrens zfs_cmd_t zc = { 0 }; 1989789Sahrens char parent[ZFS_MAXNAMELEN]; 1990789Sahrens char *slash; 19911356Seschrock zfs_handle_t *zhp; 19922082Seschrock char errbuf[1024]; 19932082Seschrock 19942082Seschrock (void) snprintf(errbuf, sizeof (errbuf), "cannot create '%s'", 19952082Seschrock path); 1996789Sahrens 1997789Sahrens /* get parent, and check to see if this is just a pool */ 1998789Sahrens if (parent_name(path, parent, sizeof (parent)) != 0) { 19992082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20002082Seschrock "missing dataset name")); 20012082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2002789Sahrens } 2003789Sahrens 2004789Sahrens /* check to see if the pool exists */ 2005789Sahrens if ((slash = strchr(parent, '/')) == NULL) 2006789Sahrens slash = parent + strlen(parent); 2007789Sahrens (void) strncpy(zc.zc_name, parent, slash - parent); 2008789Sahrens zc.zc_name[slash - parent] = '\0'; 20092082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 && 2010789Sahrens errno == ENOENT) { 20112082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20122082Seschrock "no such pool '%s'"), zc.zc_name); 20132082Seschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2014789Sahrens } 2015789Sahrens 2016789Sahrens /* check to see if the parent dataset exists */ 20172082Seschrock if ((zhp = make_dataset_handle(hdl, parent)) == NULL) { 2018789Sahrens switch (errno) { 2019789Sahrens case ENOENT: 20202082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20212082Seschrock "parent does not exist")); 20222082Seschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2023789Sahrens 2024789Sahrens default: 20252082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 2026789Sahrens } 2027789Sahrens } 2028789Sahrens 20292676Seschrock *zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); 2030789Sahrens /* we are in a non-global zone, but parent is in the global zone */ 20312676Seschrock if (getzoneid() != GLOBAL_ZONEID && !(*zoned)) { 20322082Seschrock (void) zfs_standard_error(hdl, EPERM, errbuf); 20331356Seschrock zfs_close(zhp); 2034789Sahrens return (-1); 2035789Sahrens } 2036789Sahrens 2037789Sahrens /* make sure parent is a filesystem */ 20381356Seschrock if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 20392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20402082Seschrock "parent is not a filesystem")); 20412082Seschrock (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 20421356Seschrock zfs_close(zhp); 2043789Sahrens return (-1); 2044789Sahrens } 2045789Sahrens 20461356Seschrock zfs_close(zhp); 2047789Sahrens return (0); 2048789Sahrens } 2049789Sahrens 2050789Sahrens /* 20512676Seschrock * Create a new filesystem or volume. 2052789Sahrens */ 2053789Sahrens int 20542082Seschrock zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type, 20552676Seschrock nvlist_t *props) 2056789Sahrens { 2057789Sahrens zfs_cmd_t zc = { 0 }; 2058789Sahrens int ret; 2059789Sahrens uint64_t size = 0; 2060789Sahrens uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE); 20612082Seschrock char errbuf[1024]; 20622676Seschrock uint64_t zoned; 20632082Seschrock 20642082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 20652082Seschrock "cannot create '%s'"), path); 2066789Sahrens 2067789Sahrens /* validate the path, taking care to note the extended error message */ 20682082Seschrock if (!zfs_validate_name(hdl, path, type)) 20692082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2070789Sahrens 2071789Sahrens /* validate parents exist */ 20722676Seschrock if (check_parents(hdl, path, &zoned) != 0) 2073789Sahrens return (-1); 2074789Sahrens 2075789Sahrens /* 2076789Sahrens * The failure modes when creating a dataset of a different type over 2077789Sahrens * one that already exists is a little strange. In particular, if you 2078789Sahrens * try to create a dataset on top of an existing dataset, the ioctl() 2079789Sahrens * will return ENOENT, not EEXIST. To prevent this from happening, we 2080789Sahrens * first try to see if the dataset exists. 2081789Sahrens */ 2082789Sahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 20832082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) { 20842082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 20852082Seschrock "dataset already exists")); 20862082Seschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2087789Sahrens } 2088789Sahrens 2089789Sahrens if (type == ZFS_TYPE_VOLUME) 2090789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2091789Sahrens else 2092789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2093789Sahrens 20943912Slling if (props && (props = zfs_validate_properties(hdl, type, NULL, props, 20953912Slling zoned, NULL, errbuf)) == 0) 20962676Seschrock return (-1); 20972676Seschrock 2098789Sahrens if (type == ZFS_TYPE_VOLUME) { 20991133Seschrock /* 21001133Seschrock * If we are creating a volume, the size and block size must 21011133Seschrock * satisfy a few restraints. First, the blocksize must be a 21021133Seschrock * valid block size between SPA_{MIN,MAX}BLOCKSIZE. Second, the 21031133Seschrock * volsize must be a multiple of the block size, and cannot be 21041133Seschrock * zero. 21051133Seschrock */ 21062676Seschrock if (props == NULL || nvlist_lookup_uint64(props, 21072676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) { 21082676Seschrock nvlist_free(props); 21092082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21102676Seschrock "missing volume size")); 21112676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2112789Sahrens } 2113789Sahrens 21142676Seschrock if ((ret = nvlist_lookup_uint64(props, 21152676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 21162676Seschrock &blocksize)) != 0) { 21172676Seschrock if (ret == ENOENT) { 21182676Seschrock blocksize = zfs_prop_default_numeric( 21192676Seschrock ZFS_PROP_VOLBLOCKSIZE); 21202676Seschrock } else { 21212676Seschrock nvlist_free(props); 21222676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21232676Seschrock "missing volume block size")); 21242676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 21252676Seschrock } 21262676Seschrock } 21272676Seschrock 21282676Seschrock if (size == 0) { 21292676Seschrock nvlist_free(props); 21302082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21312676Seschrock "volume size cannot be zero")); 21322676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 21331133Seschrock } 21341133Seschrock 21351133Seschrock if (size % blocksize != 0) { 21362676Seschrock nvlist_free(props); 21372082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21382676Seschrock "volume size must be a multiple of volume block " 21392676Seschrock "size")); 21402676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 21411133Seschrock } 2142789Sahrens } 2143789Sahrens 21442676Seschrock if (props && 21452676Seschrock zcmd_write_src_nvlist(hdl, &zc, props, NULL) != 0) 21462676Seschrock return (-1); 21472676Seschrock nvlist_free(props); 21482676Seschrock 2149789Sahrens /* create the dataset */ 21502082Seschrock ret = ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE, &zc); 2151789Sahrens 21523912Slling if (ret == 0 && type == ZFS_TYPE_VOLUME) { 21532082Seschrock ret = zvol_create_link(hdl, path); 21543912Slling if (ret) { 21553912Slling (void) zfs_standard_error(hdl, errno, 21563912Slling dgettext(TEXT_DOMAIN, 21573912Slling "Volume successfully created, but device links " 21583912Slling "were not created")); 21593912Slling zcmd_free_nvlists(&zc); 21603912Slling return (-1); 21613912Slling } 21623912Slling } 2163789Sahrens 21642676Seschrock zcmd_free_nvlists(&zc); 21652676Seschrock 2166789Sahrens /* check for failure */ 2167789Sahrens if (ret != 0) { 2168789Sahrens char parent[ZFS_MAXNAMELEN]; 2169789Sahrens (void) parent_name(path, parent, sizeof (parent)); 2170789Sahrens 2171789Sahrens switch (errno) { 2172789Sahrens case ENOENT: 21732082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21742082Seschrock "no such parent '%s'"), parent); 21752082Seschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2176789Sahrens 2177789Sahrens case EINVAL: 21782082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21793413Smmusante "parent '%s' is not a filesystem"), parent); 21802082Seschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 2181789Sahrens 2182789Sahrens case EDOM: 21832082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 21842676Seschrock "volume block size must be power of 2 from " 21852676Seschrock "%u to %uk"), 2186789Sahrens (uint_t)SPA_MINBLOCKSIZE, 2187789Sahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 21882082Seschrock 21892676Seschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 21902082Seschrock 2191789Sahrens #ifdef _ILP32 2192789Sahrens case EOVERFLOW: 2193789Sahrens /* 2194789Sahrens * This platform can't address a volume this big. 2195789Sahrens */ 21962082Seschrock if (type == ZFS_TYPE_VOLUME) 21972082Seschrock return (zfs_error(hdl, EZFS_VOLTOOBIG, 21982082Seschrock errbuf)); 2199789Sahrens #endif 22002082Seschrock /* FALLTHROUGH */ 2201789Sahrens default: 22022082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 2203789Sahrens } 2204789Sahrens } 2205789Sahrens 2206789Sahrens return (0); 2207789Sahrens } 2208789Sahrens 2209789Sahrens /* 2210789Sahrens * Destroys the given dataset. The caller must make sure that the filesystem 2211789Sahrens * isn't mounted, and that there are no active dependents. 2212789Sahrens */ 2213789Sahrens int 2214789Sahrens zfs_destroy(zfs_handle_t *zhp) 2215789Sahrens { 2216789Sahrens zfs_cmd_t zc = { 0 }; 2217789Sahrens 2218789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2219789Sahrens 22202676Seschrock if (ZFS_IS_VOLUME(zhp)) { 22213126Sahl /* 22223126Sahl * Unconditionally unshare this zvol ignoring failure as it 22233126Sahl * indicates only that the volume wasn't shared initially. 22243126Sahl */ 22253126Sahl (void) zfs_unshare_iscsi(zhp); 22263126Sahl 22272082Seschrock if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0) 2228789Sahrens return (-1); 2229789Sahrens 2230789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2231789Sahrens } else { 2232789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2233789Sahrens } 2234789Sahrens 22353126Sahl if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) != 0) { 22363237Slling return (zfs_standard_error_fmt(zhp->zfs_hdl, errno, 22372082Seschrock dgettext(TEXT_DOMAIN, "cannot destroy '%s'"), 22382082Seschrock zhp->zfs_name)); 22392199Sahrens } 2240789Sahrens 2241789Sahrens remove_mountpoint(zhp); 2242789Sahrens 2243789Sahrens return (0); 2244789Sahrens } 2245789Sahrens 22462199Sahrens struct destroydata { 22472199Sahrens char *snapname; 22482199Sahrens boolean_t gotone; 22493265Sahrens boolean_t closezhp; 22502199Sahrens }; 22512199Sahrens 22522199Sahrens static int 22532199Sahrens zfs_remove_link_cb(zfs_handle_t *zhp, void *arg) 22542199Sahrens { 22552199Sahrens struct destroydata *dd = arg; 22562199Sahrens zfs_handle_t *szhp; 22572199Sahrens char name[ZFS_MAXNAMELEN]; 22583265Sahrens boolean_t closezhp = dd->closezhp; 22593265Sahrens int rv; 22602199Sahrens 22612676Seschrock (void) strlcpy(name, zhp->zfs_name, sizeof (name)); 22622676Seschrock (void) strlcat(name, "@", sizeof (name)); 22632676Seschrock (void) strlcat(name, dd->snapname, sizeof (name)); 22642199Sahrens 22652199Sahrens szhp = make_dataset_handle(zhp->zfs_hdl, name); 22662199Sahrens if (szhp) { 22672199Sahrens dd->gotone = B_TRUE; 22682199Sahrens zfs_close(szhp); 22692199Sahrens } 22702199Sahrens 22712199Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 22722199Sahrens (void) zvol_remove_link(zhp->zfs_hdl, name); 22732199Sahrens /* 22742199Sahrens * NB: this is simply a best-effort. We don't want to 22752199Sahrens * return an error, because then we wouldn't visit all 22762199Sahrens * the volumes. 22772199Sahrens */ 22782199Sahrens } 22792199Sahrens 22803265Sahrens dd->closezhp = B_TRUE; 22813265Sahrens rv = zfs_iter_filesystems(zhp, zfs_remove_link_cb, arg); 22823265Sahrens if (closezhp) 22833265Sahrens zfs_close(zhp); 22843265Sahrens return (rv); 22852199Sahrens } 22862199Sahrens 22872199Sahrens /* 22882199Sahrens * Destroys all snapshots with the given name in zhp & descendants. 22892199Sahrens */ 22902199Sahrens int 22912199Sahrens zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname) 22922199Sahrens { 22932199Sahrens zfs_cmd_t zc = { 0 }; 22942199Sahrens int ret; 22952199Sahrens struct destroydata dd = { 0 }; 22962199Sahrens 22972199Sahrens dd.snapname = snapname; 22982199Sahrens (void) zfs_remove_link_cb(zhp, &dd); 22992199Sahrens 23002199Sahrens if (!dd.gotone) { 23013237Slling return (zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT, 23022199Sahrens dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"), 23032199Sahrens zhp->zfs_name, snapname)); 23042199Sahrens } 23052199Sahrens 23062199Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 23072676Seschrock (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); 23082199Sahrens 23092199Sahrens ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY_SNAPS, &zc); 23102199Sahrens if (ret != 0) { 23112199Sahrens char errbuf[1024]; 23122199Sahrens 23132199Sahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 23142199Sahrens "cannot destroy '%s@%s'"), zc.zc_name, snapname); 23152199Sahrens 23162199Sahrens switch (errno) { 23172199Sahrens case EEXIST: 23182199Sahrens zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 23192199Sahrens "snapshot is cloned")); 23202199Sahrens return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf)); 23212199Sahrens 23222199Sahrens default: 23232199Sahrens return (zfs_standard_error(zhp->zfs_hdl, errno, 23242199Sahrens errbuf)); 23252199Sahrens } 23262199Sahrens } 23272199Sahrens 23282199Sahrens return (0); 23292199Sahrens } 23302199Sahrens 2331789Sahrens /* 2332789Sahrens * Clones the given dataset. The target must be of the same type as the source. 2333789Sahrens */ 2334789Sahrens int 23352676Seschrock zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props) 2336789Sahrens { 2337789Sahrens zfs_cmd_t zc = { 0 }; 2338789Sahrens char parent[ZFS_MAXNAMELEN]; 2339789Sahrens int ret; 23402082Seschrock char errbuf[1024]; 23412082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 23422676Seschrock zfs_type_t type; 23432676Seschrock uint64_t zoned; 2344789Sahrens 2345789Sahrens assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 2346789Sahrens 23472082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 23482082Seschrock "cannot create '%s'"), target); 23492082Seschrock 2350789Sahrens /* validate the target name */ 23512082Seschrock if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM)) 23522082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2353789Sahrens 2354789Sahrens /* validate parents exist */ 23552676Seschrock if (check_parents(hdl, target, &zoned) != 0) 2356789Sahrens return (-1); 2357789Sahrens 2358789Sahrens (void) parent_name(target, parent, sizeof (parent)); 2359789Sahrens 2360789Sahrens /* do the clone */ 23612676Seschrock if (ZFS_IS_VOLUME(zhp)) { 2362789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 23632744Snn35248 type = ZFS_TYPE_VOLUME; 23642676Seschrock } else { 2365789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 23662744Snn35248 type = ZFS_TYPE_FILESYSTEM; 23672676Seschrock } 23682676Seschrock 23692676Seschrock if (props) { 23703912Slling if ((props = zfs_validate_properties(hdl, type, NULL, props, 23713912Slling zoned, zhp, errbuf)) == NULL) 23722676Seschrock return (-1); 23732676Seschrock 23742676Seschrock if (zcmd_write_src_nvlist(hdl, &zc, props, NULL) != 0) { 23752676Seschrock nvlist_free(props); 23762676Seschrock return (-1); 23772676Seschrock } 23782676Seschrock 23792676Seschrock nvlist_free(props); 23802676Seschrock } 2381789Sahrens 2382789Sahrens (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name)); 23832676Seschrock (void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value)); 23842082Seschrock ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_CREATE, &zc); 2385789Sahrens 23862676Seschrock zcmd_free_nvlists(&zc); 23872676Seschrock 2388789Sahrens if (ret != 0) { 2389789Sahrens switch (errno) { 2390789Sahrens 2391789Sahrens case ENOENT: 2392789Sahrens /* 2393789Sahrens * The parent doesn't exist. We should have caught this 2394789Sahrens * above, but there may a race condition that has since 2395789Sahrens * destroyed the parent. 2396789Sahrens * 2397789Sahrens * At this point, we don't know whether it's the source 2398789Sahrens * that doesn't exist anymore, or whether the target 2399789Sahrens * dataset doesn't exist. 2400789Sahrens */ 24012082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 24022082Seschrock "no such parent '%s'"), parent); 24032082Seschrock return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf)); 24042082Seschrock 24052082Seschrock case EXDEV: 24062082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 24072082Seschrock "source and target pools differ")); 24082082Seschrock return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET, 24092082Seschrock errbuf)); 24102082Seschrock 24112082Seschrock default: 24122082Seschrock return (zfs_standard_error(zhp->zfs_hdl, errno, 24132082Seschrock errbuf)); 24142082Seschrock } 24152676Seschrock } else if (ZFS_IS_VOLUME(zhp)) { 24162082Seschrock ret = zvol_create_link(zhp->zfs_hdl, target); 24172082Seschrock } 24182082Seschrock 24192082Seschrock return (ret); 24202082Seschrock } 24212082Seschrock 24222082Seschrock typedef struct promote_data { 24232082Seschrock char cb_mountpoint[MAXPATHLEN]; 24242082Seschrock const char *cb_target; 24252082Seschrock const char *cb_errbuf; 24262082Seschrock uint64_t cb_pivot_txg; 24272082Seschrock } promote_data_t; 24282082Seschrock 24292082Seschrock static int 24302082Seschrock promote_snap_cb(zfs_handle_t *zhp, void *data) 24312082Seschrock { 24322082Seschrock promote_data_t *pd = data; 24332082Seschrock zfs_handle_t *szhp; 24342082Seschrock char snapname[MAXPATHLEN]; 24353265Sahrens int rv = 0; 24362082Seschrock 24372082Seschrock /* We don't care about snapshots after the pivot point */ 24383265Sahrens if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > pd->cb_pivot_txg) { 24393265Sahrens zfs_close(zhp); 24402082Seschrock return (0); 24413265Sahrens } 24422082Seschrock 24432417Sahrens /* Remove the device link if it's a zvol. */ 24442676Seschrock if (ZFS_IS_VOLUME(zhp)) 24452417Sahrens (void) zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name); 24462082Seschrock 24472082Seschrock /* Check for conflicting names */ 24482676Seschrock (void) strlcpy(snapname, pd->cb_target, sizeof (snapname)); 24492676Seschrock (void) strlcat(snapname, strchr(zhp->zfs_name, '@'), sizeof (snapname)); 24502082Seschrock szhp = make_dataset_handle(zhp->zfs_hdl, snapname); 24512082Seschrock if (szhp != NULL) { 24522082Seschrock zfs_close(szhp); 24532082Seschrock zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 24542082Seschrock "snapshot name '%s' from origin \n" 24552082Seschrock "conflicts with '%s' from target"), 24562082Seschrock zhp->zfs_name, snapname); 24573265Sahrens rv = zfs_error(zhp->zfs_hdl, EZFS_EXISTS, pd->cb_errbuf); 24582082Seschrock } 24593265Sahrens zfs_close(zhp); 24603265Sahrens return (rv); 24612082Seschrock } 24622082Seschrock 24632417Sahrens static int 24642417Sahrens promote_snap_done_cb(zfs_handle_t *zhp, void *data) 24652417Sahrens { 24662417Sahrens promote_data_t *pd = data; 24672417Sahrens 24682417Sahrens /* We don't care about snapshots after the pivot point */ 24693265Sahrens if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) <= pd->cb_pivot_txg) { 24703265Sahrens /* Create the device link if it's a zvol. */ 24713265Sahrens if (ZFS_IS_VOLUME(zhp)) 24723265Sahrens (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 24733265Sahrens } 24743265Sahrens 24753265Sahrens zfs_close(zhp); 24762417Sahrens return (0); 24772417Sahrens } 24782417Sahrens 24792082Seschrock /* 24802082Seschrock * Promotes the given clone fs to be the clone parent. 24812082Seschrock */ 24822082Seschrock int 24832082Seschrock zfs_promote(zfs_handle_t *zhp) 24842082Seschrock { 24852082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 24862082Seschrock zfs_cmd_t zc = { 0 }; 24872082Seschrock char parent[MAXPATHLEN]; 24882082Seschrock char *cp; 24892082Seschrock int ret; 24902082Seschrock zfs_handle_t *pzhp; 24912082Seschrock promote_data_t pd; 24922082Seschrock char errbuf[1024]; 24932082Seschrock 24942082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 24952082Seschrock "cannot promote '%s'"), zhp->zfs_name); 24962082Seschrock 24972082Seschrock if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 24982082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 24992082Seschrock "snapshots can not be promoted")); 25002082Seschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 25012082Seschrock } 25022082Seschrock 25032676Seschrock (void) strlcpy(parent, zhp->zfs_dmustats.dds_clone_of, sizeof (parent)); 25042082Seschrock if (parent[0] == '\0') { 25052082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 25062082Seschrock "not a cloned filesystem")); 25072082Seschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 25082082Seschrock } 25092082Seschrock cp = strchr(parent, '@'); 25102082Seschrock *cp = '\0'; 25112082Seschrock 25122082Seschrock /* Walk the snapshots we will be moving */ 25132082Seschrock pzhp = zfs_open(hdl, zhp->zfs_dmustats.dds_clone_of, ZFS_TYPE_SNAPSHOT); 25142082Seschrock if (pzhp == NULL) 25152082Seschrock return (-1); 25162082Seschrock pd.cb_pivot_txg = zfs_prop_get_int(pzhp, ZFS_PROP_CREATETXG); 25172082Seschrock zfs_close(pzhp); 25182082Seschrock pd.cb_target = zhp->zfs_name; 25192082Seschrock pd.cb_errbuf = errbuf; 25202082Seschrock pzhp = zfs_open(hdl, parent, ZFS_TYPE_ANY); 25212082Seschrock if (pzhp == NULL) 25222082Seschrock return (-1); 25232082Seschrock (void) zfs_prop_get(pzhp, ZFS_PROP_MOUNTPOINT, pd.cb_mountpoint, 25242082Seschrock sizeof (pd.cb_mountpoint), NULL, NULL, 0, FALSE); 25252082Seschrock ret = zfs_iter_snapshots(pzhp, promote_snap_cb, &pd); 25262417Sahrens if (ret != 0) { 25272417Sahrens zfs_close(pzhp); 25282082Seschrock return (-1); 25292417Sahrens } 25302082Seschrock 25312082Seschrock /* issue the ioctl */ 25322676Seschrock (void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_clone_of, 25332676Seschrock sizeof (zc.zc_value)); 25342082Seschrock (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 25352082Seschrock ret = ioctl(hdl->libzfs_fd, ZFS_IOC_PROMOTE, &zc); 25362082Seschrock 25372082Seschrock if (ret != 0) { 25382417Sahrens int save_errno = errno; 25392417Sahrens 25402417Sahrens (void) zfs_iter_snapshots(pzhp, promote_snap_done_cb, &pd); 25412417Sahrens zfs_close(pzhp); 25422417Sahrens 25432417Sahrens switch (save_errno) { 2544789Sahrens case EEXIST: 2545789Sahrens /* 25462082Seschrock * There is a conflicting snapshot name. We 25472082Seschrock * should have caught this above, but they could 25482082Seschrock * have renamed something in the mean time. 2549789Sahrens */ 25502082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 25512082Seschrock "conflicting snapshot name from parent '%s'"), 25522082Seschrock parent); 25532082Seschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2554789Sahrens 2555789Sahrens default: 25562417Sahrens return (zfs_standard_error(hdl, save_errno, errbuf)); 2557789Sahrens } 25582417Sahrens } else { 25592417Sahrens (void) zfs_iter_snapshots(zhp, promote_snap_done_cb, &pd); 2560789Sahrens } 2561789Sahrens 25622417Sahrens zfs_close(pzhp); 2563789Sahrens return (ret); 2564789Sahrens } 2565789Sahrens 25664007Smmusante struct createdata { 25674007Smmusante const char *cd_snapname; 25684007Smmusante int cd_ifexists; 25694007Smmusante }; 25704007Smmusante 25712199Sahrens static int 25722199Sahrens zfs_create_link_cb(zfs_handle_t *zhp, void *arg) 25732199Sahrens { 25744007Smmusante struct createdata *cd = arg; 25752676Seschrock int ret; 25762199Sahrens 25772199Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 25782199Sahrens char name[MAXPATHLEN]; 25792199Sahrens 25802676Seschrock (void) strlcpy(name, zhp->zfs_name, sizeof (name)); 25812676Seschrock (void) strlcat(name, "@", sizeof (name)); 25824007Smmusante (void) strlcat(name, cd->cd_snapname, sizeof (name)); 25834007Smmusante (void) zvol_create_link_common(zhp->zfs_hdl, name, 25844007Smmusante cd->cd_ifexists); 25852199Sahrens /* 25862199Sahrens * NB: this is simply a best-effort. We don't want to 25872199Sahrens * return an error, because then we wouldn't visit all 25882199Sahrens * the volumes. 25892199Sahrens */ 25902199Sahrens } 25912676Seschrock 25924007Smmusante ret = zfs_iter_filesystems(zhp, zfs_create_link_cb, cd); 25932676Seschrock 25942676Seschrock zfs_close(zhp); 25952676Seschrock 25962676Seschrock return (ret); 25972199Sahrens } 25982199Sahrens 2599789Sahrens /* 26003504Sahl * Takes a snapshot of the given dataset. 2601789Sahrens */ 2602789Sahrens int 26032199Sahrens zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive) 2604789Sahrens { 2605789Sahrens const char *delim; 2606789Sahrens char *parent; 2607789Sahrens zfs_handle_t *zhp; 2608789Sahrens zfs_cmd_t zc = { 0 }; 2609789Sahrens int ret; 26102082Seschrock char errbuf[1024]; 26112082Seschrock 26122082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 26132082Seschrock "cannot snapshot '%s'"), path); 26142082Seschrock 26152082Seschrock /* validate the target name */ 26162082Seschrock if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT)) 26172082Seschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2618789Sahrens 2619789Sahrens /* make sure the parent exists and is of the appropriate type */ 26202199Sahrens delim = strchr(path, '@'); 26212082Seschrock if ((parent = zfs_alloc(hdl, delim - path + 1)) == NULL) 26222082Seschrock return (-1); 2623789Sahrens (void) strncpy(parent, path, delim - path); 2624789Sahrens parent[delim - path] = '\0'; 2625789Sahrens 26262082Seschrock if ((zhp = zfs_open(hdl, parent, ZFS_TYPE_FILESYSTEM | 2627789Sahrens ZFS_TYPE_VOLUME)) == NULL) { 2628789Sahrens free(parent); 2629789Sahrens return (-1); 2630789Sahrens } 2631789Sahrens 26322199Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 26332676Seschrock (void) strlcpy(zc.zc_value, delim+1, sizeof (zc.zc_value)); 26342199Sahrens zc.zc_cookie = recursive; 26352199Sahrens ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT, &zc); 26362199Sahrens 26372199Sahrens /* 26382199Sahrens * if it was recursive, the one that actually failed will be in 26392199Sahrens * zc.zc_name. 26402199Sahrens */ 26412199Sahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 26422676Seschrock "cannot create snapshot '%s@%s'"), zc.zc_name, zc.zc_value); 26432199Sahrens if (ret == 0 && recursive) { 26444007Smmusante struct createdata cd; 26454007Smmusante 26464007Smmusante cd.cd_snapname = delim + 1; 26474007Smmusante cd.cd_ifexists = B_FALSE; 26484007Smmusante (void) zfs_iter_filesystems(zhp, zfs_create_link_cb, &cd); 26492199Sahrens } 2650789Sahrens if (ret == 0 && zhp->zfs_type == ZFS_TYPE_VOLUME) { 26512082Seschrock ret = zvol_create_link(zhp->zfs_hdl, path); 26522199Sahrens if (ret != 0) { 26532082Seschrock (void) ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, 26542082Seschrock &zc); 26552199Sahrens } 2656789Sahrens } 2657789Sahrens 26582082Seschrock if (ret != 0) 26592082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 2660789Sahrens 2661789Sahrens free(parent); 2662789Sahrens zfs_close(zhp); 2663789Sahrens 2664789Sahrens return (ret); 2665789Sahrens } 2666789Sahrens 2667789Sahrens /* 26683504Sahl * Dumps a backup of the given snapshot (incremental from fromsnap if it's not 26693504Sahl * NULL) to the file descriptor specified by outfd. 2670789Sahrens */ 2671789Sahrens int 26723504Sahl zfs_send(zfs_handle_t *zhp, const char *fromsnap, int outfd) 2673789Sahrens { 2674789Sahrens zfs_cmd_t zc = { 0 }; 26752082Seschrock char errbuf[1024]; 26762885Sahrens libzfs_handle_t *hdl = zhp->zfs_hdl; 26772082Seschrock 26783504Sahl assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 26793504Sahl 26802885Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 26812885Sahrens if (fromsnap) 26822885Sahrens (void) strlcpy(zc.zc_value, fromsnap, sizeof (zc.zc_name)); 26833504Sahl zc.zc_cookie = outfd; 26843504Sahl 26853504Sahl if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SENDBACKUP, &zc) != 0) { 26863504Sahl (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 26873504Sahl "cannot send '%s'"), zhp->zfs_name); 26883504Sahl 2689789Sahrens switch (errno) { 2690789Sahrens 2691789Sahrens case EXDEV: 26922082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 26933413Smmusante "not an earlier snapshot from the same fs")); 26942082Seschrock return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); 2695789Sahrens 2696789Sahrens case EDQUOT: 2697789Sahrens case EFBIG: 2698789Sahrens case EIO: 2699789Sahrens case ENOLINK: 2700789Sahrens case ENOSPC: 2701789Sahrens case ENOSTR: 2702789Sahrens case ENXIO: 2703789Sahrens case EPIPE: 2704789Sahrens case ERANGE: 2705789Sahrens case EFAULT: 2706789Sahrens case EROFS: 27072082Seschrock zfs_error_aux(hdl, strerror(errno)); 27082082Seschrock return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); 2709789Sahrens 2710789Sahrens default: 27112082Seschrock return (zfs_standard_error(hdl, errno, errbuf)); 2712789Sahrens } 2713789Sahrens } 2714789Sahrens 27153504Sahl return (0); 2716789Sahrens } 2717789Sahrens 2718789Sahrens /* 27192885Sahrens * Create ancestors of 'target', but not target itself, and not 27202885Sahrens * ancestors whose names are shorter than prefixlen. Die if 27212885Sahrens * prefixlen-ancestor does not exist. 27222885Sahrens */ 27232885Sahrens static int 27242885Sahrens create_parents(libzfs_handle_t *hdl, char *target, int prefixlen) 27252885Sahrens { 27262885Sahrens zfs_handle_t *h; 27272885Sahrens char *cp; 27282885Sahrens 27292885Sahrens /* make sure prefix exists */ 27302885Sahrens cp = strchr(target + prefixlen, '/'); 27312885Sahrens *cp = '\0'; 27322885Sahrens h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 27332885Sahrens *cp = '/'; 27342885Sahrens if (h == NULL) 27352885Sahrens return (-1); 27362885Sahrens zfs_close(h); 27372885Sahrens 27382885Sahrens /* 27392885Sahrens * Attempt to create, mount, and share any ancestor filesystems, 27402885Sahrens * up to the prefixlen-long one. 27412885Sahrens */ 27422885Sahrens for (cp = target + prefixlen + 1; 27432885Sahrens cp = strchr(cp, '/'); *cp = '/', cp++) { 27442885Sahrens const char *opname; 27452885Sahrens 27462885Sahrens *cp = '\0'; 27472885Sahrens 27482885Sahrens h = make_dataset_handle(hdl, target); 27492885Sahrens if (h) { 27502885Sahrens /* it already exists, nothing to do here */ 27512885Sahrens zfs_close(h); 27522885Sahrens continue; 27532885Sahrens } 27542885Sahrens 27552885Sahrens opname = dgettext(TEXT_DOMAIN, "create"); 27562885Sahrens if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM, 27572885Sahrens NULL) != 0) 27582885Sahrens goto ancestorerr; 27592885Sahrens 27602885Sahrens opname = dgettext(TEXT_DOMAIN, "open"); 27612885Sahrens h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 27622885Sahrens if (h == NULL) 27632885Sahrens goto ancestorerr; 27642885Sahrens 27652885Sahrens opname = dgettext(TEXT_DOMAIN, "mount"); 27662885Sahrens if (zfs_mount(h, NULL, 0) != 0) 27672885Sahrens goto ancestorerr; 27682885Sahrens 27692885Sahrens opname = dgettext(TEXT_DOMAIN, "share"); 27702885Sahrens if (zfs_share(h) != 0) 27712885Sahrens goto ancestorerr; 27722885Sahrens 27732885Sahrens zfs_close(h); 27742885Sahrens 27752885Sahrens continue; 27762885Sahrens ancestorerr: 27772885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 27782885Sahrens "failed to %s ancestor '%s'"), opname, target); 27792885Sahrens return (-1); 27802885Sahrens } 27812885Sahrens 27822885Sahrens return (0); 27832885Sahrens } 27842885Sahrens 27852885Sahrens /* 27863504Sahl * Restores a backup of tosnap from the file descriptor specified by infd. 2787789Sahrens */ 2788789Sahrens int 27892082Seschrock zfs_receive(libzfs_handle_t *hdl, const char *tosnap, int isprefix, 27903504Sahl int verbose, int dryrun, boolean_t force, int infd) 2791789Sahrens { 2792789Sahrens zfs_cmd_t zc = { 0 }; 2793789Sahrens time_t begin_time; 27942885Sahrens int ioctl_err, err, bytes, size, choplen; 2795789Sahrens char *cp; 2796789Sahrens dmu_replay_record_t drr; 2797789Sahrens struct drr_begin *drrb = &zc.zc_begin_record; 27982082Seschrock char errbuf[1024]; 27992665Snd150628 prop_changelist_t *clp; 28002885Sahrens char chopprefix[ZFS_MAXNAMELEN]; 2801789Sahrens 2802789Sahrens begin_time = time(NULL); 2803789Sahrens 28042082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 28052082Seschrock "cannot receive")); 28062082Seschrock 2807789Sahrens /* read in the BEGIN record */ 2808789Sahrens cp = (char *)&drr; 2809789Sahrens bytes = 0; 2810789Sahrens do { 28113504Sahl size = read(infd, cp, sizeof (drr) - bytes); 2812868Sahrens cp += size; 2813868Sahrens bytes += size; 2814868Sahrens } while (size > 0); 2815868Sahrens 2816868Sahrens if (size < 0 || bytes != sizeof (drr)) { 28172082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 28182082Seschrock "stream (failed to read first record)")); 28192082Seschrock return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2820789Sahrens } 2821789Sahrens 2822789Sahrens zc.zc_begin_record = drr.drr_u.drr_begin; 2823789Sahrens 2824789Sahrens if (drrb->drr_magic != DMU_BACKUP_MAGIC && 2825789Sahrens drrb->drr_magic != BSWAP_64(DMU_BACKUP_MAGIC)) { 28262082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 28272082Seschrock "stream (bad magic number)")); 28282082Seschrock return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2829789Sahrens } 2830789Sahrens 2831789Sahrens if (drrb->drr_version != DMU_BACKUP_VERSION && 2832789Sahrens drrb->drr_version != BSWAP_64(DMU_BACKUP_VERSION)) { 28332082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only version " 28342082Seschrock "0x%llx is supported (stream is version 0x%llx)"), 2835789Sahrens DMU_BACKUP_VERSION, drrb->drr_version); 28362082Seschrock return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2837789Sahrens } 2838789Sahrens 28392885Sahrens if (strchr(drr.drr_u.drr_begin.drr_toname, '@') == NULL) { 28402885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 28413912Slling "stream (bad snapshot name)")); 28422885Sahrens return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 28432885Sahrens } 2844789Sahrens /* 28452885Sahrens * Determine how much of the snapshot name stored in the stream 28462885Sahrens * we are going to tack on to the name they specified on the 28472885Sahrens * command line, and how much we are going to chop off. 28482885Sahrens * 28492885Sahrens * If they specified a snapshot, chop the entire name stored in 28502885Sahrens * the stream. 2851789Sahrens */ 28522885Sahrens (void) strcpy(chopprefix, drr.drr_u.drr_begin.drr_toname); 2853789Sahrens if (isprefix) { 28542885Sahrens /* 28552885Sahrens * They specified a fs with -d, we want to tack on 28562885Sahrens * everything but the pool name stored in the stream 28572885Sahrens */ 28582885Sahrens if (strchr(tosnap, '@')) { 28592885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 28602885Sahrens "argument - snapshot not allowed with -d")); 28612885Sahrens return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2862789Sahrens } 28632885Sahrens cp = strchr(chopprefix, '/'); 2864789Sahrens if (cp == NULL) 28652885Sahrens cp = strchr(chopprefix, '@'); 28662885Sahrens *cp = '\0'; 2867789Sahrens } else if (strchr(tosnap, '@') == NULL) { 2868789Sahrens /* 28692885Sahrens * If they specified a filesystem without -d, we want to 28702885Sahrens * tack on everything after the fs specified in the 28712885Sahrens * first name from the stream. 2872789Sahrens */ 28732885Sahrens cp = strchr(chopprefix, '@'); 28742885Sahrens *cp = '\0'; 2875789Sahrens } 28762885Sahrens choplen = strlen(chopprefix); 28772885Sahrens 28782885Sahrens /* 28792885Sahrens * Determine name of destination snapshot, store in zc_value. 28802885Sahrens */ 28812885Sahrens (void) strcpy(zc.zc_value, tosnap); 28822885Sahrens (void) strncat(zc.zc_value, drr.drr_u.drr_begin.drr_toname+choplen, 28832885Sahrens sizeof (zc.zc_value)); 28843265Sahrens if (!zfs_validate_name(hdl, zc.zc_value, ZFS_TYPE_SNAPSHOT)) 28853265Sahrens return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 28862885Sahrens 28872885Sahrens (void) strcpy(zc.zc_name, zc.zc_value); 2888789Sahrens if (drrb->drr_fromguid) { 2889789Sahrens /* incremental backup stream */ 28902885Sahrens zfs_handle_t *h; 28912885Sahrens 28922885Sahrens /* do the recvbackup ioctl to the containing fs */ 28932885Sahrens *strchr(zc.zc_name, '@') = '\0'; 2894789Sahrens 2895789Sahrens /* make sure destination fs exists */ 28962082Seschrock h = zfs_open(hdl, zc.zc_name, 28972082Seschrock ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 28982082Seschrock if (h == NULL) 2899789Sahrens return (-1); 2900868Sahrens if (!dryrun) { 29012665Snd150628 /* 29022665Snd150628 * We need to unmount all the dependents of the dataset 29032665Snd150628 * and the dataset itself. If it's a volume 29042665Snd150628 * then remove device link. 29052665Snd150628 */ 2906868Sahrens if (h->zfs_type == ZFS_TYPE_FILESYSTEM) { 29072665Snd150628 clp = changelist_gather(h, ZFS_PROP_NAME, 0); 29082665Snd150628 if (clp == NULL) 29092665Snd150628 return (-1); 29102665Snd150628 if (changelist_prefix(clp) != 0) { 29112665Snd150628 changelist_free(clp); 29122665Snd150628 return (-1); 29132665Snd150628 } 2914868Sahrens } else { 29152082Seschrock (void) zvol_remove_link(hdl, h->zfs_name); 2916868Sahrens } 2917868Sahrens } 2918789Sahrens zfs_close(h); 2919789Sahrens } else { 2920789Sahrens /* full backup stream */ 2921789Sahrens 2922868Sahrens /* Make sure destination fs does not exist */ 29232885Sahrens *strchr(zc.zc_name, '@') = '\0'; 29242082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) { 29252082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29262082Seschrock "destination '%s' exists"), zc.zc_name); 29272082Seschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2928868Sahrens } 2929868Sahrens 29302885Sahrens if (strchr(zc.zc_name, '/') == NULL) { 29312885Sahrens /* 29322885Sahrens * they're trying to do a recv into a 29332885Sahrens * nonexistant topmost filesystem. 29342885Sahrens */ 29352885Sahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29362885Sahrens "destination does not exist"), zc.zc_name); 29372885Sahrens return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 29382885Sahrens } 29392885Sahrens 2940868Sahrens /* Do the recvbackup ioctl to the fs's parent. */ 29412885Sahrens *strrchr(zc.zc_name, '/') = '\0'; 29422885Sahrens 29432885Sahrens if (isprefix && (err = create_parents(hdl, 29442885Sahrens zc.zc_value, strlen(tosnap))) != 0) { 29452885Sahrens return (zfs_error(hdl, EZFS_BADRESTORE, errbuf)); 29462885Sahrens } 29472885Sahrens 2948789Sahrens } 2949789Sahrens 29503504Sahl zc.zc_cookie = infd; 29512676Seschrock zc.zc_guid = force; 2952789Sahrens if (verbose) { 29531749Sahrens (void) printf("%s %s stream of %s into %s\n", 29541749Sahrens dryrun ? "would receive" : "receiving", 2955789Sahrens drrb->drr_fromguid ? "incremental" : "full", 2956789Sahrens drr.drr_u.drr_begin.drr_toname, 29572676Seschrock zc.zc_value); 2958789Sahrens (void) fflush(stdout); 2959789Sahrens } 2960789Sahrens if (dryrun) 2961789Sahrens return (0); 29622082Seschrock err = ioctl_err = ioctl(hdl->libzfs_fd, ZFS_IOC_RECVBACKUP, &zc); 2963868Sahrens if (ioctl_err != 0) { 2964789Sahrens switch (errno) { 2965789Sahrens case ENODEV: 29662082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29672082Seschrock "most recent snapshot does not match incremental " 29682082Seschrock "source")); 29692082Seschrock (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); 2970789Sahrens break; 2971789Sahrens case ETXTBSY: 29722082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29732082Seschrock "destination has been modified since most recent " 29742082Seschrock "snapshot")); 29752082Seschrock (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); 2976789Sahrens break; 2977789Sahrens case EEXIST: 2978789Sahrens if (drrb->drr_fromguid == 0) { 2979789Sahrens /* it's the containing fs that exists */ 29802676Seschrock cp = strchr(zc.zc_value, '@'); 2981789Sahrens *cp = '\0'; 2982789Sahrens } 29832082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29842082Seschrock "destination already exists")); 29853237Slling (void) zfs_error_fmt(hdl, EZFS_EXISTS, 29863237Slling dgettext(TEXT_DOMAIN, "cannot restore to %s"), 29873237Slling zc.zc_value); 2988789Sahrens break; 2989789Sahrens case EINVAL: 29902082Seschrock (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); 2991868Sahrens break; 29921544Seschrock case ECKSUM: 29932082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 29942082Seschrock "invalid stream (checksum mismatch)")); 29952082Seschrock (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); 2996789Sahrens break; 2997789Sahrens default: 29982082Seschrock (void) zfs_standard_error(hdl, errno, errbuf); 2999789Sahrens } 3000789Sahrens } 3001789Sahrens 3002789Sahrens /* 3003868Sahrens * Mount or recreate the /dev links for the target filesystem 3004868Sahrens * (if created, or if we tore them down to do an incremental 3005868Sahrens * restore), and the /dev links for the new snapshot (if 30062665Snd150628 * created). Also mount any children of the target filesystem 30072665Snd150628 * if we did an incremental receive. 3008789Sahrens */ 30092676Seschrock cp = strchr(zc.zc_value, '@'); 3010868Sahrens if (cp && (ioctl_err == 0 || drrb->drr_fromguid)) { 3011789Sahrens zfs_handle_t *h; 3012789Sahrens 3013789Sahrens *cp = '\0'; 30142676Seschrock h = zfs_open(hdl, zc.zc_value, 3015789Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 3016868Sahrens *cp = '@'; 3017789Sahrens if (h) { 30182665Snd150628 if (h->zfs_type == ZFS_TYPE_VOLUME) { 30192082Seschrock err = zvol_create_link(hdl, h->zfs_name); 30201544Seschrock if (err == 0 && ioctl_err == 0) 30212082Seschrock err = zvol_create_link(hdl, 30222676Seschrock zc.zc_value); 30232665Snd150628 } else { 30242665Snd150628 if (drrb->drr_fromguid) { 30252665Snd150628 err = changelist_postfix(clp); 30262665Snd150628 changelist_free(clp); 30272665Snd150628 } else { 30282665Snd150628 err = zfs_mount(h, NULL, 0); 30292665Snd150628 } 3030868Sahrens } 30312665Snd150628 zfs_close(h); 3032789Sahrens } 3033789Sahrens } 3034789Sahrens 3035868Sahrens if (err || ioctl_err) 3036868Sahrens return (-1); 3037789Sahrens 3038789Sahrens if (verbose) { 3039789Sahrens char buf1[64]; 3040789Sahrens char buf2[64]; 3041789Sahrens uint64_t bytes = zc.zc_cookie; 3042789Sahrens time_t delta = time(NULL) - begin_time; 3043789Sahrens if (delta == 0) 3044789Sahrens delta = 1; 3045789Sahrens zfs_nicenum(bytes, buf1, sizeof (buf1)); 3046789Sahrens zfs_nicenum(bytes/delta, buf2, sizeof (buf1)); 3047789Sahrens 30481749Sahrens (void) printf("received %sb stream in %lu seconds (%sb/sec)\n", 3049789Sahrens buf1, delta, buf2); 3050789Sahrens } 30512665Snd150628 3052789Sahrens return (0); 3053789Sahrens } 3054789Sahrens 3055789Sahrens /* 30561294Slling * Destroy any more recent snapshots. We invoke this callback on any dependents 30571294Slling * of the snapshot first. If the 'cb_dependent' member is non-zero, then this 30581294Slling * is a dependent and we should just destroy it without checking the transaction 30591294Slling * group. 3060789Sahrens */ 30611294Slling typedef struct rollback_data { 30621294Slling const char *cb_target; /* the snapshot */ 30631294Slling uint64_t cb_create; /* creation time reference */ 30641294Slling prop_changelist_t *cb_clp; /* changelist pointer */ 30651294Slling int cb_error; 30662082Seschrock boolean_t cb_dependent; 30671294Slling } rollback_data_t; 30681294Slling 30691294Slling static int 30701294Slling rollback_destroy(zfs_handle_t *zhp, void *data) 30711294Slling { 30721294Slling rollback_data_t *cbp = data; 30731294Slling 30741294Slling if (!cbp->cb_dependent) { 30751294Slling if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 && 30761294Slling zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && 30771294Slling zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > 30781294Slling cbp->cb_create) { 30791294Slling 30802082Seschrock cbp->cb_dependent = B_TRUE; 30812474Seschrock if (zfs_iter_dependents(zhp, B_FALSE, rollback_destroy, 30822474Seschrock cbp) != 0) 30832474Seschrock cbp->cb_error = 1; 30842082Seschrock cbp->cb_dependent = B_FALSE; 30851294Slling 30861294Slling if (zfs_destroy(zhp) != 0) 30871294Slling cbp->cb_error = 1; 30881294Slling else 30891294Slling changelist_remove(zhp, cbp->cb_clp); 30901294Slling } 30911294Slling } else { 30921294Slling if (zfs_destroy(zhp) != 0) 30931294Slling cbp->cb_error = 1; 30941294Slling else 30951294Slling changelist_remove(zhp, cbp->cb_clp); 30961294Slling } 30971294Slling 30981294Slling zfs_close(zhp); 30991294Slling return (0); 31001294Slling } 31011294Slling 31021294Slling /* 31031294Slling * Rollback the dataset to its latest snapshot. 31041294Slling */ 31051294Slling static int 31061294Slling do_rollback(zfs_handle_t *zhp) 3107789Sahrens { 3108789Sahrens int ret; 3109789Sahrens zfs_cmd_t zc = { 0 }; 3110789Sahrens 3111789Sahrens assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM || 3112789Sahrens zhp->zfs_type == ZFS_TYPE_VOLUME); 3113789Sahrens 3114789Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME && 31152082Seschrock zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0) 3116789Sahrens return (-1); 3117789Sahrens 3118789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3119789Sahrens 31202676Seschrock if (ZFS_IS_VOLUME(zhp)) 3121789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3122789Sahrens else 3123789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3124789Sahrens 3125789Sahrens /* 3126789Sahrens * We rely on the consumer to verify that there are no newer snapshots 3127789Sahrens * for the given dataset. Given these constraints, we can simply pass 3128789Sahrens * the name on to the ioctl() call. There is still an unlikely race 3129789Sahrens * condition where the user has taken a snapshot since we verified that 3130789Sahrens * this was the most recent. 3131789Sahrens */ 31322082Seschrock if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_ROLLBACK, 31332082Seschrock &zc)) != 0) { 31343237Slling (void) zfs_standard_error_fmt(zhp->zfs_hdl, errno, 31352082Seschrock dgettext(TEXT_DOMAIN, "cannot rollback '%s'"), 31362082Seschrock zhp->zfs_name); 3137789Sahrens } else if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 31382082Seschrock ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 3139789Sahrens } 3140789Sahrens 3141789Sahrens return (ret); 3142789Sahrens } 3143789Sahrens 3144789Sahrens /* 31451294Slling * Given a dataset, rollback to a specific snapshot, discarding any 31461294Slling * data changes since then and making it the active dataset. 31471294Slling * 31481294Slling * Any snapshots more recent than the target are destroyed, along with 31491294Slling * their dependents. 31501294Slling */ 31511294Slling int 31521294Slling zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, int flag) 31531294Slling { 31541294Slling int ret; 31551294Slling rollback_data_t cb = { 0 }; 31561294Slling prop_changelist_t *clp; 31571294Slling 31581294Slling /* 31591294Slling * Unmount all dependendents of the dataset and the dataset itself. 31601294Slling * The list we need to gather is the same as for doing rename 31611294Slling */ 31621294Slling clp = changelist_gather(zhp, ZFS_PROP_NAME, flag ? MS_FORCE: 0); 31631294Slling if (clp == NULL) 31641294Slling return (-1); 31651294Slling 31661294Slling if ((ret = changelist_prefix(clp)) != 0) 31671294Slling goto out; 31681294Slling 31691294Slling /* 31701294Slling * Destroy all recent snapshots and its dependends. 31711294Slling */ 31721294Slling cb.cb_target = snap->zfs_name; 31731294Slling cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG); 31741294Slling cb.cb_clp = clp; 31751294Slling (void) zfs_iter_children(zhp, rollback_destroy, &cb); 31761294Slling 31771294Slling if ((ret = cb.cb_error) != 0) { 31781294Slling (void) changelist_postfix(clp); 31791294Slling goto out; 31801294Slling } 31811294Slling 31821294Slling /* 31831294Slling * Now that we have verified that the snapshot is the latest, 31841294Slling * rollback to the given snapshot. 31851294Slling */ 31861294Slling ret = do_rollback(zhp); 31871294Slling 31881294Slling if (ret != 0) { 31891294Slling (void) changelist_postfix(clp); 31901294Slling goto out; 31911294Slling } 31921294Slling 31931294Slling /* 31941294Slling * We only want to re-mount the filesystem if it was mounted in the 31951294Slling * first place. 31961294Slling */ 31971294Slling ret = changelist_postfix(clp); 31981294Slling 31991294Slling out: 32001294Slling changelist_free(clp); 32011294Slling return (ret); 32021294Slling } 32031294Slling 32041294Slling /* 3205789Sahrens * Iterate over all dependents for a given dataset. This includes both 3206789Sahrens * hierarchical dependents (children) and data dependents (snapshots and 3207789Sahrens * clones). The bulk of the processing occurs in get_dependents() in 3208789Sahrens * libzfs_graph.c. 3209789Sahrens */ 3210789Sahrens int 32112474Seschrock zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion, 32122474Seschrock zfs_iter_f func, void *data) 3213789Sahrens { 3214789Sahrens char **dependents; 3215789Sahrens size_t count; 3216789Sahrens int i; 3217789Sahrens zfs_handle_t *child; 3218789Sahrens int ret = 0; 3219789Sahrens 32202474Seschrock if (get_dependents(zhp->zfs_hdl, allowrecursion, zhp->zfs_name, 32212474Seschrock &dependents, &count) != 0) 32222474Seschrock return (-1); 32232474Seschrock 3224789Sahrens for (i = 0; i < count; i++) { 32252082Seschrock if ((child = make_dataset_handle(zhp->zfs_hdl, 32262082Seschrock dependents[i])) == NULL) 3227789Sahrens continue; 3228789Sahrens 3229789Sahrens if ((ret = func(child, data)) != 0) 3230789Sahrens break; 3231789Sahrens } 3232789Sahrens 3233789Sahrens for (i = 0; i < count; i++) 3234789Sahrens free(dependents[i]); 3235789Sahrens free(dependents); 3236789Sahrens 3237789Sahrens return (ret); 3238789Sahrens } 3239789Sahrens 3240789Sahrens /* 3241789Sahrens * Renames the given dataset. 3242789Sahrens */ 3243789Sahrens int 32444007Smmusante zfs_rename(zfs_handle_t *zhp, const char *target, int recursive) 3245789Sahrens { 3246789Sahrens int ret; 3247789Sahrens zfs_cmd_t zc = { 0 }; 3248789Sahrens char *delim; 32494007Smmusante prop_changelist_t *cl = NULL; 32504007Smmusante zfs_handle_t *zhrp = NULL; 32514007Smmusante char *parentname = NULL; 3252789Sahrens char parent[ZFS_MAXNAMELEN]; 32532082Seschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 32542082Seschrock char errbuf[1024]; 3255789Sahrens 3256789Sahrens /* if we have the same exact name, just return success */ 3257789Sahrens if (strcmp(zhp->zfs_name, target) == 0) 3258789Sahrens return (0); 3259789Sahrens 32602082Seschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 32612082Seschrock "cannot rename to '%s'"), target); 32622082Seschrock 3263789Sahrens /* 3264789Sahrens * Make sure the target name is valid 3265789Sahrens */ 3266789Sahrens if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 32672665Snd150628 if ((strchr(target, '@') == NULL) || 32682665Snd150628 *target == '@') { 32692665Snd150628 /* 32702665Snd150628 * Snapshot target name is abbreviated, 32712665Snd150628 * reconstruct full dataset name 32722665Snd150628 */ 32732665Snd150628 (void) strlcpy(parent, zhp->zfs_name, 32742665Snd150628 sizeof (parent)); 32752665Snd150628 delim = strchr(parent, '@'); 32762665Snd150628 if (strchr(target, '@') == NULL) 32772665Snd150628 *(++delim) = '\0'; 32782665Snd150628 else 32792665Snd150628 *delim = '\0'; 32802665Snd150628 (void) strlcat(parent, target, sizeof (parent)); 32812665Snd150628 target = parent; 32822665Snd150628 } else { 32832665Snd150628 /* 32842665Snd150628 * Make sure we're renaming within the same dataset. 32852665Snd150628 */ 32862665Snd150628 delim = strchr(target, '@'); 32872665Snd150628 if (strncmp(zhp->zfs_name, target, delim - target) 32882665Snd150628 != 0 || zhp->zfs_name[delim - target] != '@') { 32892665Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 32902665Snd150628 "snapshots must be part of same " 32912665Snd150628 "dataset")); 32922665Snd150628 return (zfs_error(hdl, EZFS_CROSSTARGET, 32933912Slling errbuf)); 32942665Snd150628 } 3295789Sahrens } 32962665Snd150628 if (!zfs_validate_name(hdl, target, zhp->zfs_type)) 32972665Snd150628 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 3298789Sahrens } else { 32994007Smmusante if (recursive) { 33004007Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33014007Smmusante "recursive rename must be a snapshot")); 33024007Smmusante return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 33034007Smmusante } 33044007Smmusante 33052665Snd150628 if (!zfs_validate_name(hdl, target, zhp->zfs_type)) 33062665Snd150628 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 33072676Seschrock uint64_t unused; 33082676Seschrock 3309789Sahrens /* validate parents */ 33102676Seschrock if (check_parents(hdl, target, &unused) != 0) 3311789Sahrens return (-1); 3312789Sahrens 3313789Sahrens (void) parent_name(target, parent, sizeof (parent)); 3314789Sahrens 3315789Sahrens /* make sure we're in the same pool */ 3316789Sahrens verify((delim = strchr(target, '/')) != NULL); 3317789Sahrens if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 3318789Sahrens zhp->zfs_name[delim - target] != '/') { 33192082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33202082Seschrock "datasets must be within same pool")); 33212082Seschrock return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); 3322789Sahrens } 33232440Snd150628 33242440Snd150628 /* new name cannot be a child of the current dataset name */ 33252440Snd150628 if (strncmp(parent, zhp->zfs_name, 33263912Slling strlen(zhp->zfs_name)) == 0) { 33272440Snd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33282440Snd150628 "New dataset name cannot be a descendent of " 33292440Snd150628 "current dataset name")); 33302440Snd150628 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 33312440Snd150628 } 3332789Sahrens } 3333789Sahrens 33342082Seschrock (void) snprintf(errbuf, sizeof (errbuf), 33352082Seschrock dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name); 33362082Seschrock 3337789Sahrens if (getzoneid() == GLOBAL_ZONEID && 3338789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 33392082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33402082Seschrock "dataset is used in a non-global zone")); 33412082Seschrock return (zfs_error(hdl, EZFS_ZONED, errbuf)); 3342789Sahrens } 3343789Sahrens 33444007Smmusante if (recursive) { 33454007Smmusante struct destroydata dd; 33464007Smmusante 33474007Smmusante parentname = strdup(zhp->zfs_name); 33484007Smmusante delim = strchr(parentname, '@'); 33494007Smmusante *delim = '\0'; 33504007Smmusante zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_ANY); 33514007Smmusante if (zhrp == NULL) { 33524007Smmusante return (-1); 33534007Smmusante } 33544007Smmusante 33554007Smmusante dd.snapname = delim + 1; 33564007Smmusante dd.gotone = B_FALSE; 33574007Smmusante dd.closezhp = B_FALSE; 33584007Smmusante 33594007Smmusante /* We remove any zvol links prior to renaming them */ 33604007Smmusante ret = zfs_iter_filesystems(zhrp, zfs_remove_link_cb, &dd); 33614007Smmusante if (ret) { 33624007Smmusante goto error; 33634007Smmusante } 33644007Smmusante } else { 33654007Smmusante if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0)) == NULL) 33664007Smmusante return (-1); 33674007Smmusante 33684007Smmusante if (changelist_haszonedchild(cl)) { 33694007Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 33704007Smmusante "child dataset with inherited mountpoint is used " 33714007Smmusante "in a non-global zone")); 33724007Smmusante (void) zfs_error(hdl, EZFS_ZONED, errbuf); 33734007Smmusante goto error; 33744007Smmusante } 33754007Smmusante 33764007Smmusante if ((ret = changelist_prefix(cl)) != 0) 33774007Smmusante goto error; 3378789Sahrens } 3379789Sahrens 33802676Seschrock if (ZFS_IS_VOLUME(zhp)) 3381789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3382789Sahrens else 3383789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3384789Sahrens 33852665Snd150628 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 33862676Seschrock (void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value)); 33872665Snd150628 33884007Smmusante zc.zc_cookie = recursive; 33894007Smmusante 33902082Seschrock if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_RENAME, &zc)) != 0) { 33914007Smmusante /* 33924007Smmusante * if it was recursive, the one that actually failed will 33934007Smmusante * be in zc.zc_name 33944007Smmusante */ 33954007Smmusante (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 33964007Smmusante "cannot rename to '%s'"), zc.zc_name); 33974007Smmusante 33984007Smmusante if (recursive && errno == EEXIST) { 33994007Smmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 34004007Smmusante "a child dataset already has a snapshot " 34014007Smmusante "with the new name")); 34024007Smmusante (void) zfs_error(hdl, EZFS_CROSSTARGET, errbuf); 34034007Smmusante } else { 34044007Smmusante (void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf); 34054007Smmusante } 3406789Sahrens 3407789Sahrens /* 3408789Sahrens * On failure, we still want to remount any filesystems that 3409789Sahrens * were previously mounted, so we don't alter the system state. 3410789Sahrens */ 34114007Smmusante if (recursive) { 34124007Smmusante struct createdata cd; 34134007Smmusante 34144007Smmusante /* only create links for datasets that had existed */ 34154007Smmusante cd.cd_snapname = delim + 1; 34164007Smmusante cd.cd_ifexists = B_TRUE; 34174007Smmusante (void) zfs_iter_filesystems(zhrp, zfs_create_link_cb, 34184007Smmusante &cd); 34194007Smmusante } else { 34204007Smmusante (void) changelist_postfix(cl); 34214007Smmusante } 3422789Sahrens } else { 34234007Smmusante if (recursive) { 34244007Smmusante struct createdata cd; 34254007Smmusante 34264007Smmusante /* only create links for datasets that had existed */ 34274007Smmusante cd.cd_snapname = strchr(target, '@') + 1; 34284007Smmusante cd.cd_ifexists = B_TRUE; 34294007Smmusante ret = zfs_iter_filesystems(zhrp, zfs_create_link_cb, 34304007Smmusante &cd); 34314007Smmusante } else { 34324007Smmusante changelist_rename(cl, zfs_get_name(zhp), target); 34334007Smmusante ret = changelist_postfix(cl); 34344007Smmusante } 3435789Sahrens } 3436789Sahrens 3437789Sahrens error: 34384007Smmusante if (parentname) { 34394007Smmusante free(parentname); 34404007Smmusante } 34414007Smmusante if (zhrp) { 34424007Smmusante zfs_close(zhrp); 34434007Smmusante } 34444007Smmusante if (cl) { 34454007Smmusante changelist_free(cl); 34464007Smmusante } 3447789Sahrens return (ret); 3448789Sahrens } 3449789Sahrens 3450789Sahrens /* 3451789Sahrens * Given a zvol dataset, issue the ioctl to create the appropriate minor node, 3452789Sahrens * poke devfsadm to create the /dev link, and then wait for the link to appear. 3453789Sahrens */ 3454789Sahrens int 34552082Seschrock zvol_create_link(libzfs_handle_t *hdl, const char *dataset) 3456789Sahrens { 34574007Smmusante return (zvol_create_link_common(hdl, dataset, B_FALSE)); 34584007Smmusante } 34594007Smmusante 34604007Smmusante static int 34614007Smmusante zvol_create_link_common(libzfs_handle_t *hdl, const char *dataset, int ifexists) 34624007Smmusante { 3463789Sahrens zfs_cmd_t zc = { 0 }; 34642082Seschrock di_devlink_handle_t dhdl; 3465789Sahrens 3466789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3467789Sahrens 3468789Sahrens /* 3469789Sahrens * Issue the appropriate ioctl. 3470789Sahrens */ 34712082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE_MINOR, &zc) != 0) { 3472789Sahrens switch (errno) { 3473789Sahrens case EEXIST: 3474789Sahrens /* 3475789Sahrens * Silently ignore the case where the link already 3476789Sahrens * exists. This allows 'zfs volinit' to be run multiple 3477789Sahrens * times without errors. 3478789Sahrens */ 3479789Sahrens return (0); 3480789Sahrens 34814007Smmusante case ENOENT: 34824007Smmusante /* 34834007Smmusante * Dataset does not exist in the kernel. If we 34844007Smmusante * don't care (see zfs_rename), then ignore the 34854007Smmusante * error quietly. 34864007Smmusante */ 34874007Smmusante if (ifexists) { 34884007Smmusante return (0); 34894007Smmusante } 34904007Smmusante 34914007Smmusante /* FALLTHROUGH */ 34924007Smmusante 3493789Sahrens default: 34943237Slling return (zfs_standard_error_fmt(hdl, errno, 34952082Seschrock dgettext(TEXT_DOMAIN, "cannot create device links " 34962082Seschrock "for '%s'"), dataset)); 3497789Sahrens } 3498789Sahrens } 3499789Sahrens 3500789Sahrens /* 3501789Sahrens * Call devfsadm and wait for the links to magically appear. 3502789Sahrens */ 35032082Seschrock if ((dhdl = di_devlink_init(ZFS_DRIVER, DI_MAKE_LINK)) == NULL) { 35042082Seschrock zfs_error_aux(hdl, strerror(errno)); 35053237Slling (void) zfs_error_fmt(hdl, EZFS_DEVLINKS, 35062082Seschrock dgettext(TEXT_DOMAIN, "cannot create device links " 35072082Seschrock "for '%s'"), dataset); 35082082Seschrock (void) ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc); 3509789Sahrens return (-1); 3510789Sahrens } else { 35112082Seschrock (void) di_devlink_fini(&dhdl); 3512789Sahrens } 3513789Sahrens 3514789Sahrens return (0); 3515789Sahrens } 3516789Sahrens 3517789Sahrens /* 3518789Sahrens * Remove a minor node for the given zvol and the associated /dev links. 3519789Sahrens */ 3520789Sahrens int 35212082Seschrock zvol_remove_link(libzfs_handle_t *hdl, const char *dataset) 3522789Sahrens { 3523789Sahrens zfs_cmd_t zc = { 0 }; 3524789Sahrens 3525789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3526789Sahrens 35272082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc) != 0) { 3528789Sahrens switch (errno) { 3529789Sahrens case ENXIO: 3530789Sahrens /* 3531789Sahrens * Silently ignore the case where the link no longer 3532789Sahrens * exists, so that 'zfs volfini' can be run multiple 3533789Sahrens * times without errors. 3534789Sahrens */ 3535789Sahrens return (0); 3536789Sahrens 3537789Sahrens default: 35383237Slling return (zfs_standard_error_fmt(hdl, errno, 35392082Seschrock dgettext(TEXT_DOMAIN, "cannot remove device " 35402082Seschrock "links for '%s'"), dataset)); 3541789Sahrens } 3542789Sahrens } 3543789Sahrens 3544789Sahrens return (0); 3545789Sahrens } 35462676Seschrock 35472676Seschrock nvlist_t * 35482676Seschrock zfs_get_user_props(zfs_handle_t *zhp) 35492676Seschrock { 35502676Seschrock return (zhp->zfs_user_props); 35512676Seschrock } 35522676Seschrock 35532676Seschrock /* 35542676Seschrock * Given a comma-separated list of properties, contruct a property list 35552676Seschrock * containing both user-defined and native properties. This function will 35562676Seschrock * return a NULL list if 'all' is specified, which can later be expanded on a 35572676Seschrock * per-dataset basis by zfs_expand_proplist(). 35582676Seschrock */ 35592676Seschrock int 35603912Slling zfs_get_proplist_common(libzfs_handle_t *hdl, char *fields, 35613912Slling zfs_proplist_t **listp, zfs_type_t type) 35622676Seschrock { 35632676Seschrock size_t len; 35642676Seschrock char *s, *p; 35652676Seschrock char c; 35662676Seschrock zfs_prop_t prop; 35672676Seschrock zfs_proplist_t *entry; 35682676Seschrock zfs_proplist_t **last; 35692676Seschrock 35702676Seschrock *listp = NULL; 35712676Seschrock last = listp; 35722676Seschrock 35732676Seschrock /* 35742676Seschrock * If 'all' is specified, return a NULL list. 35752676Seschrock */ 35762676Seschrock if (strcmp(fields, "all") == 0) 35772676Seschrock return (0); 35782676Seschrock 35792676Seschrock /* 35802676Seschrock * If no fields were specified, return an error. 35812676Seschrock */ 35822676Seschrock if (fields[0] == '\0') { 35832676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 35842676Seschrock "no properties specified")); 35852676Seschrock return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, 35862676Seschrock "bad property list"))); 35872676Seschrock } 35882676Seschrock 35892676Seschrock /* 35902676Seschrock * It would be nice to use getsubopt() here, but the inclusion of column 35912676Seschrock * aliases makes this more effort than it's worth. 35922676Seschrock */ 35932676Seschrock s = fields; 35942676Seschrock while (*s != '\0') { 35952676Seschrock if ((p = strchr(s, ',')) == NULL) { 35962676Seschrock len = strlen(s); 35972676Seschrock p = s + len; 35982676Seschrock } else { 35992676Seschrock len = p - s; 36002676Seschrock } 36012676Seschrock 36022676Seschrock /* 36032676Seschrock * Check for empty options. 36042676Seschrock */ 36052676Seschrock if (len == 0) { 36062676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 36072676Seschrock "empty property name")); 36082676Seschrock return (zfs_error(hdl, EZFS_BADPROP, 36092676Seschrock dgettext(TEXT_DOMAIN, "bad property list"))); 36102676Seschrock } 36112676Seschrock 36122676Seschrock /* 36132676Seschrock * Check all regular property names. 36142676Seschrock */ 36152676Seschrock c = s[len]; 36162676Seschrock s[len] = '\0'; 36173912Slling prop = zfs_name_to_prop_common(s, type); 36183912Slling 36193912Slling if (prop != ZFS_PROP_INVAL && 36203912Slling !zfs_prop_valid_for_type(prop, type)) 36213912Slling prop = ZFS_PROP_INVAL; 36222676Seschrock 36232676Seschrock /* 36243912Slling * When no property table entry can be found, return failure if 36253912Slling * this is a pool property or if this isn't a user-defined 36263912Slling * dataset property, 36272676Seschrock */ 36283912Slling if (prop == ZFS_PROP_INVAL && 36293912Slling (type & ZFS_TYPE_POOL || !zfs_prop_user(s))) { 36302676Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 36312676Seschrock "invalid property '%s'"), s); 36322676Seschrock return (zfs_error(hdl, EZFS_BADPROP, 36332676Seschrock dgettext(TEXT_DOMAIN, "bad property list"))); 36342676Seschrock } 36352676Seschrock 36362676Seschrock if ((entry = zfs_alloc(hdl, sizeof (zfs_proplist_t))) == NULL) 36372676Seschrock return (-1); 36382676Seschrock 36392676Seschrock entry->pl_prop = prop; 36402676Seschrock if (prop == ZFS_PROP_INVAL) { 36412676Seschrock if ((entry->pl_user_prop = 36422676Seschrock zfs_strdup(hdl, s)) == NULL) { 36432676Seschrock free(entry); 36442676Seschrock return (-1); 36452676Seschrock } 36462676Seschrock entry->pl_width = strlen(s); 36472676Seschrock } else { 36482676Seschrock entry->pl_width = zfs_prop_width(prop, 36492676Seschrock &entry->pl_fixed); 36502676Seschrock } 36512676Seschrock 36522676Seschrock *last = entry; 36532676Seschrock last = &entry->pl_next; 36542676Seschrock 36552676Seschrock s = p; 36562676Seschrock if (c == ',') 36572676Seschrock s++; 36582676Seschrock } 36592676Seschrock 36602676Seschrock return (0); 36612676Seschrock } 36622676Seschrock 36633912Slling int 36643912Slling zfs_get_proplist(libzfs_handle_t *hdl, char *fields, zfs_proplist_t **listp) 36653912Slling { 36663912Slling return (zfs_get_proplist_common(hdl, fields, listp, ZFS_TYPE_ANY)); 36673912Slling } 36683912Slling 36692676Seschrock void 36702676Seschrock zfs_free_proplist(zfs_proplist_t *pl) 36712676Seschrock { 36722676Seschrock zfs_proplist_t *next; 36732676Seschrock 36742676Seschrock while (pl != NULL) { 36752676Seschrock next = pl->pl_next; 36762676Seschrock free(pl->pl_user_prop); 36772676Seschrock free(pl); 36782676Seschrock pl = next; 36792676Seschrock } 36802676Seschrock } 36812676Seschrock 36823654Sgw25295 typedef struct expand_data { 36833654Sgw25295 zfs_proplist_t **last; 36843654Sgw25295 libzfs_handle_t *hdl; 36853654Sgw25295 } expand_data_t; 36863654Sgw25295 36873654Sgw25295 static zfs_prop_t 36883654Sgw25295 zfs_expand_proplist_cb(zfs_prop_t prop, void *cb) 36893654Sgw25295 { 36903654Sgw25295 zfs_proplist_t *entry; 36913654Sgw25295 expand_data_t *edp = cb; 36923654Sgw25295 36933654Sgw25295 if ((entry = zfs_alloc(edp->hdl, sizeof (zfs_proplist_t))) == NULL) 36943654Sgw25295 return (ZFS_PROP_INVAL); 36953654Sgw25295 36963654Sgw25295 entry->pl_prop = prop; 36973654Sgw25295 entry->pl_width = zfs_prop_width(prop, &entry->pl_fixed); 36983654Sgw25295 entry->pl_all = B_TRUE; 36993654Sgw25295 37003654Sgw25295 *(edp->last) = entry; 37013654Sgw25295 edp->last = &entry->pl_next; 37023654Sgw25295 37033654Sgw25295 return (ZFS_PROP_CONT); 37043654Sgw25295 } 37053654Sgw25295 37062676Seschrock int 37073912Slling zfs_expand_proplist_common(libzfs_handle_t *hdl, zfs_proplist_t **plp, 37083912Slling zfs_type_t type) 37092676Seschrock { 37102676Seschrock zfs_proplist_t *entry; 37113912Slling zfs_proplist_t **last; 37123654Sgw25295 expand_data_t exp; 37132676Seschrock 37142676Seschrock if (*plp == NULL) { 37152676Seschrock /* 37162676Seschrock * If this is the very first time we've been called for an 'all' 37172676Seschrock * specification, expand the list to include all native 37182676Seschrock * properties. 37192676Seschrock */ 37202676Seschrock last = plp; 37213654Sgw25295 37223654Sgw25295 exp.last = last; 37233654Sgw25295 exp.hdl = hdl; 37243654Sgw25295 37253912Slling if (zfs_prop_iter_common(zfs_expand_proplist_cb, &exp, type, 37263654Sgw25295 B_FALSE) == ZFS_PROP_INVAL) 37273654Sgw25295 return (-1); 37282676Seschrock 37292676Seschrock /* 37302676Seschrock * Add 'name' to the beginning of the list, which is handled 37312676Seschrock * specially. 37322676Seschrock */ 37332676Seschrock if ((entry = zfs_alloc(hdl, 37342676Seschrock sizeof (zfs_proplist_t))) == NULL) 37352676Seschrock return (-1); 37362676Seschrock 37372676Seschrock entry->pl_prop = ZFS_PROP_NAME; 37382676Seschrock entry->pl_width = zfs_prop_width(ZFS_PROP_NAME, 37392676Seschrock &entry->pl_fixed); 37402676Seschrock entry->pl_all = B_TRUE; 37412676Seschrock entry->pl_next = *plp; 37422676Seschrock *plp = entry; 37432676Seschrock } 37443912Slling return (0); 37453912Slling } 37463912Slling 37473912Slling /* 37483912Slling * This function is used by 'zfs list' to determine the exact set of columns to 37493912Slling * display, and their maximum widths. This does two main things: 37503912Slling * 37513912Slling * - If this is a list of all properties, then expand the list to include 37523912Slling * all native properties, and set a flag so that for each dataset we look 37533912Slling * for new unique user properties and add them to the list. 37543912Slling * 37553912Slling * - For non fixed-width properties, keep track of the maximum width seen 37563912Slling * so that we can size the column appropriately. 37573912Slling */ 37583912Slling int 37593912Slling zfs_expand_proplist(zfs_handle_t *zhp, zfs_proplist_t **plp) 37603912Slling { 37613912Slling libzfs_handle_t *hdl = zhp->zfs_hdl; 37623912Slling zfs_proplist_t *entry; 37633912Slling zfs_proplist_t **last, **start; 37643912Slling nvlist_t *userprops, *propval; 37653912Slling nvpair_t *elem; 37663912Slling char *strval; 37673912Slling char buf[ZFS_MAXPROPLEN]; 37683912Slling 37693912Slling if (zfs_expand_proplist_common(hdl, plp, ZFS_TYPE_ANY) != 0) 37703912Slling return (-1); 37712676Seschrock 37722676Seschrock userprops = zfs_get_user_props(zhp); 37732676Seschrock 37742676Seschrock entry = *plp; 37752676Seschrock if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) { 37762676Seschrock /* 37772676Seschrock * Go through and add any user properties as necessary. We 37782676Seschrock * start by incrementing our list pointer to the first 37792676Seschrock * non-native property. 37802676Seschrock */ 37812676Seschrock start = plp; 37822676Seschrock while (*start != NULL) { 37832676Seschrock if ((*start)->pl_prop == ZFS_PROP_INVAL) 37842676Seschrock break; 37852676Seschrock start = &(*start)->pl_next; 37862676Seschrock } 37872676Seschrock 37882676Seschrock elem = NULL; 37892676Seschrock while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) { 37902676Seschrock /* 37912676Seschrock * See if we've already found this property in our list. 37922676Seschrock */ 37932676Seschrock for (last = start; *last != NULL; 37942676Seschrock last = &(*last)->pl_next) { 37952676Seschrock if (strcmp((*last)->pl_user_prop, 37962676Seschrock nvpair_name(elem)) == 0) 37972676Seschrock break; 37982676Seschrock } 37992676Seschrock 38002676Seschrock if (*last == NULL) { 38012676Seschrock if ((entry = zfs_alloc(hdl, 38022676Seschrock sizeof (zfs_proplist_t))) == NULL || 38032676Seschrock ((entry->pl_user_prop = zfs_strdup(hdl, 38042676Seschrock nvpair_name(elem)))) == NULL) { 38052676Seschrock free(entry); 38062676Seschrock return (-1); 38072676Seschrock } 38082676Seschrock 38092676Seschrock entry->pl_prop = ZFS_PROP_INVAL; 38102676Seschrock entry->pl_width = strlen(nvpair_name(elem)); 38112676Seschrock entry->pl_all = B_TRUE; 38122676Seschrock *last = entry; 38132676Seschrock } 38142676Seschrock } 38152676Seschrock } 38162676Seschrock 38172676Seschrock /* 38182676Seschrock * Now go through and check the width of any non-fixed columns 38192676Seschrock */ 38202676Seschrock for (entry = *plp; entry != NULL; entry = entry->pl_next) { 38212676Seschrock if (entry->pl_fixed) 38222676Seschrock continue; 38232676Seschrock 38242676Seschrock if (entry->pl_prop != ZFS_PROP_INVAL) { 38252676Seschrock if (zfs_prop_get(zhp, entry->pl_prop, 38262676Seschrock buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0) { 38272676Seschrock if (strlen(buf) > entry->pl_width) 38282676Seschrock entry->pl_width = strlen(buf); 38292676Seschrock } 38302676Seschrock } else if (nvlist_lookup_nvlist(userprops, 38312676Seschrock entry->pl_user_prop, &propval) == 0) { 38322676Seschrock verify(nvlist_lookup_string(propval, 38332676Seschrock ZFS_PROP_VALUE, &strval) == 0); 38342676Seschrock if (strlen(strval) > entry->pl_width) 38352676Seschrock entry->pl_width = strlen(strval); 38362676Seschrock } 38372676Seschrock } 38382676Seschrock 38392676Seschrock return (0); 38402676Seschrock } 3841