1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 221294Slling * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <assert.h> 29789Sahrens #include <ctype.h> 30789Sahrens #include <errno.h> 31789Sahrens #include <libdevinfo.h> 32789Sahrens #include <libintl.h> 33789Sahrens #include <math.h> 34789Sahrens #include <stdio.h> 35789Sahrens #include <stdlib.h> 36789Sahrens #include <strings.h> 37789Sahrens #include <unistd.h> 38789Sahrens #include <zone.h> 39789Sahrens #include <sys/mntent.h> 40789Sahrens #include <sys/mnttab.h> 411294Slling #include <sys/mount.h> 42789Sahrens 43789Sahrens #include <sys/spa.h> 44789Sahrens #include <sys/zio.h> 45789Sahrens #include <libzfs.h> 46789Sahrens 47789Sahrens #include "zfs_namecheck.h" 48789Sahrens #include "zfs_prop.h" 49789Sahrens #include "libzfs_impl.h" 50789Sahrens 51789Sahrens /* 52789Sahrens * Given a single type (not a mask of types), return the type in a human 53789Sahrens * readable form. 54789Sahrens */ 55789Sahrens const char * 56789Sahrens zfs_type_to_name(zfs_type_t type) 57789Sahrens { 58789Sahrens switch (type) { 59789Sahrens case ZFS_TYPE_FILESYSTEM: 60789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 61789Sahrens case ZFS_TYPE_SNAPSHOT: 62789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 63789Sahrens case ZFS_TYPE_VOLUME: 64789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 65789Sahrens } 66789Sahrens 67789Sahrens zfs_baderror(type); 68789Sahrens return (NULL); 69789Sahrens } 70789Sahrens 71789Sahrens /* 72789Sahrens * Given a path and mask of ZFS types, return a string describing this dataset. 73789Sahrens * This is used when we fail to open a dataset and we cannot get an exact type. 74789Sahrens * We guess what the type would have been based on the path and the mask of 75789Sahrens * acceptable types. 76789Sahrens */ 77789Sahrens static const char * 78789Sahrens path_to_str(const char *path, int types) 79789Sahrens { 80789Sahrens /* 81789Sahrens * When given a single type, always report the exact type. 82789Sahrens */ 83789Sahrens if (types == ZFS_TYPE_SNAPSHOT) 84789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 85789Sahrens if (types == ZFS_TYPE_FILESYSTEM) 86789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 87789Sahrens if (types == ZFS_TYPE_VOLUME) 88789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 89789Sahrens 90789Sahrens /* 91789Sahrens * The user is requesting more than one type of dataset. If this is the 92789Sahrens * case, consult the path itself. If we're looking for a snapshot, and 93789Sahrens * a '@' is found, then report it as "snapshot". Otherwise, remove the 94789Sahrens * snapshot attribute and try again. 95789Sahrens */ 96789Sahrens if (types & ZFS_TYPE_SNAPSHOT) { 97789Sahrens if (strchr(path, '@') != NULL) 98789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 99789Sahrens return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 100789Sahrens } 101789Sahrens 102789Sahrens 103789Sahrens /* 104789Sahrens * The user has requested either filesystems or volumes. 105789Sahrens * We have no way of knowing a priori what type this would be, so always 106789Sahrens * report it as "filesystem" or "volume", our two primitive types. 107789Sahrens */ 108789Sahrens if (types & ZFS_TYPE_FILESYSTEM) 109789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 110789Sahrens 111789Sahrens assert(types & ZFS_TYPE_VOLUME); 112789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 113789Sahrens } 114789Sahrens 115789Sahrens /* 116789Sahrens * Validate a ZFS path. This is used even before trying to open the dataset, to 117789Sahrens * provide a more meaningful error message. We place a more useful message in 118789Sahrens * 'buf' detailing exactly why the name was not valid. 119789Sahrens */ 120789Sahrens static int 121789Sahrens zfs_validate_name(const char *path, int type, char *buf, size_t buflen) 122789Sahrens { 123789Sahrens namecheck_err_t why; 124789Sahrens char what; 125789Sahrens 126789Sahrens if (dataset_namecheck(path, &why, &what) != 0) { 127789Sahrens if (buf != NULL) { 128789Sahrens switch (why) { 1291003Slling case NAME_ERR_TOOLONG: 1301003Slling (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 1311003Slling "name is too long"), buflen); 1321003Slling break; 1331003Slling 134789Sahrens case NAME_ERR_LEADING_SLASH: 135789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 136789Sahrens "leading slash"), buflen); 137789Sahrens break; 138789Sahrens 139789Sahrens case NAME_ERR_EMPTY_COMPONENT: 140789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 141789Sahrens "empty component"), buflen); 142789Sahrens break; 143789Sahrens 144789Sahrens case NAME_ERR_TRAILING_SLASH: 145789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 146789Sahrens "trailing slash"), buflen); 147789Sahrens break; 148789Sahrens 149789Sahrens case NAME_ERR_INVALCHAR: 150789Sahrens (void) snprintf(buf, buflen, 151789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 152789Sahrens "'%c'"), what); 153789Sahrens break; 154789Sahrens 155789Sahrens case NAME_ERR_MULTIPLE_AT: 156789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 157789Sahrens "multiple '@' delimiters"), buflen); 158789Sahrens break; 159789Sahrens } 160789Sahrens } 161789Sahrens 162789Sahrens return (0); 163789Sahrens } 164789Sahrens 165789Sahrens if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) { 166789Sahrens if (buf != NULL) 167789Sahrens (void) strlcpy(buf, 168789Sahrens dgettext(TEXT_DOMAIN, 169789Sahrens "snapshot delimiter '@'"), buflen); 170789Sahrens return (0); 171789Sahrens } 172789Sahrens 173789Sahrens return (1); 174789Sahrens } 175789Sahrens 176789Sahrens int 177789Sahrens zfs_name_valid(const char *name, zfs_type_t type) 178789Sahrens { 179789Sahrens return (zfs_validate_name(name, type, NULL, NULL)); 180789Sahrens } 181789Sahrens 182789Sahrens /* 183789Sahrens * Utility function to gather stats (objset and zpl) for the given object. 184789Sahrens */ 185789Sahrens static int 186789Sahrens get_stats(zfs_handle_t *zhp) 187789Sahrens { 188789Sahrens zfs_cmd_t zc = { 0 }; 189789Sahrens 190789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 191789Sahrens 1921356Seschrock zc.zc_config_src = (uint64_t)(uintptr_t)zfs_malloc(1024); 1931356Seschrock zc.zc_config_src_size = 1024; 1941356Seschrock 1951544Seschrock while (zfs_ioctl(ZFS_IOC_OBJSET_STATS, &zc) != 0) { 1961356Seschrock if (errno == ENOMEM) { 1971356Seschrock zc.zc_config_src = (uint64_t)(uintptr_t) 1981356Seschrock zfs_malloc(zc.zc_config_src_size); 1991356Seschrock } else { 2001356Seschrock free((void *)(uintptr_t)zc.zc_config_src); 2011356Seschrock return (-1); 2021356Seschrock } 2031356Seschrock } 204789Sahrens 205789Sahrens bcopy(&zc.zc_objset_stats, &zhp->zfs_dmustats, 206789Sahrens sizeof (zc.zc_objset_stats)); 207789Sahrens 2081544Seschrock (void) strcpy(zhp->zfs_root, zc.zc_root); 2091544Seschrock 2101356Seschrock verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_src, 2111356Seschrock zc.zc_config_src_size, &zhp->zfs_props, 0) == 0); 212789Sahrens 213789Sahrens zhp->zfs_volsize = zc.zc_volsize; 214789Sahrens zhp->zfs_volblocksize = zc.zc_volblocksize; 215789Sahrens 216789Sahrens return (0); 217789Sahrens } 218789Sahrens 219789Sahrens /* 220789Sahrens * Refresh the properties currently stored in the handle. 221789Sahrens */ 222789Sahrens void 223789Sahrens zfs_refresh_properties(zfs_handle_t *zhp) 224789Sahrens { 225789Sahrens (void) get_stats(zhp); 226789Sahrens } 227789Sahrens 228789Sahrens /* 229789Sahrens * Makes a handle from the given dataset name. Used by zfs_open() and 230789Sahrens * zfs_iter_* to create child handles on the fly. 231789Sahrens */ 232789Sahrens zfs_handle_t * 233789Sahrens make_dataset_handle(const char *path) 234789Sahrens { 235789Sahrens zfs_handle_t *zhp = zfs_malloc(sizeof (zfs_handle_t)); 236789Sahrens 237*1758Sahrens top: 238789Sahrens (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); 239789Sahrens 240789Sahrens if (get_stats(zhp) != 0) { 241789Sahrens free(zhp); 242789Sahrens return (NULL); 243789Sahrens } 244789Sahrens 245*1758Sahrens if (zhp->zfs_dmustats.dds_inconsistent) { 246*1758Sahrens zfs_cmd_t zc = { 0 }; 247*1758Sahrens int err; 248*1758Sahrens 249*1758Sahrens /* 250*1758Sahrens * If it is dds_inconsistent, then we've caught it in 251*1758Sahrens * the middle of a 'zfs receive' or 'zfs destroy', and 252*1758Sahrens * it is inconsistent from the ZPL's point of view, so 253*1758Sahrens * can't be mounted. However, it could also be that we 254*1758Sahrens * have crashed in the middle of one of those 255*1758Sahrens * operations, in which case we need to get rid of the 256*1758Sahrens * inconsistent state. We do that by either rolling 257*1758Sahrens * back to the previous snapshot (which will fail if 258*1758Sahrens * there is none), or destroying the filesystem. Note 259*1758Sahrens * that if we are still in the middle of an active 260*1758Sahrens * 'receive' or 'destroy', then the rollback and destroy 261*1758Sahrens * will fail with EBUSY and we will drive on as usual. 262*1758Sahrens */ 263*1758Sahrens 264*1758Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 265*1758Sahrens 266*1758Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 267*1758Sahrens (void) zvol_remove_link(zhp->zfs_name); 268*1758Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 269*1758Sahrens } else { 270*1758Sahrens zc.zc_objset_type = DMU_OST_ZFS; 271*1758Sahrens } 272*1758Sahrens 273*1758Sahrens /* If we can successfully roll it back, reget the stats */ 274*1758Sahrens if (zfs_ioctl(ZFS_IOC_ROLLBACK, &zc) == 0) 275*1758Sahrens goto top; 276*1758Sahrens /* 277*1758Sahrens * If we can sucessfully destroy it, pretend that it 278*1758Sahrens * never existed. 279*1758Sahrens */ 280*1758Sahrens if (zfs_ioctl(ZFS_IOC_DESTROY, &zc) == 0) { 281*1758Sahrens free(zhp); 282*1758Sahrens errno = ENOENT; 283*1758Sahrens return (NULL); 284*1758Sahrens } 285*1758Sahrens } 286*1758Sahrens 287789Sahrens /* 288789Sahrens * We've managed to open the dataset and gather statistics. Determine 289789Sahrens * the high-level type. 290789Sahrens */ 291789Sahrens if (zhp->zfs_dmustats.dds_is_snapshot) 292789Sahrens zhp->zfs_type = ZFS_TYPE_SNAPSHOT; 293789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 294789Sahrens zhp->zfs_type = ZFS_TYPE_VOLUME; 295789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 296789Sahrens zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 297789Sahrens else 298789Sahrens /* we should never see any other dataset types */ 299789Sahrens zfs_baderror(zhp->zfs_dmustats.dds_type); 300789Sahrens 301789Sahrens return (zhp); 302789Sahrens } 303789Sahrens 304789Sahrens /* 305789Sahrens * Opens the given snapshot, filesystem, or volume. The 'types' 306789Sahrens * argument is a mask of acceptable types. The function will print an 307789Sahrens * appropriate error message and return NULL if it can't be opened. 308789Sahrens */ 309789Sahrens zfs_handle_t * 310789Sahrens zfs_open(const char *path, int types) 311789Sahrens { 312789Sahrens zfs_handle_t *zhp; 313789Sahrens 314789Sahrens /* 315789Sahrens * Validate the name before we even try to open it. We don't care about 316789Sahrens * the verbose invalid messages here; just report a generic error. 317789Sahrens */ 318789Sahrens if (!zfs_validate_name(path, types, NULL, 0)) { 319789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 320789Sahrens "cannot open '%s': invalid %s name"), path, 321789Sahrens path_to_str(path, types)); 322789Sahrens return (NULL); 323789Sahrens } 324789Sahrens 325789Sahrens /* 326789Sahrens * Try to get stats for the dataset, which will tell us if it exists. 327789Sahrens */ 328789Sahrens errno = 0; 329789Sahrens if ((zhp = make_dataset_handle(path)) == NULL) { 330789Sahrens switch (errno) { 331789Sahrens case ENOENT: 332789Sahrens /* 333789Sahrens * The dataset doesn't exist. 334789Sahrens */ 335789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 336789Sahrens "cannot open '%s': no such %s"), path, 337789Sahrens path_to_str(path, types)); 338789Sahrens break; 339789Sahrens 340789Sahrens case EBUSY: 341789Sahrens /* 342789Sahrens * We were able to open the dataset but couldn't 343789Sahrens * get the stats. 344789Sahrens */ 345789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 346789Sahrens "cannot open '%s': %s is busy"), path, 347789Sahrens path_to_str(path, types)); 348789Sahrens break; 349789Sahrens 3501544Seschrock case ENXIO: 3511544Seschrock case EIO: 3521544Seschrock /* 3531544Seschrock * I/O error from the underlying pool. 3541544Seschrock */ 3551544Seschrock zfs_error(dgettext(TEXT_DOMAIN, 3561544Seschrock "cannot open '%s': I/O error"), path, 3571544Seschrock path_to_str(path, types)); 3581544Seschrock break; 3591544Seschrock 360789Sahrens default: 361789Sahrens zfs_baderror(errno); 362789Sahrens 363789Sahrens } 364789Sahrens return (NULL); 365789Sahrens } 366789Sahrens 367789Sahrens if (!(types & zhp->zfs_type)) { 368789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': operation " 369789Sahrens "not supported for %ss"), path, 370789Sahrens zfs_type_to_name(zhp->zfs_type)); 371789Sahrens free(zhp); 372789Sahrens return (NULL); 373789Sahrens } 374789Sahrens 375789Sahrens return (zhp); 376789Sahrens } 377789Sahrens 378789Sahrens /* 379789Sahrens * Release a ZFS handle. Nothing to do but free the associated memory. 380789Sahrens */ 381789Sahrens void 382789Sahrens zfs_close(zfs_handle_t *zhp) 383789Sahrens { 384789Sahrens if (zhp->zfs_mntopts) 385789Sahrens free(zhp->zfs_mntopts); 386789Sahrens free(zhp); 387789Sahrens } 388789Sahrens 389789Sahrens struct { 390789Sahrens const char *name; 391789Sahrens uint64_t value; 392789Sahrens } checksum_table[] = { 393789Sahrens { "on", ZIO_CHECKSUM_ON }, 394789Sahrens { "off", ZIO_CHECKSUM_OFF }, 395789Sahrens { "fletcher2", ZIO_CHECKSUM_FLETCHER_2 }, 396789Sahrens { "fletcher4", ZIO_CHECKSUM_FLETCHER_4 }, 397789Sahrens { "sha256", ZIO_CHECKSUM_SHA256 }, 398789Sahrens { NULL } 399789Sahrens }; 400789Sahrens 401789Sahrens struct { 402789Sahrens const char *name; 403789Sahrens uint64_t value; 404789Sahrens } compress_table[] = { 405789Sahrens { "on", ZIO_COMPRESS_ON }, 406789Sahrens { "off", ZIO_COMPRESS_OFF }, 407789Sahrens { "lzjb", ZIO_COMPRESS_LZJB }, 408789Sahrens { NULL } 409789Sahrens }; 410789Sahrens 411789Sahrens struct { 412789Sahrens const char *name; 413789Sahrens uint64_t value; 414789Sahrens } snapdir_table[] = { 415849Sbonwick { "hidden", ZFS_SNAPDIR_HIDDEN }, 416849Sbonwick { "visible", ZFS_SNAPDIR_VISIBLE }, 417789Sahrens { NULL } 418789Sahrens }; 419789Sahrens 420789Sahrens struct { 421789Sahrens const char *name; 422789Sahrens uint64_t value; 423789Sahrens } acl_mode_table[] = { 424789Sahrens { "discard", DISCARD }, 425789Sahrens { "groupmask", GROUPMASK }, 426789Sahrens { "passthrough", PASSTHROUGH }, 427789Sahrens { NULL } 428789Sahrens }; 429789Sahrens 430789Sahrens struct { 431789Sahrens const char *name; 432789Sahrens uint64_t value; 433789Sahrens } acl_inherit_table[] = { 434789Sahrens { "discard", DISCARD }, 435789Sahrens { "noallow", NOALLOW }, 436789Sahrens { "secure", SECURE }, 437789Sahrens { "passthrough", PASSTHROUGH }, 438789Sahrens { NULL } 439789Sahrens }; 440789Sahrens 441789Sahrens 442789Sahrens /* 443789Sahrens * Given a numeric suffix, convert the value into a number of bits that the 444789Sahrens * resulting value must be shifted. 445789Sahrens */ 446789Sahrens static int 447789Sahrens str2shift(const char *buf, char *reason, size_t len) 448789Sahrens { 449789Sahrens const char *ends = "BKMGTPEZ"; 450789Sahrens int i; 451789Sahrens 452789Sahrens if (buf[0] == '\0') 453789Sahrens return (0); 454789Sahrens for (i = 0; i < strlen(ends); i++) { 455789Sahrens if (toupper(buf[0]) == ends[i]) 456789Sahrens break; 457789Sahrens } 458789Sahrens if (i == strlen(ends)) { 459789Sahrens (void) snprintf(reason, len, dgettext(TEXT_DOMAIN, "invalid " 460789Sahrens "numeric suffix '%s'"), buf); 461789Sahrens return (-1); 462789Sahrens } 463789Sahrens 464789Sahrens /* 465789Sahrens * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 466789Sahrens * allow 'BB' - that's just weird. 467789Sahrens */ 468789Sahrens if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 469789Sahrens toupper(buf[0]) != 'B')) { 470789Sahrens return (10*i); 471789Sahrens } 472789Sahrens 473789Sahrens (void) snprintf(reason, len, dgettext(TEXT_DOMAIN, "invalid numeric " 474789Sahrens "suffix '%s'"), buf); 475789Sahrens return (-1); 476789Sahrens } 477789Sahrens 478789Sahrens /* 479789Sahrens * Convert a string of the form '100G' into a real number. Used when setting 480789Sahrens * properties or creating a volume. 'buf' is used to place an extended error 481789Sahrens * message for the caller to use. 482789Sahrens */ 483789Sahrens static int 484789Sahrens nicestrtonum(const char *value, uint64_t *num, char *buf, size_t buflen) 485789Sahrens { 486789Sahrens char *end; 487789Sahrens int shift; 488789Sahrens 489789Sahrens *num = 0; 490789Sahrens 491789Sahrens /* Check to see if this looks like a number. */ 492789Sahrens if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 493789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 494789Sahrens "must be a numeric value"), buflen); 495789Sahrens return (-1); 496789Sahrens } 497789Sahrens 498789Sahrens /* Rely on stroll() to process the numeric portion. */ 499789Sahrens errno = 0; 500789Sahrens *num = strtoll(value, &end, 10); 501789Sahrens 502789Sahrens /* 503789Sahrens * Check for ERANGE, which indicates that the value is too large to fit 504789Sahrens * in a 64-bit value. 505789Sahrens */ 506789Sahrens if (errno == ERANGE) { 507789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 508789Sahrens "value is too large"), buflen); 509789Sahrens return (-1); 510789Sahrens } 511789Sahrens 512789Sahrens /* 513789Sahrens * If we have a decimal value, then do the computation with floating 514789Sahrens * point arithmetic. Otherwise, use standard arithmetic. 515789Sahrens */ 516789Sahrens if (*end == '.') { 517789Sahrens double fval = strtod(value, &end); 518789Sahrens 519789Sahrens if ((shift = str2shift(end, buf, buflen)) == -1) 520789Sahrens return (-1); 521789Sahrens 522789Sahrens fval *= pow(2, shift); 523789Sahrens 524789Sahrens if (fval > UINT64_MAX) { 525789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 526789Sahrens "value is too large"), buflen); 527789Sahrens return (-1); 528789Sahrens } 529789Sahrens 530789Sahrens *num = (uint64_t)fval; 531789Sahrens } else { 532789Sahrens if ((shift = str2shift(end, buf, buflen)) == -1) 533789Sahrens return (-1); 534789Sahrens 535789Sahrens /* Check for overflow */ 536789Sahrens if (shift >= 64 || (*num << shift) >> shift != *num) { 537789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 538789Sahrens "value is too large"), buflen); 539789Sahrens return (-1); 540789Sahrens } 541789Sahrens 542789Sahrens *num <<= shift; 543789Sahrens } 544789Sahrens 545789Sahrens return (0); 546789Sahrens } 547789Sahrens 548789Sahrens int 549789Sahrens zfs_nicestrtonum(const char *str, uint64_t *val) 550789Sahrens { 551789Sahrens char buf[1]; 552789Sahrens 553789Sahrens return (nicestrtonum(str, val, buf, sizeof (buf))); 554789Sahrens } 555789Sahrens 556789Sahrens /* 557789Sahrens * Given a property type and value, verify that the value is appropriate. Used 558789Sahrens * by zfs_prop_set() and some libzfs consumers. 559789Sahrens */ 560789Sahrens int 561789Sahrens zfs_prop_validate(zfs_prop_t prop, const char *value, uint64_t *intval) 562789Sahrens { 563789Sahrens const char *propname = zfs_prop_to_name(prop); 564789Sahrens uint64_t number; 565789Sahrens char reason[64]; 566789Sahrens int i; 567789Sahrens 568789Sahrens /* 569789Sahrens * Check to see if this a read-only property. 570789Sahrens */ 571789Sahrens if (zfs_prop_readonly(prop)) { 572789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 573789Sahrens "cannot set %s property: read-only property"), propname); 574789Sahrens return (-1); 575789Sahrens } 576789Sahrens 577789Sahrens /* See if the property value is too long */ 578789Sahrens if (strlen(value) >= ZFS_MAXPROPLEN) { 579789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 580789Sahrens "bad %s value '%s': value is too long"), propname, 581789Sahrens value); 582789Sahrens return (-1); 583789Sahrens } 584789Sahrens 585789Sahrens /* Perform basic checking based on property type */ 586789Sahrens switch (zfs_prop_get_type(prop)) { 587789Sahrens case prop_type_boolean: 588789Sahrens if (strcmp(value, "on") == 0) { 589789Sahrens number = 1; 590789Sahrens } else if (strcmp(value, "off") == 0) { 591789Sahrens number = 0; 592789Sahrens } else { 593789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 594789Sahrens "bad %s value '%s': must be 'on' or 'off'"), 595789Sahrens propname, value); 596789Sahrens return (-1); 597789Sahrens } 598789Sahrens break; 599789Sahrens 600789Sahrens case prop_type_number: 601789Sahrens /* treat 'none' as 0 */ 602789Sahrens if (strcmp(value, "none") == 0) { 603789Sahrens number = 0; 604789Sahrens break; 605789Sahrens } 606789Sahrens 607789Sahrens if (nicestrtonum(value, &number, reason, 608789Sahrens sizeof (reason)) != 0) { 609789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 610789Sahrens "bad %s value '%s': %s"), propname, value, 611789Sahrens reason); 612789Sahrens return (-1); 613789Sahrens } 614789Sahrens 615789Sahrens /* don't allow 0 for quota, use 'none' instead */ 616789Sahrens if (prop == ZFS_PROP_QUOTA && number == 0 && 617789Sahrens strcmp(value, "none") != 0) { 618789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 619789Sahrens "bad %s value '%s': use '%s=none' to disable"), 620789Sahrens propname, value, propname); 621789Sahrens return (-1); 622789Sahrens } 623789Sahrens 624789Sahrens /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */ 625789Sahrens if (prop == ZFS_PROP_RECORDSIZE || 626789Sahrens prop == ZFS_PROP_VOLBLOCKSIZE) { 627789Sahrens if (number < SPA_MINBLOCKSIZE || 628789Sahrens number > SPA_MAXBLOCKSIZE || !ISP2(number)) { 629789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 630789Sahrens "bad %s value '%s': " 631789Sahrens "must be power of 2 from %u to %uk"), 632789Sahrens propname, value, 633789Sahrens (uint_t)SPA_MINBLOCKSIZE, 634789Sahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 635789Sahrens return (-1); 636789Sahrens } 637789Sahrens } 638789Sahrens 639789Sahrens break; 640789Sahrens 641789Sahrens case prop_type_string: 642789Sahrens case prop_type_index: 643789Sahrens /* 644789Sahrens * The two writable string values, 'mountpoint' and 645789Sahrens * 'checksum' need special consideration. The 'index' types are 646789Sahrens * specified as strings by the user, but passed to the kernel as 647789Sahrens * integers. 648789Sahrens */ 649789Sahrens switch (prop) { 650789Sahrens case ZFS_PROP_MOUNTPOINT: 651789Sahrens if (strcmp(value, ZFS_MOUNTPOINT_NONE) == 0 || 652789Sahrens strcmp(value, ZFS_MOUNTPOINT_LEGACY) == 0) 653789Sahrens break; 654789Sahrens 655789Sahrens if (value[0] != '/') { 656789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 657789Sahrens "bad %s value '%s': must be an absolute " 658789Sahrens "path, 'none', or 'legacy'"), 659789Sahrens propname, value); 660789Sahrens return (-1); 661789Sahrens } 662789Sahrens break; 663789Sahrens 664789Sahrens case ZFS_PROP_CHECKSUM: 665789Sahrens for (i = 0; checksum_table[i].name != NULL; i++) { 666789Sahrens if (strcmp(value, checksum_table[i].name) 667789Sahrens == 0) { 668789Sahrens number = checksum_table[i].value; 669789Sahrens break; 670789Sahrens } 671789Sahrens } 672789Sahrens 673789Sahrens if (checksum_table[i].name == NULL) { 674789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 675789Sahrens "bad %s value '%s': must be 'on', 'off', " 676789Sahrens "'fletcher2', 'fletcher4', or 'sha256'"), 677789Sahrens propname, value); 678789Sahrens return (-1); 679789Sahrens } 680789Sahrens break; 681789Sahrens 682789Sahrens case ZFS_PROP_COMPRESSION: 683789Sahrens for (i = 0; compress_table[i].name != NULL; i++) { 684789Sahrens if (strcmp(value, compress_table[i].name) 685789Sahrens == 0) { 686789Sahrens number = compress_table[i].value; 687789Sahrens break; 688789Sahrens } 689789Sahrens } 690789Sahrens 691789Sahrens if (compress_table[i].name == NULL) { 692789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 693789Sahrens "bad %s value '%s': must be 'on', 'off', " 694789Sahrens "or 'lzjb'"), 695789Sahrens propname, value); 696789Sahrens return (-1); 697789Sahrens } 698789Sahrens break; 699789Sahrens 700789Sahrens case ZFS_PROP_SNAPDIR: 701789Sahrens for (i = 0; snapdir_table[i].name != NULL; i++) { 702789Sahrens if (strcmp(value, snapdir_table[i].name) == 0) { 703789Sahrens number = snapdir_table[i].value; 704789Sahrens break; 705789Sahrens } 706789Sahrens } 707789Sahrens 708789Sahrens if (snapdir_table[i].name == NULL) { 709789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 710789Sahrens "bad %s value '%s': must be 'hidden' " 711789Sahrens "or 'visible'"), 712789Sahrens propname, value); 713789Sahrens return (-1); 714789Sahrens } 715789Sahrens break; 716789Sahrens 717789Sahrens case ZFS_PROP_ACLMODE: 718789Sahrens for (i = 0; acl_mode_table[i].name != NULL; i++) { 719789Sahrens if (strcmp(value, acl_mode_table[i].name) 720789Sahrens == 0) { 721789Sahrens number = acl_mode_table[i].value; 722789Sahrens break; 723789Sahrens } 724789Sahrens } 725789Sahrens 726789Sahrens if (acl_mode_table[i].name == NULL) { 727789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 728789Sahrens "bad %s value '%s': must be 'discard', " 729789Sahrens "'groupmask' or 'passthrough'"), 730789Sahrens propname, value); 731789Sahrens return (-1); 732789Sahrens } 733789Sahrens break; 734789Sahrens 735789Sahrens case ZFS_PROP_ACLINHERIT: 736789Sahrens for (i = 0; acl_inherit_table[i].name != NULL; i++) { 737789Sahrens if (strcmp(value, acl_inherit_table[i].name) 738789Sahrens == 0) { 739789Sahrens number = acl_inherit_table[i].value; 740789Sahrens break; 741789Sahrens } 742789Sahrens } 743789Sahrens 744789Sahrens if (acl_inherit_table[i].name == NULL) { 745789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 746789Sahrens "bad %s value '%s': must be 'discard', " 747905Smarks "'noallow', 'secure' or 'passthrough'"), 748789Sahrens propname, value); 749789Sahrens return (-1); 750789Sahrens } 751789Sahrens break; 752789Sahrens 753789Sahrens case ZFS_PROP_SHARENFS: 754789Sahrens /* 755789Sahrens * Nothing to do for 'sharenfs', this gets passed on to 756789Sahrens * share(1M) verbatim. 757789Sahrens */ 758789Sahrens break; 759789Sahrens } 760789Sahrens } 761789Sahrens 762789Sahrens if (intval != NULL) 763789Sahrens *intval = number; 764789Sahrens 765789Sahrens return (0); 766789Sahrens } 767789Sahrens 768789Sahrens /* 769789Sahrens * Given a property name and value, set the property for the given dataset. 770789Sahrens */ 771789Sahrens int 772789Sahrens zfs_prop_set(zfs_handle_t *zhp, zfs_prop_t prop, const char *propval) 773789Sahrens { 774789Sahrens const char *propname = zfs_prop_to_name(prop); 775789Sahrens uint64_t number; 776789Sahrens zfs_cmd_t zc = { 0 }; 777789Sahrens int ret; 778789Sahrens prop_changelist_t *cl; 779789Sahrens 780789Sahrens if (zfs_prop_validate(prop, propval, &number) != 0) 781789Sahrens return (-1); 782789Sahrens 783789Sahrens /* 784789Sahrens * Check to see if the value applies to this type 785789Sahrens */ 786789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) { 787789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 788789Sahrens "cannot set %s for '%s': property does not apply to %ss"), 789789Sahrens propname, zhp->zfs_name, zfs_type_to_name(zhp->zfs_type)); 790789Sahrens return (-1); 791789Sahrens } 792789Sahrens 793789Sahrens /* 794789Sahrens * For the mountpoint and sharenfs properties, check if it can be set 795789Sahrens * in a global/non-global zone based on the zoned property value: 796789Sahrens * 797789Sahrens * global zone non-global zone 798789Sahrens * ----------------------------------------------------- 799789Sahrens * zoned=on mountpoint (no) mountpoint (yes) 800789Sahrens * sharenfs (no) sharenfs (no) 801789Sahrens * 802789Sahrens * zoned=off mountpoint (yes) N/A 803789Sahrens * sharenfs (yes) 804789Sahrens */ 805789Sahrens if (prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS) { 806789Sahrens if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 807789Sahrens if (getzoneid() == GLOBAL_ZONEID) { 808789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 8091133Seschrock "cannot set %s for '%s': " 810789Sahrens "dataset is used in a non-global zone"), 811789Sahrens propname, zhp->zfs_name); 812789Sahrens return (-1); 813789Sahrens } else if (prop == ZFS_PROP_SHARENFS) { 814789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 8151133Seschrock "cannot set %s for '%s': filesystems " 816789Sahrens "cannot be shared in a non-global zone"), 817789Sahrens propname, zhp->zfs_name); 818789Sahrens return (-1); 819789Sahrens } 820789Sahrens } else if (getzoneid() != GLOBAL_ZONEID) { 821789Sahrens /* 822789Sahrens * If zoned property is 'off', this must be in 823789Sahrens * a globle zone. If not, something is wrong. 824789Sahrens */ 825789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 8261133Seschrock "cannot set %s for '%s': dataset is " 827789Sahrens "used in a non-global zone, but 'zoned' " 828789Sahrens "property is not set"), 829789Sahrens propname, zhp->zfs_name); 830789Sahrens return (-1); 831789Sahrens } 832789Sahrens } 833789Sahrens 834789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 835789Sahrens return (-1); 836789Sahrens 837789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 838789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s for '%s', " 839789Sahrens "child dataset with inherited mountpoint is used " 840789Sahrens "in a non-global zone"), 841789Sahrens propname, zhp->zfs_name); 842789Sahrens ret = -1; 843789Sahrens goto error; 844789Sahrens } 845789Sahrens 846789Sahrens if ((ret = changelist_prefix(cl)) != 0) 847789Sahrens goto error; 848789Sahrens 849789Sahrens /* 850789Sahrens * Execute the corresponding ioctl() to set this property. 851789Sahrens */ 852789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 853789Sahrens 854789Sahrens switch (prop) { 855789Sahrens case ZFS_PROP_QUOTA: 856789Sahrens zc.zc_cookie = number; 8571544Seschrock ret = zfs_ioctl(ZFS_IOC_SET_QUOTA, &zc); 858789Sahrens break; 859789Sahrens case ZFS_PROP_RESERVATION: 860789Sahrens zc.zc_cookie = number; 8611544Seschrock ret = zfs_ioctl(ZFS_IOC_SET_RESERVATION, &zc); 862789Sahrens break; 863789Sahrens case ZFS_PROP_MOUNTPOINT: 864789Sahrens case ZFS_PROP_SHARENFS: 865789Sahrens /* 866789Sahrens * These properties are passed down as real strings. 867789Sahrens */ 868789Sahrens (void) strlcpy(zc.zc_prop_name, propname, 869789Sahrens sizeof (zc.zc_prop_name)); 870789Sahrens (void) strlcpy(zc.zc_prop_value, propval, 871789Sahrens sizeof (zc.zc_prop_value)); 872789Sahrens zc.zc_intsz = 1; 873789Sahrens zc.zc_numints = strlen(propval) + 1; 8741544Seschrock ret = zfs_ioctl(ZFS_IOC_SET_PROP, &zc); 875789Sahrens break; 876789Sahrens case ZFS_PROP_VOLSIZE: 877789Sahrens zc.zc_volsize = number; 8781544Seschrock ret = zfs_ioctl(ZFS_IOC_SET_VOLSIZE, &zc); 879789Sahrens break; 880789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 881789Sahrens zc.zc_volblocksize = number; 8821544Seschrock ret = zfs_ioctl(ZFS_IOC_SET_VOLBLOCKSIZE, &zc); 883789Sahrens break; 884789Sahrens default: 885789Sahrens (void) strlcpy(zc.zc_prop_name, propname, 886789Sahrens sizeof (zc.zc_prop_name)); 887789Sahrens /* LINTED - alignment */ 888789Sahrens *(uint64_t *)zc.zc_prop_value = number; 889789Sahrens zc.zc_intsz = 8; 890789Sahrens zc.zc_numints = 1; 8911544Seschrock ret = zfs_ioctl(ZFS_IOC_SET_PROP, &zc); 892789Sahrens break; 893789Sahrens } 894789Sahrens 895789Sahrens if (ret != 0) { 896789Sahrens switch (errno) { 897789Sahrens 898789Sahrens case EPERM: 899789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 900789Sahrens "cannot set %s for '%s': permission " 901789Sahrens "denied"), propname, zhp->zfs_name); 902789Sahrens break; 903789Sahrens 904789Sahrens case ENOENT: 905789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 906789Sahrens "cannot open '%s': no such %s"), zhp->zfs_name, 907789Sahrens zfs_type_to_name(zhp->zfs_type)); 908789Sahrens break; 909789Sahrens 910789Sahrens case ENOSPC: 911789Sahrens /* 912789Sahrens * For quotas and reservations, ENOSPC indicates 913789Sahrens * something different; setting a quota or reservation 914789Sahrens * doesn't use any disk space. 915789Sahrens */ 916789Sahrens switch (prop) { 917789Sahrens case ZFS_PROP_QUOTA: 918789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s " 919789Sahrens "for '%s': size is less than current " 920789Sahrens "used or reserved space"), propname, 921789Sahrens zhp->zfs_name); 922789Sahrens break; 923789Sahrens 924789Sahrens case ZFS_PROP_RESERVATION: 925789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s " 926789Sahrens "for '%s': size is greater than available " 927789Sahrens "space"), propname, zhp->zfs_name); 928789Sahrens break; 929789Sahrens 930789Sahrens default: 931789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 932789Sahrens "cannot set %s for '%s': out of space"), 933789Sahrens propname, zhp->zfs_name); 934789Sahrens break; 935789Sahrens } 936789Sahrens break; 937789Sahrens 938789Sahrens case EBUSY: 939789Sahrens if (prop == ZFS_PROP_VOLBLOCKSIZE) { 940789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 941789Sahrens "cannot set %s for '%s': " 942789Sahrens "volume already contains data"), 943789Sahrens propname, zhp->zfs_name); 944789Sahrens } else { 945789Sahrens zfs_baderror(errno); 946789Sahrens } 947789Sahrens break; 948789Sahrens 9491175Slling case EROFS: 9501175Slling zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s for " 9511175Slling "'%s': read only %s"), propname, zhp->zfs_name, 9521175Slling zfs_type_to_name(zhp->zfs_type)); 9531175Slling break; 9541175Slling 955789Sahrens case EOVERFLOW: 956789Sahrens /* 957789Sahrens * This platform can't address a volume this big. 958789Sahrens */ 959789Sahrens #ifdef _ILP32 960789Sahrens if (prop == ZFS_PROP_VOLSIZE) { 961789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 962789Sahrens "cannot set %s for '%s': " 963789Sahrens "max volume size is 1TB on 32-bit systems"), 964789Sahrens propname, zhp->zfs_name); 965789Sahrens break; 966789Sahrens } 967789Sahrens #endif 968789Sahrens zfs_baderror(errno); 969789Sahrens default: 970789Sahrens zfs_baderror(errno); 971789Sahrens } 972789Sahrens } else { 973789Sahrens /* 974789Sahrens * Refresh the statistics so the new property value 975789Sahrens * is reflected. 976789Sahrens */ 977789Sahrens if ((ret = changelist_postfix(cl)) != 0) 978789Sahrens goto error; 979789Sahrens 980789Sahrens (void) get_stats(zhp); 981789Sahrens } 982789Sahrens 983789Sahrens error: 984789Sahrens changelist_free(cl); 985789Sahrens return (ret); 986789Sahrens } 987789Sahrens 988789Sahrens /* 989789Sahrens * Given a property, inherit the value from the parent dataset. 990789Sahrens */ 991789Sahrens int 992789Sahrens zfs_prop_inherit(zfs_handle_t *zhp, zfs_prop_t prop) 993789Sahrens { 994789Sahrens const char *propname = zfs_prop_to_name(prop); 995789Sahrens zfs_cmd_t zc = { 0 }; 996789Sahrens int ret; 997789Sahrens prop_changelist_t *cl; 998789Sahrens 999789Sahrens /* 1000789Sahrens * Verify that this property is inheritable. 1001789Sahrens */ 1002789Sahrens if (zfs_prop_readonly(prop)) { 1003789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1004789Sahrens "cannot inherit %s for '%s': property is read-only"), 1005789Sahrens propname, zhp->zfs_name); 1006789Sahrens return (-1); 1007789Sahrens } 1008789Sahrens 1009789Sahrens if (!zfs_prop_inheritable(prop)) { 1010789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1011789Sahrens "cannot inherit %s for '%s': property is not inheritable"), 1012789Sahrens propname, zhp->zfs_name); 1013789Sahrens return (-1); 1014789Sahrens } 1015789Sahrens 1016789Sahrens /* 1017789Sahrens * Check to see if the value applies to this type 1018789Sahrens */ 1019789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) { 1020789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1021789Sahrens "cannot inherit %s for '%s': property does " 1022789Sahrens "not apply to %ss"), propname, zhp->zfs_name, 1023789Sahrens zfs_type_to_name(zhp->zfs_type)); 1024789Sahrens return (-1); 1025789Sahrens } 1026789Sahrens 1027789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1028789Sahrens (void) strlcpy(zc.zc_prop_name, propname, sizeof (zc.zc_prop_name)); 1029789Sahrens 1030789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID && 1031789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 1032789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot inherit %s for '%s', " 1033789Sahrens "dataset is used in a non-global zone"), propname, 1034789Sahrens zhp->zfs_name); 1035789Sahrens return (-1); 1036789Sahrens } 1037789Sahrens 1038789Sahrens /* 1039789Sahrens * Determine datasets which will be affected by this change, if any. 1040789Sahrens */ 1041789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 1042789Sahrens return (-1); 1043789Sahrens 1044789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 1045789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot inherit %s for '%s', " 1046789Sahrens "child dataset with inherited mountpoint is " 1047789Sahrens "used in a non-global zone"), 1048789Sahrens propname, zhp->zfs_name); 1049789Sahrens ret = -1; 1050789Sahrens goto error; 1051789Sahrens } 1052789Sahrens 1053789Sahrens if ((ret = changelist_prefix(cl)) != 0) 1054789Sahrens goto error; 1055789Sahrens 1056789Sahrens zc.zc_numints = 0; 1057789Sahrens 10581544Seschrock if ((ret = zfs_ioctl(ZFS_IOC_SET_PROP, &zc)) != 0) { 1059789Sahrens switch (errno) { 1060789Sahrens case EPERM: 1061789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1062789Sahrens "cannot inherit %s for '%s': permission " 1063789Sahrens "denied"), propname, zhp->zfs_name); 1064789Sahrens break; 1065789Sahrens case ENOENT: 1066789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1067789Sahrens "cannot open '%s': no such %s"), zhp->zfs_name, 1068789Sahrens zfs_type_to_name(zhp->zfs_type)); 1069789Sahrens break; 1070789Sahrens case ENOSPC: 1071789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1072789Sahrens "cannot inherit %s for '%s': " 1073789Sahrens "out of space"), propname, zhp->zfs_name); 1074789Sahrens break; 1075789Sahrens default: 1076789Sahrens zfs_baderror(errno); 1077789Sahrens } 1078789Sahrens 1079789Sahrens } else { 1080789Sahrens 1081789Sahrens if ((ret = changelist_postfix(cl)) != 0) 1082789Sahrens goto error; 1083789Sahrens 1084789Sahrens /* 1085789Sahrens * Refresh the statistics so the new property is reflected. 1086789Sahrens */ 1087789Sahrens (void) get_stats(zhp); 1088789Sahrens } 1089789Sahrens 1090789Sahrens 1091789Sahrens error: 1092789Sahrens changelist_free(cl); 1093789Sahrens return (ret); 1094789Sahrens } 1095789Sahrens 1096789Sahrens static void 1097789Sahrens nicebool(int value, char *buf, size_t buflen) 1098789Sahrens { 1099789Sahrens if (value) 1100789Sahrens (void) strlcpy(buf, "on", buflen); 1101789Sahrens else 1102789Sahrens (void) strlcpy(buf, "off", buflen); 1103789Sahrens } 1104789Sahrens 1105789Sahrens /* 11061356Seschrock * True DSL properties are stored in an nvlist. The following two functions 11071356Seschrock * extract them appropriately. 11081356Seschrock */ 11091356Seschrock static uint64_t 11101356Seschrock getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 11111356Seschrock { 11121356Seschrock nvlist_t *nv; 11131356Seschrock uint64_t value; 11141356Seschrock 11151356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 11161356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 11171356Seschrock verify(nvlist_lookup_uint64(nv, ZFS_PROP_VALUE, &value) == 0); 11181356Seschrock verify(nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source) == 0); 11191356Seschrock } else { 11201356Seschrock value = zfs_prop_default_numeric(prop); 11211356Seschrock *source = ""; 11221356Seschrock } 11231356Seschrock 11241356Seschrock return (value); 11251356Seschrock } 11261356Seschrock 11271356Seschrock static char * 11281356Seschrock getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 11291356Seschrock { 11301356Seschrock nvlist_t *nv; 11311356Seschrock char *value; 11321356Seschrock 11331356Seschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 11341356Seschrock zfs_prop_to_name(prop), &nv) == 0) { 11351356Seschrock verify(nvlist_lookup_string(nv, ZFS_PROP_VALUE, &value) == 0); 11361356Seschrock verify(nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source) == 0); 11371356Seschrock } else { 11381356Seschrock if ((value = (char *)zfs_prop_default_string(prop)) == NULL) 11391356Seschrock value = ""; 11401356Seschrock *source = ""; 11411356Seschrock } 11421356Seschrock 11431356Seschrock return (value); 11441356Seschrock } 11451356Seschrock 11461356Seschrock /* 1147789Sahrens * Internal function for getting a numeric property. Both zfs_prop_get() and 1148789Sahrens * zfs_prop_get_int() are built using this interface. 1149789Sahrens * 1150789Sahrens * Certain properties can be overridden using 'mount -o'. In this case, scan 1151789Sahrens * the contents of the /etc/mnttab entry, searching for the appropriate options. 1152789Sahrens * If they differ from the on-disk values, report the current values and mark 1153789Sahrens * the source "temporary". 1154789Sahrens */ 1155789Sahrens static uint64_t 1156789Sahrens get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zfs_source_t *src, 1157789Sahrens char **source) 1158789Sahrens { 1159789Sahrens uint64_t val; 1160789Sahrens struct mnttab mnt; 1161789Sahrens 1162789Sahrens *source = NULL; 1163789Sahrens 1164789Sahrens if (zhp->zfs_mntopts == NULL) 1165789Sahrens mnt.mnt_mntopts = ""; 1166789Sahrens else 1167789Sahrens mnt.mnt_mntopts = zhp->zfs_mntopts; 1168789Sahrens 1169789Sahrens switch (prop) { 1170789Sahrens case ZFS_PROP_ATIME: 11711356Seschrock val = getprop_uint64(zhp, prop, source); 1172789Sahrens 1173789Sahrens if (hasmntopt(&mnt, MNTOPT_ATIME) && !val) { 1174789Sahrens val = TRUE; 1175789Sahrens if (src) 1176789Sahrens *src = ZFS_SRC_TEMPORARY; 1177789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NOATIME) && val) { 1178789Sahrens val = FALSE; 1179789Sahrens if (src) 1180789Sahrens *src = ZFS_SRC_TEMPORARY; 1181789Sahrens } 11821356Seschrock return (val); 1183789Sahrens 1184789Sahrens case ZFS_PROP_AVAILABLE: 1185789Sahrens return (zhp->zfs_dmustats.dds_available); 1186789Sahrens 1187789Sahrens case ZFS_PROP_DEVICES: 11881356Seschrock val = getprop_uint64(zhp, prop, source); 1189789Sahrens 1190789Sahrens if (hasmntopt(&mnt, MNTOPT_DEVICES) && !val) { 1191789Sahrens val = TRUE; 1192789Sahrens if (src) 1193789Sahrens *src = ZFS_SRC_TEMPORARY; 1194789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NODEVICES) && val) { 1195789Sahrens val = FALSE; 1196789Sahrens if (src) 1197789Sahrens *src = ZFS_SRC_TEMPORARY; 1198789Sahrens } 1199789Sahrens return (val); 1200789Sahrens 1201789Sahrens case ZFS_PROP_EXEC: 12021356Seschrock val = getprop_uint64(zhp, prop, source); 1203789Sahrens 1204789Sahrens if (hasmntopt(&mnt, MNTOPT_EXEC) && !val) { 1205789Sahrens val = TRUE; 1206789Sahrens if (src) 1207789Sahrens *src = ZFS_SRC_TEMPORARY; 1208789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NOEXEC) && val) { 1209789Sahrens val = FALSE; 1210789Sahrens if (src) 1211789Sahrens *src = ZFS_SRC_TEMPORARY; 1212789Sahrens } 1213789Sahrens return (val); 1214789Sahrens 1215789Sahrens case ZFS_PROP_RECORDSIZE: 1216789Sahrens case ZFS_PROP_COMPRESSION: 12171356Seschrock case ZFS_PROP_ZONED: 12181356Seschrock val = getprop_uint64(zhp, prop, source); 12191356Seschrock return (val); 1220789Sahrens 1221789Sahrens case ZFS_PROP_READONLY: 12221356Seschrock val = getprop_uint64(zhp, prop, source); 1223789Sahrens 1224789Sahrens if (hasmntopt(&mnt, MNTOPT_RO) && !val) { 1225789Sahrens val = TRUE; 1226789Sahrens if (src) 1227789Sahrens *src = ZFS_SRC_TEMPORARY; 1228789Sahrens } else if (hasmntopt(&mnt, MNTOPT_RW) && val) { 1229789Sahrens val = FALSE; 1230789Sahrens if (src) 1231789Sahrens *src = ZFS_SRC_TEMPORARY; 1232789Sahrens } 1233789Sahrens return (val); 1234789Sahrens 12351544Seschrock case ZFS_PROP_CREATION: 12361544Seschrock return (zhp->zfs_dmustats.dds_creation_time); 12371544Seschrock 1238789Sahrens case ZFS_PROP_QUOTA: 1239789Sahrens if (zhp->zfs_dmustats.dds_quota == 0) 1240789Sahrens *source = ""; /* default */ 1241789Sahrens else 1242789Sahrens *source = zhp->zfs_name; 1243789Sahrens return (zhp->zfs_dmustats.dds_quota); 1244789Sahrens 1245789Sahrens case ZFS_PROP_RESERVATION: 1246789Sahrens if (zhp->zfs_dmustats.dds_reserved == 0) 1247789Sahrens *source = ""; /* default */ 1248789Sahrens else 1249789Sahrens *source = zhp->zfs_name; 1250789Sahrens return (zhp->zfs_dmustats.dds_reserved); 1251789Sahrens 1252789Sahrens case ZFS_PROP_COMPRESSRATIO: 1253789Sahrens /* 1254789Sahrens * Using physical space and logical space, calculate the 1255789Sahrens * compression ratio. We return the number as a multiple of 1256789Sahrens * 100, so '2.5x' would be returned as 250. 1257789Sahrens */ 1258789Sahrens if (zhp->zfs_dmustats.dds_compressed_bytes == 0) 1259789Sahrens return (100ULL); 1260789Sahrens else 1261789Sahrens return (zhp->zfs_dmustats.dds_uncompressed_bytes * 100 / 1262789Sahrens zhp->zfs_dmustats.dds_compressed_bytes); 1263789Sahrens 1264789Sahrens case ZFS_PROP_REFERENCED: 1265789Sahrens /* 1266789Sahrens * 'referenced' refers to the amount of physical space 1267789Sahrens * referenced (possibly shared) by this object. 1268789Sahrens */ 1269789Sahrens return (zhp->zfs_dmustats.dds_space_refd); 1270789Sahrens 1271789Sahrens case ZFS_PROP_SETUID: 12721356Seschrock val = getprop_uint64(zhp, prop, source); 1273789Sahrens 1274789Sahrens if (hasmntopt(&mnt, MNTOPT_SETUID) && !val) { 1275789Sahrens val = TRUE; 1276789Sahrens if (src) 1277789Sahrens *src = ZFS_SRC_TEMPORARY; 1278789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NOSETUID) && val) { 1279789Sahrens val = FALSE; 1280789Sahrens if (src) 1281789Sahrens *src = ZFS_SRC_TEMPORARY; 1282789Sahrens } 1283789Sahrens return (val); 1284789Sahrens 1285789Sahrens case ZFS_PROP_VOLSIZE: 1286789Sahrens return (zhp->zfs_volsize); 1287789Sahrens 1288789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 1289789Sahrens return (zhp->zfs_volblocksize); 1290789Sahrens 1291789Sahrens case ZFS_PROP_USED: 1292789Sahrens return (zhp->zfs_dmustats.dds_space_used); 1293789Sahrens 1294789Sahrens case ZFS_PROP_CREATETXG: 1295789Sahrens return (zhp->zfs_dmustats.dds_creation_txg); 1296789Sahrens 1297789Sahrens case ZFS_PROP_MOUNTED: 1298789Sahrens /* 1299789Sahrens * Unlike other properties, we defer calculation of 'MOUNTED' 1300789Sahrens * until actually requested. This is because the getmntany() 1301789Sahrens * call can be extremely expensive on systems with a large 1302789Sahrens * number of filesystems, and the property isn't needed in 1303789Sahrens * normal use cases. 1304789Sahrens */ 1305789Sahrens if (zhp->zfs_mntopts == NULL) { 1306789Sahrens struct mnttab search = { 0 }, entry; 1307789Sahrens 1308789Sahrens search.mnt_special = (char *)zhp->zfs_name; 13091407Snd150628 search.mnt_fstype = MNTTYPE_ZFS; 13101544Seschrock rewind(zfs_mnttab()); 13111544Seschrock 13121544Seschrock if (getmntany(zfs_mnttab(), &entry, &search) == 0) 1313789Sahrens zhp->zfs_mntopts = 1314789Sahrens zfs_strdup(entry.mnt_mntopts); 1315789Sahrens } 1316789Sahrens return (zhp->zfs_mntopts != NULL); 1317789Sahrens 1318789Sahrens default: 1319789Sahrens zfs_baderror(EINVAL); 1320789Sahrens } 1321789Sahrens 1322789Sahrens return (0); 1323789Sahrens } 1324789Sahrens 1325789Sahrens /* 1326789Sahrens * Calculate the source type, given the raw source string. 1327789Sahrens */ 1328789Sahrens static void 1329789Sahrens get_source(zfs_handle_t *zhp, zfs_source_t *srctype, char *source, 1330789Sahrens char *statbuf, size_t statlen) 1331789Sahrens { 1332789Sahrens if (statbuf == NULL || *srctype == ZFS_SRC_TEMPORARY) 1333789Sahrens return; 1334789Sahrens 1335789Sahrens if (source == NULL) { 1336789Sahrens *srctype = ZFS_SRC_NONE; 1337789Sahrens } else if (source[0] == '\0') { 1338789Sahrens *srctype = ZFS_SRC_DEFAULT; 1339789Sahrens } else { 1340789Sahrens if (strcmp(source, zhp->zfs_name) == 0) { 1341789Sahrens *srctype = ZFS_SRC_LOCAL; 1342789Sahrens } else { 1343789Sahrens (void) strlcpy(statbuf, source, statlen); 1344789Sahrens *srctype = ZFS_SRC_INHERITED; 1345789Sahrens } 1346789Sahrens } 1347789Sahrens 1348789Sahrens } 1349789Sahrens 1350789Sahrens /* 1351789Sahrens * Retrieve a property from the given object. If 'literal' is specified, then 1352789Sahrens * numbers are left as exact values. Otherwise, numbers are converted to a 1353789Sahrens * human-readable form. 1354789Sahrens * 1355789Sahrens * Returns 0 on success, or -1 on error. 1356789Sahrens */ 1357789Sahrens int 1358789Sahrens zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, 1359789Sahrens zfs_source_t *src, char *statbuf, size_t statlen, int literal) 1360789Sahrens { 1361789Sahrens char *source = NULL; 1362789Sahrens uint64_t val; 1363789Sahrens char *str; 1364789Sahrens int i; 1365789Sahrens const char *root; 1366789Sahrens 1367789Sahrens /* 1368789Sahrens * Check to see if this property applies to our object 1369789Sahrens */ 1370789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1371789Sahrens return (-1); 1372789Sahrens 1373789Sahrens if (src) 1374789Sahrens *src = ZFS_SRC_NONE; 1375789Sahrens 1376789Sahrens switch (prop) { 1377789Sahrens case ZFS_PROP_ATIME: 1378789Sahrens case ZFS_PROP_READONLY: 1379789Sahrens case ZFS_PROP_SETUID: 1380789Sahrens case ZFS_PROP_ZONED: 1381789Sahrens case ZFS_PROP_DEVICES: 1382789Sahrens case ZFS_PROP_EXEC: 1383789Sahrens /* 1384789Sahrens * Basic boolean values are built on top of 1385789Sahrens * get_numeric_property(). 1386789Sahrens */ 1387789Sahrens nicebool(get_numeric_property(zhp, prop, src, &source), 1388789Sahrens propbuf, proplen); 1389789Sahrens 1390789Sahrens break; 1391789Sahrens 1392789Sahrens case ZFS_PROP_AVAILABLE: 1393789Sahrens case ZFS_PROP_RECORDSIZE: 1394789Sahrens case ZFS_PROP_CREATETXG: 1395789Sahrens case ZFS_PROP_REFERENCED: 1396789Sahrens case ZFS_PROP_USED: 1397789Sahrens case ZFS_PROP_VOLSIZE: 1398789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 1399789Sahrens /* 1400789Sahrens * Basic numeric values are built on top of 1401789Sahrens * get_numeric_property(). 1402789Sahrens */ 1403789Sahrens val = get_numeric_property(zhp, prop, src, &source); 1404789Sahrens if (literal) 1405789Sahrens (void) snprintf(propbuf, proplen, "%llu", val); 1406789Sahrens else 1407789Sahrens zfs_nicenum(val, propbuf, proplen); 1408789Sahrens break; 1409789Sahrens 1410789Sahrens case ZFS_PROP_COMPRESSION: 14111356Seschrock val = getprop_uint64(zhp, prop, &source); 1412789Sahrens for (i = 0; compress_table[i].name != NULL; i++) { 14131356Seschrock if (compress_table[i].value == val) 1414789Sahrens break; 1415789Sahrens } 1416789Sahrens assert(compress_table[i].name != NULL); 1417789Sahrens (void) strlcpy(propbuf, compress_table[i].name, proplen); 1418789Sahrens break; 1419789Sahrens 1420789Sahrens case ZFS_PROP_CHECKSUM: 14211356Seschrock val = getprop_uint64(zhp, prop, &source); 1422789Sahrens for (i = 0; checksum_table[i].name != NULL; i++) { 14231356Seschrock if (checksum_table[i].value == val) 1424789Sahrens break; 1425789Sahrens } 1426789Sahrens assert(checksum_table[i].name != NULL); 1427789Sahrens (void) strlcpy(propbuf, checksum_table[i].name, proplen); 1428789Sahrens break; 1429789Sahrens 1430789Sahrens case ZFS_PROP_SNAPDIR: 14311356Seschrock val = getprop_uint64(zhp, prop, &source); 1432789Sahrens for (i = 0; snapdir_table[i].name != NULL; i++) { 14331356Seschrock if (snapdir_table[i].value == val) 1434789Sahrens break; 1435789Sahrens } 1436789Sahrens assert(snapdir_table[i].name != NULL); 1437789Sahrens (void) strlcpy(propbuf, snapdir_table[i].name, proplen); 1438789Sahrens break; 1439789Sahrens 1440789Sahrens case ZFS_PROP_ACLMODE: 14411356Seschrock val = getprop_uint64(zhp, prop, &source); 1442789Sahrens for (i = 0; acl_mode_table[i].name != NULL; i++) { 14431356Seschrock if (acl_mode_table[i].value == val) 1444789Sahrens break; 1445789Sahrens } 1446789Sahrens assert(acl_mode_table[i].name != NULL); 1447789Sahrens (void) strlcpy(propbuf, acl_mode_table[i].name, proplen); 1448789Sahrens break; 1449789Sahrens 1450789Sahrens case ZFS_PROP_ACLINHERIT: 14511356Seschrock val = getprop_uint64(zhp, prop, &source); 1452789Sahrens for (i = 0; acl_inherit_table[i].name != NULL; i++) { 14531356Seschrock if (acl_inherit_table[i].value == val) 1454789Sahrens break; 1455789Sahrens } 1456789Sahrens assert(acl_inherit_table[i].name != NULL); 1457789Sahrens (void) strlcpy(propbuf, acl_inherit_table[i].name, proplen); 1458789Sahrens break; 1459789Sahrens 1460789Sahrens case ZFS_PROP_CREATION: 1461789Sahrens /* 1462789Sahrens * 'creation' is a time_t stored in the statistics. We convert 1463789Sahrens * this into a string unless 'literal' is specified. 1464789Sahrens */ 1465789Sahrens { 1466789Sahrens time_t time = (time_t) 1467789Sahrens zhp->zfs_dmustats.dds_creation_time; 1468789Sahrens struct tm t; 1469789Sahrens 1470789Sahrens if (literal || 1471789Sahrens localtime_r(&time, &t) == NULL || 1472789Sahrens strftime(propbuf, proplen, "%a %b %e %k:%M %Y", 1473789Sahrens &t) == 0) 1474789Sahrens (void) snprintf(propbuf, proplen, "%llu", 1475789Sahrens zhp->zfs_dmustats.dds_creation_time); 1476789Sahrens } 1477789Sahrens break; 1478789Sahrens 1479789Sahrens case ZFS_PROP_MOUNTPOINT: 1480789Sahrens /* 1481789Sahrens * Getting the precise mountpoint can be tricky. 1482789Sahrens * 1483789Sahrens * - for 'none' or 'legacy', return those values. 1484789Sahrens * - for default mountpoints, construct it as /zfs/<dataset> 1485789Sahrens * - for inherited mountpoints, we want to take everything 1486789Sahrens * after our ancestor and append it to the inherited value. 1487789Sahrens * 1488789Sahrens * If the pool has an alternate root, we want to prepend that 1489789Sahrens * root to any values we return. 1490789Sahrens */ 14911544Seschrock root = zhp->zfs_root; 14921356Seschrock str = getprop_string(zhp, prop, &source); 14931356Seschrock 14941356Seschrock if (str[0] == '\0') { 1495789Sahrens (void) snprintf(propbuf, proplen, "%s/zfs/%s", 1496789Sahrens root, zhp->zfs_name); 14971356Seschrock } else if (str[0] == '/') { 14981356Seschrock const char *relpath = zhp->zfs_name + strlen(source); 1499789Sahrens 1500789Sahrens if (relpath[0] == '/') 1501789Sahrens relpath++; 15021356Seschrock if (str[1] == '\0') 15031356Seschrock str++; 1504789Sahrens 1505789Sahrens if (relpath[0] == '\0') 1506789Sahrens (void) snprintf(propbuf, proplen, "%s%s", 15071356Seschrock root, str); 1508789Sahrens else 1509789Sahrens (void) snprintf(propbuf, proplen, "%s%s%s%s", 15101356Seschrock root, str, relpath[0] == '@' ? "" : "/", 1511789Sahrens relpath); 1512789Sahrens } else { 1513789Sahrens /* 'legacy' or 'none' */ 15141356Seschrock (void) strlcpy(propbuf, str, proplen); 1515789Sahrens } 1516789Sahrens 1517789Sahrens break; 1518789Sahrens 1519789Sahrens case ZFS_PROP_SHARENFS: 15201356Seschrock (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 15211356Seschrock proplen); 1522789Sahrens break; 1523789Sahrens 1524789Sahrens case ZFS_PROP_ORIGIN: 15251544Seschrock (void) strlcpy(propbuf, zhp->zfs_dmustats.dds_clone_of, 1526789Sahrens proplen); 1527789Sahrens /* 1528789Sahrens * If there is no parent at all, return failure to indicate that 1529789Sahrens * it doesn't apply to this dataset. 1530789Sahrens */ 1531789Sahrens if (propbuf[0] == '\0') 1532789Sahrens return (-1); 1533789Sahrens break; 1534789Sahrens 1535789Sahrens case ZFS_PROP_QUOTA: 1536789Sahrens case ZFS_PROP_RESERVATION: 1537789Sahrens val = get_numeric_property(zhp, prop, src, &source); 1538789Sahrens 1539789Sahrens /* 1540789Sahrens * If quota or reservation is 0, we translate this into 'none' 1541789Sahrens * (unless literal is set), and indicate that it's the default 1542789Sahrens * value. Otherwise, we print the number nicely and indicate 1543789Sahrens * that its set locally. 1544789Sahrens */ 1545789Sahrens if (val == 0) { 1546789Sahrens if (literal) 1547789Sahrens (void) strlcpy(propbuf, "0", proplen); 1548789Sahrens else 1549789Sahrens (void) strlcpy(propbuf, "none", proplen); 1550789Sahrens } else { 1551789Sahrens if (literal) 1552789Sahrens (void) snprintf(propbuf, proplen, "%llu", val); 1553789Sahrens else 1554789Sahrens zfs_nicenum(val, propbuf, proplen); 1555789Sahrens } 1556789Sahrens break; 1557789Sahrens 1558789Sahrens case ZFS_PROP_COMPRESSRATIO: 1559789Sahrens val = get_numeric_property(zhp, prop, src, &source); 1560789Sahrens (void) snprintf(propbuf, proplen, "%lld.%02lldx", val / 100, 1561789Sahrens val % 100); 1562789Sahrens break; 1563789Sahrens 1564789Sahrens case ZFS_PROP_TYPE: 1565789Sahrens switch (zhp->zfs_type) { 1566789Sahrens case ZFS_TYPE_FILESYSTEM: 1567789Sahrens str = "filesystem"; 1568789Sahrens break; 1569789Sahrens case ZFS_TYPE_VOLUME: 1570789Sahrens str = "volume"; 1571789Sahrens break; 1572789Sahrens case ZFS_TYPE_SNAPSHOT: 1573789Sahrens str = "snapshot"; 1574789Sahrens break; 1575789Sahrens default: 1576789Sahrens zfs_baderror(zhp->zfs_type); 1577789Sahrens } 1578789Sahrens (void) snprintf(propbuf, proplen, "%s", str); 1579789Sahrens break; 1580789Sahrens 1581789Sahrens case ZFS_PROP_MOUNTED: 1582789Sahrens /* 1583789Sahrens * The 'mounted' property is a pseudo-property that described 1584789Sahrens * whether the filesystem is currently mounted. Even though 1585789Sahrens * it's a boolean value, the typical values of "on" and "off" 1586789Sahrens * don't make sense, so we translate to "yes" and "no". 1587789Sahrens */ 1588789Sahrens if (get_numeric_property(zhp, ZFS_PROP_MOUNTED, src, &source)) 1589789Sahrens (void) strlcpy(propbuf, "yes", proplen); 1590789Sahrens else 1591789Sahrens (void) strlcpy(propbuf, "no", proplen); 1592789Sahrens break; 1593789Sahrens 1594789Sahrens case ZFS_PROP_NAME: 1595789Sahrens /* 1596789Sahrens * The 'name' property is a pseudo-property derived from the 1597789Sahrens * dataset name. It is presented as a real property to simplify 1598789Sahrens * consumers. 1599789Sahrens */ 1600789Sahrens (void) strlcpy(propbuf, zhp->zfs_name, proplen); 1601789Sahrens break; 1602789Sahrens 1603789Sahrens default: 1604789Sahrens zfs_baderror(EINVAL); 1605789Sahrens } 1606789Sahrens 1607789Sahrens get_source(zhp, src, source, statbuf, statlen); 1608789Sahrens 1609789Sahrens return (0); 1610789Sahrens } 1611789Sahrens 1612789Sahrens /* 1613789Sahrens * Utility function to get the given numeric property. Does no validation that 1614789Sahrens * the given property is the appropriate type; should only be used with 1615789Sahrens * hard-coded property types. 1616789Sahrens */ 1617789Sahrens uint64_t 1618789Sahrens zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop) 1619789Sahrens { 1620789Sahrens char *source; 1621789Sahrens zfs_source_t sourcetype = ZFS_SRC_NONE; 1622789Sahrens 1623789Sahrens return (get_numeric_property(zhp, prop, &sourcetype, &source)); 1624789Sahrens } 1625789Sahrens 1626789Sahrens /* 1627789Sahrens * Similar to zfs_prop_get(), but returns the value as an integer. 1628789Sahrens */ 1629789Sahrens int 1630789Sahrens zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, 1631789Sahrens zfs_source_t *src, char *statbuf, size_t statlen) 1632789Sahrens { 1633789Sahrens char *source; 1634789Sahrens 1635789Sahrens /* 1636789Sahrens * Check to see if this property applies to our object 1637789Sahrens */ 1638789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1639789Sahrens return (-1); 1640789Sahrens 1641789Sahrens if (src) 1642789Sahrens *src = ZFS_SRC_NONE; 1643789Sahrens 1644789Sahrens *value = get_numeric_property(zhp, prop, src, &source); 1645789Sahrens 1646789Sahrens get_source(zhp, src, source, statbuf, statlen); 1647789Sahrens 1648789Sahrens return (0); 1649789Sahrens } 1650789Sahrens 1651789Sahrens /* 1652789Sahrens * Returns the name of the given zfs handle. 1653789Sahrens */ 1654789Sahrens const char * 1655789Sahrens zfs_get_name(const zfs_handle_t *zhp) 1656789Sahrens { 1657789Sahrens return (zhp->zfs_name); 1658789Sahrens } 1659789Sahrens 1660789Sahrens /* 1661789Sahrens * Returns the type of the given zfs handle. 1662789Sahrens */ 1663789Sahrens zfs_type_t 1664789Sahrens zfs_get_type(const zfs_handle_t *zhp) 1665789Sahrens { 1666789Sahrens return (zhp->zfs_type); 1667789Sahrens } 1668789Sahrens 1669789Sahrens /* 16701356Seschrock * Iterate over all child filesystems 1671789Sahrens */ 1672789Sahrens int 16731356Seschrock zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) 1674789Sahrens { 1675789Sahrens zfs_cmd_t zc = { 0 }; 1676789Sahrens zfs_handle_t *nzhp; 1677789Sahrens int ret; 1678789Sahrens 1679789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 16801544Seschrock zfs_ioctl(ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; 1681789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1682789Sahrens /* 1683789Sahrens * Ignore private dataset names. 1684789Sahrens */ 1685789Sahrens if (dataset_name_hidden(zc.zc_name)) 1686789Sahrens continue; 1687789Sahrens 1688789Sahrens /* 1689789Sahrens * Silently ignore errors, as the only plausible explanation is 1690789Sahrens * that the pool has since been removed. 1691789Sahrens */ 1692789Sahrens if ((nzhp = make_dataset_handle(zc.zc_name)) == NULL) 1693789Sahrens continue; 1694789Sahrens 1695789Sahrens if ((ret = func(nzhp, data)) != 0) 1696789Sahrens return (ret); 1697789Sahrens } 1698789Sahrens 1699789Sahrens /* 1700789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1701789Sahrens * returned, then the underlying dataset has been removed since we 1702789Sahrens * obtained the handle. 1703789Sahrens */ 1704789Sahrens if (errno != ESRCH && errno != ENOENT) 1705789Sahrens zfs_baderror(errno); 1706789Sahrens 17071356Seschrock return (0); 17081356Seschrock } 17091356Seschrock 17101356Seschrock /* 17111356Seschrock * Iterate over all snapshots 17121356Seschrock */ 17131356Seschrock int 17141356Seschrock zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) 17151356Seschrock { 17161356Seschrock zfs_cmd_t zc = { 0 }; 17171356Seschrock zfs_handle_t *nzhp; 17181356Seschrock int ret; 1719789Sahrens 1720789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 17211544Seschrock zfs_ioctl(ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc) == 0; 1722789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1723789Sahrens 1724789Sahrens if ((nzhp = make_dataset_handle(zc.zc_name)) == NULL) 1725789Sahrens continue; 1726789Sahrens 1727789Sahrens if ((ret = func(nzhp, data)) != 0) 1728789Sahrens return (ret); 1729789Sahrens } 1730789Sahrens 1731789Sahrens /* 1732789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1733789Sahrens * returned, then the underlying dataset has been removed since we 1734789Sahrens * obtained the handle. Silently ignore this case, and return success. 1735789Sahrens */ 1736789Sahrens if (errno != ESRCH && errno != ENOENT) 1737789Sahrens zfs_baderror(errno); 1738789Sahrens 1739789Sahrens return (0); 1740789Sahrens } 1741789Sahrens 1742789Sahrens /* 17431356Seschrock * Iterate over all children, snapshots and filesystems 17441356Seschrock */ 17451356Seschrock int 17461356Seschrock zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 17471356Seschrock { 17481356Seschrock int ret; 17491356Seschrock 17501356Seschrock if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0) 17511356Seschrock return (ret); 17521356Seschrock 17531356Seschrock return (zfs_iter_snapshots(zhp, func, data)); 17541356Seschrock } 17551356Seschrock 17561356Seschrock /* 1757789Sahrens * Given a complete name, return just the portion that refers to the parent. 1758789Sahrens * Can return NULL if this is a pool. 1759789Sahrens */ 1760789Sahrens static int 1761789Sahrens parent_name(const char *path, char *buf, size_t buflen) 1762789Sahrens { 1763789Sahrens char *loc; 1764789Sahrens 1765789Sahrens if ((loc = strrchr(path, '/')) == NULL) 1766789Sahrens return (-1); 1767789Sahrens 1768789Sahrens (void) strncpy(buf, path, MIN(buflen, loc - path)); 1769789Sahrens buf[loc - path] = '\0'; 1770789Sahrens 1771789Sahrens return (0); 1772789Sahrens } 1773789Sahrens 1774789Sahrens /* 1775789Sahrens * Checks to make sure that the given path has a parent, and that it exists. 1776789Sahrens */ 1777789Sahrens static int 1778789Sahrens check_parents(const char *path, zfs_type_t type) 1779789Sahrens { 1780789Sahrens zfs_cmd_t zc = { 0 }; 1781789Sahrens char parent[ZFS_MAXNAMELEN]; 1782789Sahrens char *slash; 17831356Seschrock zfs_handle_t *zhp; 1784789Sahrens 1785789Sahrens /* get parent, and check to see if this is just a pool */ 1786789Sahrens if (parent_name(path, parent, sizeof (parent)) != 0) { 1787789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1788789Sahrens "cannot create '%s': missing dataset name"), 1789789Sahrens path, zfs_type_to_name(type)); 1790789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1791789Sahrens "use 'zpool create' to create a storage pool")); 1792789Sahrens return (-1); 1793789Sahrens } 1794789Sahrens 1795789Sahrens /* check to see if the pool exists */ 1796789Sahrens if ((slash = strchr(parent, '/')) == NULL) 1797789Sahrens slash = parent + strlen(parent); 1798789Sahrens (void) strncpy(zc.zc_name, parent, slash - parent); 1799789Sahrens zc.zc_name[slash - parent] = '\0'; 18001544Seschrock if (zfs_ioctl(ZFS_IOC_OBJSET_STATS, &zc) != 0 && 1801789Sahrens errno == ENOENT) { 1802789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1803789Sahrens "cannot create '%s': no such pool '%s'"), path, zc.zc_name); 1804789Sahrens return (-1); 1805789Sahrens } 1806789Sahrens 1807789Sahrens /* check to see if the parent dataset exists */ 18081356Seschrock if ((zhp = make_dataset_handle(parent)) == NULL) { 1809789Sahrens switch (errno) { 1810789Sahrens case ENOENT: 1811789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1812789Sahrens "cannot create '%s': parent does not exist"), path); 1813789Sahrens return (-1); 1814789Sahrens 1815789Sahrens default: 1816789Sahrens zfs_baderror(errno); 1817789Sahrens } 1818789Sahrens } 1819789Sahrens 1820789Sahrens /* we are in a non-global zone, but parent is in the global zone */ 18211356Seschrock if (getzoneid() != GLOBAL_ZONEID && 18221393Slling !zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 1823789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1824789Sahrens "cannot create '%s': permission denied"), path); 18251356Seschrock zfs_close(zhp); 1826789Sahrens return (-1); 1827789Sahrens } 1828789Sahrens 1829789Sahrens /* make sure parent is a filesystem */ 18301356Seschrock if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 1831789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1832789Sahrens "cannot create '%s': parent is not a filesystem"), 1833789Sahrens path); 18341356Seschrock zfs_close(zhp); 1835789Sahrens return (-1); 1836789Sahrens } 1837789Sahrens 18381356Seschrock zfs_close(zhp); 1839789Sahrens return (0); 1840789Sahrens } 1841789Sahrens 1842789Sahrens /* 1843789Sahrens * Create a new filesystem or volume. 'sizestr' and 'blocksizestr' are used 1844789Sahrens * only for volumes, and indicate the size and blocksize of the volume. 1845789Sahrens */ 1846789Sahrens int 1847789Sahrens zfs_create(const char *path, zfs_type_t type, 1848789Sahrens const char *sizestr, const char *blocksizestr) 1849789Sahrens { 1850789Sahrens char reason[64]; 1851789Sahrens zfs_cmd_t zc = { 0 }; 1852789Sahrens int ret; 1853789Sahrens uint64_t size = 0; 1854789Sahrens uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE); 1855789Sahrens 1856789Sahrens /* convert sizestr into integer size */ 1857789Sahrens if (sizestr != NULL && nicestrtonum(sizestr, &size, 1858789Sahrens reason, sizeof (reason)) != 0) { 1859789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1860789Sahrens "bad volume size '%s': %s"), sizestr, reason); 1861789Sahrens return (-1); 1862789Sahrens } 1863789Sahrens 1864789Sahrens /* convert blocksizestr into integer blocksize */ 1865789Sahrens if (blocksizestr != NULL && nicestrtonum(blocksizestr, &blocksize, 1866789Sahrens reason, sizeof (reason)) != 0) { 1867789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1868789Sahrens "bad volume blocksize '%s': %s"), blocksizestr, reason); 1869789Sahrens return (-1); 1870789Sahrens } 1871789Sahrens 1872789Sahrens /* validate the path, taking care to note the extended error message */ 1873789Sahrens if (!zfs_validate_name(path, type, reason, sizeof (reason))) { 1874789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1875789Sahrens "cannot create '%s': %s in %s name"), path, reason, 1876789Sahrens zfs_type_to_name(type)); 1877789Sahrens if (strstr(reason, "snapshot") != NULL) 1878789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1879789Sahrens "use 'zfs snapshot' to create a snapshot")); 1880789Sahrens return (-1); 1881789Sahrens } 1882789Sahrens 1883789Sahrens /* validate parents exist */ 1884789Sahrens if (check_parents(path, type) != 0) 1885789Sahrens return (-1); 1886789Sahrens 1887789Sahrens /* 1888789Sahrens * The failure modes when creating a dataset of a different type over 1889789Sahrens * one that already exists is a little strange. In particular, if you 1890789Sahrens * try to create a dataset on top of an existing dataset, the ioctl() 1891789Sahrens * will return ENOENT, not EEXIST. To prevent this from happening, we 1892789Sahrens * first try to see if the dataset exists. 1893789Sahrens */ 1894789Sahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 18951544Seschrock if (zfs_ioctl(ZFS_IOC_OBJSET_STATS, &zc) == 0) { 1896789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1897789Sahrens "cannot create '%s': dataset exists"), path); 1898789Sahrens return (-1); 1899789Sahrens } 1900789Sahrens 1901789Sahrens if (type == ZFS_TYPE_VOLUME) 1902789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 1903789Sahrens else 1904789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 1905789Sahrens 1906789Sahrens if (type == ZFS_TYPE_VOLUME) { 19071133Seschrock /* 19081133Seschrock * If we are creating a volume, the size and block size must 19091133Seschrock * satisfy a few restraints. First, the blocksize must be a 19101133Seschrock * valid block size between SPA_{MIN,MAX}BLOCKSIZE. Second, the 19111133Seschrock * volsize must be a multiple of the block size, and cannot be 19121133Seschrock * zero. 19131133Seschrock */ 1914789Sahrens if (size == 0) { 1915789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1916789Sahrens "bad volume size '%s': cannot be zero"), sizestr); 1917789Sahrens return (-1); 1918789Sahrens } 1919789Sahrens 19201133Seschrock if (blocksize < SPA_MINBLOCKSIZE || 19211133Seschrock blocksize > SPA_MAXBLOCKSIZE || !ISP2(blocksize)) { 19221133Seschrock zfs_error(dgettext(TEXT_DOMAIN, 19231133Seschrock "bad volume block size '%s': " 19241133Seschrock "must be power of 2 from %u to %uk"), 19251133Seschrock blocksizestr, 19261133Seschrock (uint_t)SPA_MINBLOCKSIZE, 19271133Seschrock (uint_t)SPA_MAXBLOCKSIZE >> 10); 19281133Seschrock return (-1); 19291133Seschrock } 19301133Seschrock 19311133Seschrock if (size % blocksize != 0) { 19321133Seschrock char buf[64]; 19331133Seschrock zfs_nicenum(blocksize, buf, sizeof (buf)); 19341133Seschrock zfs_error(dgettext(TEXT_DOMAIN, 19351133Seschrock "bad volume size '%s': " 19361133Seschrock "must be multiple of volume block size (%s)"), 19371133Seschrock sizestr, buf); 19381133Seschrock return (-1); 19391133Seschrock } 19401133Seschrock 1941789Sahrens zc.zc_volsize = size; 1942789Sahrens zc.zc_volblocksize = blocksize; 1943789Sahrens } 1944789Sahrens 1945789Sahrens /* create the dataset */ 19461544Seschrock ret = zfs_ioctl(ZFS_IOC_CREATE, &zc); 1947789Sahrens 1948789Sahrens if (ret == 0 && type == ZFS_TYPE_VOLUME) 1949789Sahrens ret = zvol_create_link(path); 1950789Sahrens 1951789Sahrens /* check for failure */ 1952789Sahrens if (ret != 0) { 1953789Sahrens char parent[ZFS_MAXNAMELEN]; 1954789Sahrens (void) parent_name(path, parent, sizeof (parent)); 1955789Sahrens 1956789Sahrens switch (errno) { 1957789Sahrens case ENOENT: 1958789Sahrens /* 1959789Sahrens * The parent dataset has been deleted since our 1960789Sahrens * previous check. 1961789Sahrens */ 1962789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1963789Sahrens "cannot create '%s': no such parent '%s'"), 1964789Sahrens path, parent); 1965789Sahrens break; 1966789Sahrens 1967789Sahrens case EPERM: 1968789Sahrens /* 1969789Sahrens * The user doesn't have permission to create a new 1970789Sahrens * dataset here. 1971789Sahrens */ 1972789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1973789Sahrens "cannot create '%s': permission denied"), path); 1974789Sahrens break; 1975789Sahrens 1976789Sahrens case EDQUOT: 1977789Sahrens case ENOSPC: 1978789Sahrens /* 1979789Sahrens * The parent dataset does not have enough free space 1980789Sahrens * to create a new dataset. 1981789Sahrens */ 1982789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1983789Sahrens "cannot create '%s': not enough space in '%s'"), 1984789Sahrens path, parent); 1985789Sahrens break; 1986789Sahrens 1987789Sahrens case EEXIST: 1988789Sahrens /* 1989789Sahrens * The target dataset already exists. We should have 1990789Sahrens * caught this above, but there may be some unexplained 1991789Sahrens * race condition. 1992789Sahrens */ 1993789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1994789Sahrens "cannot create '%s': dataset exists"), path); 1995789Sahrens break; 1996789Sahrens 1997789Sahrens case EINVAL: 1998789Sahrens /* 1999789Sahrens * The target dataset does not support children. 2000789Sahrens */ 2001789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2002789Sahrens "cannot create '%s': children unsupported in '%s'"), 2003789Sahrens path, parent); 2004789Sahrens break; 2005789Sahrens 2006789Sahrens case EDOM: 2007789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "bad %s value '%s': " 2008789Sahrens "must be power of 2 from %u to %uk"), 2009789Sahrens zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 2010789Sahrens blocksizestr ? blocksizestr : "<unknown>", 2011789Sahrens (uint_t)SPA_MINBLOCKSIZE, 2012789Sahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 2013789Sahrens break; 2014789Sahrens #ifdef _ILP32 2015789Sahrens case EOVERFLOW: 2016789Sahrens /* 2017789Sahrens * This platform can't address a volume this big. 2018789Sahrens */ 2019789Sahrens if (type == ZFS_TYPE_VOLUME) { 2020789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2021789Sahrens "cannot create '%s': " 2022789Sahrens "max volume size is 1TB on 32-bit systems"), 2023789Sahrens path); 2024789Sahrens break; 2025789Sahrens } 2026789Sahrens #endif 2027789Sahrens 2028789Sahrens default: 2029789Sahrens zfs_baderror(errno); 2030789Sahrens } 2031789Sahrens 2032789Sahrens return (-1); 2033789Sahrens } 2034789Sahrens 2035789Sahrens return (0); 2036789Sahrens } 2037789Sahrens 2038789Sahrens /* 2039789Sahrens * Destroys the given dataset. The caller must make sure that the filesystem 2040789Sahrens * isn't mounted, and that there are no active dependents. 2041789Sahrens */ 2042789Sahrens int 2043789Sahrens zfs_destroy(zfs_handle_t *zhp) 2044789Sahrens { 2045789Sahrens zfs_cmd_t zc = { 0 }; 2046789Sahrens int ret; 2047789Sahrens 2048789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2049789Sahrens 2050789Sahrens /* 2051789Sahrens * We use the check for 'zfs_volblocksize' instead of ZFS_TYPE_VOLUME 2052789Sahrens * so that we do the right thing for snapshots of volumes. 2053789Sahrens */ 2054789Sahrens if (zhp->zfs_volblocksize != 0) { 2055789Sahrens if (zvol_remove_link(zhp->zfs_name) != 0) 2056789Sahrens return (-1); 2057789Sahrens 2058789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2059789Sahrens } else { 2060789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2061789Sahrens } 2062789Sahrens 20631544Seschrock ret = zfs_ioctl(ZFS_IOC_DESTROY, &zc); 2064789Sahrens 2065789Sahrens if (ret != 0) { 2066789Sahrens switch (errno) { 2067789Sahrens 2068789Sahrens case EPERM: 2069789Sahrens /* 2070789Sahrens * We don't have permission to destroy this dataset. 2071789Sahrens */ 2072789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2073789Sahrens "cannot destroy '%s': permission denied"), 2074789Sahrens zhp->zfs_name); 2075789Sahrens break; 2076789Sahrens 2077789Sahrens case ENOENT: 2078789Sahrens /* 2079789Sahrens * We've hit a race condition where the dataset has been 2080789Sahrens * destroyed since we opened it. 2081789Sahrens */ 2082789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2083789Sahrens "cannot destroy '%s': no such %s"), 2084789Sahrens zhp->zfs_name, zfs_type_to_name(zhp->zfs_type)); 2085789Sahrens break; 2086789Sahrens 2087789Sahrens case EBUSY: 2088789Sahrens /* 2089789Sahrens * Even if we destroy all children, there is a chance we 2090789Sahrens * can hit this case if: 2091789Sahrens * 2092789Sahrens * - A child dataset has since been created 2093789Sahrens * - A filesystem is mounted 2094789Sahrens * 2095789Sahrens * This error message is awful, but hopefully we've 2096789Sahrens * already caught the common cases (and aborted more 2097789Sahrens * appropriately) before calling this function. There's 2098789Sahrens * nothing else we can do at this point. 2099789Sahrens */ 2100789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2101789Sahrens "cannot destroy '%s': %s is busy"), 2102789Sahrens zhp->zfs_name, zfs_type_to_name(zhp->zfs_type)); 2103789Sahrens break; 2104789Sahrens 2105789Sahrens default: 2106789Sahrens zfs_baderror(errno); 2107789Sahrens } 2108789Sahrens 2109789Sahrens return (-1); 2110789Sahrens } 2111789Sahrens 2112789Sahrens remove_mountpoint(zhp); 2113789Sahrens 2114789Sahrens return (0); 2115789Sahrens } 2116789Sahrens 2117789Sahrens /* 2118789Sahrens * Clones the given dataset. The target must be of the same type as the source. 2119789Sahrens */ 2120789Sahrens int 2121789Sahrens zfs_clone(zfs_handle_t *zhp, const char *target) 2122789Sahrens { 2123789Sahrens char reason[64]; 2124789Sahrens zfs_cmd_t zc = { 0 }; 2125789Sahrens char parent[ZFS_MAXNAMELEN]; 2126789Sahrens int ret; 2127789Sahrens 2128789Sahrens assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 2129789Sahrens 2130789Sahrens /* validate the target name */ 2131789Sahrens if (!zfs_validate_name(target, ZFS_TYPE_FILESYSTEM, reason, 2132789Sahrens sizeof (reason))) { 2133789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2134789Sahrens "cannot create '%s': %s in filesystem name"), target, 2135789Sahrens reason, zfs_type_to_name(ZFS_TYPE_FILESYSTEM)); 2136789Sahrens return (-1); 2137789Sahrens } 2138789Sahrens 2139789Sahrens /* validate parents exist */ 2140789Sahrens if (check_parents(target, zhp->zfs_type) != 0) 2141789Sahrens return (-1); 2142789Sahrens 2143789Sahrens (void) parent_name(target, parent, sizeof (parent)); 2144789Sahrens 2145789Sahrens /* do the clone */ 2146789Sahrens if (zhp->zfs_volblocksize != 0) 2147789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2148789Sahrens else 2149789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2150789Sahrens 2151789Sahrens (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name)); 2152789Sahrens (void) strlcpy(zc.zc_filename, zhp->zfs_name, sizeof (zc.zc_filename)); 21531544Seschrock ret = zfs_ioctl(ZFS_IOC_CREATE, &zc); 2154789Sahrens 2155789Sahrens if (ret != 0) { 2156789Sahrens switch (errno) { 2157789Sahrens case EPERM: 2158789Sahrens /* 2159789Sahrens * The user doesn't have permission to create the clone. 2160789Sahrens */ 2161789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2162789Sahrens "cannot create '%s': permission denied"), 2163789Sahrens target); 2164789Sahrens break; 2165789Sahrens 2166789Sahrens case ENOENT: 2167789Sahrens /* 2168789Sahrens * The parent doesn't exist. We should have caught this 2169789Sahrens * above, but there may a race condition that has since 2170789Sahrens * destroyed the parent. 2171789Sahrens * 2172789Sahrens * At this point, we don't know whether it's the source 2173789Sahrens * that doesn't exist anymore, or whether the target 2174789Sahrens * dataset doesn't exist. 2175789Sahrens */ 2176789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2177789Sahrens "cannot create '%s': no such parent '%s'"), 2178789Sahrens target, parent); 2179789Sahrens break; 2180789Sahrens 2181789Sahrens case EDQUOT: 2182789Sahrens case ENOSPC: 2183789Sahrens /* 2184789Sahrens * There is not enough space in the target dataset 2185789Sahrens */ 2186789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2187789Sahrens "cannot create '%s': not enough space in '%s'"), 2188789Sahrens target, parent); 2189789Sahrens break; 2190789Sahrens 2191789Sahrens case EEXIST: 2192789Sahrens /* 2193789Sahrens * The target already exists. 2194789Sahrens */ 2195789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2196789Sahrens "cannot create '%s': dataset exists"), target); 2197789Sahrens break; 2198789Sahrens 2199789Sahrens case EXDEV: 2200789Sahrens /* 2201789Sahrens * The source and target pools differ. 2202789Sahrens */ 2203789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2204789Sahrens "source and target pools differ"), target); 2205789Sahrens break; 2206789Sahrens 2207789Sahrens default: 2208789Sahrens zfs_baderror(errno); 2209789Sahrens } 2210789Sahrens } else if (zhp->zfs_volblocksize != 0) { 2211789Sahrens ret = zvol_create_link(target); 2212789Sahrens } 2213789Sahrens 2214789Sahrens return (ret); 2215789Sahrens } 2216789Sahrens 2217789Sahrens /* 2218789Sahrens * Takes a snapshot of the given dataset 2219789Sahrens */ 2220789Sahrens int 2221789Sahrens zfs_snapshot(const char *path) 2222789Sahrens { 2223789Sahrens char reason[64]; 2224789Sahrens const char *delim; 2225789Sahrens char *parent; 2226789Sahrens zfs_handle_t *zhp; 2227789Sahrens zfs_cmd_t zc = { 0 }; 2228789Sahrens int ret; 2229789Sahrens 2230789Sahrens /* validate the snapshot name */ 2231789Sahrens if (!zfs_validate_name(path, ZFS_TYPE_SNAPSHOT, reason, 2232789Sahrens sizeof (reason))) { 2233789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2234789Sahrens "cannot snapshot '%s': %s in snapshot name"), path, 2235789Sahrens reason); 2236789Sahrens return (-1); 2237789Sahrens } 2238789Sahrens 2239789Sahrens /* make sure we have a snapshot */ 2240789Sahrens if ((delim = strchr(path, '@')) == NULL) { 2241789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2242789Sahrens "cannot snapshot '%s': missing '@' delim in snapshot " 2243789Sahrens "name"), path); 2244789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2245789Sahrens "use 'zfs create' to create a filesystem")); 2246789Sahrens return (-1); 2247789Sahrens } 2248789Sahrens 2249789Sahrens /* make sure the parent exists and is of the appropriate type */ 2250789Sahrens parent = zfs_malloc(delim - path + 1); 2251789Sahrens (void) strncpy(parent, path, delim - path); 2252789Sahrens parent[delim - path] = '\0'; 2253789Sahrens 2254789Sahrens if ((zhp = zfs_open(parent, ZFS_TYPE_FILESYSTEM | 2255789Sahrens ZFS_TYPE_VOLUME)) == NULL) { 2256789Sahrens free(parent); 2257789Sahrens return (-1); 2258789Sahrens } 2259789Sahrens 2260789Sahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 2261789Sahrens 2262789Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) 2263789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2264789Sahrens else 2265789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2266789Sahrens 22671544Seschrock ret = zfs_ioctl(ZFS_IOC_CREATE, &zc); 2268789Sahrens 2269789Sahrens if (ret == 0 && zhp->zfs_type == ZFS_TYPE_VOLUME) { 2270789Sahrens ret = zvol_create_link(path); 2271789Sahrens if (ret != 0) 22721544Seschrock (void) zfs_ioctl(ZFS_IOC_DESTROY, &zc); 2273789Sahrens } 2274789Sahrens 2275789Sahrens if (ret != 0) { 2276789Sahrens switch (errno) { 2277789Sahrens case EPERM: 2278789Sahrens /* 2279789Sahrens * User doesn't have permission to create a snapshot 2280789Sahrens */ 2281789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2282789Sahrens "permission denied"), path); 2283789Sahrens break; 2284789Sahrens 2285789Sahrens case EDQUOT: 2286789Sahrens case ENOSPC: 2287789Sahrens /* 2288789Sahrens * Out of space in parent. 2289789Sahrens */ 2290789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2291789Sahrens "not enough space in '%s'"), path, parent); 2292789Sahrens break; 2293789Sahrens 2294789Sahrens case EEXIST: 2295789Sahrens /* 2296789Sahrens * Snapshot already exists. 2297789Sahrens */ 2298789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2299789Sahrens "snapshot exists"), path); 2300789Sahrens break; 2301789Sahrens 2302789Sahrens case ENOENT: 2303789Sahrens /* 2304789Sahrens * Shouldn't happen because we verified the parent 2305789Sahrens * above. But there may be a race condition where it 2306789Sahrens * has since been removed. 2307789Sahrens */ 2308789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': " 2309789Sahrens "no such %s"), parent, 2310789Sahrens zfs_type_to_name(zhp->zfs_type)); 2311789Sahrens break; 2312789Sahrens 2313789Sahrens default: 2314789Sahrens zfs_baderror(errno); 2315789Sahrens } 2316789Sahrens } 2317789Sahrens 2318789Sahrens free(parent); 2319789Sahrens zfs_close(zhp); 2320789Sahrens 2321789Sahrens return (ret); 2322789Sahrens } 2323789Sahrens 2324789Sahrens /* 2325789Sahrens * Dumps a backup of tosnap, incremental from fromsnap if it isn't NULL. 2326789Sahrens */ 2327789Sahrens int 23281749Sahrens zfs_send(zfs_handle_t *zhp_to, zfs_handle_t *zhp_from) 2329789Sahrens { 2330789Sahrens zfs_cmd_t zc = { 0 }; 2331789Sahrens int ret; 2332789Sahrens 2333789Sahrens /* do the ioctl() */ 2334789Sahrens (void) strlcpy(zc.zc_name, zhp_to->zfs_name, sizeof (zc.zc_name)); 2335789Sahrens if (zhp_from) { 2336789Sahrens (void) strlcpy(zc.zc_prop_value, zhp_from->zfs_name, 2337789Sahrens sizeof (zc.zc_name)); 2338789Sahrens } else { 2339789Sahrens zc.zc_prop_value[0] = '\0'; 2340789Sahrens } 2341789Sahrens zc.zc_cookie = STDOUT_FILENO; 2342789Sahrens 23431544Seschrock ret = zfs_ioctl(ZFS_IOC_SENDBACKUP, &zc); 2344789Sahrens if (ret != 0) { 2345789Sahrens switch (errno) { 2346789Sahrens case EPERM: 2347789Sahrens /* 23481749Sahrens * User doesn't have permission to do a send 2349789Sahrens */ 23501749Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot send '%s': " 2351789Sahrens "permission denied"), zhp_to->zfs_name); 2352789Sahrens break; 2353789Sahrens 2354789Sahrens case EXDEV: 2355789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 23561749Sahrens "cannot send incremental from %s:\n" 2357789Sahrens "it is not an earlier snapshot from the " 2358789Sahrens "same fs as %s"), 2359789Sahrens zhp_from->zfs_name, zhp_to->zfs_name); 2360789Sahrens break; 2361789Sahrens 2362789Sahrens case ENOENT: 2363789Sahrens /* 2364789Sahrens * Shouldn't happen because we verified the parent 2365789Sahrens * above. But there may be a race condition where it 2366789Sahrens * has since been removed. 2367789Sahrens */ 2368789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open: " 2369789Sahrens "no such snapshot")); 2370789Sahrens break; 2371789Sahrens 2372789Sahrens case EDQUOT: 2373789Sahrens case EFBIG: 2374789Sahrens case EIO: 2375789Sahrens case ENOLINK: 2376789Sahrens case ENOSPC: 2377789Sahrens case ENOSTR: 2378789Sahrens case ENXIO: 2379789Sahrens case EPIPE: 2380789Sahrens case ERANGE: 2381789Sahrens case EFAULT: 2382789Sahrens case EROFS: 2383789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 23841749Sahrens "cannot write stream: %s"), 2385789Sahrens strerror(errno)); 2386789Sahrens break; 2387789Sahrens 2388789Sahrens case EINTR: 2389789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 23901749Sahrens "send failed: signal received")); 2391789Sahrens break; 2392789Sahrens 2393789Sahrens default: 2394789Sahrens zfs_baderror(errno); 2395789Sahrens } 2396789Sahrens } 2397789Sahrens 2398789Sahrens return (ret); 2399789Sahrens } 2400789Sahrens 2401789Sahrens /* 2402789Sahrens * Restores a backup of tosnap from stdin. 2403789Sahrens */ 2404789Sahrens int 24051749Sahrens zfs_receive(const char *tosnap, int isprefix, int verbose, int dryrun) 2406789Sahrens { 2407789Sahrens zfs_cmd_t zc = { 0 }; 2408789Sahrens time_t begin_time; 2409868Sahrens int ioctl_err, err, bytes, size; 2410789Sahrens char *cp; 2411789Sahrens dmu_replay_record_t drr; 2412789Sahrens struct drr_begin *drrb = &zc.zc_begin_record; 2413789Sahrens 2414789Sahrens begin_time = time(NULL); 2415789Sahrens 2416789Sahrens /* trim off snapname, if any */ 2417789Sahrens (void) strcpy(zc.zc_name, tosnap); 2418789Sahrens cp = strchr(zc.zc_name, '@'); 2419789Sahrens if (cp) 2420789Sahrens *cp = '\0'; 2421789Sahrens 2422789Sahrens /* read in the BEGIN record */ 2423789Sahrens cp = (char *)&drr; 2424789Sahrens bytes = 0; 2425789Sahrens do { 2426868Sahrens size = read(STDIN_FILENO, cp, sizeof (drr) - bytes); 2427868Sahrens cp += size; 2428868Sahrens bytes += size; 2429868Sahrens } while (size > 0); 2430868Sahrens 2431868Sahrens if (size < 0 || bytes != sizeof (drr)) { 2432789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 24331749Sahrens "cannot receive: invalid stream " 2434789Sahrens "(couldn't read first record)")); 2435789Sahrens return (-1); 2436789Sahrens } 2437789Sahrens 2438789Sahrens zc.zc_begin_record = drr.drr_u.drr_begin; 2439789Sahrens 2440789Sahrens if (drrb->drr_magic != DMU_BACKUP_MAGIC && 2441789Sahrens drrb->drr_magic != BSWAP_64(DMU_BACKUP_MAGIC)) { 2442789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 24431749Sahrens "cannot receive: invalid stream " 2444789Sahrens "(invalid magic number)")); 2445789Sahrens return (-1); 2446789Sahrens } 2447789Sahrens 2448789Sahrens if (drrb->drr_version != DMU_BACKUP_VERSION && 2449789Sahrens drrb->drr_version != BSWAP_64(DMU_BACKUP_VERSION)) { 2450789Sahrens if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) 2451789Sahrens drrb->drr_version = BSWAP_64(drrb->drr_version); 2452789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 24531749Sahrens "cannot receive: only stream version 0x%llx is supported, " 2454789Sahrens "stream is version %llx."), 2455789Sahrens DMU_BACKUP_VERSION, drrb->drr_version); 2456789Sahrens return (-1); 2457789Sahrens } 2458789Sahrens 2459789Sahrens /* 2460789Sahrens * Determine name of destination snapshot. 2461789Sahrens */ 24621544Seschrock (void) strcpy(zc.zc_filename, tosnap); 2463789Sahrens if (isprefix) { 2464789Sahrens if (strchr(tosnap, '@') != NULL) { 2465789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 24661749Sahrens "cannot receive: " 2467789Sahrens "argument to -d must be a filesystem")); 2468789Sahrens return (-1); 2469789Sahrens } 2470789Sahrens 2471789Sahrens cp = strchr(drr.drr_u.drr_begin.drr_toname, '/'); 2472789Sahrens if (cp == NULL) 2473789Sahrens cp = drr.drr_u.drr_begin.drr_toname; 2474789Sahrens else 2475789Sahrens cp++; 2476789Sahrens 24771544Seschrock (void) strcat(zc.zc_filename, "/"); 24781544Seschrock (void) strcat(zc.zc_filename, cp); 2479789Sahrens } else if (strchr(tosnap, '@') == NULL) { 2480789Sahrens /* 2481789Sahrens * they specified just a filesystem; tack on the 2482789Sahrens * snapname from the backup. 2483789Sahrens */ 2484789Sahrens cp = strchr(drr.drr_u.drr_begin.drr_toname, '@'); 2485789Sahrens if (cp == NULL || strlen(tosnap) + strlen(cp) >= MAXNAMELEN) { 2486789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 24871749Sahrens "cannot receive: invalid snapshot name")); 2488789Sahrens return (-1); 2489789Sahrens } 24901544Seschrock (void) strcat(zc.zc_filename, cp); 2491789Sahrens } 2492789Sahrens 2493789Sahrens if (drrb->drr_fromguid) { 2494789Sahrens zfs_handle_t *h; 2495789Sahrens /* incremental backup stream */ 2496789Sahrens 2497789Sahrens /* do the ioctl to the containing fs */ 24981544Seschrock (void) strcpy(zc.zc_name, zc.zc_filename); 2499789Sahrens cp = strchr(zc.zc_name, '@'); 2500789Sahrens *cp = '\0'; 2501789Sahrens 2502789Sahrens /* make sure destination fs exists */ 2503789Sahrens h = zfs_open(zc.zc_name, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2504789Sahrens if (h == NULL) { 2505789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 25061749Sahrens "cannot receive incrememtal stream: destination\n" 2507789Sahrens "filesystem %s does not exist"), 2508789Sahrens zc.zc_name); 2509789Sahrens return (-1); 2510789Sahrens } 2511868Sahrens if (!dryrun) { 2512868Sahrens /* unmount destination fs or remove device link. */ 2513868Sahrens if (h->zfs_type == ZFS_TYPE_FILESYSTEM) { 2514868Sahrens (void) zfs_unmount(h, NULL, 0); 2515868Sahrens } else { 2516868Sahrens (void) zvol_remove_link(h->zfs_name); 2517868Sahrens } 2518868Sahrens } 2519789Sahrens zfs_close(h); 2520789Sahrens } else { 2521789Sahrens /* full backup stream */ 2522789Sahrens 25231544Seschrock (void) strcpy(zc.zc_name, zc.zc_filename); 2524868Sahrens 25251749Sahrens /* make sure they aren't trying to receive into the root */ 2526868Sahrens if (strchr(zc.zc_name, '/') == NULL) { 2527789Sahrens cp = strchr(zc.zc_name, '@'); 2528789Sahrens if (cp) 2529789Sahrens *cp = '\0'; 2530789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 25311749Sahrens "cannot receive: destination fs %s already exists"), 2532789Sahrens zc.zc_name); 2533789Sahrens return (-1); 2534789Sahrens } 2535789Sahrens 2536789Sahrens if (isprefix) { 2537868Sahrens zfs_handle_t *h; 2538868Sahrens 2539789Sahrens /* make sure prefix exists */ 25401566Smaybee h = zfs_open(tosnap, ZFS_TYPE_FILESYSTEM); 2541789Sahrens if (h == NULL) { 2542789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 25431749Sahrens "cannot receive: " 25441566Smaybee "%s is an invalid destination"), 2545789Sahrens tosnap); 2546789Sahrens return (-1); 2547789Sahrens } 25481544Seschrock zfs_close(h); 2549789Sahrens 2550789Sahrens /* create any necessary ancestors up to prefix */ 2551868Sahrens zc.zc_objset_type = DMU_OST_ZFS; 25521544Seschrock 2553868Sahrens /* 2554868Sahrens * zc.zc_name is now the full name of the snap 25551544Seschrock * we're restoring into. Attempt to create, 25561544Seschrock * mount, and share any ancestor filesystems, up 25571544Seschrock * to the one that was named. 2558868Sahrens */ 25591544Seschrock for (cp = zc.zc_name + strlen(tosnap) + 1; 25601544Seschrock cp = strchr(cp, '/'); *cp = '/', cp++) { 25611544Seschrock const char *opname; 2562789Sahrens *cp = '\0'; 25631544Seschrock 25641544Seschrock opname = "create"; 25651544Seschrock if (zfs_create(zc.zc_name, ZFS_TYPE_FILESYSTEM, 25661544Seschrock NULL, NULL) != 0) { 25671544Seschrock if (errno == EEXIST) 25681544Seschrock continue; 25691544Seschrock goto ancestorerr; 2570789Sahrens } 25711544Seschrock 25721544Seschrock opname = "open"; 25731544Seschrock h = zfs_open(zc.zc_name, ZFS_TYPE_FILESYSTEM); 25741544Seschrock if (h == NULL) 25751544Seschrock goto ancestorerr; 25761544Seschrock 25771544Seschrock opname = "mount"; 25781544Seschrock if (zfs_mount(h, NULL, 0) != 0) 25791544Seschrock goto ancestorerr; 25801544Seschrock 25811544Seschrock opname = "share"; 25821544Seschrock if (zfs_share(h) != 0) 25831544Seschrock goto ancestorerr; 25841544Seschrock 25851544Seschrock zfs_close(h); 25861544Seschrock 25871544Seschrock continue; 25881544Seschrock ancestorerr: 25891544Seschrock zfs_error(dgettext(TEXT_DOMAIN, 25901749Sahrens "cannot receive: couldn't %s ancestor %s"), 25911544Seschrock opname, zc.zc_name); 25921544Seschrock return (-1); 2593789Sahrens } 2594789Sahrens } 2595868Sahrens 2596868Sahrens /* Make sure destination fs does not exist */ 2597868Sahrens cp = strchr(zc.zc_name, '@'); 2598868Sahrens *cp = '\0'; 25991544Seschrock if (zfs_ioctl(ZFS_IOC_OBJSET_STATS, &zc) == 0) { 2600868Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26011749Sahrens "cannot receive full stream: " 2602868Sahrens "destination filesystem %s already exists"), 2603868Sahrens zc.zc_name); 2604868Sahrens return (-1); 2605868Sahrens } 2606868Sahrens 2607868Sahrens /* Do the recvbackup ioctl to the fs's parent. */ 2608868Sahrens cp = strrchr(zc.zc_name, '/'); 2609868Sahrens *cp = '\0'; 2610789Sahrens } 2611789Sahrens 2612789Sahrens (void) strcpy(zc.zc_prop_value, tosnap); 2613789Sahrens zc.zc_cookie = STDIN_FILENO; 2614789Sahrens zc.zc_intsz = isprefix; 2615789Sahrens if (verbose) { 26161749Sahrens (void) printf("%s %s stream of %s into %s\n", 26171749Sahrens dryrun ? "would receive" : "receiving", 2618789Sahrens drrb->drr_fromguid ? "incremental" : "full", 2619789Sahrens drr.drr_u.drr_begin.drr_toname, 26201544Seschrock zc.zc_filename); 2621789Sahrens (void) fflush(stdout); 2622789Sahrens } 2623789Sahrens if (dryrun) 2624789Sahrens return (0); 26251544Seschrock err = ioctl_err = zfs_ioctl(ZFS_IOC_RECVBACKUP, &zc); 2626868Sahrens if (ioctl_err != 0) { 2627789Sahrens switch (errno) { 2628789Sahrens case ENODEV: 2629789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26301749Sahrens "cannot receive: " 2631868Sahrens "most recent snapshot does not " 26321749Sahrens "match incremental source")); 2633789Sahrens break; 2634789Sahrens case ETXTBSY: 2635789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26361749Sahrens "cannot receive: " 2637868Sahrens "destination has been modified since " 2638868Sahrens "most recent snapshot --\n" 2639868Sahrens "use 'zfs rollback' to discard changes")); 2640789Sahrens break; 2641789Sahrens case EEXIST: 2642789Sahrens if (drrb->drr_fromguid == 0) { 2643789Sahrens /* it's the containing fs that exists */ 26441544Seschrock cp = strchr(zc.zc_filename, '@'); 2645789Sahrens *cp = '\0'; 2646789Sahrens } 2647789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26481749Sahrens "cannot receive to %s: destination already exists"), 26491544Seschrock zc.zc_filename); 2650789Sahrens break; 2651789Sahrens case ENOENT: 2652789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26531749Sahrens "cannot receive: destination does not exist")); 2654789Sahrens break; 2655789Sahrens case EBUSY: 2656789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26571749Sahrens "cannot receive: destination is in use")); 2658789Sahrens break; 2659789Sahrens case ENOSPC: 2660789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26611749Sahrens "cannot receive: out of space")); 2662789Sahrens break; 2663789Sahrens case EDQUOT: 2664789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26651749Sahrens "cannot receive: quota exceeded")); 2666789Sahrens break; 2667789Sahrens case EINTR: 2668789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26691749Sahrens "receive failed: signal received")); 2670789Sahrens break; 2671789Sahrens case EINVAL: 2672789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26731749Sahrens "cannot receive: invalid stream")); 2674868Sahrens break; 26751544Seschrock case ECKSUM: 26761544Seschrock zfs_error(dgettext(TEXT_DOMAIN, 26771749Sahrens "cannot receive: invalid stream " 26781544Seschrock "(checksum mismatch)")); 26791544Seschrock break; 2680868Sahrens case EPERM: 2681868Sahrens zfs_error(dgettext(TEXT_DOMAIN, 26821749Sahrens "cannot receive: permission denied")); 2683789Sahrens break; 2684789Sahrens default: 2685789Sahrens zfs_baderror(errno); 2686789Sahrens } 2687789Sahrens } 2688789Sahrens 2689789Sahrens /* 2690868Sahrens * Mount or recreate the /dev links for the target filesystem 2691868Sahrens * (if created, or if we tore them down to do an incremental 2692868Sahrens * restore), and the /dev links for the new snapshot (if 2693868Sahrens * created). 2694789Sahrens */ 26951544Seschrock cp = strchr(zc.zc_filename, '@'); 2696868Sahrens if (cp && (ioctl_err == 0 || drrb->drr_fromguid)) { 2697789Sahrens zfs_handle_t *h; 2698789Sahrens 2699789Sahrens *cp = '\0'; 27001544Seschrock h = zfs_open(zc.zc_filename, 2701789Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2702868Sahrens *cp = '@'; 2703789Sahrens if (h) { 2704868Sahrens if (h->zfs_type == ZFS_TYPE_FILESYSTEM) { 2705789Sahrens err = zfs_mount(h, NULL, 0); 2706868Sahrens } else { 2707789Sahrens err = zvol_create_link(h->zfs_name); 27081544Seschrock if (err == 0 && ioctl_err == 0) 27091544Seschrock err = zvol_create_link(zc.zc_filename); 2710868Sahrens } 2711789Sahrens zfs_close(h); 2712789Sahrens } 2713789Sahrens } 2714789Sahrens 2715868Sahrens if (err || ioctl_err) 2716868Sahrens return (-1); 2717789Sahrens 2718789Sahrens if (verbose) { 2719789Sahrens char buf1[64]; 2720789Sahrens char buf2[64]; 2721789Sahrens uint64_t bytes = zc.zc_cookie; 2722789Sahrens time_t delta = time(NULL) - begin_time; 2723789Sahrens if (delta == 0) 2724789Sahrens delta = 1; 2725789Sahrens zfs_nicenum(bytes, buf1, sizeof (buf1)); 2726789Sahrens zfs_nicenum(bytes/delta, buf2, sizeof (buf1)); 2727789Sahrens 27281749Sahrens (void) printf("received %sb stream in %lu seconds (%sb/sec)\n", 2729789Sahrens buf1, delta, buf2); 2730789Sahrens } 2731789Sahrens return (0); 2732789Sahrens } 2733789Sahrens 2734789Sahrens /* 27351294Slling * Destroy any more recent snapshots. We invoke this callback on any dependents 27361294Slling * of the snapshot first. If the 'cb_dependent' member is non-zero, then this 27371294Slling * is a dependent and we should just destroy it without checking the transaction 27381294Slling * group. 2739789Sahrens */ 27401294Slling typedef struct rollback_data { 27411294Slling const char *cb_target; /* the snapshot */ 27421294Slling uint64_t cb_create; /* creation time reference */ 27431294Slling prop_changelist_t *cb_clp; /* changelist pointer */ 27441294Slling int cb_error; 27451294Slling int cb_dependent; 27461294Slling } rollback_data_t; 27471294Slling 27481294Slling static int 27491294Slling rollback_destroy(zfs_handle_t *zhp, void *data) 27501294Slling { 27511294Slling rollback_data_t *cbp = data; 27521294Slling 27531294Slling if (!cbp->cb_dependent) { 27541294Slling if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 && 27551294Slling zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && 27561294Slling zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > 27571294Slling cbp->cb_create) { 27581294Slling 27591294Slling cbp->cb_dependent = TRUE; 27601294Slling (void) zfs_iter_dependents(zhp, rollback_destroy, cbp); 27611294Slling cbp->cb_dependent = FALSE; 27621294Slling 27631294Slling if (zfs_destroy(zhp) != 0) 27641294Slling cbp->cb_error = 1; 27651294Slling else 27661294Slling changelist_remove(zhp, cbp->cb_clp); 27671294Slling } 27681294Slling } else { 27691294Slling if (zfs_destroy(zhp) != 0) 27701294Slling cbp->cb_error = 1; 27711294Slling else 27721294Slling changelist_remove(zhp, cbp->cb_clp); 27731294Slling } 27741294Slling 27751294Slling zfs_close(zhp); 27761294Slling return (0); 27771294Slling } 27781294Slling 27791294Slling /* 27801294Slling * Rollback the dataset to its latest snapshot. 27811294Slling */ 27821294Slling static int 27831294Slling do_rollback(zfs_handle_t *zhp) 2784789Sahrens { 2785789Sahrens int ret; 2786789Sahrens zfs_cmd_t zc = { 0 }; 2787789Sahrens 2788789Sahrens assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM || 2789789Sahrens zhp->zfs_type == ZFS_TYPE_VOLUME); 2790789Sahrens 2791789Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME && 2792789Sahrens zvol_remove_link(zhp->zfs_name) != 0) 2793789Sahrens return (-1); 2794789Sahrens 2795789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2796789Sahrens 2797789Sahrens if (zhp->zfs_volblocksize != 0) 2798789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2799789Sahrens else 2800789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2801789Sahrens 2802789Sahrens /* 2803789Sahrens * We rely on the consumer to verify that there are no newer snapshots 2804789Sahrens * for the given dataset. Given these constraints, we can simply pass 2805789Sahrens * the name on to the ioctl() call. There is still an unlikely race 2806789Sahrens * condition where the user has taken a snapshot since we verified that 2807789Sahrens * this was the most recent. 2808789Sahrens */ 28091544Seschrock if ((ret = zfs_ioctl(ZFS_IOC_ROLLBACK, &zc)) != 0) { 2810789Sahrens switch (errno) { 2811789Sahrens case EPERM: 2812789Sahrens /* 2813789Sahrens * The user doesn't have permission to rollback the 2814789Sahrens * given dataset. 2815789Sahrens */ 2816789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rollback '%s': " 2817789Sahrens "permission denied"), zhp->zfs_name); 2818789Sahrens break; 2819789Sahrens 2820789Sahrens case EDQUOT: 2821789Sahrens case ENOSPC: 2822789Sahrens /* 2823789Sahrens * The parent dataset doesn't have enough space to 2824789Sahrens * rollback to the last snapshot. 2825789Sahrens */ 2826789Sahrens { 2827789Sahrens char parent[ZFS_MAXNAMELEN]; 2828789Sahrens (void) parent_name(zhp->zfs_name, parent, 2829789Sahrens sizeof (parent)); 2830789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 2831789Sahrens "rollback '%s': out of space"), parent); 2832789Sahrens } 2833789Sahrens break; 2834789Sahrens 2835789Sahrens case ENOENT: 2836789Sahrens /* 2837789Sahrens * The dataset doesn't exist. This shouldn't happen 2838789Sahrens * except in race conditions. 2839789Sahrens */ 2840789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rollback '%s': " 2841789Sahrens "no such %s"), zhp->zfs_name, 2842789Sahrens zfs_type_to_name(zhp->zfs_type)); 2843789Sahrens break; 2844789Sahrens 2845789Sahrens case EBUSY: 2846789Sahrens /* 2847789Sahrens * The filesystem is busy. This should have been caught 2848789Sahrens * by the caller before getting here, but there may be 2849789Sahrens * an unexpected problem. 2850789Sahrens */ 2851789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rollback '%s': " 2852789Sahrens "%s is busy"), zhp->zfs_name, 2853789Sahrens zfs_type_to_name(zhp->zfs_type)); 2854789Sahrens break; 2855789Sahrens 2856789Sahrens default: 2857789Sahrens zfs_baderror(errno); 2858789Sahrens } 2859789Sahrens } else if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 2860789Sahrens ret = zvol_create_link(zhp->zfs_name); 2861789Sahrens } 2862789Sahrens 2863789Sahrens return (ret); 2864789Sahrens } 2865789Sahrens 2866789Sahrens /* 28671294Slling * Given a dataset, rollback to a specific snapshot, discarding any 28681294Slling * data changes since then and making it the active dataset. 28691294Slling * 28701294Slling * Any snapshots more recent than the target are destroyed, along with 28711294Slling * their dependents. 28721294Slling */ 28731294Slling int 28741294Slling zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, int flag) 28751294Slling { 28761294Slling int ret; 28771294Slling rollback_data_t cb = { 0 }; 28781294Slling prop_changelist_t *clp; 28791294Slling 28801294Slling /* 28811294Slling * Unmount all dependendents of the dataset and the dataset itself. 28821294Slling * The list we need to gather is the same as for doing rename 28831294Slling */ 28841294Slling clp = changelist_gather(zhp, ZFS_PROP_NAME, flag ? MS_FORCE: 0); 28851294Slling if (clp == NULL) 28861294Slling return (-1); 28871294Slling 28881294Slling if ((ret = changelist_prefix(clp)) != 0) 28891294Slling goto out; 28901294Slling 28911294Slling /* 28921294Slling * Destroy all recent snapshots and its dependends. 28931294Slling */ 28941294Slling cb.cb_target = snap->zfs_name; 28951294Slling cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG); 28961294Slling cb.cb_clp = clp; 28971294Slling (void) zfs_iter_children(zhp, rollback_destroy, &cb); 28981294Slling 28991294Slling if ((ret = cb.cb_error) != 0) { 29001294Slling (void) changelist_postfix(clp); 29011294Slling goto out; 29021294Slling } 29031294Slling 29041294Slling /* 29051294Slling * Now that we have verified that the snapshot is the latest, 29061294Slling * rollback to the given snapshot. 29071294Slling */ 29081294Slling ret = do_rollback(zhp); 29091294Slling 29101294Slling if (ret != 0) { 29111294Slling (void) changelist_postfix(clp); 29121294Slling goto out; 29131294Slling } 29141294Slling 29151294Slling /* 29161294Slling * We only want to re-mount the filesystem if it was mounted in the 29171294Slling * first place. 29181294Slling */ 29191294Slling ret = changelist_postfix(clp); 29201294Slling 29211294Slling out: 29221294Slling changelist_free(clp); 29231294Slling return (ret); 29241294Slling } 29251294Slling 29261294Slling /* 2927789Sahrens * Iterate over all dependents for a given dataset. This includes both 2928789Sahrens * hierarchical dependents (children) and data dependents (snapshots and 2929789Sahrens * clones). The bulk of the processing occurs in get_dependents() in 2930789Sahrens * libzfs_graph.c. 2931789Sahrens */ 2932789Sahrens int 2933789Sahrens zfs_iter_dependents(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2934789Sahrens { 2935789Sahrens char **dependents; 2936789Sahrens size_t count; 2937789Sahrens int i; 2938789Sahrens zfs_handle_t *child; 2939789Sahrens int ret = 0; 2940789Sahrens 2941789Sahrens dependents = get_dependents(zhp->zfs_name, &count); 2942789Sahrens for (i = 0; i < count; i++) { 2943789Sahrens if ((child = make_dataset_handle(dependents[i])) == NULL) 2944789Sahrens continue; 2945789Sahrens 2946789Sahrens if ((ret = func(child, data)) != 0) 2947789Sahrens break; 2948789Sahrens } 2949789Sahrens 2950789Sahrens for (i = 0; i < count; i++) 2951789Sahrens free(dependents[i]); 2952789Sahrens free(dependents); 2953789Sahrens 2954789Sahrens return (ret); 2955789Sahrens } 2956789Sahrens 2957789Sahrens /* 2958789Sahrens * Renames the given dataset. 2959789Sahrens */ 2960789Sahrens int 2961789Sahrens zfs_rename(zfs_handle_t *zhp, const char *target) 2962789Sahrens { 2963789Sahrens int ret; 2964789Sahrens zfs_cmd_t zc = { 0 }; 2965789Sahrens char reason[64]; 2966789Sahrens char *delim; 2967789Sahrens prop_changelist_t *cl; 2968789Sahrens char parent[ZFS_MAXNAMELEN]; 2969789Sahrens 2970789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2971789Sahrens (void) strlcpy(zc.zc_prop_value, target, sizeof (zc.zc_prop_value)); 2972789Sahrens 2973789Sahrens /* if we have the same exact name, just return success */ 2974789Sahrens if (strcmp(zhp->zfs_name, target) == 0) 2975789Sahrens return (0); 2976789Sahrens 2977789Sahrens /* 2978789Sahrens * Make sure the target name is valid 2979789Sahrens */ 2980789Sahrens if (!zfs_validate_name(target, zhp->zfs_type, reason, 2981789Sahrens sizeof (reason))) { 2982789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2983789Sahrens "cannot create '%s': %s in %s name"), target, reason, 2984789Sahrens zfs_type_to_name(zhp->zfs_type)); 2985789Sahrens return (-1); 2986789Sahrens } 2987789Sahrens 2988789Sahrens if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 2989789Sahrens if ((delim = strchr(target, '@')) == NULL) { 2990789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2991789Sahrens "cannot rename to '%s': not a snapshot"), target); 2992789Sahrens return (-1); 2993789Sahrens } 2994789Sahrens 2995789Sahrens /* 2996789Sahrens * Make sure we're renaming within the same dataset. 2997789Sahrens */ 2998789Sahrens if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 2999789Sahrens zhp->zfs_name[delim - target] != '@') { 3000789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 3001789Sahrens "cannot rename to '%s': snapshots must be part " 3002789Sahrens "of same dataset"), target); 3003789Sahrens return (-1); 3004789Sahrens } 3005789Sahrens 3006789Sahrens (void) strncpy(parent, target, delim - target); 3007789Sahrens parent[delim - target] = '\0'; 3008789Sahrens } else { 3009789Sahrens /* validate parents */ 3010789Sahrens if (check_parents(target, zhp->zfs_type) != 0) 3011789Sahrens return (-1); 3012789Sahrens 3013789Sahrens (void) parent_name(target, parent, sizeof (parent)); 3014789Sahrens 3015789Sahrens /* make sure we're in the same pool */ 3016789Sahrens verify((delim = strchr(target, '/')) != NULL); 3017789Sahrens if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 3018789Sahrens zhp->zfs_name[delim - target] != '/') { 3019789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 3020789Sahrens "cannot rename to '%s': " 3021789Sahrens "datasets must be within same pool"), target); 3022789Sahrens return (-1); 3023789Sahrens } 3024789Sahrens } 3025789Sahrens 3026789Sahrens if (getzoneid() == GLOBAL_ZONEID && 3027789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 3028789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename %s, " 3029789Sahrens "dataset is used in a non-global zone"), zhp->zfs_name); 3030789Sahrens return (-1); 3031789Sahrens } 3032789Sahrens 3033789Sahrens if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0)) == NULL) 3034789Sahrens return (1); 3035789Sahrens 3036789Sahrens if (changelist_haszonedchild(cl)) { 3037789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 3038789Sahrens "cannot rename '%s': child dataset with inherited " 3039789Sahrens "mountpoint is used in a non-global zone"), zhp->zfs_name); 3040789Sahrens ret = -1; 3041789Sahrens goto error; 3042789Sahrens } 3043789Sahrens 3044789Sahrens if ((ret = changelist_prefix(cl)) != 0) 3045789Sahrens goto error; 3046789Sahrens 3047789Sahrens if (zhp->zfs_volblocksize != 0) 3048789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 3049789Sahrens else 3050789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 3051789Sahrens 30521544Seschrock if ((ret = zfs_ioctl(ZFS_IOC_RENAME, &zc)) != 0) { 3053789Sahrens switch (errno) { 3054789Sahrens case EPERM: 3055789Sahrens /* 3056789Sahrens * The user doesn't have permission to rename the 3057789Sahrens * given dataset. 3058789Sahrens */ 3059789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s': " 3060789Sahrens "permission denied"), zhp->zfs_name); 3061789Sahrens break; 3062789Sahrens 3063789Sahrens case EDQUOT: 3064789Sahrens case ENOSPC: 3065789Sahrens /* 3066789Sahrens * Not enough space in the parent dataset. 3067789Sahrens */ 3068789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 3069789Sahrens "rename '%s': not enough space in '%s'"), 3070789Sahrens zhp->zfs_name, parent); 3071789Sahrens break; 3072789Sahrens 3073789Sahrens case ENOENT: 3074789Sahrens /* 3075789Sahrens * The destination doesn't exist. 3076789Sahrens */ 3077789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s' " 3078789Sahrens "to '%s': destination doesn't exist"), 3079789Sahrens zhp->zfs_name, target); 3080789Sahrens break; 3081789Sahrens 3082789Sahrens case EEXIST: 3083789Sahrens /* 3084789Sahrens * The destination already exists. 3085789Sahrens */ 3086789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s' " 3087789Sahrens "to '%s': destination already exists"), 3088789Sahrens zhp->zfs_name, target); 3089789Sahrens break; 3090789Sahrens 3091789Sahrens case EBUSY: 3092789Sahrens /* 3093789Sahrens * The filesystem is busy. This should have been caught 3094789Sahrens * by the caller before getting here, but there may be 3095789Sahrens * an unexpected problem. 3096789Sahrens */ 3097789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s': " 3098789Sahrens "%s is busy"), zhp->zfs_name, 3099789Sahrens zfs_type_to_name(zhp->zfs_type)); 3100789Sahrens break; 3101789Sahrens 3102789Sahrens default: 3103789Sahrens zfs_baderror(errno); 3104789Sahrens } 3105789Sahrens 3106789Sahrens /* 3107789Sahrens * On failure, we still want to remount any filesystems that 3108789Sahrens * were previously mounted, so we don't alter the system state. 3109789Sahrens */ 3110789Sahrens (void) changelist_postfix(cl); 3111789Sahrens } else { 3112789Sahrens changelist_rename(cl, zfs_get_name(zhp), target); 3113789Sahrens 3114789Sahrens ret = changelist_postfix(cl); 3115789Sahrens } 3116789Sahrens 3117789Sahrens error: 3118789Sahrens changelist_free(cl); 3119789Sahrens return (ret); 3120789Sahrens } 3121789Sahrens 3122789Sahrens /* 3123789Sahrens * Given a zvol dataset, issue the ioctl to create the appropriate minor node, 3124789Sahrens * poke devfsadm to create the /dev link, and then wait for the link to appear. 3125789Sahrens */ 3126789Sahrens int 3127789Sahrens zvol_create_link(const char *dataset) 3128789Sahrens { 3129789Sahrens zfs_cmd_t zc = { 0 }; 3130789Sahrens di_devlink_handle_t hdl; 3131789Sahrens 3132789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3133789Sahrens 3134789Sahrens /* 3135789Sahrens * Issue the appropriate ioctl. 3136789Sahrens */ 31371544Seschrock if (zfs_ioctl(ZFS_IOC_CREATE_MINOR, &zc) != 0) { 3138789Sahrens switch (errno) { 3139789Sahrens case EPERM: 3140789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create " 3141789Sahrens "device links for '%s': permission denied"), 3142789Sahrens dataset); 3143789Sahrens break; 3144789Sahrens 3145789Sahrens case EEXIST: 3146789Sahrens /* 3147789Sahrens * Silently ignore the case where the link already 3148789Sahrens * exists. This allows 'zfs volinit' to be run multiple 3149789Sahrens * times without errors. 3150789Sahrens */ 3151789Sahrens return (0); 3152789Sahrens 3153789Sahrens default: 3154789Sahrens zfs_baderror(errno); 3155789Sahrens } 3156789Sahrens 3157789Sahrens return (-1); 3158789Sahrens } 3159789Sahrens 3160789Sahrens /* 3161789Sahrens * Call devfsadm and wait for the links to magically appear. 3162789Sahrens */ 3163789Sahrens if ((hdl = di_devlink_init(ZFS_DRIVER, DI_MAKE_LINK)) == NULL) { 3164789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 3165789Sahrens "cannot create device links for '%s'"), dataset); 31661544Seschrock (void) zfs_ioctl(ZFS_IOC_REMOVE_MINOR, &zc); 3167789Sahrens return (-1); 3168789Sahrens } else { 3169789Sahrens (void) di_devlink_fini(&hdl); 3170789Sahrens } 3171789Sahrens 3172789Sahrens return (0); 3173789Sahrens } 3174789Sahrens 3175789Sahrens /* 3176789Sahrens * Remove a minor node for the given zvol and the associated /dev links. 3177789Sahrens */ 3178789Sahrens int 3179789Sahrens zvol_remove_link(const char *dataset) 3180789Sahrens { 3181789Sahrens zfs_cmd_t zc = { 0 }; 3182789Sahrens 3183789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3184789Sahrens 31851544Seschrock if (zfs_ioctl(ZFS_IOC_REMOVE_MINOR, &zc) != 0) { 3186789Sahrens switch (errno) { 3187789Sahrens case EPERM: 3188789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot remove " 3189789Sahrens "device links for '%s': permission denied"), 3190789Sahrens dataset); 3191789Sahrens break; 3192789Sahrens 3193789Sahrens case EBUSY: 3194789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot remove " 3195789Sahrens "device links for '%s': volume is in use"), 3196789Sahrens dataset); 3197789Sahrens break; 3198789Sahrens 3199789Sahrens case ENXIO: 3200789Sahrens /* 3201789Sahrens * Silently ignore the case where the link no longer 3202789Sahrens * exists, so that 'zfs volfini' can be run multiple 3203789Sahrens * times without errors. 3204789Sahrens */ 3205789Sahrens return (0); 3206789Sahrens 3207789Sahrens default: 3208789Sahrens zfs_baderror(errno); 3209789Sahrens } 3210789Sahrens 3211789Sahrens return (-1); 3212789Sahrens } 3213789Sahrens 3214789Sahrens return (0); 3215789Sahrens } 3216