1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5789Sahrens * Common Development and Distribution License, Version 1.0 only 6789Sahrens * (the "License"). You may not use this file except in compliance 7789Sahrens * with the License. 8789Sahrens * 9789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10789Sahrens * or http://www.opensolaris.org/os/licensing. 11789Sahrens * See the License for the specific language governing permissions 12789Sahrens * and limitations under the License. 13789Sahrens * 14789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16789Sahrens * If applicable, add the following below this CDDL HEADER, with the 17789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19789Sahrens * 20789Sahrens * CDDL HEADER END 21789Sahrens */ 22789Sahrens /* 231294Slling * Copyright 2006 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> 40789Sahrens #include <sys/mntent.h> 41789Sahrens #include <sys/mnttab.h> 421294Slling #include <sys/mount.h> 43789Sahrens 44789Sahrens #include <sys/spa.h> 45789Sahrens #include <sys/zio.h> 46789Sahrens #include <libzfs.h> 47789Sahrens 48789Sahrens #include "zfs_namecheck.h" 49789Sahrens #include "zfs_prop.h" 50789Sahrens #include "libzfs_impl.h" 51789Sahrens 52789Sahrens /* 53789Sahrens * Given a single type (not a mask of types), return the type in a human 54789Sahrens * readable form. 55789Sahrens */ 56789Sahrens const char * 57789Sahrens zfs_type_to_name(zfs_type_t type) 58789Sahrens { 59789Sahrens switch (type) { 60789Sahrens case ZFS_TYPE_FILESYSTEM: 61789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 62789Sahrens case ZFS_TYPE_SNAPSHOT: 63789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 64789Sahrens case ZFS_TYPE_VOLUME: 65789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 66789Sahrens } 67789Sahrens 68789Sahrens zfs_baderror(type); 69789Sahrens return (NULL); 70789Sahrens } 71789Sahrens 72789Sahrens /* 73789Sahrens * Given a path and mask of ZFS types, return a string describing this dataset. 74789Sahrens * This is used when we fail to open a dataset and we cannot get an exact type. 75789Sahrens * We guess what the type would have been based on the path and the mask of 76789Sahrens * acceptable types. 77789Sahrens */ 78789Sahrens static const char * 79789Sahrens path_to_str(const char *path, int types) 80789Sahrens { 81789Sahrens /* 82789Sahrens * When given a single type, always report the exact type. 83789Sahrens */ 84789Sahrens if (types == ZFS_TYPE_SNAPSHOT) 85789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 86789Sahrens if (types == ZFS_TYPE_FILESYSTEM) 87789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 88789Sahrens if (types == ZFS_TYPE_VOLUME) 89789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 90789Sahrens 91789Sahrens /* 92789Sahrens * The user is requesting more than one type of dataset. If this is the 93789Sahrens * case, consult the path itself. If we're looking for a snapshot, and 94789Sahrens * a '@' is found, then report it as "snapshot". Otherwise, remove the 95789Sahrens * snapshot attribute and try again. 96789Sahrens */ 97789Sahrens if (types & ZFS_TYPE_SNAPSHOT) { 98789Sahrens if (strchr(path, '@') != NULL) 99789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 100789Sahrens return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 101789Sahrens } 102789Sahrens 103789Sahrens 104789Sahrens /* 105789Sahrens * The user has requested either filesystems or volumes. 106789Sahrens * We have no way of knowing a priori what type this would be, so always 107789Sahrens * report it as "filesystem" or "volume", our two primitive types. 108789Sahrens */ 109789Sahrens if (types & ZFS_TYPE_FILESYSTEM) 110789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 111789Sahrens 112789Sahrens assert(types & ZFS_TYPE_VOLUME); 113789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 114789Sahrens } 115789Sahrens 116789Sahrens /* 117789Sahrens * Validate a ZFS path. This is used even before trying to open the dataset, to 118789Sahrens * provide a more meaningful error message. We place a more useful message in 119789Sahrens * 'buf' detailing exactly why the name was not valid. 120789Sahrens */ 121789Sahrens static int 122789Sahrens zfs_validate_name(const char *path, int type, char *buf, size_t buflen) 123789Sahrens { 124789Sahrens namecheck_err_t why; 125789Sahrens char what; 126789Sahrens 127789Sahrens if (dataset_namecheck(path, &why, &what) != 0) { 128789Sahrens if (buf != NULL) { 129789Sahrens switch (why) { 1301003Slling case NAME_ERR_TOOLONG: 1311003Slling (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 1321003Slling "name is too long"), buflen); 1331003Slling break; 1341003Slling 135789Sahrens case NAME_ERR_LEADING_SLASH: 136789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 137789Sahrens "leading slash"), buflen); 138789Sahrens break; 139789Sahrens 140789Sahrens case NAME_ERR_EMPTY_COMPONENT: 141789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 142789Sahrens "empty component"), buflen); 143789Sahrens break; 144789Sahrens 145789Sahrens case NAME_ERR_TRAILING_SLASH: 146789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 147789Sahrens "trailing slash"), buflen); 148789Sahrens break; 149789Sahrens 150789Sahrens case NAME_ERR_INVALCHAR: 151789Sahrens (void) snprintf(buf, buflen, 152789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 153789Sahrens "'%c'"), what); 154789Sahrens break; 155789Sahrens 156789Sahrens case NAME_ERR_MULTIPLE_AT: 157789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 158789Sahrens "multiple '@' delimiters"), buflen); 159789Sahrens break; 160789Sahrens } 161789Sahrens } 162789Sahrens 163789Sahrens return (0); 164789Sahrens } 165789Sahrens 166789Sahrens if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) { 167789Sahrens if (buf != NULL) 168789Sahrens (void) strlcpy(buf, 169789Sahrens dgettext(TEXT_DOMAIN, 170789Sahrens "snapshot delimiter '@'"), buflen); 171789Sahrens return (0); 172789Sahrens } 173789Sahrens 174789Sahrens return (1); 175789Sahrens } 176789Sahrens 177789Sahrens int 178789Sahrens zfs_name_valid(const char *name, zfs_type_t type) 179789Sahrens { 180789Sahrens return (zfs_validate_name(name, type, NULL, NULL)); 181789Sahrens } 182789Sahrens 183789Sahrens /* 184789Sahrens * Utility function to gather stats (objset and zpl) for the given object. 185789Sahrens */ 186789Sahrens static int 187789Sahrens get_stats(zfs_handle_t *zhp) 188789Sahrens { 189789Sahrens zfs_cmd_t zc = { 0 }; 190789Sahrens 191789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 192789Sahrens 1931356Seschrock zc.zc_config_src = (uint64_t)(uintptr_t)zfs_malloc(1024); 1941356Seschrock zc.zc_config_src_size = 1024; 1951356Seschrock 1961356Seschrock while (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) { 1971356Seschrock if (errno == ENOMEM) { 1981356Seschrock zc.zc_config_src = (uint64_t)(uintptr_t) 1991356Seschrock zfs_malloc(zc.zc_config_src_size); 2001356Seschrock } else { 2011356Seschrock free((void *)(uintptr_t)zc.zc_config_src); 2021356Seschrock return (-1); 2031356Seschrock } 2041356Seschrock } 205789Sahrens 206789Sahrens bcopy(&zc.zc_objset_stats, &zhp->zfs_dmustats, 207789Sahrens sizeof (zc.zc_objset_stats)); 208789Sahrens 2091356Seschrock verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_src, 2101356Seschrock zc.zc_config_src_size, &zhp->zfs_props, 0) == 0); 211789Sahrens 212789Sahrens zhp->zfs_volsize = zc.zc_volsize; 213789Sahrens zhp->zfs_volblocksize = zc.zc_volblocksize; 214789Sahrens 215789Sahrens return (0); 216789Sahrens } 217789Sahrens 218789Sahrens /* 219789Sahrens * Refresh the properties currently stored in the handle. 220789Sahrens */ 221789Sahrens void 222789Sahrens zfs_refresh_properties(zfs_handle_t *zhp) 223789Sahrens { 224789Sahrens (void) get_stats(zhp); 225789Sahrens } 226789Sahrens 227789Sahrens /* 228789Sahrens * Makes a handle from the given dataset name. Used by zfs_open() and 229789Sahrens * zfs_iter_* to create child handles on the fly. 230789Sahrens */ 231789Sahrens zfs_handle_t * 232789Sahrens make_dataset_handle(const char *path) 233789Sahrens { 234789Sahrens zfs_handle_t *zhp = zfs_malloc(sizeof (zfs_handle_t)); 235789Sahrens 236789Sahrens (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); 237789Sahrens 238789Sahrens if (get_stats(zhp) != 0) { 239789Sahrens free(zhp); 240789Sahrens return (NULL); 241789Sahrens } 242789Sahrens 243789Sahrens /* 244789Sahrens * We've managed to open the dataset and gather statistics. Determine 245789Sahrens * the high-level type. 246789Sahrens */ 247789Sahrens if (zhp->zfs_dmustats.dds_is_snapshot) 248789Sahrens zhp->zfs_type = ZFS_TYPE_SNAPSHOT; 249789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 250789Sahrens zhp->zfs_type = ZFS_TYPE_VOLUME; 251789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 252789Sahrens zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 253789Sahrens else 254789Sahrens /* we should never see any other dataset types */ 255789Sahrens zfs_baderror(zhp->zfs_dmustats.dds_type); 256789Sahrens 257789Sahrens return (zhp); 258789Sahrens } 259789Sahrens 260789Sahrens /* 261789Sahrens * Opens the given snapshot, filesystem, or volume. The 'types' 262789Sahrens * argument is a mask of acceptable types. The function will print an 263789Sahrens * appropriate error message and return NULL if it can't be opened. 264789Sahrens */ 265789Sahrens zfs_handle_t * 266789Sahrens zfs_open(const char *path, int types) 267789Sahrens { 268789Sahrens zfs_handle_t *zhp; 269789Sahrens 270789Sahrens /* 271789Sahrens * Validate the name before we even try to open it. We don't care about 272789Sahrens * the verbose invalid messages here; just report a generic error. 273789Sahrens */ 274789Sahrens if (!zfs_validate_name(path, types, NULL, 0)) { 275789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 276789Sahrens "cannot open '%s': invalid %s name"), path, 277789Sahrens path_to_str(path, types)); 278789Sahrens return (NULL); 279789Sahrens } 280789Sahrens 281789Sahrens /* 282789Sahrens * Try to get stats for the dataset, which will tell us if it exists. 283789Sahrens */ 284789Sahrens errno = 0; 285789Sahrens if ((zhp = make_dataset_handle(path)) == NULL) { 286789Sahrens switch (errno) { 287789Sahrens case ENOENT: 288789Sahrens /* 289789Sahrens * The dataset doesn't exist. 290789Sahrens */ 291789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 292789Sahrens "cannot open '%s': no such %s"), path, 293789Sahrens path_to_str(path, types)); 294789Sahrens break; 295789Sahrens 296789Sahrens case EBUSY: 297789Sahrens /* 298789Sahrens * We were able to open the dataset but couldn't 299789Sahrens * get the stats. 300789Sahrens */ 301789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 302789Sahrens "cannot open '%s': %s is busy"), path, 303789Sahrens path_to_str(path, types)); 304789Sahrens break; 305789Sahrens 306789Sahrens default: 307789Sahrens zfs_baderror(errno); 308789Sahrens 309789Sahrens } 310789Sahrens return (NULL); 311789Sahrens } 312789Sahrens 313789Sahrens if (!(types & zhp->zfs_type)) { 314789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': operation " 315789Sahrens "not supported for %ss"), path, 316789Sahrens zfs_type_to_name(zhp->zfs_type)); 317789Sahrens free(zhp); 318789Sahrens return (NULL); 319789Sahrens } 320789Sahrens 321789Sahrens return (zhp); 322789Sahrens } 323789Sahrens 324789Sahrens /* 325789Sahrens * Release a ZFS handle. Nothing to do but free the associated memory. 326789Sahrens */ 327789Sahrens void 328789Sahrens zfs_close(zfs_handle_t *zhp) 329789Sahrens { 330789Sahrens if (zhp->zfs_mntopts) 331789Sahrens free(zhp->zfs_mntopts); 332789Sahrens free(zhp); 333789Sahrens } 334789Sahrens 335789Sahrens struct { 336789Sahrens const char *name; 337789Sahrens uint64_t value; 338789Sahrens } checksum_table[] = { 339789Sahrens { "on", ZIO_CHECKSUM_ON }, 340789Sahrens { "off", ZIO_CHECKSUM_OFF }, 341789Sahrens { "fletcher2", ZIO_CHECKSUM_FLETCHER_2 }, 342789Sahrens { "fletcher4", ZIO_CHECKSUM_FLETCHER_4 }, 343789Sahrens { "sha256", ZIO_CHECKSUM_SHA256 }, 344789Sahrens { NULL } 345789Sahrens }; 346789Sahrens 347789Sahrens struct { 348789Sahrens const char *name; 349789Sahrens uint64_t value; 350789Sahrens } compress_table[] = { 351789Sahrens { "on", ZIO_COMPRESS_ON }, 352789Sahrens { "off", ZIO_COMPRESS_OFF }, 353789Sahrens { "lzjb", ZIO_COMPRESS_LZJB }, 354789Sahrens { NULL } 355789Sahrens }; 356789Sahrens 357789Sahrens struct { 358789Sahrens const char *name; 359789Sahrens uint64_t value; 360789Sahrens } snapdir_table[] = { 361849Sbonwick { "hidden", ZFS_SNAPDIR_HIDDEN }, 362849Sbonwick { "visible", ZFS_SNAPDIR_VISIBLE }, 363789Sahrens { NULL } 364789Sahrens }; 365789Sahrens 366789Sahrens struct { 367789Sahrens const char *name; 368789Sahrens uint64_t value; 369789Sahrens } acl_mode_table[] = { 370789Sahrens { "discard", DISCARD }, 371789Sahrens { "groupmask", GROUPMASK }, 372789Sahrens { "passthrough", PASSTHROUGH }, 373789Sahrens { NULL } 374789Sahrens }; 375789Sahrens 376789Sahrens struct { 377789Sahrens const char *name; 378789Sahrens uint64_t value; 379789Sahrens } acl_inherit_table[] = { 380789Sahrens { "discard", DISCARD }, 381789Sahrens { "noallow", NOALLOW }, 382789Sahrens { "secure", SECURE }, 383789Sahrens { "passthrough", PASSTHROUGH }, 384789Sahrens { NULL } 385789Sahrens }; 386789Sahrens 387789Sahrens 388789Sahrens /* 389789Sahrens * Given a numeric suffix, convert the value into a number of bits that the 390789Sahrens * resulting value must be shifted. 391789Sahrens */ 392789Sahrens static int 393789Sahrens str2shift(const char *buf, char *reason, size_t len) 394789Sahrens { 395789Sahrens const char *ends = "BKMGTPEZ"; 396789Sahrens int i; 397789Sahrens 398789Sahrens if (buf[0] == '\0') 399789Sahrens return (0); 400789Sahrens for (i = 0; i < strlen(ends); i++) { 401789Sahrens if (toupper(buf[0]) == ends[i]) 402789Sahrens break; 403789Sahrens } 404789Sahrens if (i == strlen(ends)) { 405789Sahrens (void) snprintf(reason, len, dgettext(TEXT_DOMAIN, "invalid " 406789Sahrens "numeric suffix '%s'"), buf); 407789Sahrens return (-1); 408789Sahrens } 409789Sahrens 410789Sahrens /* 411789Sahrens * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 412789Sahrens * allow 'BB' - that's just weird. 413789Sahrens */ 414789Sahrens if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 415789Sahrens toupper(buf[0]) != 'B')) { 416789Sahrens return (10*i); 417789Sahrens } 418789Sahrens 419789Sahrens (void) snprintf(reason, len, dgettext(TEXT_DOMAIN, "invalid numeric " 420789Sahrens "suffix '%s'"), buf); 421789Sahrens return (-1); 422789Sahrens } 423789Sahrens 424789Sahrens /* 425789Sahrens * Convert a string of the form '100G' into a real number. Used when setting 426789Sahrens * properties or creating a volume. 'buf' is used to place an extended error 427789Sahrens * message for the caller to use. 428789Sahrens */ 429789Sahrens static int 430789Sahrens nicestrtonum(const char *value, uint64_t *num, char *buf, size_t buflen) 431789Sahrens { 432789Sahrens char *end; 433789Sahrens int shift; 434789Sahrens 435789Sahrens *num = 0; 436789Sahrens 437789Sahrens /* Check to see if this looks like a number. */ 438789Sahrens if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 439789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 440789Sahrens "must be a numeric value"), buflen); 441789Sahrens return (-1); 442789Sahrens } 443789Sahrens 444789Sahrens /* Rely on stroll() to process the numeric portion. */ 445789Sahrens errno = 0; 446789Sahrens *num = strtoll(value, &end, 10); 447789Sahrens 448789Sahrens /* 449789Sahrens * Check for ERANGE, which indicates that the value is too large to fit 450789Sahrens * in a 64-bit value. 451789Sahrens */ 452789Sahrens if (errno == ERANGE) { 453789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 454789Sahrens "value is too large"), buflen); 455789Sahrens return (-1); 456789Sahrens } 457789Sahrens 458789Sahrens /* 459789Sahrens * If we have a decimal value, then do the computation with floating 460789Sahrens * point arithmetic. Otherwise, use standard arithmetic. 461789Sahrens */ 462789Sahrens if (*end == '.') { 463789Sahrens double fval = strtod(value, &end); 464789Sahrens 465789Sahrens if ((shift = str2shift(end, buf, buflen)) == -1) 466789Sahrens return (-1); 467789Sahrens 468789Sahrens fval *= pow(2, shift); 469789Sahrens 470789Sahrens if (fval > UINT64_MAX) { 471789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 472789Sahrens "value is too large"), buflen); 473789Sahrens return (-1); 474789Sahrens } 475789Sahrens 476789Sahrens *num = (uint64_t)fval; 477789Sahrens } else { 478789Sahrens if ((shift = str2shift(end, buf, buflen)) == -1) 479789Sahrens return (-1); 480789Sahrens 481789Sahrens /* Check for overflow */ 482789Sahrens if (shift >= 64 || (*num << shift) >> shift != *num) { 483789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 484789Sahrens "value is too large"), buflen); 485789Sahrens return (-1); 486789Sahrens } 487789Sahrens 488789Sahrens *num <<= shift; 489789Sahrens } 490789Sahrens 491789Sahrens return (0); 492789Sahrens } 493789Sahrens 494789Sahrens int 495789Sahrens zfs_nicestrtonum(const char *str, uint64_t *val) 496789Sahrens { 497789Sahrens char buf[1]; 498789Sahrens 499789Sahrens return (nicestrtonum(str, val, buf, sizeof (buf))); 500789Sahrens } 501789Sahrens 502789Sahrens /* 503789Sahrens * Given a property type and value, verify that the value is appropriate. Used 504789Sahrens * by zfs_prop_set() and some libzfs consumers. 505789Sahrens */ 506789Sahrens int 507789Sahrens zfs_prop_validate(zfs_prop_t prop, const char *value, uint64_t *intval) 508789Sahrens { 509789Sahrens const char *propname = zfs_prop_to_name(prop); 510789Sahrens uint64_t number; 511789Sahrens char reason[64]; 512789Sahrens int i; 513789Sahrens 514789Sahrens /* 515789Sahrens * Check to see if this a read-only property. 516789Sahrens */ 517789Sahrens if (zfs_prop_readonly(prop)) { 518789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 519789Sahrens "cannot set %s property: read-only property"), propname); 520789Sahrens return (-1); 521789Sahrens } 522789Sahrens 523789Sahrens /* See if the property value is too long */ 524789Sahrens if (strlen(value) >= ZFS_MAXPROPLEN) { 525789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 526789Sahrens "bad %s value '%s': value is too long"), propname, 527789Sahrens value); 528789Sahrens return (-1); 529789Sahrens } 530789Sahrens 531789Sahrens /* Perform basic checking based on property type */ 532789Sahrens switch (zfs_prop_get_type(prop)) { 533789Sahrens case prop_type_boolean: 534789Sahrens if (strcmp(value, "on") == 0) { 535789Sahrens number = 1; 536789Sahrens } else if (strcmp(value, "off") == 0) { 537789Sahrens number = 0; 538789Sahrens } else { 539789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 540789Sahrens "bad %s value '%s': must be 'on' or 'off'"), 541789Sahrens propname, value); 542789Sahrens return (-1); 543789Sahrens } 544789Sahrens break; 545789Sahrens 546789Sahrens case prop_type_number: 547789Sahrens /* treat 'none' as 0 */ 548789Sahrens if (strcmp(value, "none") == 0) { 549789Sahrens number = 0; 550789Sahrens break; 551789Sahrens } 552789Sahrens 553789Sahrens if (nicestrtonum(value, &number, reason, 554789Sahrens sizeof (reason)) != 0) { 555789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 556789Sahrens "bad %s value '%s': %s"), propname, value, 557789Sahrens reason); 558789Sahrens return (-1); 559789Sahrens } 560789Sahrens 561789Sahrens /* don't allow 0 for quota, use 'none' instead */ 562789Sahrens if (prop == ZFS_PROP_QUOTA && number == 0 && 563789Sahrens strcmp(value, "none") != 0) { 564789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 565789Sahrens "bad %s value '%s': use '%s=none' to disable"), 566789Sahrens propname, value, propname); 567789Sahrens return (-1); 568789Sahrens } 569789Sahrens 570789Sahrens /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */ 571789Sahrens if (prop == ZFS_PROP_RECORDSIZE || 572789Sahrens prop == ZFS_PROP_VOLBLOCKSIZE) { 573789Sahrens if (number < SPA_MINBLOCKSIZE || 574789Sahrens number > SPA_MAXBLOCKSIZE || !ISP2(number)) { 575789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 576789Sahrens "bad %s value '%s': " 577789Sahrens "must be power of 2 from %u to %uk"), 578789Sahrens propname, value, 579789Sahrens (uint_t)SPA_MINBLOCKSIZE, 580789Sahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 581789Sahrens return (-1); 582789Sahrens } 583789Sahrens } 584789Sahrens 585789Sahrens break; 586789Sahrens 587789Sahrens case prop_type_string: 588789Sahrens case prop_type_index: 589789Sahrens /* 590789Sahrens * The two writable string values, 'mountpoint' and 591789Sahrens * 'checksum' need special consideration. The 'index' types are 592789Sahrens * specified as strings by the user, but passed to the kernel as 593789Sahrens * integers. 594789Sahrens */ 595789Sahrens switch (prop) { 596789Sahrens case ZFS_PROP_MOUNTPOINT: 597789Sahrens if (strcmp(value, ZFS_MOUNTPOINT_NONE) == 0 || 598789Sahrens strcmp(value, ZFS_MOUNTPOINT_LEGACY) == 0) 599789Sahrens break; 600789Sahrens 601789Sahrens if (value[0] != '/') { 602789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 603789Sahrens "bad %s value '%s': must be an absolute " 604789Sahrens "path, 'none', or 'legacy'"), 605789Sahrens propname, value); 606789Sahrens return (-1); 607789Sahrens } 608789Sahrens break; 609789Sahrens 610789Sahrens case ZFS_PROP_CHECKSUM: 611789Sahrens for (i = 0; checksum_table[i].name != NULL; i++) { 612789Sahrens if (strcmp(value, checksum_table[i].name) 613789Sahrens == 0) { 614789Sahrens number = checksum_table[i].value; 615789Sahrens break; 616789Sahrens } 617789Sahrens } 618789Sahrens 619789Sahrens if (checksum_table[i].name == NULL) { 620789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 621789Sahrens "bad %s value '%s': must be 'on', 'off', " 622789Sahrens "'fletcher2', 'fletcher4', or 'sha256'"), 623789Sahrens propname, value); 624789Sahrens return (-1); 625789Sahrens } 626789Sahrens break; 627789Sahrens 628789Sahrens case ZFS_PROP_COMPRESSION: 629789Sahrens for (i = 0; compress_table[i].name != NULL; i++) { 630789Sahrens if (strcmp(value, compress_table[i].name) 631789Sahrens == 0) { 632789Sahrens number = compress_table[i].value; 633789Sahrens break; 634789Sahrens } 635789Sahrens } 636789Sahrens 637789Sahrens if (compress_table[i].name == NULL) { 638789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 639789Sahrens "bad %s value '%s': must be 'on', 'off', " 640789Sahrens "or 'lzjb'"), 641789Sahrens propname, value); 642789Sahrens return (-1); 643789Sahrens } 644789Sahrens break; 645789Sahrens 646789Sahrens case ZFS_PROP_SNAPDIR: 647789Sahrens for (i = 0; snapdir_table[i].name != NULL; i++) { 648789Sahrens if (strcmp(value, snapdir_table[i].name) == 0) { 649789Sahrens number = snapdir_table[i].value; 650789Sahrens break; 651789Sahrens } 652789Sahrens } 653789Sahrens 654789Sahrens if (snapdir_table[i].name == NULL) { 655789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 656789Sahrens "bad %s value '%s': must be 'hidden' " 657789Sahrens "or 'visible'"), 658789Sahrens propname, value); 659789Sahrens return (-1); 660789Sahrens } 661789Sahrens break; 662789Sahrens 663789Sahrens case ZFS_PROP_ACLMODE: 664789Sahrens for (i = 0; acl_mode_table[i].name != NULL; i++) { 665789Sahrens if (strcmp(value, acl_mode_table[i].name) 666789Sahrens == 0) { 667789Sahrens number = acl_mode_table[i].value; 668789Sahrens break; 669789Sahrens } 670789Sahrens } 671789Sahrens 672789Sahrens if (acl_mode_table[i].name == NULL) { 673789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 674789Sahrens "bad %s value '%s': must be 'discard', " 675789Sahrens "'groupmask' or 'passthrough'"), 676789Sahrens propname, value); 677789Sahrens return (-1); 678789Sahrens } 679789Sahrens break; 680789Sahrens 681789Sahrens case ZFS_PROP_ACLINHERIT: 682789Sahrens for (i = 0; acl_inherit_table[i].name != NULL; i++) { 683789Sahrens if (strcmp(value, acl_inherit_table[i].name) 684789Sahrens == 0) { 685789Sahrens number = acl_inherit_table[i].value; 686789Sahrens break; 687789Sahrens } 688789Sahrens } 689789Sahrens 690789Sahrens if (acl_inherit_table[i].name == NULL) { 691789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 692789Sahrens "bad %s value '%s': must be 'discard', " 693905Smarks "'noallow', 'secure' or 'passthrough'"), 694789Sahrens propname, value); 695789Sahrens return (-1); 696789Sahrens } 697789Sahrens break; 698789Sahrens 699789Sahrens case ZFS_PROP_SHARENFS: 700789Sahrens /* 701789Sahrens * Nothing to do for 'sharenfs', this gets passed on to 702789Sahrens * share(1M) verbatim. 703789Sahrens */ 704789Sahrens break; 705789Sahrens } 706789Sahrens } 707789Sahrens 708789Sahrens if (intval != NULL) 709789Sahrens *intval = number; 710789Sahrens 711789Sahrens return (0); 712789Sahrens } 713789Sahrens 714789Sahrens /* 715789Sahrens * Given a property name and value, set the property for the given dataset. 716789Sahrens */ 717789Sahrens int 718789Sahrens zfs_prop_set(zfs_handle_t *zhp, zfs_prop_t prop, const char *propval) 719789Sahrens { 720789Sahrens const char *propname = zfs_prop_to_name(prop); 721789Sahrens uint64_t number; 722789Sahrens zfs_cmd_t zc = { 0 }; 723789Sahrens int ret; 724789Sahrens prop_changelist_t *cl; 725789Sahrens 726789Sahrens if (zfs_prop_validate(prop, propval, &number) != 0) 727789Sahrens return (-1); 728789Sahrens 729789Sahrens /* 730789Sahrens * Check to see if the value applies to this type 731789Sahrens */ 732789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) { 733789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 734789Sahrens "cannot set %s for '%s': property does not apply to %ss"), 735789Sahrens propname, zhp->zfs_name, zfs_type_to_name(zhp->zfs_type)); 736789Sahrens return (-1); 737789Sahrens } 738789Sahrens 739789Sahrens /* 740789Sahrens * For the mountpoint and sharenfs properties, check if it can be set 741789Sahrens * in a global/non-global zone based on the zoned property value: 742789Sahrens * 743789Sahrens * global zone non-global zone 744789Sahrens * ----------------------------------------------------- 745789Sahrens * zoned=on mountpoint (no) mountpoint (yes) 746789Sahrens * sharenfs (no) sharenfs (no) 747789Sahrens * 748789Sahrens * zoned=off mountpoint (yes) N/A 749789Sahrens * sharenfs (yes) 750789Sahrens */ 751789Sahrens if (prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS) { 752789Sahrens if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 753789Sahrens if (getzoneid() == GLOBAL_ZONEID) { 754789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 7551133Seschrock "cannot set %s for '%s': " 756789Sahrens "dataset is used in a non-global zone"), 757789Sahrens propname, zhp->zfs_name); 758789Sahrens return (-1); 759789Sahrens } else if (prop == ZFS_PROP_SHARENFS) { 760789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 7611133Seschrock "cannot set %s for '%s': filesystems " 762789Sahrens "cannot be shared in a non-global zone"), 763789Sahrens propname, zhp->zfs_name); 764789Sahrens return (-1); 765789Sahrens } 766789Sahrens } else if (getzoneid() != GLOBAL_ZONEID) { 767789Sahrens /* 768789Sahrens * If zoned property is 'off', this must be in 769789Sahrens * a globle zone. If not, something is wrong. 770789Sahrens */ 771789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 7721133Seschrock "cannot set %s for '%s': dataset is " 773789Sahrens "used in a non-global zone, but 'zoned' " 774789Sahrens "property is not set"), 775789Sahrens propname, zhp->zfs_name); 776789Sahrens return (-1); 777789Sahrens } 778789Sahrens } 779789Sahrens 780789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 781789Sahrens return (-1); 782789Sahrens 783789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 784789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s for '%s', " 785789Sahrens "child dataset with inherited mountpoint is used " 786789Sahrens "in a non-global zone"), 787789Sahrens propname, zhp->zfs_name); 788789Sahrens ret = -1; 789789Sahrens goto error; 790789Sahrens } 791789Sahrens 792789Sahrens if ((ret = changelist_prefix(cl)) != 0) 793789Sahrens goto error; 794789Sahrens 795789Sahrens /* 796789Sahrens * Execute the corresponding ioctl() to set this property. 797789Sahrens */ 798789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 799789Sahrens 800789Sahrens switch (prop) { 801789Sahrens case ZFS_PROP_QUOTA: 802789Sahrens zc.zc_cookie = number; 803789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_QUOTA, &zc); 804789Sahrens break; 805789Sahrens case ZFS_PROP_RESERVATION: 806789Sahrens zc.zc_cookie = number; 807789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_RESERVATION, &zc); 808789Sahrens break; 809789Sahrens case ZFS_PROP_MOUNTPOINT: 810789Sahrens case ZFS_PROP_SHARENFS: 811789Sahrens /* 812789Sahrens * These properties are passed down as real strings. 813789Sahrens */ 814789Sahrens (void) strlcpy(zc.zc_prop_name, propname, 815789Sahrens sizeof (zc.zc_prop_name)); 816789Sahrens (void) strlcpy(zc.zc_prop_value, propval, 817789Sahrens sizeof (zc.zc_prop_value)); 818789Sahrens zc.zc_intsz = 1; 819789Sahrens zc.zc_numints = strlen(propval) + 1; 820789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_PROP, &zc); 821789Sahrens break; 822789Sahrens case ZFS_PROP_VOLSIZE: 823789Sahrens zc.zc_volsize = number; 824789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_VOLSIZE, &zc); 825789Sahrens break; 826789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 827789Sahrens zc.zc_volblocksize = number; 828789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_VOLBLOCKSIZE, &zc); 829789Sahrens break; 830789Sahrens default: 831789Sahrens (void) strlcpy(zc.zc_prop_name, propname, 832789Sahrens sizeof (zc.zc_prop_name)); 833789Sahrens /* LINTED - alignment */ 834789Sahrens *(uint64_t *)zc.zc_prop_value = number; 835789Sahrens zc.zc_intsz = 8; 836789Sahrens zc.zc_numints = 1; 837789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_PROP, &zc); 838789Sahrens break; 839789Sahrens } 840789Sahrens 841789Sahrens if (ret != 0) { 842789Sahrens switch (errno) { 843789Sahrens 844789Sahrens case EPERM: 845789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 846789Sahrens "cannot set %s for '%s': permission " 847789Sahrens "denied"), propname, zhp->zfs_name); 848789Sahrens break; 849789Sahrens 850789Sahrens case ENOENT: 851789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 852789Sahrens "cannot open '%s': no such %s"), zhp->zfs_name, 853789Sahrens zfs_type_to_name(zhp->zfs_type)); 854789Sahrens break; 855789Sahrens 856789Sahrens case ENOSPC: 857789Sahrens /* 858789Sahrens * For quotas and reservations, ENOSPC indicates 859789Sahrens * something different; setting a quota or reservation 860789Sahrens * doesn't use any disk space. 861789Sahrens */ 862789Sahrens switch (prop) { 863789Sahrens case ZFS_PROP_QUOTA: 864789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s " 865789Sahrens "for '%s': size is less than current " 866789Sahrens "used or reserved space"), propname, 867789Sahrens zhp->zfs_name); 868789Sahrens break; 869789Sahrens 870789Sahrens case ZFS_PROP_RESERVATION: 871789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s " 872789Sahrens "for '%s': size is greater than available " 873789Sahrens "space"), propname, zhp->zfs_name); 874789Sahrens break; 875789Sahrens 876789Sahrens default: 877789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 878789Sahrens "cannot set %s for '%s': out of space"), 879789Sahrens propname, zhp->zfs_name); 880789Sahrens break; 881789Sahrens } 882789Sahrens break; 883789Sahrens 884789Sahrens case EBUSY: 885789Sahrens if (prop == ZFS_PROP_VOLBLOCKSIZE) { 886789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 887789Sahrens "cannot set %s for '%s': " 888789Sahrens "volume already contains data"), 889789Sahrens propname, zhp->zfs_name); 890789Sahrens } else { 891789Sahrens zfs_baderror(errno); 892789Sahrens } 893789Sahrens break; 894789Sahrens 8951175Slling case EROFS: 8961175Slling zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s for " 8971175Slling "'%s': read only %s"), propname, zhp->zfs_name, 8981175Slling zfs_type_to_name(zhp->zfs_type)); 8991175Slling break; 9001175Slling 901789Sahrens case EOVERFLOW: 902789Sahrens /* 903789Sahrens * This platform can't address a volume this big. 904789Sahrens */ 905789Sahrens #ifdef _ILP32 906789Sahrens if (prop == ZFS_PROP_VOLSIZE) { 907789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 908789Sahrens "cannot set %s for '%s': " 909789Sahrens "max volume size is 1TB on 32-bit systems"), 910789Sahrens propname, zhp->zfs_name); 911789Sahrens break; 912789Sahrens } 913789Sahrens #endif 914789Sahrens zfs_baderror(errno); 915789Sahrens default: 916789Sahrens zfs_baderror(errno); 917789Sahrens } 918789Sahrens } else { 919789Sahrens /* 920789Sahrens * Refresh the statistics so the new property value 921789Sahrens * is reflected. 922789Sahrens */ 923789Sahrens if ((ret = changelist_postfix(cl)) != 0) 924789Sahrens goto error; 925789Sahrens 926789Sahrens (void) get_stats(zhp); 927789Sahrens } 928789Sahrens 929789Sahrens error: 930789Sahrens changelist_free(cl); 931789Sahrens return (ret); 932789Sahrens } 933789Sahrens 934789Sahrens /* 935789Sahrens * Given a property, inherit the value from the parent dataset. 936789Sahrens */ 937789Sahrens int 938789Sahrens zfs_prop_inherit(zfs_handle_t *zhp, zfs_prop_t prop) 939789Sahrens { 940789Sahrens const char *propname = zfs_prop_to_name(prop); 941789Sahrens zfs_cmd_t zc = { 0 }; 942789Sahrens int ret; 943789Sahrens prop_changelist_t *cl; 944789Sahrens 945789Sahrens /* 946789Sahrens * Verify that this property is inheritable. 947789Sahrens */ 948789Sahrens if (zfs_prop_readonly(prop)) { 949789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 950789Sahrens "cannot inherit %s for '%s': property is read-only"), 951789Sahrens propname, zhp->zfs_name); 952789Sahrens return (-1); 953789Sahrens } 954789Sahrens 955789Sahrens if (!zfs_prop_inheritable(prop)) { 956789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 957789Sahrens "cannot inherit %s for '%s': property is not inheritable"), 958789Sahrens propname, zhp->zfs_name); 959789Sahrens return (-1); 960789Sahrens } 961789Sahrens 962789Sahrens /* 963789Sahrens * Check to see if the value applies to this type 964789Sahrens */ 965789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) { 966789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 967789Sahrens "cannot inherit %s for '%s': property does " 968789Sahrens "not apply to %ss"), propname, zhp->zfs_name, 969789Sahrens zfs_type_to_name(zhp->zfs_type)); 970789Sahrens return (-1); 971789Sahrens } 972789Sahrens 973789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 974789Sahrens (void) strlcpy(zc.zc_prop_name, propname, sizeof (zc.zc_prop_name)); 975789Sahrens 976789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID && 977789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 978789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot inherit %s for '%s', " 979789Sahrens "dataset is used in a non-global zone"), propname, 980789Sahrens zhp->zfs_name); 981789Sahrens return (-1); 982789Sahrens } 983789Sahrens 984789Sahrens /* 985789Sahrens * Determine datasets which will be affected by this change, if any. 986789Sahrens */ 987789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 988789Sahrens return (-1); 989789Sahrens 990789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 991789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot inherit %s for '%s', " 992789Sahrens "child dataset with inherited mountpoint is " 993789Sahrens "used in a non-global zone"), 994789Sahrens propname, zhp->zfs_name); 995789Sahrens ret = -1; 996789Sahrens goto error; 997789Sahrens } 998789Sahrens 999789Sahrens if ((ret = changelist_prefix(cl)) != 0) 1000789Sahrens goto error; 1001789Sahrens 1002789Sahrens zc.zc_numints = 0; 1003789Sahrens 1004789Sahrens if ((ret = ioctl(zfs_fd, ZFS_IOC_SET_PROP, &zc)) != 0) { 1005789Sahrens switch (errno) { 1006789Sahrens case EPERM: 1007789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1008789Sahrens "cannot inherit %s for '%s': permission " 1009789Sahrens "denied"), propname, zhp->zfs_name); 1010789Sahrens break; 1011789Sahrens case ENOENT: 1012789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1013789Sahrens "cannot open '%s': no such %s"), zhp->zfs_name, 1014789Sahrens zfs_type_to_name(zhp->zfs_type)); 1015789Sahrens break; 1016789Sahrens case ENOSPC: 1017789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1018789Sahrens "cannot inherit %s for '%s': " 1019789Sahrens "out of space"), propname, zhp->zfs_name); 1020789Sahrens break; 1021789Sahrens default: 1022789Sahrens zfs_baderror(errno); 1023789Sahrens } 1024789Sahrens 1025789Sahrens } else { 1026789Sahrens 1027789Sahrens if ((ret = changelist_postfix(cl)) != 0) 1028789Sahrens goto error; 1029789Sahrens 1030789Sahrens /* 1031789Sahrens * Refresh the statistics so the new property is reflected. 1032789Sahrens */ 1033789Sahrens (void) get_stats(zhp); 1034789Sahrens } 1035789Sahrens 1036789Sahrens 1037789Sahrens error: 1038789Sahrens changelist_free(cl); 1039789Sahrens return (ret); 1040789Sahrens } 1041789Sahrens 1042789Sahrens static void 1043789Sahrens nicebool(int value, char *buf, size_t buflen) 1044789Sahrens { 1045789Sahrens if (value) 1046789Sahrens (void) strlcpy(buf, "on", buflen); 1047789Sahrens else 1048789Sahrens (void) strlcpy(buf, "off", buflen); 1049789Sahrens } 1050789Sahrens 1051789Sahrens /* 10521356Seschrock * True DSL properties are stored in an nvlist. The following two functions 10531356Seschrock * extract them appropriately. 10541356Seschrock */ 10551356Seschrock static uint64_t 10561356Seschrock getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 10571356Seschrock { 10581356Seschrock nvlist_t *nv; 10591356Seschrock uint64_t value; 10601356Seschrock 10611356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 10621356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 10631356Seschrock verify(nvlist_lookup_uint64(nv, ZFS_PROP_VALUE, &value) == 0); 10641356Seschrock verify(nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source) == 0); 10651356Seschrock } else { 10661356Seschrock value = zfs_prop_default_numeric(prop); 10671356Seschrock *source = ""; 10681356Seschrock } 10691356Seschrock 10701356Seschrock return (value); 10711356Seschrock } 10721356Seschrock 10731356Seschrock static char * 10741356Seschrock getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 10751356Seschrock { 10761356Seschrock nvlist_t *nv; 10771356Seschrock char *value; 10781356Seschrock 10791356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 10801356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 10811356Seschrock verify(nvlist_lookup_string(nv, ZFS_PROP_VALUE, &value) == 0); 10821356Seschrock verify(nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source) == 0); 10831356Seschrock } else { 10841356Seschrock if ((value = (char *)zfs_prop_default_string(prop)) == NULL) 10851356Seschrock value = ""; 10861356Seschrock *source = ""; 10871356Seschrock } 10881356Seschrock 10891356Seschrock return (value); 10901356Seschrock } 10911356Seschrock 10921356Seschrock /* 1093789Sahrens * Internal function for getting a numeric property. Both zfs_prop_get() and 1094789Sahrens * zfs_prop_get_int() are built using this interface. 1095789Sahrens * 1096789Sahrens * Certain properties can be overridden using 'mount -o'. In this case, scan 1097789Sahrens * the contents of the /etc/mnttab entry, searching for the appropriate options. 1098789Sahrens * If they differ from the on-disk values, report the current values and mark 1099789Sahrens * the source "temporary". 1100789Sahrens */ 1101789Sahrens static uint64_t 1102789Sahrens get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zfs_source_t *src, 1103789Sahrens char **source) 1104789Sahrens { 1105789Sahrens uint64_t val; 1106789Sahrens struct mnttab mnt; 1107789Sahrens 1108789Sahrens *source = NULL; 1109789Sahrens 1110789Sahrens if (zhp->zfs_mntopts == NULL) 1111789Sahrens mnt.mnt_mntopts = ""; 1112789Sahrens else 1113789Sahrens mnt.mnt_mntopts = zhp->zfs_mntopts; 1114789Sahrens 1115789Sahrens switch (prop) { 1116789Sahrens case ZFS_PROP_ATIME: 11171356Seschrock val = getprop_uint64(zhp, prop, source); 1118789Sahrens 1119789Sahrens if (hasmntopt(&mnt, MNTOPT_ATIME) && !val) { 1120789Sahrens val = TRUE; 1121789Sahrens if (src) 1122789Sahrens *src = ZFS_SRC_TEMPORARY; 1123789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NOATIME) && val) { 1124789Sahrens val = FALSE; 1125789Sahrens if (src) 1126789Sahrens *src = ZFS_SRC_TEMPORARY; 1127789Sahrens } 11281356Seschrock return (val); 1129789Sahrens 1130789Sahrens case ZFS_PROP_AVAILABLE: 1131789Sahrens return (zhp->zfs_dmustats.dds_available); 1132789Sahrens 1133789Sahrens case ZFS_PROP_DEVICES: 11341356Seschrock val = getprop_uint64(zhp, prop, source); 1135789Sahrens 1136789Sahrens if (hasmntopt(&mnt, MNTOPT_DEVICES) && !val) { 1137789Sahrens val = TRUE; 1138789Sahrens if (src) 1139789Sahrens *src = ZFS_SRC_TEMPORARY; 1140789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NODEVICES) && val) { 1141789Sahrens val = FALSE; 1142789Sahrens if (src) 1143789Sahrens *src = ZFS_SRC_TEMPORARY; 1144789Sahrens } 1145789Sahrens return (val); 1146789Sahrens 1147789Sahrens case ZFS_PROP_EXEC: 11481356Seschrock val = getprop_uint64(zhp, prop, source); 1149789Sahrens 1150789Sahrens if (hasmntopt(&mnt, MNTOPT_EXEC) && !val) { 1151789Sahrens val = TRUE; 1152789Sahrens if (src) 1153789Sahrens *src = ZFS_SRC_TEMPORARY; 1154789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NOEXEC) && val) { 1155789Sahrens val = FALSE; 1156789Sahrens if (src) 1157789Sahrens *src = ZFS_SRC_TEMPORARY; 1158789Sahrens } 1159789Sahrens return (val); 1160789Sahrens 1161789Sahrens case ZFS_PROP_RECORDSIZE: 1162789Sahrens case ZFS_PROP_COMPRESSION: 11631356Seschrock case ZFS_PROP_ZONED: 11641356Seschrock val = getprop_uint64(zhp, prop, source); 11651356Seschrock return (val); 1166789Sahrens 1167789Sahrens case ZFS_PROP_READONLY: 11681356Seschrock val = getprop_uint64(zhp, prop, source); 1169789Sahrens 1170789Sahrens if (hasmntopt(&mnt, MNTOPT_RO) && !val) { 1171789Sahrens val = TRUE; 1172789Sahrens if (src) 1173789Sahrens *src = ZFS_SRC_TEMPORARY; 1174789Sahrens } else if (hasmntopt(&mnt, MNTOPT_RW) && val) { 1175789Sahrens val = FALSE; 1176789Sahrens if (src) 1177789Sahrens *src = ZFS_SRC_TEMPORARY; 1178789Sahrens } 1179789Sahrens return (val); 1180789Sahrens 1181789Sahrens case ZFS_PROP_QUOTA: 1182789Sahrens if (zhp->zfs_dmustats.dds_quota == 0) 1183789Sahrens *source = ""; /* default */ 1184789Sahrens else 1185789Sahrens *source = zhp->zfs_name; 1186789Sahrens return (zhp->zfs_dmustats.dds_quota); 1187789Sahrens 1188789Sahrens case ZFS_PROP_RESERVATION: 1189789Sahrens if (zhp->zfs_dmustats.dds_reserved == 0) 1190789Sahrens *source = ""; /* default */ 1191789Sahrens else 1192789Sahrens *source = zhp->zfs_name; 1193789Sahrens return (zhp->zfs_dmustats.dds_reserved); 1194789Sahrens 1195789Sahrens case ZFS_PROP_COMPRESSRATIO: 1196789Sahrens /* 1197789Sahrens * Using physical space and logical space, calculate the 1198789Sahrens * compression ratio. We return the number as a multiple of 1199789Sahrens * 100, so '2.5x' would be returned as 250. 1200789Sahrens */ 1201789Sahrens if (zhp->zfs_dmustats.dds_compressed_bytes == 0) 1202789Sahrens return (100ULL); 1203789Sahrens else 1204789Sahrens return (zhp->zfs_dmustats.dds_uncompressed_bytes * 100 / 1205789Sahrens zhp->zfs_dmustats.dds_compressed_bytes); 1206789Sahrens 1207789Sahrens case ZFS_PROP_REFERENCED: 1208789Sahrens /* 1209789Sahrens * 'referenced' refers to the amount of physical space 1210789Sahrens * referenced (possibly shared) by this object. 1211789Sahrens */ 1212789Sahrens return (zhp->zfs_dmustats.dds_space_refd); 1213789Sahrens 1214789Sahrens case ZFS_PROP_SETUID: 12151356Seschrock val = getprop_uint64(zhp, prop, source); 1216789Sahrens 1217789Sahrens if (hasmntopt(&mnt, MNTOPT_SETUID) && !val) { 1218789Sahrens val = TRUE; 1219789Sahrens if (src) 1220789Sahrens *src = ZFS_SRC_TEMPORARY; 1221789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NOSETUID) && val) { 1222789Sahrens val = FALSE; 1223789Sahrens if (src) 1224789Sahrens *src = ZFS_SRC_TEMPORARY; 1225789Sahrens } 1226789Sahrens return (val); 1227789Sahrens 1228789Sahrens case ZFS_PROP_VOLSIZE: 1229789Sahrens return (zhp->zfs_volsize); 1230789Sahrens 1231789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 1232789Sahrens return (zhp->zfs_volblocksize); 1233789Sahrens 1234789Sahrens case ZFS_PROP_USED: 1235789Sahrens return (zhp->zfs_dmustats.dds_space_used); 1236789Sahrens 1237789Sahrens case ZFS_PROP_CREATETXG: 1238789Sahrens return (zhp->zfs_dmustats.dds_creation_txg); 1239789Sahrens 1240789Sahrens case ZFS_PROP_MOUNTED: 1241789Sahrens /* 1242789Sahrens * Unlike other properties, we defer calculation of 'MOUNTED' 1243789Sahrens * until actually requested. This is because the getmntany() 1244789Sahrens * call can be extremely expensive on systems with a large 1245789Sahrens * number of filesystems, and the property isn't needed in 1246789Sahrens * normal use cases. 1247789Sahrens */ 1248789Sahrens if (zhp->zfs_mntopts == NULL) { 1249789Sahrens struct mnttab search = { 0 }, entry; 1250789Sahrens 1251789Sahrens search.mnt_special = (char *)zhp->zfs_name; 1252*1407Snd150628 search.mnt_fstype = MNTTYPE_ZFS; 1253789Sahrens rewind(mnttab_file); 1254789Sahrens 1255789Sahrens if (getmntany(mnttab_file, &entry, &search) == 0) 1256789Sahrens zhp->zfs_mntopts = 1257789Sahrens zfs_strdup(entry.mnt_mntopts); 1258789Sahrens } 1259789Sahrens return (zhp->zfs_mntopts != NULL); 1260789Sahrens 1261789Sahrens default: 1262789Sahrens zfs_baderror(EINVAL); 1263789Sahrens } 1264789Sahrens 1265789Sahrens return (0); 1266789Sahrens } 1267789Sahrens 1268789Sahrens /* 1269789Sahrens * Calculate the source type, given the raw source string. 1270789Sahrens */ 1271789Sahrens static void 1272789Sahrens get_source(zfs_handle_t *zhp, zfs_source_t *srctype, char *source, 1273789Sahrens char *statbuf, size_t statlen) 1274789Sahrens { 1275789Sahrens if (statbuf == NULL || *srctype == ZFS_SRC_TEMPORARY) 1276789Sahrens return; 1277789Sahrens 1278789Sahrens if (source == NULL) { 1279789Sahrens *srctype = ZFS_SRC_NONE; 1280789Sahrens } else if (source[0] == '\0') { 1281789Sahrens *srctype = ZFS_SRC_DEFAULT; 1282789Sahrens } else { 1283789Sahrens if (strcmp(source, zhp->zfs_name) == 0) { 1284789Sahrens *srctype = ZFS_SRC_LOCAL; 1285789Sahrens } else { 1286789Sahrens (void) strlcpy(statbuf, source, statlen); 1287789Sahrens *srctype = ZFS_SRC_INHERITED; 1288789Sahrens } 1289789Sahrens } 1290789Sahrens 1291789Sahrens } 1292789Sahrens 1293789Sahrens /* 1294789Sahrens * Retrieve a property from the given object. If 'literal' is specified, then 1295789Sahrens * numbers are left as exact values. Otherwise, numbers are converted to a 1296789Sahrens * human-readable form. 1297789Sahrens * 1298789Sahrens * Returns 0 on success, or -1 on error. 1299789Sahrens */ 1300789Sahrens int 1301789Sahrens zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, 1302789Sahrens zfs_source_t *src, char *statbuf, size_t statlen, int literal) 1303789Sahrens { 1304789Sahrens char *source = NULL; 1305789Sahrens uint64_t val; 1306789Sahrens char *str; 1307789Sahrens int i; 1308789Sahrens const char *root; 1309789Sahrens 1310789Sahrens /* 1311789Sahrens * Check to see if this property applies to our object 1312789Sahrens */ 1313789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1314789Sahrens return (-1); 1315789Sahrens 1316789Sahrens if (src) 1317789Sahrens *src = ZFS_SRC_NONE; 1318789Sahrens 1319789Sahrens switch (prop) { 1320789Sahrens case ZFS_PROP_ATIME: 1321789Sahrens case ZFS_PROP_READONLY: 1322789Sahrens case ZFS_PROP_SETUID: 1323789Sahrens case ZFS_PROP_ZONED: 1324789Sahrens case ZFS_PROP_DEVICES: 1325789Sahrens case ZFS_PROP_EXEC: 1326789Sahrens /* 1327789Sahrens * Basic boolean values are built on top of 1328789Sahrens * get_numeric_property(). 1329789Sahrens */ 1330789Sahrens nicebool(get_numeric_property(zhp, prop, src, &source), 1331789Sahrens propbuf, proplen); 1332789Sahrens 1333789Sahrens break; 1334789Sahrens 1335789Sahrens case ZFS_PROP_AVAILABLE: 1336789Sahrens case ZFS_PROP_RECORDSIZE: 1337789Sahrens case ZFS_PROP_CREATETXG: 1338789Sahrens case ZFS_PROP_REFERENCED: 1339789Sahrens case ZFS_PROP_USED: 1340789Sahrens case ZFS_PROP_VOLSIZE: 1341789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 1342789Sahrens /* 1343789Sahrens * Basic numeric values are built on top of 1344789Sahrens * get_numeric_property(). 1345789Sahrens */ 1346789Sahrens val = get_numeric_property(zhp, prop, src, &source); 1347789Sahrens if (literal) 1348789Sahrens (void) snprintf(propbuf, proplen, "%llu", val); 1349789Sahrens else 1350789Sahrens zfs_nicenum(val, propbuf, proplen); 1351789Sahrens break; 1352789Sahrens 1353789Sahrens case ZFS_PROP_COMPRESSION: 13541356Seschrock val = getprop_uint64(zhp, prop, &source); 1355789Sahrens for (i = 0; compress_table[i].name != NULL; i++) { 13561356Seschrock if (compress_table[i].value == val) 1357789Sahrens break; 1358789Sahrens } 1359789Sahrens assert(compress_table[i].name != NULL); 1360789Sahrens (void) strlcpy(propbuf, compress_table[i].name, proplen); 1361789Sahrens break; 1362789Sahrens 1363789Sahrens case ZFS_PROP_CHECKSUM: 13641356Seschrock val = getprop_uint64(zhp, prop, &source); 1365789Sahrens for (i = 0; checksum_table[i].name != NULL; i++) { 13661356Seschrock if (checksum_table[i].value == val) 1367789Sahrens break; 1368789Sahrens } 1369789Sahrens assert(checksum_table[i].name != NULL); 1370789Sahrens (void) strlcpy(propbuf, checksum_table[i].name, proplen); 1371789Sahrens break; 1372789Sahrens 1373789Sahrens case ZFS_PROP_SNAPDIR: 13741356Seschrock val = getprop_uint64(zhp, prop, &source); 1375789Sahrens for (i = 0; snapdir_table[i].name != NULL; i++) { 13761356Seschrock if (snapdir_table[i].value == val) 1377789Sahrens break; 1378789Sahrens } 1379789Sahrens assert(snapdir_table[i].name != NULL); 1380789Sahrens (void) strlcpy(propbuf, snapdir_table[i].name, proplen); 1381789Sahrens break; 1382789Sahrens 1383789Sahrens case ZFS_PROP_ACLMODE: 13841356Seschrock val = getprop_uint64(zhp, prop, &source); 1385789Sahrens for (i = 0; acl_mode_table[i].name != NULL; i++) { 13861356Seschrock if (acl_mode_table[i].value == val) 1387789Sahrens break; 1388789Sahrens } 1389789Sahrens assert(acl_mode_table[i].name != NULL); 1390789Sahrens (void) strlcpy(propbuf, acl_mode_table[i].name, proplen); 1391789Sahrens break; 1392789Sahrens 1393789Sahrens case ZFS_PROP_ACLINHERIT: 13941356Seschrock val = getprop_uint64(zhp, prop, &source); 1395789Sahrens for (i = 0; acl_inherit_table[i].name != NULL; i++) { 13961356Seschrock if (acl_inherit_table[i].value == val) 1397789Sahrens break; 1398789Sahrens } 1399789Sahrens assert(acl_inherit_table[i].name != NULL); 1400789Sahrens (void) strlcpy(propbuf, acl_inherit_table[i].name, proplen); 1401789Sahrens break; 1402789Sahrens 1403789Sahrens case ZFS_PROP_CREATION: 1404789Sahrens /* 1405789Sahrens * 'creation' is a time_t stored in the statistics. We convert 1406789Sahrens * this into a string unless 'literal' is specified. 1407789Sahrens */ 1408789Sahrens { 1409789Sahrens time_t time = (time_t) 1410789Sahrens zhp->zfs_dmustats.dds_creation_time; 1411789Sahrens struct tm t; 1412789Sahrens 1413789Sahrens if (literal || 1414789Sahrens localtime_r(&time, &t) == NULL || 1415789Sahrens strftime(propbuf, proplen, "%a %b %e %k:%M %Y", 1416789Sahrens &t) == 0) 1417789Sahrens (void) snprintf(propbuf, proplen, "%llu", 1418789Sahrens zhp->zfs_dmustats.dds_creation_time); 1419789Sahrens } 1420789Sahrens break; 1421789Sahrens 1422789Sahrens case ZFS_PROP_MOUNTPOINT: 1423789Sahrens /* 1424789Sahrens * Getting the precise mountpoint can be tricky. 1425789Sahrens * 1426789Sahrens * - for 'none' or 'legacy', return those values. 1427789Sahrens * - for default mountpoints, construct it as /zfs/<dataset> 1428789Sahrens * - for inherited mountpoints, we want to take everything 1429789Sahrens * after our ancestor and append it to the inherited value. 1430789Sahrens * 1431789Sahrens * If the pool has an alternate root, we want to prepend that 1432789Sahrens * root to any values we return. 1433789Sahrens */ 1434789Sahrens root = zhp->zfs_dmustats.dds_altroot; 14351356Seschrock str = getprop_string(zhp, prop, &source); 14361356Seschrock 14371356Seschrock if (str[0] == '\0') { 1438789Sahrens (void) snprintf(propbuf, proplen, "%s/zfs/%s", 1439789Sahrens root, zhp->zfs_name); 14401356Seschrock } else if (str[0] == '/') { 14411356Seschrock const char *relpath = zhp->zfs_name + strlen(source); 1442789Sahrens 1443789Sahrens if (relpath[0] == '/') 1444789Sahrens relpath++; 14451356Seschrock if (str[1] == '\0') 14461356Seschrock str++; 1447789Sahrens 1448789Sahrens if (relpath[0] == '\0') 1449789Sahrens (void) snprintf(propbuf, proplen, "%s%s", 14501356Seschrock root, str); 1451789Sahrens else 1452789Sahrens (void) snprintf(propbuf, proplen, "%s%s%s%s", 14531356Seschrock root, str, relpath[0] == '@' ? "" : "/", 1454789Sahrens relpath); 1455789Sahrens } else { 1456789Sahrens /* 'legacy' or 'none' */ 14571356Seschrock (void) strlcpy(propbuf, str, proplen); 1458789Sahrens } 1459789Sahrens 1460789Sahrens break; 1461789Sahrens 1462789Sahrens case ZFS_PROP_SHARENFS: 14631356Seschrock (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 14641356Seschrock proplen); 1465789Sahrens break; 1466789Sahrens 1467789Sahrens case ZFS_PROP_ORIGIN: 14681356Seschrock (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 1469789Sahrens proplen); 1470789Sahrens /* 1471789Sahrens * If there is no parent at all, return failure to indicate that 1472789Sahrens * it doesn't apply to this dataset. 1473789Sahrens */ 1474789Sahrens if (propbuf[0] == '\0') 1475789Sahrens return (-1); 1476789Sahrens break; 1477789Sahrens 1478789Sahrens case ZFS_PROP_QUOTA: 1479789Sahrens case ZFS_PROP_RESERVATION: 1480789Sahrens val = get_numeric_property(zhp, prop, src, &source); 1481789Sahrens 1482789Sahrens /* 1483789Sahrens * If quota or reservation is 0, we translate this into 'none' 1484789Sahrens * (unless literal is set), and indicate that it's the default 1485789Sahrens * value. Otherwise, we print the number nicely and indicate 1486789Sahrens * that its set locally. 1487789Sahrens */ 1488789Sahrens if (val == 0) { 1489789Sahrens if (literal) 1490789Sahrens (void) strlcpy(propbuf, "0", proplen); 1491789Sahrens else 1492789Sahrens (void) strlcpy(propbuf, "none", proplen); 1493789Sahrens } else { 1494789Sahrens if (literal) 1495789Sahrens (void) snprintf(propbuf, proplen, "%llu", val); 1496789Sahrens else 1497789Sahrens zfs_nicenum(val, propbuf, proplen); 1498789Sahrens } 1499789Sahrens break; 1500789Sahrens 1501789Sahrens case ZFS_PROP_COMPRESSRATIO: 1502789Sahrens val = get_numeric_property(zhp, prop, src, &source); 1503789Sahrens (void) snprintf(propbuf, proplen, "%lld.%02lldx", val / 100, 1504789Sahrens val % 100); 1505789Sahrens break; 1506789Sahrens 1507789Sahrens case ZFS_PROP_TYPE: 1508789Sahrens switch (zhp->zfs_type) { 1509789Sahrens case ZFS_TYPE_FILESYSTEM: 1510789Sahrens str = "filesystem"; 1511789Sahrens break; 1512789Sahrens case ZFS_TYPE_VOLUME: 1513789Sahrens str = "volume"; 1514789Sahrens break; 1515789Sahrens case ZFS_TYPE_SNAPSHOT: 1516789Sahrens str = "snapshot"; 1517789Sahrens break; 1518789Sahrens default: 1519789Sahrens zfs_baderror(zhp->zfs_type); 1520789Sahrens } 1521789Sahrens (void) snprintf(propbuf, proplen, "%s", str); 1522789Sahrens break; 1523789Sahrens 1524789Sahrens case ZFS_PROP_MOUNTED: 1525789Sahrens /* 1526789Sahrens * The 'mounted' property is a pseudo-property that described 1527789Sahrens * whether the filesystem is currently mounted. Even though 1528789Sahrens * it's a boolean value, the typical values of "on" and "off" 1529789Sahrens * don't make sense, so we translate to "yes" and "no". 1530789Sahrens */ 1531789Sahrens if (get_numeric_property(zhp, ZFS_PROP_MOUNTED, src, &source)) 1532789Sahrens (void) strlcpy(propbuf, "yes", proplen); 1533789Sahrens else 1534789Sahrens (void) strlcpy(propbuf, "no", proplen); 1535789Sahrens break; 1536789Sahrens 1537789Sahrens case ZFS_PROP_NAME: 1538789Sahrens /* 1539789Sahrens * The 'name' property is a pseudo-property derived from the 1540789Sahrens * dataset name. It is presented as a real property to simplify 1541789Sahrens * consumers. 1542789Sahrens */ 1543789Sahrens (void) strlcpy(propbuf, zhp->zfs_name, proplen); 1544789Sahrens break; 1545789Sahrens 1546789Sahrens default: 1547789Sahrens zfs_baderror(EINVAL); 1548789Sahrens } 1549789Sahrens 1550789Sahrens get_source(zhp, src, source, statbuf, statlen); 1551789Sahrens 1552789Sahrens return (0); 1553789Sahrens } 1554789Sahrens 1555789Sahrens /* 1556789Sahrens * Utility function to get the given numeric property. Does no validation that 1557789Sahrens * the given property is the appropriate type; should only be used with 1558789Sahrens * hard-coded property types. 1559789Sahrens */ 1560789Sahrens uint64_t 1561789Sahrens zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop) 1562789Sahrens { 1563789Sahrens char *source; 1564789Sahrens zfs_source_t sourcetype = ZFS_SRC_NONE; 1565789Sahrens 1566789Sahrens return (get_numeric_property(zhp, prop, &sourcetype, &source)); 1567789Sahrens } 1568789Sahrens 1569789Sahrens /* 1570789Sahrens * Similar to zfs_prop_get(), but returns the value as an integer. 1571789Sahrens */ 1572789Sahrens int 1573789Sahrens zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, 1574789Sahrens zfs_source_t *src, char *statbuf, size_t statlen) 1575789Sahrens { 1576789Sahrens char *source; 1577789Sahrens 1578789Sahrens /* 1579789Sahrens * Check to see if this property applies to our object 1580789Sahrens */ 1581789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1582789Sahrens return (-1); 1583789Sahrens 1584789Sahrens if (src) 1585789Sahrens *src = ZFS_SRC_NONE; 1586789Sahrens 1587789Sahrens *value = get_numeric_property(zhp, prop, src, &source); 1588789Sahrens 1589789Sahrens get_source(zhp, src, source, statbuf, statlen); 1590789Sahrens 1591789Sahrens return (0); 1592789Sahrens } 1593789Sahrens 1594789Sahrens /* 1595789Sahrens * Returns the name of the given zfs handle. 1596789Sahrens */ 1597789Sahrens const char * 1598789Sahrens zfs_get_name(const zfs_handle_t *zhp) 1599789Sahrens { 1600789Sahrens return (zhp->zfs_name); 1601789Sahrens } 1602789Sahrens 1603789Sahrens /* 1604789Sahrens * Returns the type of the given zfs handle. 1605789Sahrens */ 1606789Sahrens zfs_type_t 1607789Sahrens zfs_get_type(const zfs_handle_t *zhp) 1608789Sahrens { 1609789Sahrens return (zhp->zfs_type); 1610789Sahrens } 1611789Sahrens 1612789Sahrens /* 16131356Seschrock * Iterate over all child filesystems 1614789Sahrens */ 1615789Sahrens int 16161356Seschrock zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) 1617789Sahrens { 1618789Sahrens zfs_cmd_t zc = { 0 }; 1619789Sahrens zfs_handle_t *nzhp; 1620789Sahrens int ret; 1621789Sahrens 1622789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1623789Sahrens ioctl(zfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; 1624789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1625789Sahrens /* 1626789Sahrens * Ignore private dataset names. 1627789Sahrens */ 1628789Sahrens if (dataset_name_hidden(zc.zc_name)) 1629789Sahrens continue; 1630789Sahrens 1631789Sahrens /* 1632789Sahrens * Silently ignore errors, as the only plausible explanation is 1633789Sahrens * that the pool has since been removed. 1634789Sahrens */ 1635789Sahrens if ((nzhp = make_dataset_handle(zc.zc_name)) == NULL) 1636789Sahrens continue; 1637789Sahrens 1638789Sahrens if ((ret = func(nzhp, data)) != 0) 1639789Sahrens return (ret); 1640789Sahrens } 1641789Sahrens 1642789Sahrens /* 1643789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1644789Sahrens * returned, then the underlying dataset has been removed since we 1645789Sahrens * obtained the handle. 1646789Sahrens */ 1647789Sahrens if (errno != ESRCH && errno != ENOENT) 1648789Sahrens zfs_baderror(errno); 1649789Sahrens 16501356Seschrock return (0); 16511356Seschrock } 16521356Seschrock 16531356Seschrock /* 16541356Seschrock * Iterate over all snapshots 16551356Seschrock */ 16561356Seschrock int 16571356Seschrock zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) 16581356Seschrock { 16591356Seschrock zfs_cmd_t zc = { 0 }; 16601356Seschrock zfs_handle_t *nzhp; 16611356Seschrock int ret; 1662789Sahrens 1663789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1664789Sahrens ioctl(zfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc) == 0; 1665789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1666789Sahrens 1667789Sahrens if ((nzhp = make_dataset_handle(zc.zc_name)) == NULL) 1668789Sahrens continue; 1669789Sahrens 1670789Sahrens if ((ret = func(nzhp, data)) != 0) 1671789Sahrens return (ret); 1672789Sahrens } 1673789Sahrens 1674789Sahrens /* 1675789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1676789Sahrens * returned, then the underlying dataset has been removed since we 1677789Sahrens * obtained the handle. Silently ignore this case, and return success. 1678789Sahrens */ 1679789Sahrens if (errno != ESRCH && errno != ENOENT) 1680789Sahrens zfs_baderror(errno); 1681789Sahrens 1682789Sahrens return (0); 1683789Sahrens } 1684789Sahrens 1685789Sahrens /* 16861356Seschrock * Iterate over all children, snapshots and filesystems 16871356Seschrock */ 16881356Seschrock int 16891356Seschrock zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 16901356Seschrock { 16911356Seschrock int ret; 16921356Seschrock 16931356Seschrock if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0) 16941356Seschrock return (ret); 16951356Seschrock 16961356Seschrock return (zfs_iter_snapshots(zhp, func, data)); 16971356Seschrock } 16981356Seschrock 16991356Seschrock /* 1700789Sahrens * Given a complete name, return just the portion that refers to the parent. 1701789Sahrens * Can return NULL if this is a pool. 1702789Sahrens */ 1703789Sahrens static int 1704789Sahrens parent_name(const char *path, char *buf, size_t buflen) 1705789Sahrens { 1706789Sahrens char *loc; 1707789Sahrens 1708789Sahrens if ((loc = strrchr(path, '/')) == NULL) 1709789Sahrens return (-1); 1710789Sahrens 1711789Sahrens (void) strncpy(buf, path, MIN(buflen, loc - path)); 1712789Sahrens buf[loc - path] = '\0'; 1713789Sahrens 1714789Sahrens return (0); 1715789Sahrens } 1716789Sahrens 1717789Sahrens /* 1718789Sahrens * Checks to make sure that the given path has a parent, and that it exists. 1719789Sahrens */ 1720789Sahrens static int 1721789Sahrens check_parents(const char *path, zfs_type_t type) 1722789Sahrens { 1723789Sahrens zfs_cmd_t zc = { 0 }; 1724789Sahrens char parent[ZFS_MAXNAMELEN]; 1725789Sahrens char *slash; 17261356Seschrock zfs_handle_t *zhp; 1727789Sahrens 1728789Sahrens /* get parent, and check to see if this is just a pool */ 1729789Sahrens if (parent_name(path, parent, sizeof (parent)) != 0) { 1730789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1731789Sahrens "cannot create '%s': missing dataset name"), 1732789Sahrens path, zfs_type_to_name(type)); 1733789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1734789Sahrens "use 'zpool create' to create a storage pool")); 1735789Sahrens return (-1); 1736789Sahrens } 1737789Sahrens 1738789Sahrens /* check to see if the pool exists */ 1739789Sahrens if ((slash = strchr(parent, '/')) == NULL) 1740789Sahrens slash = parent + strlen(parent); 1741789Sahrens (void) strncpy(zc.zc_name, parent, slash - parent); 1742789Sahrens zc.zc_name[slash - parent] = '\0'; 1743789Sahrens if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 && 1744789Sahrens errno == ENOENT) { 1745789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1746789Sahrens "cannot create '%s': no such pool '%s'"), path, zc.zc_name); 1747789Sahrens return (-1); 1748789Sahrens } 1749789Sahrens 1750789Sahrens /* check to see if the parent dataset exists */ 17511356Seschrock if ((zhp = make_dataset_handle(parent)) == NULL) { 1752789Sahrens switch (errno) { 1753789Sahrens case ENOENT: 1754789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1755789Sahrens "cannot create '%s': parent does not exist"), path); 1756789Sahrens return (-1); 1757789Sahrens 1758789Sahrens default: 1759789Sahrens zfs_baderror(errno); 1760789Sahrens } 1761789Sahrens } 1762789Sahrens 1763789Sahrens /* we are in a non-global zone, but parent is in the global zone */ 17641356Seschrock if (getzoneid() != GLOBAL_ZONEID && 17651393Slling !zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 1766789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1767789Sahrens "cannot create '%s': permission denied"), path); 17681356Seschrock zfs_close(zhp); 1769789Sahrens return (-1); 1770789Sahrens } 1771789Sahrens 1772789Sahrens /* make sure parent is a filesystem */ 17731356Seschrock if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 1774789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1775789Sahrens "cannot create '%s': parent is not a filesystem"), 1776789Sahrens path); 17771356Seschrock zfs_close(zhp); 1778789Sahrens return (-1); 1779789Sahrens } 1780789Sahrens 17811356Seschrock zfs_close(zhp); 1782789Sahrens return (0); 1783789Sahrens } 1784789Sahrens 1785789Sahrens /* 1786789Sahrens * Create a new filesystem or volume. 'sizestr' and 'blocksizestr' are used 1787789Sahrens * only for volumes, and indicate the size and blocksize of the volume. 1788789Sahrens */ 1789789Sahrens int 1790789Sahrens zfs_create(const char *path, zfs_type_t type, 1791789Sahrens const char *sizestr, const char *blocksizestr) 1792789Sahrens { 1793789Sahrens char reason[64]; 1794789Sahrens zfs_cmd_t zc = { 0 }; 1795789Sahrens int ret; 1796789Sahrens uint64_t size = 0; 1797789Sahrens uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE); 1798789Sahrens 1799789Sahrens /* convert sizestr into integer size */ 1800789Sahrens if (sizestr != NULL && nicestrtonum(sizestr, &size, 1801789Sahrens reason, sizeof (reason)) != 0) { 1802789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1803789Sahrens "bad volume size '%s': %s"), sizestr, reason); 1804789Sahrens return (-1); 1805789Sahrens } 1806789Sahrens 1807789Sahrens /* convert blocksizestr into integer blocksize */ 1808789Sahrens if (blocksizestr != NULL && nicestrtonum(blocksizestr, &blocksize, 1809789Sahrens reason, sizeof (reason)) != 0) { 1810789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1811789Sahrens "bad volume blocksize '%s': %s"), blocksizestr, reason); 1812789Sahrens return (-1); 1813789Sahrens } 1814789Sahrens 1815789Sahrens /* validate the path, taking care to note the extended error message */ 1816789Sahrens if (!zfs_validate_name(path, type, reason, sizeof (reason))) { 1817789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1818789Sahrens "cannot create '%s': %s in %s name"), path, reason, 1819789Sahrens zfs_type_to_name(type)); 1820789Sahrens if (strstr(reason, "snapshot") != NULL) 1821789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1822789Sahrens "use 'zfs snapshot' to create a snapshot")); 1823789Sahrens return (-1); 1824789Sahrens } 1825789Sahrens 1826789Sahrens /* validate parents exist */ 1827789Sahrens if (check_parents(path, type) != 0) 1828789Sahrens return (-1); 1829789Sahrens 1830789Sahrens /* 1831789Sahrens * The failure modes when creating a dataset of a different type over 1832789Sahrens * one that already exists is a little strange. In particular, if you 1833789Sahrens * try to create a dataset on top of an existing dataset, the ioctl() 1834789Sahrens * will return ENOENT, not EEXIST. To prevent this from happening, we 1835789Sahrens * first try to see if the dataset exists. 1836789Sahrens */ 1837789Sahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 1838789Sahrens if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) { 1839789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1840789Sahrens "cannot create '%s': dataset exists"), path); 1841789Sahrens return (-1); 1842789Sahrens } 1843789Sahrens 1844789Sahrens if (type == ZFS_TYPE_VOLUME) 1845789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 1846789Sahrens else 1847789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 1848789Sahrens 1849789Sahrens if (type == ZFS_TYPE_VOLUME) { 18501133Seschrock /* 18511133Seschrock * If we are creating a volume, the size and block size must 18521133Seschrock * satisfy a few restraints. First, the blocksize must be a 18531133Seschrock * valid block size between SPA_{MIN,MAX}BLOCKSIZE. Second, the 18541133Seschrock * volsize must be a multiple of the block size, and cannot be 18551133Seschrock * zero. 18561133Seschrock */ 1857789Sahrens if (size == 0) { 1858789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1859789Sahrens "bad volume size '%s': cannot be zero"), sizestr); 1860789Sahrens return (-1); 1861789Sahrens } 1862789Sahrens 18631133Seschrock if (blocksize < SPA_MINBLOCKSIZE || 18641133Seschrock blocksize > SPA_MAXBLOCKSIZE || !ISP2(blocksize)) { 18651133Seschrock zfs_error(dgettext(TEXT_DOMAIN, 18661133Seschrock "bad volume block size '%s': " 18671133Seschrock "must be power of 2 from %u to %uk"), 18681133Seschrock blocksizestr, 18691133Seschrock (uint_t)SPA_MINBLOCKSIZE, 18701133Seschrock (uint_t)SPA_MAXBLOCKSIZE >> 10); 18711133Seschrock return (-1); 18721133Seschrock } 18731133Seschrock 18741133Seschrock if (size % blocksize != 0) { 18751133Seschrock char buf[64]; 18761133Seschrock zfs_nicenum(blocksize, buf, sizeof (buf)); 18771133Seschrock zfs_error(dgettext(TEXT_DOMAIN, 18781133Seschrock "bad volume size '%s': " 18791133Seschrock "must be multiple of volume block size (%s)"), 18801133Seschrock sizestr, buf); 18811133Seschrock return (-1); 18821133Seschrock } 18831133Seschrock 1884789Sahrens zc.zc_volsize = size; 1885789Sahrens zc.zc_volblocksize = blocksize; 1886789Sahrens } 1887789Sahrens 1888789Sahrens /* create the dataset */ 1889789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_CREATE, &zc); 1890789Sahrens 1891789Sahrens if (ret == 0 && type == ZFS_TYPE_VOLUME) 1892789Sahrens ret = zvol_create_link(path); 1893789Sahrens 1894789Sahrens /* check for failure */ 1895789Sahrens if (ret != 0) { 1896789Sahrens char parent[ZFS_MAXNAMELEN]; 1897789Sahrens (void) parent_name(path, parent, sizeof (parent)); 1898789Sahrens 1899789Sahrens switch (errno) { 1900789Sahrens case ENOENT: 1901789Sahrens /* 1902789Sahrens * The parent dataset has been deleted since our 1903789Sahrens * previous check. 1904789Sahrens */ 1905789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1906789Sahrens "cannot create '%s': no such parent '%s'"), 1907789Sahrens path, parent); 1908789Sahrens break; 1909789Sahrens 1910789Sahrens case EPERM: 1911789Sahrens /* 1912789Sahrens * The user doesn't have permission to create a new 1913789Sahrens * dataset here. 1914789Sahrens */ 1915789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1916789Sahrens "cannot create '%s': permission denied"), path); 1917789Sahrens break; 1918789Sahrens 1919789Sahrens case EDQUOT: 1920789Sahrens case ENOSPC: 1921789Sahrens /* 1922789Sahrens * The parent dataset does not have enough free space 1923789Sahrens * to create a new dataset. 1924789Sahrens */ 1925789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1926789Sahrens "cannot create '%s': not enough space in '%s'"), 1927789Sahrens path, parent); 1928789Sahrens break; 1929789Sahrens 1930789Sahrens case EEXIST: 1931789Sahrens /* 1932789Sahrens * The target dataset already exists. We should have 1933789Sahrens * caught this above, but there may be some unexplained 1934789Sahrens * race condition. 1935789Sahrens */ 1936789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1937789Sahrens "cannot create '%s': dataset exists"), path); 1938789Sahrens break; 1939789Sahrens 1940789Sahrens case EINVAL: 1941789Sahrens /* 1942789Sahrens * The target dataset does not support children. 1943789Sahrens */ 1944789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1945789Sahrens "cannot create '%s': children unsupported in '%s'"), 1946789Sahrens path, parent); 1947789Sahrens break; 1948789Sahrens 1949789Sahrens case EDOM: 1950789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "bad %s value '%s': " 1951789Sahrens "must be power of 2 from %u to %uk"), 1952789Sahrens zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 1953789Sahrens blocksizestr ? blocksizestr : "<unknown>", 1954789Sahrens (uint_t)SPA_MINBLOCKSIZE, 1955789Sahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 1956789Sahrens break; 1957789Sahrens #ifdef _ILP32 1958789Sahrens case EOVERFLOW: 1959789Sahrens /* 1960789Sahrens * This platform can't address a volume this big. 1961789Sahrens */ 1962789Sahrens if (type == ZFS_TYPE_VOLUME) { 1963789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1964789Sahrens "cannot create '%s': " 1965789Sahrens "max volume size is 1TB on 32-bit systems"), 1966789Sahrens path); 1967789Sahrens break; 1968789Sahrens } 1969789Sahrens #endif 1970789Sahrens 1971789Sahrens default: 1972789Sahrens zfs_baderror(errno); 1973789Sahrens } 1974789Sahrens 1975789Sahrens return (-1); 1976789Sahrens } 1977789Sahrens 1978789Sahrens return (0); 1979789Sahrens } 1980789Sahrens 1981789Sahrens /* 1982789Sahrens * Destroys the given dataset. The caller must make sure that the filesystem 1983789Sahrens * isn't mounted, and that there are no active dependents. 1984789Sahrens */ 1985789Sahrens int 1986789Sahrens zfs_destroy(zfs_handle_t *zhp) 1987789Sahrens { 1988789Sahrens zfs_cmd_t zc = { 0 }; 1989789Sahrens int ret; 1990789Sahrens 1991789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1992789Sahrens 1993789Sahrens /* 1994789Sahrens * We use the check for 'zfs_volblocksize' instead of ZFS_TYPE_VOLUME 1995789Sahrens * so that we do the right thing for snapshots of volumes. 1996789Sahrens */ 1997789Sahrens if (zhp->zfs_volblocksize != 0) { 1998789Sahrens if (zvol_remove_link(zhp->zfs_name) != 0) 1999789Sahrens return (-1); 2000789Sahrens 2001789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2002789Sahrens } else { 2003789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2004789Sahrens } 2005789Sahrens 2006789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_DESTROY, &zc); 2007789Sahrens 2008789Sahrens if (ret != 0) { 2009789Sahrens switch (errno) { 2010789Sahrens 2011789Sahrens case EPERM: 2012789Sahrens /* 2013789Sahrens * We don't have permission to destroy this dataset. 2014789Sahrens */ 2015789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2016789Sahrens "cannot destroy '%s': permission denied"), 2017789Sahrens zhp->zfs_name); 2018789Sahrens break; 2019789Sahrens 2020789Sahrens case ENOENT: 2021789Sahrens /* 2022789Sahrens * We've hit a race condition where the dataset has been 2023789Sahrens * destroyed since we opened it. 2024789Sahrens */ 2025789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2026789Sahrens "cannot destroy '%s': no such %s"), 2027789Sahrens zhp->zfs_name, zfs_type_to_name(zhp->zfs_type)); 2028789Sahrens break; 2029789Sahrens 2030789Sahrens case EBUSY: 2031789Sahrens /* 2032789Sahrens * Even if we destroy all children, there is a chance we 2033789Sahrens * can hit this case if: 2034789Sahrens * 2035789Sahrens * - A child dataset has since been created 2036789Sahrens * - A filesystem is mounted 2037789Sahrens * 2038789Sahrens * This error message is awful, but hopefully we've 2039789Sahrens * already caught the common cases (and aborted more 2040789Sahrens * appropriately) before calling this function. There's 2041789Sahrens * nothing else we can do at this point. 2042789Sahrens */ 2043789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2044789Sahrens "cannot destroy '%s': %s is busy"), 2045789Sahrens zhp->zfs_name, zfs_type_to_name(zhp->zfs_type)); 2046789Sahrens break; 2047789Sahrens 2048789Sahrens default: 2049789Sahrens zfs_baderror(errno); 2050789Sahrens } 2051789Sahrens 2052789Sahrens return (-1); 2053789Sahrens } 2054789Sahrens 2055789Sahrens remove_mountpoint(zhp); 2056789Sahrens 2057789Sahrens return (0); 2058789Sahrens } 2059789Sahrens 2060789Sahrens /* 2061789Sahrens * Clones the given dataset. The target must be of the same type as the source. 2062789Sahrens */ 2063789Sahrens int 2064789Sahrens zfs_clone(zfs_handle_t *zhp, const char *target) 2065789Sahrens { 2066789Sahrens char reason[64]; 2067789Sahrens zfs_cmd_t zc = { 0 }; 2068789Sahrens char parent[ZFS_MAXNAMELEN]; 2069789Sahrens int ret; 2070789Sahrens 2071789Sahrens assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 2072789Sahrens 2073789Sahrens /* validate the target name */ 2074789Sahrens if (!zfs_validate_name(target, ZFS_TYPE_FILESYSTEM, reason, 2075789Sahrens sizeof (reason))) { 2076789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2077789Sahrens "cannot create '%s': %s in filesystem name"), target, 2078789Sahrens reason, zfs_type_to_name(ZFS_TYPE_FILESYSTEM)); 2079789Sahrens return (-1); 2080789Sahrens } 2081789Sahrens 2082789Sahrens /* validate parents exist */ 2083789Sahrens if (check_parents(target, zhp->zfs_type) != 0) 2084789Sahrens return (-1); 2085789Sahrens 2086789Sahrens (void) parent_name(target, parent, sizeof (parent)); 2087789Sahrens 2088789Sahrens /* do the clone */ 2089789Sahrens if (zhp->zfs_volblocksize != 0) 2090789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2091789Sahrens else 2092789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2093789Sahrens 2094789Sahrens (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name)); 2095789Sahrens (void) strlcpy(zc.zc_filename, zhp->zfs_name, sizeof (zc.zc_filename)); 2096789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_CREATE, &zc); 2097789Sahrens 2098789Sahrens if (ret != 0) { 2099789Sahrens switch (errno) { 2100789Sahrens case EPERM: 2101789Sahrens /* 2102789Sahrens * The user doesn't have permission to create the clone. 2103789Sahrens */ 2104789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2105789Sahrens "cannot create '%s': permission denied"), 2106789Sahrens target); 2107789Sahrens break; 2108789Sahrens 2109789Sahrens case ENOENT: 2110789Sahrens /* 2111789Sahrens * The parent doesn't exist. We should have caught this 2112789Sahrens * above, but there may a race condition that has since 2113789Sahrens * destroyed the parent. 2114789Sahrens * 2115789Sahrens * At this point, we don't know whether it's the source 2116789Sahrens * that doesn't exist anymore, or whether the target 2117789Sahrens * dataset doesn't exist. 2118789Sahrens */ 2119789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2120789Sahrens "cannot create '%s': no such parent '%s'"), 2121789Sahrens target, parent); 2122789Sahrens break; 2123789Sahrens 2124789Sahrens case EDQUOT: 2125789Sahrens case ENOSPC: 2126789Sahrens /* 2127789Sahrens * There is not enough space in the target dataset 2128789Sahrens */ 2129789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2130789Sahrens "cannot create '%s': not enough space in '%s'"), 2131789Sahrens target, parent); 2132789Sahrens break; 2133789Sahrens 2134789Sahrens case EEXIST: 2135789Sahrens /* 2136789Sahrens * The target already exists. 2137789Sahrens */ 2138789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2139789Sahrens "cannot create '%s': dataset exists"), target); 2140789Sahrens break; 2141789Sahrens 2142789Sahrens case EXDEV: 2143789Sahrens /* 2144789Sahrens * The source and target pools differ. 2145789Sahrens */ 2146789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2147789Sahrens "source and target pools differ"), target); 2148789Sahrens break; 2149789Sahrens 2150789Sahrens default: 2151789Sahrens zfs_baderror(errno); 2152789Sahrens } 2153789Sahrens } else if (zhp->zfs_volblocksize != 0) { 2154789Sahrens ret = zvol_create_link(target); 2155789Sahrens } 2156789Sahrens 2157789Sahrens return (ret); 2158789Sahrens } 2159789Sahrens 2160789Sahrens /* 2161789Sahrens * Takes a snapshot of the given dataset 2162789Sahrens */ 2163789Sahrens int 2164789Sahrens zfs_snapshot(const char *path) 2165789Sahrens { 2166789Sahrens char reason[64]; 2167789Sahrens const char *delim; 2168789Sahrens char *parent; 2169789Sahrens zfs_handle_t *zhp; 2170789Sahrens zfs_cmd_t zc = { 0 }; 2171789Sahrens int ret; 2172789Sahrens 2173789Sahrens /* validate the snapshot name */ 2174789Sahrens if (!zfs_validate_name(path, ZFS_TYPE_SNAPSHOT, reason, 2175789Sahrens sizeof (reason))) { 2176789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2177789Sahrens "cannot snapshot '%s': %s in snapshot name"), path, 2178789Sahrens reason); 2179789Sahrens return (-1); 2180789Sahrens } 2181789Sahrens 2182789Sahrens /* make sure we have a snapshot */ 2183789Sahrens if ((delim = strchr(path, '@')) == NULL) { 2184789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2185789Sahrens "cannot snapshot '%s': missing '@' delim in snapshot " 2186789Sahrens "name"), path); 2187789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2188789Sahrens "use 'zfs create' to create a filesystem")); 2189789Sahrens return (-1); 2190789Sahrens } 2191789Sahrens 2192789Sahrens /* make sure the parent exists and is of the appropriate type */ 2193789Sahrens parent = zfs_malloc(delim - path + 1); 2194789Sahrens (void) strncpy(parent, path, delim - path); 2195789Sahrens parent[delim - path] = '\0'; 2196789Sahrens 2197789Sahrens if ((zhp = zfs_open(parent, ZFS_TYPE_FILESYSTEM | 2198789Sahrens ZFS_TYPE_VOLUME)) == NULL) { 2199789Sahrens free(parent); 2200789Sahrens return (-1); 2201789Sahrens } 2202789Sahrens 2203789Sahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 2204789Sahrens 2205789Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) 2206789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2207789Sahrens else 2208789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2209789Sahrens 2210789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_CREATE, &zc); 2211789Sahrens 2212789Sahrens if (ret == 0 && zhp->zfs_type == ZFS_TYPE_VOLUME) { 2213789Sahrens ret = zvol_create_link(path); 2214789Sahrens if (ret != 0) 2215789Sahrens (void) ioctl(zfs_fd, ZFS_IOC_DESTROY, &zc); 2216789Sahrens } 2217789Sahrens 2218789Sahrens if (ret != 0) { 2219789Sahrens switch (errno) { 2220789Sahrens case EPERM: 2221789Sahrens /* 2222789Sahrens * User doesn't have permission to create a snapshot 2223789Sahrens */ 2224789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2225789Sahrens "permission denied"), path); 2226789Sahrens break; 2227789Sahrens 2228789Sahrens case EDQUOT: 2229789Sahrens case ENOSPC: 2230789Sahrens /* 2231789Sahrens * Out of space in parent. 2232789Sahrens */ 2233789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2234789Sahrens "not enough space in '%s'"), path, parent); 2235789Sahrens break; 2236789Sahrens 2237789Sahrens case EEXIST: 2238789Sahrens /* 2239789Sahrens * Snapshot already exists. 2240789Sahrens */ 2241789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2242789Sahrens "snapshot exists"), path); 2243789Sahrens break; 2244789Sahrens 2245789Sahrens case ENOENT: 2246789Sahrens /* 2247789Sahrens * Shouldn't happen because we verified the parent 2248789Sahrens * above. But there may be a race condition where it 2249789Sahrens * has since been removed. 2250789Sahrens */ 2251789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': " 2252789Sahrens "no such %s"), parent, 2253789Sahrens zfs_type_to_name(zhp->zfs_type)); 2254789Sahrens break; 2255789Sahrens 2256789Sahrens default: 2257789Sahrens zfs_baderror(errno); 2258789Sahrens } 2259789Sahrens } 2260789Sahrens 2261789Sahrens free(parent); 2262789Sahrens zfs_close(zhp); 2263789Sahrens 2264789Sahrens return (ret); 2265789Sahrens } 2266789Sahrens 2267789Sahrens /* 2268789Sahrens * Dumps a backup of tosnap, incremental from fromsnap if it isn't NULL. 2269789Sahrens */ 2270789Sahrens int 2271789Sahrens zfs_backup(zfs_handle_t *zhp_to, zfs_handle_t *zhp_from) 2272789Sahrens { 2273789Sahrens zfs_cmd_t zc = { 0 }; 2274789Sahrens int ret; 2275789Sahrens 2276789Sahrens /* do the ioctl() */ 2277789Sahrens (void) strlcpy(zc.zc_name, zhp_to->zfs_name, sizeof (zc.zc_name)); 2278789Sahrens if (zhp_from) { 2279789Sahrens (void) strlcpy(zc.zc_prop_value, zhp_from->zfs_name, 2280789Sahrens sizeof (zc.zc_name)); 2281789Sahrens } else { 2282789Sahrens zc.zc_prop_value[0] = '\0'; 2283789Sahrens } 2284789Sahrens zc.zc_cookie = STDOUT_FILENO; 2285789Sahrens 2286789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SENDBACKUP, &zc); 2287789Sahrens if (ret != 0) { 2288789Sahrens switch (errno) { 2289789Sahrens case EPERM: 2290789Sahrens /* 2291789Sahrens * User doesn't have permission to do a backup 2292789Sahrens */ 2293789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot backup '%s': " 2294789Sahrens "permission denied"), zhp_to->zfs_name); 2295789Sahrens break; 2296789Sahrens 2297789Sahrens case EXDEV: 2298789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2299789Sahrens "cannot do incremental backup from %s:\n" 2300789Sahrens "it is not an earlier snapshot from the " 2301789Sahrens "same fs as %s"), 2302789Sahrens zhp_from->zfs_name, zhp_to->zfs_name); 2303789Sahrens break; 2304789Sahrens 2305789Sahrens case ENOENT: 2306789Sahrens /* 2307789Sahrens * Shouldn't happen because we verified the parent 2308789Sahrens * above. But there may be a race condition where it 2309789Sahrens * has since been removed. 2310789Sahrens */ 2311789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open: " 2312789Sahrens "no such snapshot")); 2313789Sahrens break; 2314789Sahrens 2315789Sahrens case EDQUOT: 2316789Sahrens case EFBIG: 2317789Sahrens case EIO: 2318789Sahrens case ENOLINK: 2319789Sahrens case ENOSPC: 2320789Sahrens case ENOSTR: 2321789Sahrens case ENXIO: 2322789Sahrens case EPIPE: 2323789Sahrens case ERANGE: 2324789Sahrens case EFAULT: 2325789Sahrens case EROFS: 2326789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2327789Sahrens "cannot write backup stream: %s"), 2328789Sahrens strerror(errno)); 2329789Sahrens break; 2330789Sahrens 2331789Sahrens case EINTR: 2332789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2333789Sahrens "backup failed: signal recieved")); 2334789Sahrens break; 2335789Sahrens 2336789Sahrens default: 2337789Sahrens zfs_baderror(errno); 2338789Sahrens } 2339789Sahrens } 2340789Sahrens 2341789Sahrens return (ret); 2342789Sahrens } 2343789Sahrens 2344789Sahrens /* 2345789Sahrens * Restores a backup of tosnap from stdin. 2346789Sahrens */ 2347789Sahrens int 2348789Sahrens zfs_restore(const char *tosnap, int isprefix, int verbose, int dryrun) 2349789Sahrens { 2350789Sahrens zfs_cmd_t zc = { 0 }; 2351789Sahrens time_t begin_time; 2352868Sahrens int ioctl_err, err, bytes, size; 2353789Sahrens char *cp; 2354789Sahrens dmu_replay_record_t drr; 2355789Sahrens struct drr_begin *drrb = &zc.zc_begin_record; 2356789Sahrens 2357789Sahrens begin_time = time(NULL); 2358789Sahrens 2359789Sahrens /* trim off snapname, if any */ 2360789Sahrens (void) strcpy(zc.zc_name, tosnap); 2361789Sahrens cp = strchr(zc.zc_name, '@'); 2362789Sahrens if (cp) 2363789Sahrens *cp = '\0'; 2364789Sahrens 2365789Sahrens /* read in the BEGIN record */ 2366789Sahrens cp = (char *)&drr; 2367789Sahrens bytes = 0; 2368789Sahrens do { 2369868Sahrens size = read(STDIN_FILENO, cp, sizeof (drr) - bytes); 2370868Sahrens cp += size; 2371868Sahrens bytes += size; 2372868Sahrens } while (size > 0); 2373868Sahrens 2374868Sahrens if (size < 0 || bytes != sizeof (drr)) { 2375789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2376868Sahrens "cannot restore: invalid backup stream " 2377789Sahrens "(couldn't read first record)")); 2378789Sahrens return (-1); 2379789Sahrens } 2380789Sahrens 2381789Sahrens zc.zc_begin_record = drr.drr_u.drr_begin; 2382789Sahrens 2383789Sahrens if (drrb->drr_magic != DMU_BACKUP_MAGIC && 2384789Sahrens drrb->drr_magic != BSWAP_64(DMU_BACKUP_MAGIC)) { 2385789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2386868Sahrens "cannot restore: invalid backup stream " 2387789Sahrens "(invalid magic number)")); 2388789Sahrens return (-1); 2389789Sahrens } 2390789Sahrens 2391789Sahrens if (drrb->drr_version != DMU_BACKUP_VERSION && 2392789Sahrens drrb->drr_version != BSWAP_64(DMU_BACKUP_VERSION)) { 2393789Sahrens if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) 2394789Sahrens drrb->drr_version = BSWAP_64(drrb->drr_version); 2395789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2396868Sahrens "cannot restore: only backup version 0x%llx is supported, " 2397789Sahrens "stream is version %llx."), 2398789Sahrens DMU_BACKUP_VERSION, drrb->drr_version); 2399789Sahrens return (-1); 2400789Sahrens } 2401789Sahrens 2402789Sahrens /* 2403789Sahrens * Determine name of destination snapshot. 2404789Sahrens */ 2405789Sahrens (void) strcpy(drrb->drr_toname, tosnap); 2406789Sahrens if (isprefix) { 2407789Sahrens if (strchr(tosnap, '@') != NULL) { 2408789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2409868Sahrens "cannot restore: " 2410789Sahrens "argument to -d must be a filesystem")); 2411789Sahrens return (-1); 2412789Sahrens } 2413789Sahrens 2414789Sahrens cp = strchr(drr.drr_u.drr_begin.drr_toname, '/'); 2415789Sahrens if (cp == NULL) 2416789Sahrens cp = drr.drr_u.drr_begin.drr_toname; 2417789Sahrens else 2418789Sahrens cp++; 2419789Sahrens 2420789Sahrens (void) strcat(drrb->drr_toname, "/"); 2421789Sahrens (void) strcat(drrb->drr_toname, cp); 2422789Sahrens } else if (strchr(tosnap, '@') == NULL) { 2423789Sahrens /* 2424789Sahrens * they specified just a filesystem; tack on the 2425789Sahrens * snapname from the backup. 2426789Sahrens */ 2427789Sahrens cp = strchr(drr.drr_u.drr_begin.drr_toname, '@'); 2428789Sahrens if (cp == NULL || strlen(tosnap) + strlen(cp) >= MAXNAMELEN) { 2429789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2430868Sahrens "cannot restore: invalid backup stream " 2431789Sahrens "(invalid snapshot name)")); 2432789Sahrens return (-1); 2433789Sahrens } 2434789Sahrens (void) strcat(drrb->drr_toname, cp); 2435789Sahrens } 2436789Sahrens 2437789Sahrens if (drrb->drr_fromguid) { 2438789Sahrens zfs_handle_t *h; 2439789Sahrens /* incremental backup stream */ 2440789Sahrens 2441789Sahrens /* do the ioctl to the containing fs */ 2442789Sahrens (void) strcpy(zc.zc_name, drrb->drr_toname); 2443789Sahrens cp = strchr(zc.zc_name, '@'); 2444789Sahrens *cp = '\0'; 2445789Sahrens 2446789Sahrens /* make sure destination fs exists */ 2447789Sahrens h = zfs_open(zc.zc_name, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2448789Sahrens if (h == NULL) { 2449789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2450868Sahrens "cannot restore incrememtal backup: destination\n" 2451789Sahrens "filesystem %s does not exist"), 2452789Sahrens zc.zc_name); 2453789Sahrens return (-1); 2454789Sahrens } 2455868Sahrens if (!dryrun) { 2456868Sahrens /* unmount destination fs or remove device link. */ 2457868Sahrens if (h->zfs_type == ZFS_TYPE_FILESYSTEM) { 2458868Sahrens (void) zfs_unmount(h, NULL, 0); 2459868Sahrens } else { 2460868Sahrens (void) zvol_remove_link(h->zfs_name); 2461868Sahrens } 2462868Sahrens } 2463789Sahrens zfs_close(h); 2464789Sahrens } else { 2465789Sahrens /* full backup stream */ 2466789Sahrens 2467789Sahrens (void) strcpy(zc.zc_name, drrb->drr_toname); 2468868Sahrens 2469868Sahrens /* make sure they aren't trying to restore into the root */ 2470868Sahrens if (strchr(zc.zc_name, '/') == NULL) { 2471789Sahrens cp = strchr(zc.zc_name, '@'); 2472789Sahrens if (cp) 2473789Sahrens *cp = '\0'; 2474789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2475868Sahrens "cannot restore: destination fs %s already exists"), 2476789Sahrens zc.zc_name); 2477789Sahrens return (-1); 2478789Sahrens } 2479789Sahrens 2480789Sahrens if (isprefix) { 2481868Sahrens zfs_handle_t *h; 2482868Sahrens 2483789Sahrens /* make sure prefix exists */ 2484789Sahrens h = zfs_open(tosnap, ZFS_TYPE_FILESYSTEM | 2485789Sahrens ZFS_TYPE_VOLUME); 2486789Sahrens if (h == NULL) { 2487789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2488868Sahrens "cannot restore: " 2489789Sahrens "filesystem %s does not exist"), 2490789Sahrens tosnap); 2491789Sahrens return (-1); 2492789Sahrens } 2493789Sahrens 2494789Sahrens /* create any necessary ancestors up to prefix */ 2495868Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2496868Sahrens /* 2497868Sahrens * zc.zc_name is now the full name of the snap 2498868Sahrens * we're restoring into 2499868Sahrens */ 2500789Sahrens cp = zc.zc_name + strlen(tosnap) + 1; 2501789Sahrens while (cp = strchr(cp, '/')) { 2502789Sahrens *cp = '\0'; 2503789Sahrens err = ioctl(zfs_fd, ZFS_IOC_CREATE, &zc); 2504868Sahrens if (err && errno != ENOENT && errno != EEXIST) { 2505789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2506868Sahrens "cannot restore: " 2507789Sahrens "couldn't create ancestor %s"), 2508789Sahrens zc.zc_name); 2509789Sahrens return (-1); 2510789Sahrens } 2511868Sahrens *cp = '/'; 2512868Sahrens cp++; 2513789Sahrens } 2514789Sahrens } 2515868Sahrens 2516868Sahrens /* Make sure destination fs does not exist */ 2517868Sahrens cp = strchr(zc.zc_name, '@'); 2518868Sahrens *cp = '\0'; 2519868Sahrens if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) { 2520868Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2521868Sahrens "cannot restore full backup: " 2522868Sahrens "destination filesystem %s already exists"), 2523868Sahrens zc.zc_name); 2524868Sahrens return (-1); 2525868Sahrens } 2526868Sahrens 2527868Sahrens /* Do the recvbackup ioctl to the fs's parent. */ 2528868Sahrens cp = strrchr(zc.zc_name, '/'); 2529868Sahrens *cp = '\0'; 2530789Sahrens } 2531789Sahrens 2532789Sahrens (void) strcpy(zc.zc_prop_value, tosnap); 2533789Sahrens zc.zc_cookie = STDIN_FILENO; 2534789Sahrens zc.zc_intsz = isprefix; 2535789Sahrens if (verbose) { 2536789Sahrens (void) printf("%s %s backup of %s into %s\n", 2537789Sahrens dryrun ? "would restore" : "restoring", 2538789Sahrens drrb->drr_fromguid ? "incremental" : "full", 2539789Sahrens drr.drr_u.drr_begin.drr_toname, 2540789Sahrens zc.zc_begin_record.drr_toname); 2541789Sahrens (void) fflush(stdout); 2542789Sahrens } 2543789Sahrens if (dryrun) 2544789Sahrens return (0); 2545868Sahrens err = ioctl_err = ioctl(zfs_fd, ZFS_IOC_RECVBACKUP, &zc); 2546868Sahrens if (ioctl_err != 0) { 2547789Sahrens switch (errno) { 2548789Sahrens case ENODEV: 2549789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2550868Sahrens "cannot restore: " 2551868Sahrens "most recent snapshot does not " 2552789Sahrens "match incremental backup source")); 2553789Sahrens break; 2554789Sahrens case ETXTBSY: 2555789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2556868Sahrens "cannot restore: " 2557868Sahrens "destination has been modified since " 2558868Sahrens "most recent snapshot --\n" 2559868Sahrens "use 'zfs rollback' to discard changes")); 2560789Sahrens break; 2561789Sahrens case EEXIST: 2562789Sahrens if (drrb->drr_fromguid == 0) { 2563789Sahrens /* it's the containing fs that exists */ 2564789Sahrens cp = strchr(drrb->drr_toname, '@'); 2565789Sahrens *cp = '\0'; 2566789Sahrens } 2567789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2568868Sahrens "cannot restore to %s: destination already exists"), 2569789Sahrens drrb->drr_toname); 2570789Sahrens break; 2571789Sahrens case ENOENT: 2572789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2573868Sahrens "cannot restore: destination does not exist")); 2574789Sahrens break; 2575789Sahrens case EBUSY: 2576789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2577868Sahrens "cannot restore: destination is in use")); 2578789Sahrens break; 2579789Sahrens case ENOSPC: 2580789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2581868Sahrens "cannot restore: out of space")); 2582789Sahrens break; 2583789Sahrens case EDQUOT: 2584789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2585868Sahrens "cannot restore: quota exceeded")); 2586789Sahrens break; 2587789Sahrens case EINTR: 2588789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2589868Sahrens "restore failed: signal recieved")); 2590789Sahrens break; 2591789Sahrens case EINVAL: 2592789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2593868Sahrens "cannot restore: invalid backup stream")); 2594868Sahrens break; 2595868Sahrens case EPERM: 2596868Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2597868Sahrens "cannot restore: permission denied")); 2598789Sahrens break; 2599789Sahrens default: 2600789Sahrens zfs_baderror(errno); 2601789Sahrens } 2602789Sahrens } 2603789Sahrens 2604789Sahrens /* 2605868Sahrens * Mount or recreate the /dev links for the target filesystem 2606868Sahrens * (if created, or if we tore them down to do an incremental 2607868Sahrens * restore), and the /dev links for the new snapshot (if 2608868Sahrens * created). 2609789Sahrens */ 2610789Sahrens cp = strchr(drrb->drr_toname, '@'); 2611868Sahrens if (cp && (ioctl_err == 0 || drrb->drr_fromguid)) { 2612789Sahrens zfs_handle_t *h; 2613789Sahrens 2614789Sahrens *cp = '\0'; 2615789Sahrens h = zfs_open(drrb->drr_toname, 2616789Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2617868Sahrens *cp = '@'; 2618789Sahrens if (h) { 2619868Sahrens if (h->zfs_type == ZFS_TYPE_FILESYSTEM) { 2620789Sahrens err = zfs_mount(h, NULL, 0); 2621868Sahrens } else { 2622789Sahrens err = zvol_create_link(h->zfs_name); 2623868Sahrens if (err == 0 && ioctl_err == 0) { 2624868Sahrens err = 2625868Sahrens zvol_create_link(drrb->drr_toname); 2626868Sahrens } 2627868Sahrens } 2628789Sahrens zfs_close(h); 2629789Sahrens } 2630789Sahrens } 2631789Sahrens 2632868Sahrens if (err || ioctl_err) 2633868Sahrens return (-1); 2634789Sahrens 2635789Sahrens if (verbose) { 2636789Sahrens char buf1[64]; 2637789Sahrens char buf2[64]; 2638789Sahrens uint64_t bytes = zc.zc_cookie; 2639789Sahrens time_t delta = time(NULL) - begin_time; 2640789Sahrens if (delta == 0) 2641789Sahrens delta = 1; 2642789Sahrens zfs_nicenum(bytes, buf1, sizeof (buf1)); 2643789Sahrens zfs_nicenum(bytes/delta, buf2, sizeof (buf1)); 2644789Sahrens 2645789Sahrens (void) printf("restored %sb backup in %lu seconds (%sb/sec)\n", 2646789Sahrens buf1, delta, buf2); 2647789Sahrens } 2648789Sahrens return (0); 2649789Sahrens } 2650789Sahrens 2651789Sahrens /* 26521294Slling * Destroy any more recent snapshots. We invoke this callback on any dependents 26531294Slling * of the snapshot first. If the 'cb_dependent' member is non-zero, then this 26541294Slling * is a dependent and we should just destroy it without checking the transaction 26551294Slling * group. 2656789Sahrens */ 26571294Slling typedef struct rollback_data { 26581294Slling const char *cb_target; /* the snapshot */ 26591294Slling uint64_t cb_create; /* creation time reference */ 26601294Slling prop_changelist_t *cb_clp; /* changelist pointer */ 26611294Slling int cb_error; 26621294Slling int cb_dependent; 26631294Slling } rollback_data_t; 26641294Slling 26651294Slling static int 26661294Slling rollback_destroy(zfs_handle_t *zhp, void *data) 26671294Slling { 26681294Slling rollback_data_t *cbp = data; 26691294Slling 26701294Slling if (!cbp->cb_dependent) { 26711294Slling if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 && 26721294Slling zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && 26731294Slling zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > 26741294Slling cbp->cb_create) { 26751294Slling 26761294Slling cbp->cb_dependent = TRUE; 26771294Slling (void) zfs_iter_dependents(zhp, rollback_destroy, cbp); 26781294Slling cbp->cb_dependent = FALSE; 26791294Slling 26801294Slling if (zfs_destroy(zhp) != 0) 26811294Slling cbp->cb_error = 1; 26821294Slling else 26831294Slling changelist_remove(zhp, cbp->cb_clp); 26841294Slling } 26851294Slling } else { 26861294Slling if (zfs_destroy(zhp) != 0) 26871294Slling cbp->cb_error = 1; 26881294Slling else 26891294Slling changelist_remove(zhp, cbp->cb_clp); 26901294Slling } 26911294Slling 26921294Slling zfs_close(zhp); 26931294Slling return (0); 26941294Slling } 26951294Slling 26961294Slling /* 26971294Slling * Rollback the dataset to its latest snapshot. 26981294Slling */ 26991294Slling static int 27001294Slling do_rollback(zfs_handle_t *zhp) 2701789Sahrens { 2702789Sahrens int ret; 2703789Sahrens zfs_cmd_t zc = { 0 }; 2704789Sahrens 2705789Sahrens assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM || 2706789Sahrens zhp->zfs_type == ZFS_TYPE_VOLUME); 2707789Sahrens 2708789Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME && 2709789Sahrens zvol_remove_link(zhp->zfs_name) != 0) 2710789Sahrens return (-1); 2711789Sahrens 2712789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2713789Sahrens 2714789Sahrens if (zhp->zfs_volblocksize != 0) 2715789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2716789Sahrens else 2717789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2718789Sahrens 2719789Sahrens /* 2720789Sahrens * We rely on the consumer to verify that there are no newer snapshots 2721789Sahrens * for the given dataset. Given these constraints, we can simply pass 2722789Sahrens * the name on to the ioctl() call. There is still an unlikely race 2723789Sahrens * condition where the user has taken a snapshot since we verified that 2724789Sahrens * this was the most recent. 2725789Sahrens */ 2726789Sahrens if ((ret = ioctl(zfs_fd, ZFS_IOC_ROLLBACK, &zc)) != 0) { 2727789Sahrens switch (errno) { 2728789Sahrens case EPERM: 2729789Sahrens /* 2730789Sahrens * The user doesn't have permission to rollback the 2731789Sahrens * given dataset. 2732789Sahrens */ 2733789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rollback '%s': " 2734789Sahrens "permission denied"), zhp->zfs_name); 2735789Sahrens break; 2736789Sahrens 2737789Sahrens case EDQUOT: 2738789Sahrens case ENOSPC: 2739789Sahrens /* 2740789Sahrens * The parent dataset doesn't have enough space to 2741789Sahrens * rollback to the last snapshot. 2742789Sahrens */ 2743789Sahrens { 2744789Sahrens char parent[ZFS_MAXNAMELEN]; 2745789Sahrens (void) parent_name(zhp->zfs_name, parent, 2746789Sahrens sizeof (parent)); 2747789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 2748789Sahrens "rollback '%s': out of space"), parent); 2749789Sahrens } 2750789Sahrens break; 2751789Sahrens 2752789Sahrens case ENOENT: 2753789Sahrens /* 2754789Sahrens * The dataset doesn't exist. This shouldn't happen 2755789Sahrens * except in race conditions. 2756789Sahrens */ 2757789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rollback '%s': " 2758789Sahrens "no such %s"), zhp->zfs_name, 2759789Sahrens zfs_type_to_name(zhp->zfs_type)); 2760789Sahrens break; 2761789Sahrens 2762789Sahrens case EBUSY: 2763789Sahrens /* 2764789Sahrens * The filesystem is busy. This should have been caught 2765789Sahrens * by the caller before getting here, but there may be 2766789Sahrens * an unexpected problem. 2767789Sahrens */ 2768789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rollback '%s': " 2769789Sahrens "%s is busy"), zhp->zfs_name, 2770789Sahrens zfs_type_to_name(zhp->zfs_type)); 2771789Sahrens break; 2772789Sahrens 2773789Sahrens default: 2774789Sahrens zfs_baderror(errno); 2775789Sahrens } 2776789Sahrens } else if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 2777789Sahrens ret = zvol_create_link(zhp->zfs_name); 2778789Sahrens } 2779789Sahrens 2780789Sahrens return (ret); 2781789Sahrens } 2782789Sahrens 2783789Sahrens /* 27841294Slling * Given a dataset, rollback to a specific snapshot, discarding any 27851294Slling * data changes since then and making it the active dataset. 27861294Slling * 27871294Slling * Any snapshots more recent than the target are destroyed, along with 27881294Slling * their dependents. 27891294Slling */ 27901294Slling int 27911294Slling zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, int flag) 27921294Slling { 27931294Slling int ret; 27941294Slling rollback_data_t cb = { 0 }; 27951294Slling prop_changelist_t *clp; 27961294Slling 27971294Slling /* 27981294Slling * Unmount all dependendents of the dataset and the dataset itself. 27991294Slling * The list we need to gather is the same as for doing rename 28001294Slling */ 28011294Slling clp = changelist_gather(zhp, ZFS_PROP_NAME, flag ? MS_FORCE: 0); 28021294Slling if (clp == NULL) 28031294Slling return (-1); 28041294Slling 28051294Slling if ((ret = changelist_prefix(clp)) != 0) 28061294Slling goto out; 28071294Slling 28081294Slling /* 28091294Slling * Destroy all recent snapshots and its dependends. 28101294Slling */ 28111294Slling cb.cb_target = snap->zfs_name; 28121294Slling cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG); 28131294Slling cb.cb_clp = clp; 28141294Slling (void) zfs_iter_children(zhp, rollback_destroy, &cb); 28151294Slling 28161294Slling if ((ret = cb.cb_error) != 0) { 28171294Slling (void) changelist_postfix(clp); 28181294Slling goto out; 28191294Slling } 28201294Slling 28211294Slling /* 28221294Slling * Now that we have verified that the snapshot is the latest, 28231294Slling * rollback to the given snapshot. 28241294Slling */ 28251294Slling ret = do_rollback(zhp); 28261294Slling 28271294Slling if (ret != 0) { 28281294Slling (void) changelist_postfix(clp); 28291294Slling goto out; 28301294Slling } 28311294Slling 28321294Slling /* 28331294Slling * We only want to re-mount the filesystem if it was mounted in the 28341294Slling * first place. 28351294Slling */ 28361294Slling ret = changelist_postfix(clp); 28371294Slling 28381294Slling out: 28391294Slling changelist_free(clp); 28401294Slling return (ret); 28411294Slling } 28421294Slling 28431294Slling /* 2844789Sahrens * Iterate over all dependents for a given dataset. This includes both 2845789Sahrens * hierarchical dependents (children) and data dependents (snapshots and 2846789Sahrens * clones). The bulk of the processing occurs in get_dependents() in 2847789Sahrens * libzfs_graph.c. 2848789Sahrens */ 2849789Sahrens int 2850789Sahrens zfs_iter_dependents(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2851789Sahrens { 2852789Sahrens char **dependents; 2853789Sahrens size_t count; 2854789Sahrens int i; 2855789Sahrens zfs_handle_t *child; 2856789Sahrens int ret = 0; 2857789Sahrens 2858789Sahrens dependents = get_dependents(zhp->zfs_name, &count); 2859789Sahrens for (i = 0; i < count; i++) { 2860789Sahrens if ((child = make_dataset_handle(dependents[i])) == NULL) 2861789Sahrens continue; 2862789Sahrens 2863789Sahrens if ((ret = func(child, data)) != 0) 2864789Sahrens break; 2865789Sahrens } 2866789Sahrens 2867789Sahrens for (i = 0; i < count; i++) 2868789Sahrens free(dependents[i]); 2869789Sahrens free(dependents); 2870789Sahrens 2871789Sahrens return (ret); 2872789Sahrens } 2873789Sahrens 2874789Sahrens /* 2875789Sahrens * Renames the given dataset. 2876789Sahrens */ 2877789Sahrens int 2878789Sahrens zfs_rename(zfs_handle_t *zhp, const char *target) 2879789Sahrens { 2880789Sahrens int ret; 2881789Sahrens zfs_cmd_t zc = { 0 }; 2882789Sahrens char reason[64]; 2883789Sahrens char *delim; 2884789Sahrens prop_changelist_t *cl; 2885789Sahrens char parent[ZFS_MAXNAMELEN]; 2886789Sahrens 2887789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2888789Sahrens (void) strlcpy(zc.zc_prop_value, target, sizeof (zc.zc_prop_value)); 2889789Sahrens 2890789Sahrens /* if we have the same exact name, just return success */ 2891789Sahrens if (strcmp(zhp->zfs_name, target) == 0) 2892789Sahrens return (0); 2893789Sahrens 2894789Sahrens /* 2895789Sahrens * Make sure the target name is valid 2896789Sahrens */ 2897789Sahrens if (!zfs_validate_name(target, zhp->zfs_type, reason, 2898789Sahrens sizeof (reason))) { 2899789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2900789Sahrens "cannot create '%s': %s in %s name"), target, reason, 2901789Sahrens zfs_type_to_name(zhp->zfs_type)); 2902789Sahrens return (-1); 2903789Sahrens } 2904789Sahrens 2905789Sahrens if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 2906789Sahrens if ((delim = strchr(target, '@')) == NULL) { 2907789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2908789Sahrens "cannot rename to '%s': not a snapshot"), target); 2909789Sahrens return (-1); 2910789Sahrens } 2911789Sahrens 2912789Sahrens /* 2913789Sahrens * Make sure we're renaming within the same dataset. 2914789Sahrens */ 2915789Sahrens if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 2916789Sahrens zhp->zfs_name[delim - target] != '@') { 2917789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2918789Sahrens "cannot rename to '%s': snapshots must be part " 2919789Sahrens "of same dataset"), target); 2920789Sahrens return (-1); 2921789Sahrens } 2922789Sahrens 2923789Sahrens (void) strncpy(parent, target, delim - target); 2924789Sahrens parent[delim - target] = '\0'; 2925789Sahrens } else { 2926789Sahrens /* validate parents */ 2927789Sahrens if (check_parents(target, zhp->zfs_type) != 0) 2928789Sahrens return (-1); 2929789Sahrens 2930789Sahrens (void) parent_name(target, parent, sizeof (parent)); 2931789Sahrens 2932789Sahrens /* make sure we're in the same pool */ 2933789Sahrens verify((delim = strchr(target, '/')) != NULL); 2934789Sahrens if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 2935789Sahrens zhp->zfs_name[delim - target] != '/') { 2936789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2937789Sahrens "cannot rename to '%s': " 2938789Sahrens "datasets must be within same pool"), target); 2939789Sahrens return (-1); 2940789Sahrens } 2941789Sahrens } 2942789Sahrens 2943789Sahrens if (getzoneid() == GLOBAL_ZONEID && 2944789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 2945789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename %s, " 2946789Sahrens "dataset is used in a non-global zone"), zhp->zfs_name); 2947789Sahrens return (-1); 2948789Sahrens } 2949789Sahrens 2950789Sahrens if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0)) == NULL) 2951789Sahrens return (1); 2952789Sahrens 2953789Sahrens if (changelist_haszonedchild(cl)) { 2954789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2955789Sahrens "cannot rename '%s': child dataset with inherited " 2956789Sahrens "mountpoint is used in a non-global zone"), zhp->zfs_name); 2957789Sahrens ret = -1; 2958789Sahrens goto error; 2959789Sahrens } 2960789Sahrens 2961789Sahrens if ((ret = changelist_prefix(cl)) != 0) 2962789Sahrens goto error; 2963789Sahrens 2964789Sahrens if (zhp->zfs_volblocksize != 0) 2965789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2966789Sahrens else 2967789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2968789Sahrens 2969789Sahrens if ((ret = ioctl(zfs_fd, ZFS_IOC_RENAME, &zc)) != 0) { 2970789Sahrens switch (errno) { 2971789Sahrens case EPERM: 2972789Sahrens /* 2973789Sahrens * The user doesn't have permission to rename the 2974789Sahrens * given dataset. 2975789Sahrens */ 2976789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s': " 2977789Sahrens "permission denied"), zhp->zfs_name); 2978789Sahrens break; 2979789Sahrens 2980789Sahrens case EDQUOT: 2981789Sahrens case ENOSPC: 2982789Sahrens /* 2983789Sahrens * Not enough space in the parent dataset. 2984789Sahrens */ 2985789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 2986789Sahrens "rename '%s': not enough space in '%s'"), 2987789Sahrens zhp->zfs_name, parent); 2988789Sahrens break; 2989789Sahrens 2990789Sahrens case ENOENT: 2991789Sahrens /* 2992789Sahrens * The destination doesn't exist. 2993789Sahrens */ 2994789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s' " 2995789Sahrens "to '%s': destination doesn't exist"), 2996789Sahrens zhp->zfs_name, target); 2997789Sahrens break; 2998789Sahrens 2999789Sahrens case EEXIST: 3000789Sahrens /* 3001789Sahrens * The destination already exists. 3002789Sahrens */ 3003789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s' " 3004789Sahrens "to '%s': destination already exists"), 3005789Sahrens zhp->zfs_name, target); 3006789Sahrens break; 3007789Sahrens 3008789Sahrens case EBUSY: 3009789Sahrens /* 3010789Sahrens * The filesystem is busy. This should have been caught 3011789Sahrens * by the caller before getting here, but there may be 3012789Sahrens * an unexpected problem. 3013789Sahrens */ 3014789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s': " 3015789Sahrens "%s is busy"), zhp->zfs_name, 3016789Sahrens zfs_type_to_name(zhp->zfs_type)); 3017789Sahrens break; 3018789Sahrens 3019789Sahrens default: 3020789Sahrens zfs_baderror(errno); 3021789Sahrens } 3022789Sahrens 3023789Sahrens /* 3024789Sahrens * On failure, we still want to remount any filesystems that 3025789Sahrens * were previously mounted, so we don't alter the system state. 3026789Sahrens */ 3027789Sahrens (void) changelist_postfix(cl); 3028789Sahrens } else { 3029789Sahrens changelist_rename(cl, zfs_get_name(zhp), target); 3030789Sahrens 3031789Sahrens ret = changelist_postfix(cl); 3032789Sahrens } 3033789Sahrens 3034789Sahrens error: 3035789Sahrens changelist_free(cl); 3036789Sahrens return (ret); 3037789Sahrens } 3038789Sahrens 3039789Sahrens /* 3040789Sahrens * Given a zvol dataset, issue the ioctl to create the appropriate minor node, 3041789Sahrens * poke devfsadm to create the /dev link, and then wait for the link to appear. 3042789Sahrens */ 3043789Sahrens int 3044789Sahrens zvol_create_link(const char *dataset) 3045789Sahrens { 3046789Sahrens zfs_cmd_t zc = { 0 }; 3047789Sahrens di_devlink_handle_t hdl; 3048789Sahrens 3049789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3050789Sahrens 3051789Sahrens /* 3052789Sahrens * Issue the appropriate ioctl. 3053789Sahrens */ 3054789Sahrens if (ioctl(zfs_fd, ZFS_IOC_CREATE_MINOR, &zc) != 0) { 3055789Sahrens switch (errno) { 3056789Sahrens case EPERM: 3057789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create " 3058789Sahrens "device links for '%s': permission denied"), 3059789Sahrens dataset); 3060789Sahrens break; 3061789Sahrens 3062789Sahrens case EEXIST: 3063789Sahrens /* 3064789Sahrens * Silently ignore the case where the link already 3065789Sahrens * exists. This allows 'zfs volinit' to be run multiple 3066789Sahrens * times without errors. 3067789Sahrens */ 3068789Sahrens return (0); 3069789Sahrens 3070789Sahrens default: 3071789Sahrens zfs_baderror(errno); 3072789Sahrens } 3073789Sahrens 3074789Sahrens return (-1); 3075789Sahrens } 3076789Sahrens 3077789Sahrens /* 3078789Sahrens * Call devfsadm and wait for the links to magically appear. 3079789Sahrens */ 3080789Sahrens if ((hdl = di_devlink_init(ZFS_DRIVER, DI_MAKE_LINK)) == NULL) { 3081789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 3082789Sahrens "cannot create device links for '%s'"), dataset); 3083789Sahrens (void) ioctl(zfs_fd, ZFS_IOC_REMOVE_MINOR, &zc); 3084789Sahrens return (-1); 3085789Sahrens } else { 3086789Sahrens (void) di_devlink_fini(&hdl); 3087789Sahrens } 3088789Sahrens 3089789Sahrens return (0); 3090789Sahrens } 3091789Sahrens 3092789Sahrens /* 3093789Sahrens * Remove a minor node for the given zvol and the associated /dev links. 3094789Sahrens */ 3095789Sahrens int 3096789Sahrens zvol_remove_link(const char *dataset) 3097789Sahrens { 3098789Sahrens zfs_cmd_t zc = { 0 }; 3099789Sahrens 3100789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3101789Sahrens 3102789Sahrens if (ioctl(zfs_fd, ZFS_IOC_REMOVE_MINOR, &zc) != 0) { 3103789Sahrens switch (errno) { 3104789Sahrens case EPERM: 3105789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot remove " 3106789Sahrens "device links for '%s': permission denied"), 3107789Sahrens dataset); 3108789Sahrens break; 3109789Sahrens 3110789Sahrens case EBUSY: 3111789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot remove " 3112789Sahrens "device links for '%s': volume is in use"), 3113789Sahrens dataset); 3114789Sahrens break; 3115789Sahrens 3116789Sahrens case ENXIO: 3117789Sahrens /* 3118789Sahrens * Silently ignore the case where the link no longer 3119789Sahrens * exists, so that 'zfs volfini' can be run multiple 3120789Sahrens * times without errors. 3121789Sahrens */ 3122789Sahrens return (0); 3123789Sahrens 3124789Sahrens default: 3125789Sahrens zfs_baderror(errno); 3126789Sahrens } 3127789Sahrens 3128789Sahrens return (-1); 3129789Sahrens } 3130789Sahrens 3131789Sahrens return (0); 3132789Sahrens } 3133