1*789Sahrens /* 2*789Sahrens * CDDL HEADER START 3*789Sahrens * 4*789Sahrens * The contents of this file are subject to the terms of the 5*789Sahrens * Common Development and Distribution License, Version 1.0 only 6*789Sahrens * (the "License"). You may not use this file except in compliance 7*789Sahrens * with the License. 8*789Sahrens * 9*789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*789Sahrens * or http://www.opensolaris.org/os/licensing. 11*789Sahrens * See the License for the specific language governing permissions 12*789Sahrens * and limitations under the License. 13*789Sahrens * 14*789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15*789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*789Sahrens * If applicable, add the following below this CDDL HEADER, with the 17*789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18*789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19*789Sahrens * 20*789Sahrens * CDDL HEADER END 21*789Sahrens */ 22*789Sahrens /* 23*789Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*789Sahrens * Use is subject to license terms. 25*789Sahrens */ 26*789Sahrens 27*789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28*789Sahrens 29*789Sahrens #include <assert.h> 30*789Sahrens #include <ctype.h> 31*789Sahrens #include <errno.h> 32*789Sahrens #include <libdevinfo.h> 33*789Sahrens #include <libintl.h> 34*789Sahrens #include <math.h> 35*789Sahrens #include <stdio.h> 36*789Sahrens #include <stdlib.h> 37*789Sahrens #include <strings.h> 38*789Sahrens #include <unistd.h> 39*789Sahrens #include <zone.h> 40*789Sahrens #include <sys/mntent.h> 41*789Sahrens #include <sys/mnttab.h> 42*789Sahrens 43*789Sahrens #include <sys/spa.h> 44*789Sahrens #include <sys/zio.h> 45*789Sahrens #include <libzfs.h> 46*789Sahrens 47*789Sahrens #include "zfs_namecheck.h" 48*789Sahrens #include "zfs_prop.h" 49*789Sahrens #include "libzfs_impl.h" 50*789Sahrens 51*789Sahrens /* 52*789Sahrens * Given a single type (not a mask of types), return the type in a human 53*789Sahrens * readable form. 54*789Sahrens */ 55*789Sahrens const char * 56*789Sahrens zfs_type_to_name(zfs_type_t type) 57*789Sahrens { 58*789Sahrens switch (type) { 59*789Sahrens case ZFS_TYPE_FILESYSTEM: 60*789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 61*789Sahrens case ZFS_TYPE_SNAPSHOT: 62*789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 63*789Sahrens case ZFS_TYPE_VOLUME: 64*789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 65*789Sahrens } 66*789Sahrens 67*789Sahrens zfs_baderror(type); 68*789Sahrens return (NULL); 69*789Sahrens } 70*789Sahrens 71*789Sahrens /* 72*789Sahrens * Given a path and mask of ZFS types, return a string describing this dataset. 73*789Sahrens * This is used when we fail to open a dataset and we cannot get an exact type. 74*789Sahrens * We guess what the type would have been based on the path and the mask of 75*789Sahrens * acceptable types. 76*789Sahrens */ 77*789Sahrens static const char * 78*789Sahrens path_to_str(const char *path, int types) 79*789Sahrens { 80*789Sahrens /* 81*789Sahrens * When given a single type, always report the exact type. 82*789Sahrens */ 83*789Sahrens if (types == ZFS_TYPE_SNAPSHOT) 84*789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 85*789Sahrens if (types == ZFS_TYPE_FILESYSTEM) 86*789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 87*789Sahrens if (types == ZFS_TYPE_VOLUME) 88*789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 89*789Sahrens 90*789Sahrens /* 91*789Sahrens * The user is requesting more than one type of dataset. If this is the 92*789Sahrens * case, consult the path itself. If we're looking for a snapshot, and 93*789Sahrens * a '@' is found, then report it as "snapshot". Otherwise, remove the 94*789Sahrens * snapshot attribute and try again. 95*789Sahrens */ 96*789Sahrens if (types & ZFS_TYPE_SNAPSHOT) { 97*789Sahrens if (strchr(path, '@') != NULL) 98*789Sahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 99*789Sahrens return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 100*789Sahrens } 101*789Sahrens 102*789Sahrens 103*789Sahrens /* 104*789Sahrens * The user has requested either filesystems or volumes. 105*789Sahrens * We have no way of knowing a priori what type this would be, so always 106*789Sahrens * report it as "filesystem" or "volume", our two primitive types. 107*789Sahrens */ 108*789Sahrens if (types & ZFS_TYPE_FILESYSTEM) 109*789Sahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 110*789Sahrens 111*789Sahrens assert(types & ZFS_TYPE_VOLUME); 112*789Sahrens return (dgettext(TEXT_DOMAIN, "volume")); 113*789Sahrens } 114*789Sahrens 115*789Sahrens /* 116*789Sahrens * Validate a ZFS path. This is used even before trying to open the dataset, to 117*789Sahrens * provide a more meaningful error message. We place a more useful message in 118*789Sahrens * 'buf' detailing exactly why the name was not valid. 119*789Sahrens */ 120*789Sahrens static int 121*789Sahrens zfs_validate_name(const char *path, int type, char *buf, size_t buflen) 122*789Sahrens { 123*789Sahrens namecheck_err_t why; 124*789Sahrens char what; 125*789Sahrens 126*789Sahrens if (dataset_namecheck(path, &why, &what) != 0) { 127*789Sahrens if (buf != NULL) { 128*789Sahrens switch (why) { 129*789Sahrens case NAME_ERR_LEADING_SLASH: 130*789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 131*789Sahrens "leading slash"), buflen); 132*789Sahrens break; 133*789Sahrens 134*789Sahrens case NAME_ERR_EMPTY_COMPONENT: 135*789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 136*789Sahrens "empty component"), buflen); 137*789Sahrens break; 138*789Sahrens 139*789Sahrens case NAME_ERR_TRAILING_SLASH: 140*789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 141*789Sahrens "trailing slash"), buflen); 142*789Sahrens break; 143*789Sahrens 144*789Sahrens case NAME_ERR_INVALCHAR: 145*789Sahrens (void) snprintf(buf, buflen, 146*789Sahrens dgettext(TEXT_DOMAIN, "invalid character " 147*789Sahrens "'%c'"), what); 148*789Sahrens break; 149*789Sahrens 150*789Sahrens case NAME_ERR_MULTIPLE_AT: 151*789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 152*789Sahrens "multiple '@' delimiters"), buflen); 153*789Sahrens break; 154*789Sahrens } 155*789Sahrens } 156*789Sahrens 157*789Sahrens return (0); 158*789Sahrens } 159*789Sahrens 160*789Sahrens if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) { 161*789Sahrens if (buf != NULL) 162*789Sahrens (void) strlcpy(buf, 163*789Sahrens dgettext(TEXT_DOMAIN, 164*789Sahrens "snapshot delimiter '@'"), buflen); 165*789Sahrens return (0); 166*789Sahrens } 167*789Sahrens 168*789Sahrens return (1); 169*789Sahrens } 170*789Sahrens 171*789Sahrens int 172*789Sahrens zfs_name_valid(const char *name, zfs_type_t type) 173*789Sahrens { 174*789Sahrens return (zfs_validate_name(name, type, NULL, NULL)); 175*789Sahrens } 176*789Sahrens 177*789Sahrens /* 178*789Sahrens * Utility function to gather stats (objset and zpl) for the given object. 179*789Sahrens */ 180*789Sahrens static int 181*789Sahrens get_stats(zfs_handle_t *zhp) 182*789Sahrens { 183*789Sahrens zfs_cmd_t zc = { 0 }; 184*789Sahrens 185*789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 186*789Sahrens 187*789Sahrens /* 188*789Sahrens * get the generic DMU stats and per-type (zfs, zvol) stats 189*789Sahrens */ 190*789Sahrens if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) 191*789Sahrens return (-1); 192*789Sahrens 193*789Sahrens bcopy(&zc.zc_objset_stats, &zhp->zfs_dmustats, 194*789Sahrens sizeof (zc.zc_objset_stats)); 195*789Sahrens 196*789Sahrens bcopy(&zc.zc_zfs_stats, &zhp->zfs_zplstats, sizeof (zc.zc_zfs_stats)); 197*789Sahrens 198*789Sahrens zhp->zfs_volsize = zc.zc_volsize; 199*789Sahrens zhp->zfs_volblocksize = zc.zc_volblocksize; 200*789Sahrens 201*789Sahrens return (0); 202*789Sahrens } 203*789Sahrens 204*789Sahrens /* 205*789Sahrens * Refresh the properties currently stored in the handle. 206*789Sahrens */ 207*789Sahrens void 208*789Sahrens zfs_refresh_properties(zfs_handle_t *zhp) 209*789Sahrens { 210*789Sahrens (void) get_stats(zhp); 211*789Sahrens } 212*789Sahrens 213*789Sahrens /* 214*789Sahrens * Makes a handle from the given dataset name. Used by zfs_open() and 215*789Sahrens * zfs_iter_* to create child handles on the fly. 216*789Sahrens */ 217*789Sahrens zfs_handle_t * 218*789Sahrens make_dataset_handle(const char *path) 219*789Sahrens { 220*789Sahrens zfs_handle_t *zhp = zfs_malloc(sizeof (zfs_handle_t)); 221*789Sahrens 222*789Sahrens (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); 223*789Sahrens 224*789Sahrens if (get_stats(zhp) != 0) { 225*789Sahrens free(zhp); 226*789Sahrens return (NULL); 227*789Sahrens } 228*789Sahrens 229*789Sahrens /* 230*789Sahrens * We've managed to open the dataset and gather statistics. Determine 231*789Sahrens * the high-level type. 232*789Sahrens */ 233*789Sahrens if (zhp->zfs_dmustats.dds_is_snapshot) 234*789Sahrens zhp->zfs_type = ZFS_TYPE_SNAPSHOT; 235*789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 236*789Sahrens zhp->zfs_type = ZFS_TYPE_VOLUME; 237*789Sahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 238*789Sahrens zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 239*789Sahrens else 240*789Sahrens /* we should never see any other dataset types */ 241*789Sahrens zfs_baderror(zhp->zfs_dmustats.dds_type); 242*789Sahrens 243*789Sahrens return (zhp); 244*789Sahrens } 245*789Sahrens 246*789Sahrens /* 247*789Sahrens * Opens the given snapshot, filesystem, or volume. The 'types' 248*789Sahrens * argument is a mask of acceptable types. The function will print an 249*789Sahrens * appropriate error message and return NULL if it can't be opened. 250*789Sahrens */ 251*789Sahrens zfs_handle_t * 252*789Sahrens zfs_open(const char *path, int types) 253*789Sahrens { 254*789Sahrens zfs_handle_t *zhp; 255*789Sahrens 256*789Sahrens /* 257*789Sahrens * If the path is longer than the maximum dataset length, treat it as 258*789Sahrens * ENOENT because we know there can't be any dataset with that path. 259*789Sahrens */ 260*789Sahrens if (strlen(path) >= ZFS_MAXNAMELEN) { 261*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 262*789Sahrens "cannot open '%s': no such %s"), path, 263*789Sahrens path_to_str(path, types)); 264*789Sahrens return (NULL); 265*789Sahrens } 266*789Sahrens 267*789Sahrens /* 268*789Sahrens * Validate the name before we even try to open it. We don't care about 269*789Sahrens * the verbose invalid messages here; just report a generic error. 270*789Sahrens */ 271*789Sahrens if (!zfs_validate_name(path, types, NULL, 0)) { 272*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 273*789Sahrens "cannot open '%s': invalid %s name"), path, 274*789Sahrens path_to_str(path, types)); 275*789Sahrens return (NULL); 276*789Sahrens } 277*789Sahrens 278*789Sahrens /* 279*789Sahrens * Try to get stats for the dataset, which will tell us if it exists. 280*789Sahrens */ 281*789Sahrens errno = 0; 282*789Sahrens if ((zhp = make_dataset_handle(path)) == NULL) { 283*789Sahrens switch (errno) { 284*789Sahrens case ENOENT: 285*789Sahrens /* 286*789Sahrens * The dataset doesn't exist. 287*789Sahrens */ 288*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 289*789Sahrens "cannot open '%s': no such %s"), path, 290*789Sahrens path_to_str(path, types)); 291*789Sahrens break; 292*789Sahrens 293*789Sahrens case EBUSY: 294*789Sahrens /* 295*789Sahrens * We were able to open the dataset but couldn't 296*789Sahrens * get the stats. 297*789Sahrens */ 298*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 299*789Sahrens "cannot open '%s': %s is busy"), path, 300*789Sahrens path_to_str(path, types)); 301*789Sahrens break; 302*789Sahrens 303*789Sahrens default: 304*789Sahrens zfs_baderror(errno); 305*789Sahrens 306*789Sahrens } 307*789Sahrens return (NULL); 308*789Sahrens } 309*789Sahrens 310*789Sahrens if (!(types & zhp->zfs_type)) { 311*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': operation " 312*789Sahrens "not supported for %ss"), path, 313*789Sahrens zfs_type_to_name(zhp->zfs_type)); 314*789Sahrens free(zhp); 315*789Sahrens return (NULL); 316*789Sahrens } 317*789Sahrens 318*789Sahrens return (zhp); 319*789Sahrens } 320*789Sahrens 321*789Sahrens /* 322*789Sahrens * Release a ZFS handle. Nothing to do but free the associated memory. 323*789Sahrens */ 324*789Sahrens void 325*789Sahrens zfs_close(zfs_handle_t *zhp) 326*789Sahrens { 327*789Sahrens if (zhp->zfs_mntopts) 328*789Sahrens free(zhp->zfs_mntopts); 329*789Sahrens free(zhp); 330*789Sahrens } 331*789Sahrens 332*789Sahrens struct { 333*789Sahrens const char *name; 334*789Sahrens uint64_t value; 335*789Sahrens } checksum_table[] = { 336*789Sahrens { "on", ZIO_CHECKSUM_ON }, 337*789Sahrens { "off", ZIO_CHECKSUM_OFF }, 338*789Sahrens { "fletcher2", ZIO_CHECKSUM_FLETCHER_2 }, 339*789Sahrens { "fletcher4", ZIO_CHECKSUM_FLETCHER_4 }, 340*789Sahrens { "sha256", ZIO_CHECKSUM_SHA256 }, 341*789Sahrens { NULL } 342*789Sahrens }; 343*789Sahrens 344*789Sahrens struct { 345*789Sahrens const char *name; 346*789Sahrens uint64_t value; 347*789Sahrens } compress_table[] = { 348*789Sahrens { "on", ZIO_COMPRESS_ON }, 349*789Sahrens { "off", ZIO_COMPRESS_OFF }, 350*789Sahrens { "lzjb", ZIO_COMPRESS_LZJB }, 351*789Sahrens { NULL } 352*789Sahrens }; 353*789Sahrens 354*789Sahrens struct { 355*789Sahrens const char *name; 356*789Sahrens uint64_t value; 357*789Sahrens } snapdir_table[] = { 358*789Sahrens { "hidden", HIDDEN }, 359*789Sahrens { "visible", VISIBLE }, 360*789Sahrens { NULL } 361*789Sahrens }; 362*789Sahrens 363*789Sahrens struct { 364*789Sahrens const char *name; 365*789Sahrens uint64_t value; 366*789Sahrens } acl_mode_table[] = { 367*789Sahrens { "discard", DISCARD }, 368*789Sahrens { "groupmask", GROUPMASK }, 369*789Sahrens { "passthrough", PASSTHROUGH }, 370*789Sahrens { NULL } 371*789Sahrens }; 372*789Sahrens 373*789Sahrens struct { 374*789Sahrens const char *name; 375*789Sahrens uint64_t value; 376*789Sahrens } acl_inherit_table[] = { 377*789Sahrens { "discard", DISCARD }, 378*789Sahrens { "noallow", NOALLOW }, 379*789Sahrens { "secure", SECURE }, 380*789Sahrens { "passthrough", PASSTHROUGH }, 381*789Sahrens { NULL } 382*789Sahrens }; 383*789Sahrens 384*789Sahrens 385*789Sahrens /* 386*789Sahrens * Given a numeric suffix, convert the value into a number of bits that the 387*789Sahrens * resulting value must be shifted. 388*789Sahrens */ 389*789Sahrens static int 390*789Sahrens str2shift(const char *buf, char *reason, size_t len) 391*789Sahrens { 392*789Sahrens const char *ends = "BKMGTPEZ"; 393*789Sahrens int i; 394*789Sahrens 395*789Sahrens if (buf[0] == '\0') 396*789Sahrens return (0); 397*789Sahrens for (i = 0; i < strlen(ends); i++) { 398*789Sahrens if (toupper(buf[0]) == ends[i]) 399*789Sahrens break; 400*789Sahrens } 401*789Sahrens if (i == strlen(ends)) { 402*789Sahrens (void) snprintf(reason, len, dgettext(TEXT_DOMAIN, "invalid " 403*789Sahrens "numeric suffix '%s'"), buf); 404*789Sahrens return (-1); 405*789Sahrens } 406*789Sahrens 407*789Sahrens /* 408*789Sahrens * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 409*789Sahrens * allow 'BB' - that's just weird. 410*789Sahrens */ 411*789Sahrens if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 412*789Sahrens toupper(buf[0]) != 'B')) { 413*789Sahrens return (10*i); 414*789Sahrens } 415*789Sahrens 416*789Sahrens (void) snprintf(reason, len, dgettext(TEXT_DOMAIN, "invalid numeric " 417*789Sahrens "suffix '%s'"), buf); 418*789Sahrens return (-1); 419*789Sahrens } 420*789Sahrens 421*789Sahrens /* 422*789Sahrens * Convert a string of the form '100G' into a real number. Used when setting 423*789Sahrens * properties or creating a volume. 'buf' is used to place an extended error 424*789Sahrens * message for the caller to use. 425*789Sahrens */ 426*789Sahrens static int 427*789Sahrens nicestrtonum(const char *value, uint64_t *num, char *buf, size_t buflen) 428*789Sahrens { 429*789Sahrens char *end; 430*789Sahrens int shift; 431*789Sahrens 432*789Sahrens *num = 0; 433*789Sahrens 434*789Sahrens /* Check to see if this looks like a number. */ 435*789Sahrens if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 436*789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 437*789Sahrens "must be a numeric value"), buflen); 438*789Sahrens return (-1); 439*789Sahrens } 440*789Sahrens 441*789Sahrens /* Rely on stroll() to process the numeric portion. */ 442*789Sahrens errno = 0; 443*789Sahrens *num = strtoll(value, &end, 10); 444*789Sahrens 445*789Sahrens /* 446*789Sahrens * Check for ERANGE, which indicates that the value is too large to fit 447*789Sahrens * in a 64-bit value. 448*789Sahrens */ 449*789Sahrens if (errno == ERANGE) { 450*789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 451*789Sahrens "value is too large"), buflen); 452*789Sahrens return (-1); 453*789Sahrens } 454*789Sahrens 455*789Sahrens /* 456*789Sahrens * If we have a decimal value, then do the computation with floating 457*789Sahrens * point arithmetic. Otherwise, use standard arithmetic. 458*789Sahrens */ 459*789Sahrens if (*end == '.') { 460*789Sahrens double fval = strtod(value, &end); 461*789Sahrens 462*789Sahrens if ((shift = str2shift(end, buf, buflen)) == -1) 463*789Sahrens return (-1); 464*789Sahrens 465*789Sahrens fval *= pow(2, shift); 466*789Sahrens 467*789Sahrens if (fval > UINT64_MAX) { 468*789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 469*789Sahrens "value is too large"), buflen); 470*789Sahrens return (-1); 471*789Sahrens } 472*789Sahrens 473*789Sahrens *num = (uint64_t)fval; 474*789Sahrens } else { 475*789Sahrens if ((shift = str2shift(end, buf, buflen)) == -1) 476*789Sahrens return (-1); 477*789Sahrens 478*789Sahrens /* Check for overflow */ 479*789Sahrens if (shift >= 64 || (*num << shift) >> shift != *num) { 480*789Sahrens (void) strlcpy(buf, dgettext(TEXT_DOMAIN, 481*789Sahrens "value is too large"), buflen); 482*789Sahrens return (-1); 483*789Sahrens } 484*789Sahrens 485*789Sahrens *num <<= shift; 486*789Sahrens } 487*789Sahrens 488*789Sahrens return (0); 489*789Sahrens } 490*789Sahrens 491*789Sahrens int 492*789Sahrens zfs_nicestrtonum(const char *str, uint64_t *val) 493*789Sahrens { 494*789Sahrens char buf[1]; 495*789Sahrens 496*789Sahrens return (nicestrtonum(str, val, buf, sizeof (buf))); 497*789Sahrens } 498*789Sahrens 499*789Sahrens /* 500*789Sahrens * Given a property type and value, verify that the value is appropriate. Used 501*789Sahrens * by zfs_prop_set() and some libzfs consumers. 502*789Sahrens */ 503*789Sahrens int 504*789Sahrens zfs_prop_validate(zfs_prop_t prop, const char *value, uint64_t *intval) 505*789Sahrens { 506*789Sahrens const char *propname = zfs_prop_to_name(prop); 507*789Sahrens uint64_t number; 508*789Sahrens char reason[64]; 509*789Sahrens int i; 510*789Sahrens 511*789Sahrens /* 512*789Sahrens * Check to see if this a read-only property. 513*789Sahrens */ 514*789Sahrens if (zfs_prop_readonly(prop)) { 515*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 516*789Sahrens "cannot set %s property: read-only property"), propname); 517*789Sahrens return (-1); 518*789Sahrens } 519*789Sahrens 520*789Sahrens /* See if the property value is too long */ 521*789Sahrens if (strlen(value) >= ZFS_MAXPROPLEN) { 522*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 523*789Sahrens "bad %s value '%s': value is too long"), propname, 524*789Sahrens value); 525*789Sahrens return (-1); 526*789Sahrens } 527*789Sahrens 528*789Sahrens /* Perform basic checking based on property type */ 529*789Sahrens switch (zfs_prop_get_type(prop)) { 530*789Sahrens case prop_type_boolean: 531*789Sahrens if (strcmp(value, "on") == 0) { 532*789Sahrens number = 1; 533*789Sahrens } else if (strcmp(value, "off") == 0) { 534*789Sahrens number = 0; 535*789Sahrens } else { 536*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 537*789Sahrens "bad %s value '%s': must be 'on' or 'off'"), 538*789Sahrens propname, value); 539*789Sahrens return (-1); 540*789Sahrens } 541*789Sahrens break; 542*789Sahrens 543*789Sahrens case prop_type_number: 544*789Sahrens /* treat 'none' as 0 */ 545*789Sahrens if (strcmp(value, "none") == 0) { 546*789Sahrens number = 0; 547*789Sahrens break; 548*789Sahrens } 549*789Sahrens 550*789Sahrens if (nicestrtonum(value, &number, reason, 551*789Sahrens sizeof (reason)) != 0) { 552*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 553*789Sahrens "bad %s value '%s': %s"), propname, value, 554*789Sahrens reason); 555*789Sahrens return (-1); 556*789Sahrens } 557*789Sahrens 558*789Sahrens /* don't allow 0 for quota, use 'none' instead */ 559*789Sahrens if (prop == ZFS_PROP_QUOTA && number == 0 && 560*789Sahrens strcmp(value, "none") != 0) { 561*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 562*789Sahrens "bad %s value '%s': use '%s=none' to disable"), 563*789Sahrens propname, value, propname); 564*789Sahrens return (-1); 565*789Sahrens } 566*789Sahrens 567*789Sahrens /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */ 568*789Sahrens if (prop == ZFS_PROP_RECORDSIZE || 569*789Sahrens prop == ZFS_PROP_VOLBLOCKSIZE) { 570*789Sahrens if (number < SPA_MINBLOCKSIZE || 571*789Sahrens number > SPA_MAXBLOCKSIZE || !ISP2(number)) { 572*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 573*789Sahrens "bad %s value '%s': " 574*789Sahrens "must be power of 2 from %u to %uk"), 575*789Sahrens propname, value, 576*789Sahrens (uint_t)SPA_MINBLOCKSIZE, 577*789Sahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 578*789Sahrens return (-1); 579*789Sahrens } 580*789Sahrens } 581*789Sahrens 582*789Sahrens break; 583*789Sahrens 584*789Sahrens case prop_type_string: 585*789Sahrens case prop_type_index: 586*789Sahrens /* 587*789Sahrens * The two writable string values, 'mountpoint' and 588*789Sahrens * 'checksum' need special consideration. The 'index' types are 589*789Sahrens * specified as strings by the user, but passed to the kernel as 590*789Sahrens * integers. 591*789Sahrens */ 592*789Sahrens switch (prop) { 593*789Sahrens case ZFS_PROP_MOUNTPOINT: 594*789Sahrens if (strcmp(value, ZFS_MOUNTPOINT_NONE) == 0 || 595*789Sahrens strcmp(value, ZFS_MOUNTPOINT_LEGACY) == 0) 596*789Sahrens break; 597*789Sahrens 598*789Sahrens if (value[0] != '/') { 599*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 600*789Sahrens "bad %s value '%s': must be an absolute " 601*789Sahrens "path, 'none', or 'legacy'"), 602*789Sahrens propname, value); 603*789Sahrens return (-1); 604*789Sahrens } 605*789Sahrens break; 606*789Sahrens 607*789Sahrens case ZFS_PROP_CHECKSUM: 608*789Sahrens for (i = 0; checksum_table[i].name != NULL; i++) { 609*789Sahrens if (strcmp(value, checksum_table[i].name) 610*789Sahrens == 0) { 611*789Sahrens number = checksum_table[i].value; 612*789Sahrens break; 613*789Sahrens } 614*789Sahrens } 615*789Sahrens 616*789Sahrens if (checksum_table[i].name == NULL) { 617*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 618*789Sahrens "bad %s value '%s': must be 'on', 'off', " 619*789Sahrens "'fletcher2', 'fletcher4', or 'sha256'"), 620*789Sahrens propname, value); 621*789Sahrens return (-1); 622*789Sahrens } 623*789Sahrens break; 624*789Sahrens 625*789Sahrens case ZFS_PROP_COMPRESSION: 626*789Sahrens for (i = 0; compress_table[i].name != NULL; i++) { 627*789Sahrens if (strcmp(value, compress_table[i].name) 628*789Sahrens == 0) { 629*789Sahrens number = compress_table[i].value; 630*789Sahrens break; 631*789Sahrens } 632*789Sahrens } 633*789Sahrens 634*789Sahrens if (compress_table[i].name == NULL) { 635*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 636*789Sahrens "bad %s value '%s': must be 'on', 'off', " 637*789Sahrens "or 'lzjb'"), 638*789Sahrens propname, value); 639*789Sahrens return (-1); 640*789Sahrens } 641*789Sahrens break; 642*789Sahrens 643*789Sahrens case ZFS_PROP_SNAPDIR: 644*789Sahrens for (i = 0; snapdir_table[i].name != NULL; i++) { 645*789Sahrens if (strcmp(value, snapdir_table[i].name) == 0) { 646*789Sahrens number = snapdir_table[i].value; 647*789Sahrens break; 648*789Sahrens } 649*789Sahrens } 650*789Sahrens 651*789Sahrens if (snapdir_table[i].name == NULL) { 652*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 653*789Sahrens "bad %s value '%s': must be 'hidden' " 654*789Sahrens "or 'visible'"), 655*789Sahrens propname, value); 656*789Sahrens return (-1); 657*789Sahrens } 658*789Sahrens break; 659*789Sahrens 660*789Sahrens case ZFS_PROP_ACLMODE: 661*789Sahrens for (i = 0; acl_mode_table[i].name != NULL; i++) { 662*789Sahrens if (strcmp(value, acl_mode_table[i].name) 663*789Sahrens == 0) { 664*789Sahrens number = acl_mode_table[i].value; 665*789Sahrens break; 666*789Sahrens } 667*789Sahrens } 668*789Sahrens 669*789Sahrens if (acl_mode_table[i].name == NULL) { 670*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 671*789Sahrens "bad %s value '%s': must be 'discard', " 672*789Sahrens "'groupmask' or 'passthrough'"), 673*789Sahrens propname, value); 674*789Sahrens return (-1); 675*789Sahrens } 676*789Sahrens break; 677*789Sahrens 678*789Sahrens case ZFS_PROP_ACLINHERIT: 679*789Sahrens for (i = 0; acl_inherit_table[i].name != NULL; i++) { 680*789Sahrens if (strcmp(value, acl_inherit_table[i].name) 681*789Sahrens == 0) { 682*789Sahrens number = acl_inherit_table[i].value; 683*789Sahrens break; 684*789Sahrens } 685*789Sahrens } 686*789Sahrens 687*789Sahrens if (acl_inherit_table[i].name == NULL) { 688*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 689*789Sahrens "bad %s value '%s': must be 'discard', " 690*789Sahrens "'noallow', 'groupmask' or 'passthrough'"), 691*789Sahrens propname, value); 692*789Sahrens return (-1); 693*789Sahrens } 694*789Sahrens break; 695*789Sahrens 696*789Sahrens case ZFS_PROP_SHARENFS: 697*789Sahrens /* 698*789Sahrens * Nothing to do for 'sharenfs', this gets passed on to 699*789Sahrens * share(1M) verbatim. 700*789Sahrens */ 701*789Sahrens break; 702*789Sahrens } 703*789Sahrens } 704*789Sahrens 705*789Sahrens if (intval != NULL) 706*789Sahrens *intval = number; 707*789Sahrens 708*789Sahrens return (0); 709*789Sahrens } 710*789Sahrens 711*789Sahrens /* 712*789Sahrens * Given a property name and value, set the property for the given dataset. 713*789Sahrens */ 714*789Sahrens int 715*789Sahrens zfs_prop_set(zfs_handle_t *zhp, zfs_prop_t prop, const char *propval) 716*789Sahrens { 717*789Sahrens const char *propname = zfs_prop_to_name(prop); 718*789Sahrens uint64_t number; 719*789Sahrens zfs_cmd_t zc = { 0 }; 720*789Sahrens int ret; 721*789Sahrens prop_changelist_t *cl; 722*789Sahrens 723*789Sahrens if (zfs_prop_validate(prop, propval, &number) != 0) 724*789Sahrens return (-1); 725*789Sahrens 726*789Sahrens /* 727*789Sahrens * Check to see if the value applies to this type 728*789Sahrens */ 729*789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) { 730*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 731*789Sahrens "cannot set %s for '%s': property does not apply to %ss"), 732*789Sahrens propname, zhp->zfs_name, zfs_type_to_name(zhp->zfs_type)); 733*789Sahrens return (-1); 734*789Sahrens } 735*789Sahrens 736*789Sahrens /* 737*789Sahrens * For the mountpoint and sharenfs properties, check if it can be set 738*789Sahrens * in a global/non-global zone based on the zoned property value: 739*789Sahrens * 740*789Sahrens * global zone non-global zone 741*789Sahrens * ----------------------------------------------------- 742*789Sahrens * zoned=on mountpoint (no) mountpoint (yes) 743*789Sahrens * sharenfs (no) sharenfs (no) 744*789Sahrens * 745*789Sahrens * zoned=off mountpoint (yes) N/A 746*789Sahrens * sharenfs (yes) 747*789Sahrens */ 748*789Sahrens if (prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS) { 749*789Sahrens if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 750*789Sahrens if (getzoneid() == GLOBAL_ZONEID) { 751*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 752*789Sahrens "cannot set %s for '%s', " 753*789Sahrens "dataset is used in a non-global zone"), 754*789Sahrens propname, zhp->zfs_name); 755*789Sahrens return (-1); 756*789Sahrens } else if (prop == ZFS_PROP_SHARENFS) { 757*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 758*789Sahrens "cannot set %s for '%s', filesystems " 759*789Sahrens "cannot be shared in a non-global zone"), 760*789Sahrens propname, zhp->zfs_name); 761*789Sahrens return (-1); 762*789Sahrens } 763*789Sahrens } else if (getzoneid() != GLOBAL_ZONEID) { 764*789Sahrens /* 765*789Sahrens * If zoned property is 'off', this must be in 766*789Sahrens * a globle zone. If not, something is wrong. 767*789Sahrens */ 768*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 769*789Sahrens "cannot set %s for '%s', dataset is " 770*789Sahrens "used in a non-global zone, but 'zoned' " 771*789Sahrens "property is not set"), 772*789Sahrens propname, zhp->zfs_name); 773*789Sahrens return (-1); 774*789Sahrens } 775*789Sahrens } 776*789Sahrens 777*789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 778*789Sahrens return (-1); 779*789Sahrens 780*789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 781*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s for '%s', " 782*789Sahrens "child dataset with inherited mountpoint is used " 783*789Sahrens "in a non-global zone"), 784*789Sahrens propname, zhp->zfs_name); 785*789Sahrens ret = -1; 786*789Sahrens goto error; 787*789Sahrens } 788*789Sahrens 789*789Sahrens if ((ret = changelist_prefix(cl)) != 0) 790*789Sahrens goto error; 791*789Sahrens 792*789Sahrens /* 793*789Sahrens * Execute the corresponding ioctl() to set this property. 794*789Sahrens */ 795*789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 796*789Sahrens 797*789Sahrens switch (prop) { 798*789Sahrens case ZFS_PROP_QUOTA: 799*789Sahrens zc.zc_cookie = number; 800*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_QUOTA, &zc); 801*789Sahrens break; 802*789Sahrens case ZFS_PROP_RESERVATION: 803*789Sahrens zc.zc_cookie = number; 804*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_RESERVATION, &zc); 805*789Sahrens break; 806*789Sahrens case ZFS_PROP_MOUNTPOINT: 807*789Sahrens case ZFS_PROP_SHARENFS: 808*789Sahrens /* 809*789Sahrens * These properties are passed down as real strings. 810*789Sahrens */ 811*789Sahrens (void) strlcpy(zc.zc_prop_name, propname, 812*789Sahrens sizeof (zc.zc_prop_name)); 813*789Sahrens (void) strlcpy(zc.zc_prop_value, propval, 814*789Sahrens sizeof (zc.zc_prop_value)); 815*789Sahrens zc.zc_intsz = 1; 816*789Sahrens zc.zc_numints = strlen(propval) + 1; 817*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_PROP, &zc); 818*789Sahrens break; 819*789Sahrens case ZFS_PROP_VOLSIZE: 820*789Sahrens zc.zc_volsize = number; 821*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_VOLSIZE, &zc); 822*789Sahrens break; 823*789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 824*789Sahrens zc.zc_volblocksize = number; 825*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_VOLBLOCKSIZE, &zc); 826*789Sahrens break; 827*789Sahrens default: 828*789Sahrens (void) strlcpy(zc.zc_prop_name, propname, 829*789Sahrens sizeof (zc.zc_prop_name)); 830*789Sahrens /* LINTED - alignment */ 831*789Sahrens *(uint64_t *)zc.zc_prop_value = number; 832*789Sahrens zc.zc_intsz = 8; 833*789Sahrens zc.zc_numints = 1; 834*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SET_PROP, &zc); 835*789Sahrens break; 836*789Sahrens } 837*789Sahrens 838*789Sahrens if (ret != 0) { 839*789Sahrens switch (errno) { 840*789Sahrens 841*789Sahrens case EPERM: 842*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 843*789Sahrens "cannot set %s for '%s': permission " 844*789Sahrens "denied"), propname, zhp->zfs_name); 845*789Sahrens break; 846*789Sahrens 847*789Sahrens case ENOENT: 848*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 849*789Sahrens "cannot open '%s': no such %s"), zhp->zfs_name, 850*789Sahrens zfs_type_to_name(zhp->zfs_type)); 851*789Sahrens break; 852*789Sahrens 853*789Sahrens case ENOSPC: 854*789Sahrens /* 855*789Sahrens * For quotas and reservations, ENOSPC indicates 856*789Sahrens * something different; setting a quota or reservation 857*789Sahrens * doesn't use any disk space. 858*789Sahrens */ 859*789Sahrens switch (prop) { 860*789Sahrens case ZFS_PROP_QUOTA: 861*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s " 862*789Sahrens "for '%s': size is less than current " 863*789Sahrens "used or reserved space"), propname, 864*789Sahrens zhp->zfs_name); 865*789Sahrens break; 866*789Sahrens 867*789Sahrens case ZFS_PROP_RESERVATION: 868*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot set %s " 869*789Sahrens "for '%s': size is greater than available " 870*789Sahrens "space"), propname, zhp->zfs_name); 871*789Sahrens break; 872*789Sahrens 873*789Sahrens default: 874*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 875*789Sahrens "cannot set %s for '%s': out of space"), 876*789Sahrens propname, zhp->zfs_name); 877*789Sahrens break; 878*789Sahrens } 879*789Sahrens break; 880*789Sahrens 881*789Sahrens case EBUSY: 882*789Sahrens if (prop == ZFS_PROP_VOLBLOCKSIZE) { 883*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 884*789Sahrens "cannot set %s for '%s': " 885*789Sahrens "volume already contains data"), 886*789Sahrens propname, zhp->zfs_name); 887*789Sahrens } else { 888*789Sahrens zfs_baderror(errno); 889*789Sahrens } 890*789Sahrens break; 891*789Sahrens 892*789Sahrens case EOVERFLOW: 893*789Sahrens /* 894*789Sahrens * This platform can't address a volume this big. 895*789Sahrens */ 896*789Sahrens #ifdef _ILP32 897*789Sahrens if (prop == ZFS_PROP_VOLSIZE) { 898*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 899*789Sahrens "cannot set %s for '%s': " 900*789Sahrens "max volume size is 1TB on 32-bit systems"), 901*789Sahrens propname, zhp->zfs_name); 902*789Sahrens break; 903*789Sahrens } 904*789Sahrens #endif 905*789Sahrens zfs_baderror(errno); 906*789Sahrens default: 907*789Sahrens zfs_baderror(errno); 908*789Sahrens } 909*789Sahrens } else { 910*789Sahrens /* 911*789Sahrens * Refresh the statistics so the new property value 912*789Sahrens * is reflected. 913*789Sahrens */ 914*789Sahrens if ((ret = changelist_postfix(cl)) != 0) 915*789Sahrens goto error; 916*789Sahrens 917*789Sahrens (void) get_stats(zhp); 918*789Sahrens } 919*789Sahrens 920*789Sahrens error: 921*789Sahrens changelist_free(cl); 922*789Sahrens return (ret); 923*789Sahrens } 924*789Sahrens 925*789Sahrens /* 926*789Sahrens * Given a property, inherit the value from the parent dataset. 927*789Sahrens */ 928*789Sahrens int 929*789Sahrens zfs_prop_inherit(zfs_handle_t *zhp, zfs_prop_t prop) 930*789Sahrens { 931*789Sahrens const char *propname = zfs_prop_to_name(prop); 932*789Sahrens zfs_cmd_t zc = { 0 }; 933*789Sahrens int ret; 934*789Sahrens prop_changelist_t *cl; 935*789Sahrens 936*789Sahrens /* 937*789Sahrens * Verify that this property is inheritable. 938*789Sahrens */ 939*789Sahrens if (zfs_prop_readonly(prop)) { 940*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 941*789Sahrens "cannot inherit %s for '%s': property is read-only"), 942*789Sahrens propname, zhp->zfs_name); 943*789Sahrens return (-1); 944*789Sahrens } 945*789Sahrens 946*789Sahrens if (!zfs_prop_inheritable(prop)) { 947*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 948*789Sahrens "cannot inherit %s for '%s': property is not inheritable"), 949*789Sahrens propname, zhp->zfs_name); 950*789Sahrens return (-1); 951*789Sahrens } 952*789Sahrens 953*789Sahrens /* 954*789Sahrens * Check to see if the value applies to this type 955*789Sahrens */ 956*789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) { 957*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 958*789Sahrens "cannot inherit %s for '%s': property does " 959*789Sahrens "not apply to %ss"), propname, zhp->zfs_name, 960*789Sahrens zfs_type_to_name(zhp->zfs_type)); 961*789Sahrens return (-1); 962*789Sahrens } 963*789Sahrens 964*789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 965*789Sahrens (void) strlcpy(zc.zc_prop_name, propname, sizeof (zc.zc_prop_name)); 966*789Sahrens 967*789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID && 968*789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 969*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot inherit %s for '%s', " 970*789Sahrens "dataset is used in a non-global zone"), propname, 971*789Sahrens zhp->zfs_name); 972*789Sahrens return (-1); 973*789Sahrens } 974*789Sahrens 975*789Sahrens /* 976*789Sahrens * Determine datasets which will be affected by this change, if any. 977*789Sahrens */ 978*789Sahrens if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 979*789Sahrens return (-1); 980*789Sahrens 981*789Sahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 982*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot inherit %s for '%s', " 983*789Sahrens "child dataset with inherited mountpoint is " 984*789Sahrens "used in a non-global zone"), 985*789Sahrens propname, zhp->zfs_name); 986*789Sahrens ret = -1; 987*789Sahrens goto error; 988*789Sahrens } 989*789Sahrens 990*789Sahrens if ((ret = changelist_prefix(cl)) != 0) 991*789Sahrens goto error; 992*789Sahrens 993*789Sahrens zc.zc_numints = 0; 994*789Sahrens 995*789Sahrens if ((ret = ioctl(zfs_fd, ZFS_IOC_SET_PROP, &zc)) != 0) { 996*789Sahrens switch (errno) { 997*789Sahrens case EPERM: 998*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 999*789Sahrens "cannot inherit %s for '%s': permission " 1000*789Sahrens "denied"), propname, zhp->zfs_name); 1001*789Sahrens break; 1002*789Sahrens case ENOENT: 1003*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1004*789Sahrens "cannot open '%s': no such %s"), zhp->zfs_name, 1005*789Sahrens zfs_type_to_name(zhp->zfs_type)); 1006*789Sahrens break; 1007*789Sahrens case ENOSPC: 1008*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1009*789Sahrens "cannot inherit %s for '%s': " 1010*789Sahrens "out of space"), propname, zhp->zfs_name); 1011*789Sahrens break; 1012*789Sahrens default: 1013*789Sahrens zfs_baderror(errno); 1014*789Sahrens } 1015*789Sahrens 1016*789Sahrens } else { 1017*789Sahrens 1018*789Sahrens if ((ret = changelist_postfix(cl)) != 0) 1019*789Sahrens goto error; 1020*789Sahrens 1021*789Sahrens /* 1022*789Sahrens * Refresh the statistics so the new property is reflected. 1023*789Sahrens */ 1024*789Sahrens (void) get_stats(zhp); 1025*789Sahrens } 1026*789Sahrens 1027*789Sahrens 1028*789Sahrens error: 1029*789Sahrens changelist_free(cl); 1030*789Sahrens return (ret); 1031*789Sahrens } 1032*789Sahrens 1033*789Sahrens static void 1034*789Sahrens nicebool(int value, char *buf, size_t buflen) 1035*789Sahrens { 1036*789Sahrens if (value) 1037*789Sahrens (void) strlcpy(buf, "on", buflen); 1038*789Sahrens else 1039*789Sahrens (void) strlcpy(buf, "off", buflen); 1040*789Sahrens } 1041*789Sahrens 1042*789Sahrens /* 1043*789Sahrens * Internal function for getting a numeric property. Both zfs_prop_get() and 1044*789Sahrens * zfs_prop_get_int() are built using this interface. 1045*789Sahrens * 1046*789Sahrens * Certain properties can be overridden using 'mount -o'. In this case, scan 1047*789Sahrens * the contents of the /etc/mnttab entry, searching for the appropriate options. 1048*789Sahrens * If they differ from the on-disk values, report the current values and mark 1049*789Sahrens * the source "temporary". 1050*789Sahrens */ 1051*789Sahrens static uint64_t 1052*789Sahrens get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zfs_source_t *src, 1053*789Sahrens char **source) 1054*789Sahrens { 1055*789Sahrens uint64_t val; 1056*789Sahrens struct mnttab mnt; 1057*789Sahrens 1058*789Sahrens *source = NULL; 1059*789Sahrens 1060*789Sahrens if (zhp->zfs_mntopts == NULL) 1061*789Sahrens mnt.mnt_mntopts = ""; 1062*789Sahrens else 1063*789Sahrens mnt.mnt_mntopts = zhp->zfs_mntopts; 1064*789Sahrens 1065*789Sahrens switch (prop) { 1066*789Sahrens case ZFS_PROP_ATIME: 1067*789Sahrens *source = zhp->zfs_zplstats.zs_atime_setpoint; 1068*789Sahrens val = zhp->zfs_zplstats.zs_devices; 1069*789Sahrens 1070*789Sahrens if (hasmntopt(&mnt, MNTOPT_ATIME) && !val) { 1071*789Sahrens val = TRUE; 1072*789Sahrens if (src) 1073*789Sahrens *src = ZFS_SRC_TEMPORARY; 1074*789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NOATIME) && val) { 1075*789Sahrens val = FALSE; 1076*789Sahrens if (src) 1077*789Sahrens *src = ZFS_SRC_TEMPORARY; 1078*789Sahrens } 1079*789Sahrens return (zhp->zfs_zplstats.zs_atime); 1080*789Sahrens 1081*789Sahrens case ZFS_PROP_AVAILABLE: 1082*789Sahrens return (zhp->zfs_dmustats.dds_available); 1083*789Sahrens 1084*789Sahrens case ZFS_PROP_DEVICES: 1085*789Sahrens *source = zhp->zfs_zplstats.zs_devices_setpoint; 1086*789Sahrens val = zhp->zfs_zplstats.zs_devices; 1087*789Sahrens 1088*789Sahrens if (hasmntopt(&mnt, MNTOPT_DEVICES) && !val) { 1089*789Sahrens val = TRUE; 1090*789Sahrens if (src) 1091*789Sahrens *src = ZFS_SRC_TEMPORARY; 1092*789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NODEVICES) && val) { 1093*789Sahrens val = FALSE; 1094*789Sahrens if (src) 1095*789Sahrens *src = ZFS_SRC_TEMPORARY; 1096*789Sahrens } 1097*789Sahrens return (val); 1098*789Sahrens 1099*789Sahrens case ZFS_PROP_EXEC: 1100*789Sahrens *source = zhp->zfs_zplstats.zs_exec_setpoint; 1101*789Sahrens val = zhp->zfs_zplstats.zs_exec; 1102*789Sahrens 1103*789Sahrens if (hasmntopt(&mnt, MNTOPT_EXEC) && !val) { 1104*789Sahrens val = TRUE; 1105*789Sahrens if (src) 1106*789Sahrens *src = ZFS_SRC_TEMPORARY; 1107*789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NOEXEC) && val) { 1108*789Sahrens val = FALSE; 1109*789Sahrens if (src) 1110*789Sahrens *src = ZFS_SRC_TEMPORARY; 1111*789Sahrens } 1112*789Sahrens return (val); 1113*789Sahrens 1114*789Sahrens case ZFS_PROP_RECORDSIZE: 1115*789Sahrens *source = zhp->zfs_zplstats.zs_recordsize_setpoint; 1116*789Sahrens return (zhp->zfs_zplstats.zs_recordsize); 1117*789Sahrens 1118*789Sahrens case ZFS_PROP_COMPRESSION: 1119*789Sahrens *source = zhp->zfs_dmustats.dds_compression_setpoint; 1120*789Sahrens return (zhp->zfs_dmustats.dds_compression); 1121*789Sahrens 1122*789Sahrens case ZFS_PROP_READONLY: 1123*789Sahrens *source = zhp->zfs_zplstats.zs_readonly_setpoint; 1124*789Sahrens val = zhp->zfs_zplstats.zs_readonly; 1125*789Sahrens 1126*789Sahrens if (hasmntopt(&mnt, MNTOPT_RO) && !val) { 1127*789Sahrens val = TRUE; 1128*789Sahrens if (src) 1129*789Sahrens *src = ZFS_SRC_TEMPORARY; 1130*789Sahrens } else if (hasmntopt(&mnt, MNTOPT_RW) && val) { 1131*789Sahrens val = FALSE; 1132*789Sahrens if (src) 1133*789Sahrens *src = ZFS_SRC_TEMPORARY; 1134*789Sahrens } 1135*789Sahrens return (val); 1136*789Sahrens 1137*789Sahrens case ZFS_PROP_QUOTA: 1138*789Sahrens if (zhp->zfs_dmustats.dds_quota == 0) 1139*789Sahrens *source = ""; /* default */ 1140*789Sahrens else 1141*789Sahrens *source = zhp->zfs_name; 1142*789Sahrens return (zhp->zfs_dmustats.dds_quota); 1143*789Sahrens 1144*789Sahrens case ZFS_PROP_RESERVATION: 1145*789Sahrens if (zhp->zfs_dmustats.dds_reserved == 0) 1146*789Sahrens *source = ""; /* default */ 1147*789Sahrens else 1148*789Sahrens *source = zhp->zfs_name; 1149*789Sahrens return (zhp->zfs_dmustats.dds_reserved); 1150*789Sahrens 1151*789Sahrens case ZFS_PROP_COMPRESSRATIO: 1152*789Sahrens /* 1153*789Sahrens * Using physical space and logical space, calculate the 1154*789Sahrens * compression ratio. We return the number as a multiple of 1155*789Sahrens * 100, so '2.5x' would be returned as 250. 1156*789Sahrens */ 1157*789Sahrens if (zhp->zfs_dmustats.dds_compressed_bytes == 0) 1158*789Sahrens return (100ULL); 1159*789Sahrens else 1160*789Sahrens return (zhp->zfs_dmustats.dds_uncompressed_bytes * 100 / 1161*789Sahrens zhp->zfs_dmustats.dds_compressed_bytes); 1162*789Sahrens 1163*789Sahrens case ZFS_PROP_REFERENCED: 1164*789Sahrens /* 1165*789Sahrens * 'referenced' refers to the amount of physical space 1166*789Sahrens * referenced (possibly shared) by this object. 1167*789Sahrens */ 1168*789Sahrens return (zhp->zfs_dmustats.dds_space_refd); 1169*789Sahrens 1170*789Sahrens case ZFS_PROP_SETUID: 1171*789Sahrens *source = zhp->zfs_zplstats.zs_setuid_setpoint; 1172*789Sahrens val = zhp->zfs_zplstats.zs_setuid; 1173*789Sahrens 1174*789Sahrens if (hasmntopt(&mnt, MNTOPT_SETUID) && !val) { 1175*789Sahrens val = TRUE; 1176*789Sahrens if (src) 1177*789Sahrens *src = ZFS_SRC_TEMPORARY; 1178*789Sahrens } else if (hasmntopt(&mnt, MNTOPT_NOSETUID) && val) { 1179*789Sahrens val = FALSE; 1180*789Sahrens if (src) 1181*789Sahrens *src = ZFS_SRC_TEMPORARY; 1182*789Sahrens } 1183*789Sahrens return (val); 1184*789Sahrens 1185*789Sahrens case ZFS_PROP_VOLSIZE: 1186*789Sahrens return (zhp->zfs_volsize); 1187*789Sahrens 1188*789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 1189*789Sahrens return (zhp->zfs_volblocksize); 1190*789Sahrens 1191*789Sahrens case ZFS_PROP_ZONED: 1192*789Sahrens *source = zhp->zfs_dmustats.dds_zoned_setpoint; 1193*789Sahrens return (zhp->zfs_dmustats.dds_zoned); 1194*789Sahrens 1195*789Sahrens case ZFS_PROP_USED: 1196*789Sahrens return (zhp->zfs_dmustats.dds_space_used); 1197*789Sahrens 1198*789Sahrens case ZFS_PROP_CREATETXG: 1199*789Sahrens return (zhp->zfs_dmustats.dds_creation_txg); 1200*789Sahrens 1201*789Sahrens case ZFS_PROP_MOUNTED: 1202*789Sahrens /* 1203*789Sahrens * Unlike other properties, we defer calculation of 'MOUNTED' 1204*789Sahrens * until actually requested. This is because the getmntany() 1205*789Sahrens * call can be extremely expensive on systems with a large 1206*789Sahrens * number of filesystems, and the property isn't needed in 1207*789Sahrens * normal use cases. 1208*789Sahrens */ 1209*789Sahrens if (zhp->zfs_mntopts == NULL) { 1210*789Sahrens struct mnttab search = { 0 }, entry; 1211*789Sahrens 1212*789Sahrens search.mnt_special = (char *)zhp->zfs_name; 1213*789Sahrens rewind(mnttab_file); 1214*789Sahrens 1215*789Sahrens if (getmntany(mnttab_file, &entry, &search) == 0) 1216*789Sahrens zhp->zfs_mntopts = 1217*789Sahrens zfs_strdup(entry.mnt_mntopts); 1218*789Sahrens } 1219*789Sahrens return (zhp->zfs_mntopts != NULL); 1220*789Sahrens 1221*789Sahrens default: 1222*789Sahrens zfs_baderror(EINVAL); 1223*789Sahrens } 1224*789Sahrens 1225*789Sahrens return (0); 1226*789Sahrens } 1227*789Sahrens 1228*789Sahrens /* 1229*789Sahrens * Calculate the source type, given the raw source string. 1230*789Sahrens */ 1231*789Sahrens static void 1232*789Sahrens get_source(zfs_handle_t *zhp, zfs_source_t *srctype, char *source, 1233*789Sahrens char *statbuf, size_t statlen) 1234*789Sahrens { 1235*789Sahrens if (statbuf == NULL || *srctype == ZFS_SRC_TEMPORARY) 1236*789Sahrens return; 1237*789Sahrens 1238*789Sahrens if (source == NULL) { 1239*789Sahrens *srctype = ZFS_SRC_NONE; 1240*789Sahrens } else if (source[0] == '\0') { 1241*789Sahrens *srctype = ZFS_SRC_DEFAULT; 1242*789Sahrens } else { 1243*789Sahrens if (strcmp(source, zhp->zfs_name) == 0) { 1244*789Sahrens *srctype = ZFS_SRC_LOCAL; 1245*789Sahrens } else { 1246*789Sahrens (void) strlcpy(statbuf, source, statlen); 1247*789Sahrens *srctype = ZFS_SRC_INHERITED; 1248*789Sahrens } 1249*789Sahrens } 1250*789Sahrens 1251*789Sahrens } 1252*789Sahrens 1253*789Sahrens /* 1254*789Sahrens * Retrieve a property from the given object. If 'literal' is specified, then 1255*789Sahrens * numbers are left as exact values. Otherwise, numbers are converted to a 1256*789Sahrens * human-readable form. 1257*789Sahrens * 1258*789Sahrens * Returns 0 on success, or -1 on error. 1259*789Sahrens */ 1260*789Sahrens int 1261*789Sahrens zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, 1262*789Sahrens zfs_source_t *src, char *statbuf, size_t statlen, int literal) 1263*789Sahrens { 1264*789Sahrens char *source = NULL; 1265*789Sahrens uint64_t val; 1266*789Sahrens char *str; 1267*789Sahrens int i; 1268*789Sahrens const char *root; 1269*789Sahrens 1270*789Sahrens /* 1271*789Sahrens * Check to see if this property applies to our object 1272*789Sahrens */ 1273*789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1274*789Sahrens return (-1); 1275*789Sahrens 1276*789Sahrens if (src) 1277*789Sahrens *src = ZFS_SRC_NONE; 1278*789Sahrens 1279*789Sahrens switch (prop) { 1280*789Sahrens case ZFS_PROP_ATIME: 1281*789Sahrens case ZFS_PROP_READONLY: 1282*789Sahrens case ZFS_PROP_SETUID: 1283*789Sahrens case ZFS_PROP_ZONED: 1284*789Sahrens case ZFS_PROP_DEVICES: 1285*789Sahrens case ZFS_PROP_EXEC: 1286*789Sahrens /* 1287*789Sahrens * Basic boolean values are built on top of 1288*789Sahrens * get_numeric_property(). 1289*789Sahrens */ 1290*789Sahrens nicebool(get_numeric_property(zhp, prop, src, &source), 1291*789Sahrens propbuf, proplen); 1292*789Sahrens 1293*789Sahrens break; 1294*789Sahrens 1295*789Sahrens case ZFS_PROP_AVAILABLE: 1296*789Sahrens case ZFS_PROP_RECORDSIZE: 1297*789Sahrens case ZFS_PROP_CREATETXG: 1298*789Sahrens case ZFS_PROP_REFERENCED: 1299*789Sahrens case ZFS_PROP_USED: 1300*789Sahrens case ZFS_PROP_VOLSIZE: 1301*789Sahrens case ZFS_PROP_VOLBLOCKSIZE: 1302*789Sahrens /* 1303*789Sahrens * Basic numeric values are built on top of 1304*789Sahrens * get_numeric_property(). 1305*789Sahrens */ 1306*789Sahrens val = get_numeric_property(zhp, prop, src, &source); 1307*789Sahrens if (literal) 1308*789Sahrens (void) snprintf(propbuf, proplen, "%llu", val); 1309*789Sahrens else 1310*789Sahrens zfs_nicenum(val, propbuf, proplen); 1311*789Sahrens break; 1312*789Sahrens 1313*789Sahrens case ZFS_PROP_COMPRESSION: 1314*789Sahrens for (i = 0; compress_table[i].name != NULL; i++) { 1315*789Sahrens if (compress_table[i].value == 1316*789Sahrens zhp->zfs_dmustats.dds_compression) 1317*789Sahrens break; 1318*789Sahrens } 1319*789Sahrens assert(compress_table[i].name != NULL); 1320*789Sahrens (void) strlcpy(propbuf, compress_table[i].name, proplen); 1321*789Sahrens source = zhp->zfs_dmustats.dds_compression_setpoint; 1322*789Sahrens break; 1323*789Sahrens 1324*789Sahrens case ZFS_PROP_CHECKSUM: 1325*789Sahrens for (i = 0; checksum_table[i].name != NULL; i++) { 1326*789Sahrens if (checksum_table[i].value == 1327*789Sahrens zhp->zfs_dmustats.dds_checksum) 1328*789Sahrens break; 1329*789Sahrens } 1330*789Sahrens assert(checksum_table[i].name != NULL); 1331*789Sahrens (void) strlcpy(propbuf, checksum_table[i].name, proplen); 1332*789Sahrens source = zhp->zfs_dmustats.dds_checksum_setpoint; 1333*789Sahrens break; 1334*789Sahrens 1335*789Sahrens case ZFS_PROP_SNAPDIR: 1336*789Sahrens for (i = 0; snapdir_table[i].name != NULL; i++) { 1337*789Sahrens if (snapdir_table[i].value == 1338*789Sahrens zhp->zfs_zplstats.zs_snapdir) 1339*789Sahrens break; 1340*789Sahrens } 1341*789Sahrens assert(snapdir_table[i].name != NULL); 1342*789Sahrens (void) strlcpy(propbuf, snapdir_table[i].name, proplen); 1343*789Sahrens source = zhp->zfs_zplstats.zs_snapdir_setpoint; 1344*789Sahrens break; 1345*789Sahrens 1346*789Sahrens case ZFS_PROP_ACLMODE: 1347*789Sahrens for (i = 0; acl_mode_table[i].name != NULL; i++) { 1348*789Sahrens if (acl_mode_table[i].value == 1349*789Sahrens zhp->zfs_zplstats.zs_acl_mode) 1350*789Sahrens break; 1351*789Sahrens } 1352*789Sahrens assert(acl_mode_table[i].name != NULL); 1353*789Sahrens (void) strlcpy(propbuf, acl_mode_table[i].name, proplen); 1354*789Sahrens source = zhp->zfs_zplstats.zs_acl_mode_setpoint; 1355*789Sahrens break; 1356*789Sahrens 1357*789Sahrens case ZFS_PROP_ACLINHERIT: 1358*789Sahrens for (i = 0; acl_inherit_table[i].name != NULL; i++) { 1359*789Sahrens if (acl_inherit_table[i].value == 1360*789Sahrens zhp->zfs_zplstats.zs_acl_inherit) 1361*789Sahrens break; 1362*789Sahrens } 1363*789Sahrens assert(acl_inherit_table[i].name != NULL); 1364*789Sahrens (void) strlcpy(propbuf, acl_inherit_table[i].name, proplen); 1365*789Sahrens source = zhp->zfs_zplstats.zs_acl_inherit_setpoint; 1366*789Sahrens break; 1367*789Sahrens 1368*789Sahrens case ZFS_PROP_CREATION: 1369*789Sahrens /* 1370*789Sahrens * 'creation' is a time_t stored in the statistics. We convert 1371*789Sahrens * this into a string unless 'literal' is specified. 1372*789Sahrens */ 1373*789Sahrens { 1374*789Sahrens time_t time = (time_t) 1375*789Sahrens zhp->zfs_dmustats.dds_creation_time; 1376*789Sahrens struct tm t; 1377*789Sahrens 1378*789Sahrens if (literal || 1379*789Sahrens localtime_r(&time, &t) == NULL || 1380*789Sahrens strftime(propbuf, proplen, "%a %b %e %k:%M %Y", 1381*789Sahrens &t) == 0) 1382*789Sahrens (void) snprintf(propbuf, proplen, "%llu", 1383*789Sahrens zhp->zfs_dmustats.dds_creation_time); 1384*789Sahrens } 1385*789Sahrens break; 1386*789Sahrens 1387*789Sahrens case ZFS_PROP_MOUNTPOINT: 1388*789Sahrens /* 1389*789Sahrens * Getting the precise mountpoint can be tricky. 1390*789Sahrens * 1391*789Sahrens * - for 'none' or 'legacy', return those values. 1392*789Sahrens * - for default mountpoints, construct it as /zfs/<dataset> 1393*789Sahrens * - for inherited mountpoints, we want to take everything 1394*789Sahrens * after our ancestor and append it to the inherited value. 1395*789Sahrens * 1396*789Sahrens * If the pool has an alternate root, we want to prepend that 1397*789Sahrens * root to any values we return. 1398*789Sahrens */ 1399*789Sahrens root = zhp->zfs_dmustats.dds_altroot; 1400*789Sahrens 1401*789Sahrens if (zhp->zfs_zplstats.zs_mountpoint[0] == '\0') { 1402*789Sahrens (void) snprintf(propbuf, proplen, "%s/zfs/%s", 1403*789Sahrens root, zhp->zfs_name); 1404*789Sahrens } else if (zhp->zfs_zplstats.zs_mountpoint[0] == '/') { 1405*789Sahrens const char *relpath = zhp->zfs_name + 1406*789Sahrens strlen(zhp->zfs_zplstats.zs_mountpoint_setpoint); 1407*789Sahrens const char *mntpoint = zhp->zfs_zplstats.zs_mountpoint; 1408*789Sahrens 1409*789Sahrens if (relpath[0] == '/') 1410*789Sahrens relpath++; 1411*789Sahrens if (mntpoint[1] == '\0') 1412*789Sahrens mntpoint++; 1413*789Sahrens 1414*789Sahrens if (relpath[0] == '\0') 1415*789Sahrens (void) snprintf(propbuf, proplen, "%s%s", 1416*789Sahrens root, mntpoint); 1417*789Sahrens else 1418*789Sahrens (void) snprintf(propbuf, proplen, "%s%s%s%s", 1419*789Sahrens root, mntpoint, 1420*789Sahrens relpath[0] == '@' ? "" : "/", 1421*789Sahrens relpath); 1422*789Sahrens } else { 1423*789Sahrens /* 'legacy' or 'none' */ 1424*789Sahrens (void) strlcpy(propbuf, zhp->zfs_zplstats.zs_mountpoint, 1425*789Sahrens proplen); 1426*789Sahrens } 1427*789Sahrens 1428*789Sahrens source = zhp->zfs_zplstats.zs_mountpoint_setpoint; 1429*789Sahrens break; 1430*789Sahrens 1431*789Sahrens case ZFS_PROP_SHARENFS: 1432*789Sahrens (void) strlcpy(propbuf, zhp->zfs_zplstats.zs_sharenfs, proplen); 1433*789Sahrens source = zhp->zfs_zplstats.zs_sharenfs_setpoint; 1434*789Sahrens break; 1435*789Sahrens 1436*789Sahrens case ZFS_PROP_ORIGIN: 1437*789Sahrens (void) strlcpy(propbuf, zhp->zfs_dmustats.dds_clone_of, 1438*789Sahrens proplen); 1439*789Sahrens /* 1440*789Sahrens * If there is no parent at all, return failure to indicate that 1441*789Sahrens * it doesn't apply to this dataset. 1442*789Sahrens */ 1443*789Sahrens if (propbuf[0] == '\0') 1444*789Sahrens return (-1); 1445*789Sahrens break; 1446*789Sahrens 1447*789Sahrens case ZFS_PROP_QUOTA: 1448*789Sahrens case ZFS_PROP_RESERVATION: 1449*789Sahrens val = get_numeric_property(zhp, prop, src, &source); 1450*789Sahrens 1451*789Sahrens /* 1452*789Sahrens * If quota or reservation is 0, we translate this into 'none' 1453*789Sahrens * (unless literal is set), and indicate that it's the default 1454*789Sahrens * value. Otherwise, we print the number nicely and indicate 1455*789Sahrens * that its set locally. 1456*789Sahrens */ 1457*789Sahrens if (val == 0) { 1458*789Sahrens if (literal) 1459*789Sahrens (void) strlcpy(propbuf, "0", proplen); 1460*789Sahrens else 1461*789Sahrens (void) strlcpy(propbuf, "none", proplen); 1462*789Sahrens } else { 1463*789Sahrens if (literal) 1464*789Sahrens (void) snprintf(propbuf, proplen, "%llu", val); 1465*789Sahrens else 1466*789Sahrens zfs_nicenum(val, propbuf, proplen); 1467*789Sahrens } 1468*789Sahrens break; 1469*789Sahrens 1470*789Sahrens case ZFS_PROP_COMPRESSRATIO: 1471*789Sahrens val = get_numeric_property(zhp, prop, src, &source); 1472*789Sahrens (void) snprintf(propbuf, proplen, "%lld.%02lldx", val / 100, 1473*789Sahrens val % 100); 1474*789Sahrens break; 1475*789Sahrens 1476*789Sahrens case ZFS_PROP_TYPE: 1477*789Sahrens switch (zhp->zfs_type) { 1478*789Sahrens case ZFS_TYPE_FILESYSTEM: 1479*789Sahrens str = "filesystem"; 1480*789Sahrens break; 1481*789Sahrens case ZFS_TYPE_VOLUME: 1482*789Sahrens str = "volume"; 1483*789Sahrens break; 1484*789Sahrens case ZFS_TYPE_SNAPSHOT: 1485*789Sahrens str = "snapshot"; 1486*789Sahrens break; 1487*789Sahrens default: 1488*789Sahrens zfs_baderror(zhp->zfs_type); 1489*789Sahrens } 1490*789Sahrens (void) snprintf(propbuf, proplen, "%s", str); 1491*789Sahrens break; 1492*789Sahrens 1493*789Sahrens case ZFS_PROP_MOUNTED: 1494*789Sahrens /* 1495*789Sahrens * The 'mounted' property is a pseudo-property that described 1496*789Sahrens * whether the filesystem is currently mounted. Even though 1497*789Sahrens * it's a boolean value, the typical values of "on" and "off" 1498*789Sahrens * don't make sense, so we translate to "yes" and "no". 1499*789Sahrens */ 1500*789Sahrens if (get_numeric_property(zhp, ZFS_PROP_MOUNTED, src, &source)) 1501*789Sahrens (void) strlcpy(propbuf, "yes", proplen); 1502*789Sahrens else 1503*789Sahrens (void) strlcpy(propbuf, "no", proplen); 1504*789Sahrens break; 1505*789Sahrens 1506*789Sahrens case ZFS_PROP_NAME: 1507*789Sahrens /* 1508*789Sahrens * The 'name' property is a pseudo-property derived from the 1509*789Sahrens * dataset name. It is presented as a real property to simplify 1510*789Sahrens * consumers. 1511*789Sahrens */ 1512*789Sahrens (void) strlcpy(propbuf, zhp->zfs_name, proplen); 1513*789Sahrens break; 1514*789Sahrens 1515*789Sahrens default: 1516*789Sahrens zfs_baderror(EINVAL); 1517*789Sahrens } 1518*789Sahrens 1519*789Sahrens get_source(zhp, src, source, statbuf, statlen); 1520*789Sahrens 1521*789Sahrens return (0); 1522*789Sahrens } 1523*789Sahrens 1524*789Sahrens /* 1525*789Sahrens * Utility function to get the given numeric property. Does no validation that 1526*789Sahrens * the given property is the appropriate type; should only be used with 1527*789Sahrens * hard-coded property types. 1528*789Sahrens */ 1529*789Sahrens uint64_t 1530*789Sahrens zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop) 1531*789Sahrens { 1532*789Sahrens char *source; 1533*789Sahrens zfs_source_t sourcetype = ZFS_SRC_NONE; 1534*789Sahrens 1535*789Sahrens return (get_numeric_property(zhp, prop, &sourcetype, &source)); 1536*789Sahrens } 1537*789Sahrens 1538*789Sahrens /* 1539*789Sahrens * Similar to zfs_prop_get(), but returns the value as an integer. 1540*789Sahrens */ 1541*789Sahrens int 1542*789Sahrens zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, 1543*789Sahrens zfs_source_t *src, char *statbuf, size_t statlen) 1544*789Sahrens { 1545*789Sahrens char *source; 1546*789Sahrens 1547*789Sahrens /* 1548*789Sahrens * Check to see if this property applies to our object 1549*789Sahrens */ 1550*789Sahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1551*789Sahrens return (-1); 1552*789Sahrens 1553*789Sahrens if (src) 1554*789Sahrens *src = ZFS_SRC_NONE; 1555*789Sahrens 1556*789Sahrens *value = get_numeric_property(zhp, prop, src, &source); 1557*789Sahrens 1558*789Sahrens get_source(zhp, src, source, statbuf, statlen); 1559*789Sahrens 1560*789Sahrens return (0); 1561*789Sahrens } 1562*789Sahrens 1563*789Sahrens /* 1564*789Sahrens * Returns the name of the given zfs handle. 1565*789Sahrens */ 1566*789Sahrens const char * 1567*789Sahrens zfs_get_name(const zfs_handle_t *zhp) 1568*789Sahrens { 1569*789Sahrens return (zhp->zfs_name); 1570*789Sahrens } 1571*789Sahrens 1572*789Sahrens /* 1573*789Sahrens * Returns the type of the given zfs handle. 1574*789Sahrens */ 1575*789Sahrens zfs_type_t 1576*789Sahrens zfs_get_type(const zfs_handle_t *zhp) 1577*789Sahrens { 1578*789Sahrens return (zhp->zfs_type); 1579*789Sahrens } 1580*789Sahrens 1581*789Sahrens /* 1582*789Sahrens * Iterate over all children, datasets and snapshots. 1583*789Sahrens */ 1584*789Sahrens int 1585*789Sahrens zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 1586*789Sahrens { 1587*789Sahrens zfs_cmd_t zc = { 0 }; 1588*789Sahrens zfs_handle_t *nzhp; 1589*789Sahrens int ret; 1590*789Sahrens 1591*789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1592*789Sahrens ioctl(zfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; 1593*789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1594*789Sahrens /* 1595*789Sahrens * Ignore private dataset names. 1596*789Sahrens */ 1597*789Sahrens if (dataset_name_hidden(zc.zc_name)) 1598*789Sahrens continue; 1599*789Sahrens 1600*789Sahrens /* 1601*789Sahrens * Silently ignore errors, as the only plausible explanation is 1602*789Sahrens * that the pool has since been removed. 1603*789Sahrens */ 1604*789Sahrens if ((nzhp = make_dataset_handle(zc.zc_name)) == NULL) 1605*789Sahrens continue; 1606*789Sahrens 1607*789Sahrens if ((ret = func(nzhp, data)) != 0) 1608*789Sahrens return (ret); 1609*789Sahrens } 1610*789Sahrens 1611*789Sahrens /* 1612*789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1613*789Sahrens * returned, then the underlying dataset has been removed since we 1614*789Sahrens * obtained the handle. 1615*789Sahrens */ 1616*789Sahrens if (errno != ESRCH && errno != ENOENT) 1617*789Sahrens zfs_baderror(errno); 1618*789Sahrens 1619*789Sahrens bzero(&zc, sizeof (zc)); 1620*789Sahrens 1621*789Sahrens for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1622*789Sahrens ioctl(zfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc) == 0; 1623*789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 1624*789Sahrens 1625*789Sahrens if ((nzhp = make_dataset_handle(zc.zc_name)) == NULL) 1626*789Sahrens continue; 1627*789Sahrens 1628*789Sahrens if ((ret = func(nzhp, data)) != 0) 1629*789Sahrens return (ret); 1630*789Sahrens } 1631*789Sahrens 1632*789Sahrens /* 1633*789Sahrens * An errno value of ESRCH indicates normal completion. If ENOENT is 1634*789Sahrens * returned, then the underlying dataset has been removed since we 1635*789Sahrens * obtained the handle. Silently ignore this case, and return success. 1636*789Sahrens */ 1637*789Sahrens if (errno != ESRCH && errno != ENOENT) 1638*789Sahrens zfs_baderror(errno); 1639*789Sahrens 1640*789Sahrens return (0); 1641*789Sahrens } 1642*789Sahrens 1643*789Sahrens /* 1644*789Sahrens * Given a complete name, return just the portion that refers to the parent. 1645*789Sahrens * Can return NULL if this is a pool. 1646*789Sahrens */ 1647*789Sahrens static int 1648*789Sahrens parent_name(const char *path, char *buf, size_t buflen) 1649*789Sahrens { 1650*789Sahrens char *loc; 1651*789Sahrens 1652*789Sahrens if ((loc = strrchr(path, '/')) == NULL) 1653*789Sahrens return (-1); 1654*789Sahrens 1655*789Sahrens (void) strncpy(buf, path, MIN(buflen, loc - path)); 1656*789Sahrens buf[loc - path] = '\0'; 1657*789Sahrens 1658*789Sahrens return (0); 1659*789Sahrens } 1660*789Sahrens 1661*789Sahrens /* 1662*789Sahrens * Checks to make sure that the given path has a parent, and that it exists. 1663*789Sahrens */ 1664*789Sahrens static int 1665*789Sahrens check_parents(const char *path, zfs_type_t type) 1666*789Sahrens { 1667*789Sahrens zfs_cmd_t zc = { 0 }; 1668*789Sahrens char parent[ZFS_MAXNAMELEN]; 1669*789Sahrens char *slash; 1670*789Sahrens 1671*789Sahrens /* get parent, and check to see if this is just a pool */ 1672*789Sahrens if (parent_name(path, parent, sizeof (parent)) != 0) { 1673*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1674*789Sahrens "cannot create '%s': missing dataset name"), 1675*789Sahrens path, zfs_type_to_name(type)); 1676*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1677*789Sahrens "use 'zpool create' to create a storage pool")); 1678*789Sahrens return (-1); 1679*789Sahrens } 1680*789Sahrens 1681*789Sahrens /* check to see if the pool exists */ 1682*789Sahrens if ((slash = strchr(parent, '/')) == NULL) 1683*789Sahrens slash = parent + strlen(parent); 1684*789Sahrens (void) strncpy(zc.zc_name, parent, slash - parent); 1685*789Sahrens zc.zc_name[slash - parent] = '\0'; 1686*789Sahrens if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 && 1687*789Sahrens errno == ENOENT) { 1688*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1689*789Sahrens "cannot create '%s': no such pool '%s'"), path, zc.zc_name); 1690*789Sahrens return (-1); 1691*789Sahrens } 1692*789Sahrens 1693*789Sahrens /* check to see if the parent dataset exists */ 1694*789Sahrens (void) strlcpy(zc.zc_name, parent, sizeof (zc.zc_name)); 1695*789Sahrens if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) { 1696*789Sahrens switch (errno) { 1697*789Sahrens case ENOENT: 1698*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1699*789Sahrens "cannot create '%s': parent does not exist"), path); 1700*789Sahrens return (-1); 1701*789Sahrens 1702*789Sahrens default: 1703*789Sahrens zfs_baderror(errno); 1704*789Sahrens } 1705*789Sahrens } 1706*789Sahrens 1707*789Sahrens /* we are in a non-global zone, but parent is in the global zone */ 1708*789Sahrens if (getzoneid() != GLOBAL_ZONEID && !zc.zc_objset_stats.dds_zoned) { 1709*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1710*789Sahrens "cannot create '%s': permission denied"), path); 1711*789Sahrens return (-1); 1712*789Sahrens } 1713*789Sahrens 1714*789Sahrens /* make sure parent is a filesystem */ 1715*789Sahrens if (zc.zc_objset_stats.dds_type != DMU_OST_ZFS) { 1716*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1717*789Sahrens "cannot create '%s': parent is not a filesystem"), 1718*789Sahrens path); 1719*789Sahrens return (-1); 1720*789Sahrens } 1721*789Sahrens 1722*789Sahrens return (0); 1723*789Sahrens } 1724*789Sahrens 1725*789Sahrens /* 1726*789Sahrens * Create a new filesystem or volume. 'sizestr' and 'blocksizestr' are used 1727*789Sahrens * only for volumes, and indicate the size and blocksize of the volume. 1728*789Sahrens */ 1729*789Sahrens int 1730*789Sahrens zfs_create(const char *path, zfs_type_t type, 1731*789Sahrens const char *sizestr, const char *blocksizestr) 1732*789Sahrens { 1733*789Sahrens char reason[64]; 1734*789Sahrens zfs_cmd_t zc = { 0 }; 1735*789Sahrens int ret; 1736*789Sahrens uint64_t size = 0; 1737*789Sahrens uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE); 1738*789Sahrens 1739*789Sahrens /* convert sizestr into integer size */ 1740*789Sahrens if (sizestr != NULL && nicestrtonum(sizestr, &size, 1741*789Sahrens reason, sizeof (reason)) != 0) { 1742*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1743*789Sahrens "bad volume size '%s': %s"), sizestr, reason); 1744*789Sahrens return (-1); 1745*789Sahrens } 1746*789Sahrens 1747*789Sahrens /* convert blocksizestr into integer blocksize */ 1748*789Sahrens if (blocksizestr != NULL && nicestrtonum(blocksizestr, &blocksize, 1749*789Sahrens reason, sizeof (reason)) != 0) { 1750*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1751*789Sahrens "bad volume blocksize '%s': %s"), blocksizestr, reason); 1752*789Sahrens return (-1); 1753*789Sahrens } 1754*789Sahrens 1755*789Sahrens /* make sure the name is not too long */ 1756*789Sahrens if (strlen(path) >= ZFS_MAXNAMELEN) { 1757*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1758*789Sahrens "cannot create '%s': %s name is too long"), 1759*789Sahrens path, zfs_type_to_name(type)); 1760*789Sahrens return (-1); 1761*789Sahrens } 1762*789Sahrens 1763*789Sahrens /* validate the path, taking care to note the extended error message */ 1764*789Sahrens if (!zfs_validate_name(path, type, reason, sizeof (reason))) { 1765*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1766*789Sahrens "cannot create '%s': %s in %s name"), path, reason, 1767*789Sahrens zfs_type_to_name(type)); 1768*789Sahrens if (strstr(reason, "snapshot") != NULL) 1769*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1770*789Sahrens "use 'zfs snapshot' to create a snapshot")); 1771*789Sahrens return (-1); 1772*789Sahrens } 1773*789Sahrens 1774*789Sahrens /* validate parents exist */ 1775*789Sahrens if (check_parents(path, type) != 0) 1776*789Sahrens return (-1); 1777*789Sahrens 1778*789Sahrens /* 1779*789Sahrens * The failure modes when creating a dataset of a different type over 1780*789Sahrens * one that already exists is a little strange. In particular, if you 1781*789Sahrens * try to create a dataset on top of an existing dataset, the ioctl() 1782*789Sahrens * will return ENOENT, not EEXIST. To prevent this from happening, we 1783*789Sahrens * first try to see if the dataset exists. 1784*789Sahrens */ 1785*789Sahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 1786*789Sahrens if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) { 1787*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1788*789Sahrens "cannot create '%s': dataset exists"), path); 1789*789Sahrens return (-1); 1790*789Sahrens } 1791*789Sahrens 1792*789Sahrens if (type == ZFS_TYPE_VOLUME) 1793*789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 1794*789Sahrens else 1795*789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 1796*789Sahrens 1797*789Sahrens if (type == ZFS_TYPE_VOLUME) { 1798*789Sahrens if (size == 0) { 1799*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1800*789Sahrens "bad volume size '%s': cannot be zero"), sizestr); 1801*789Sahrens return (-1); 1802*789Sahrens } 1803*789Sahrens 1804*789Sahrens zc.zc_volsize = size; 1805*789Sahrens zc.zc_volblocksize = blocksize; 1806*789Sahrens } 1807*789Sahrens 1808*789Sahrens /* create the dataset */ 1809*789Sahrens 1810*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_CREATE, &zc); 1811*789Sahrens 1812*789Sahrens if (ret == 0 && type == ZFS_TYPE_VOLUME) 1813*789Sahrens ret = zvol_create_link(path); 1814*789Sahrens 1815*789Sahrens /* check for failure */ 1816*789Sahrens if (ret != 0) { 1817*789Sahrens char parent[ZFS_MAXNAMELEN]; 1818*789Sahrens (void) parent_name(path, parent, sizeof (parent)); 1819*789Sahrens 1820*789Sahrens switch (errno) { 1821*789Sahrens case ENOENT: 1822*789Sahrens /* 1823*789Sahrens * The parent dataset has been deleted since our 1824*789Sahrens * previous check. 1825*789Sahrens */ 1826*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1827*789Sahrens "cannot create '%s': no such parent '%s'"), 1828*789Sahrens path, parent); 1829*789Sahrens break; 1830*789Sahrens 1831*789Sahrens case EPERM: 1832*789Sahrens /* 1833*789Sahrens * The user doesn't have permission to create a new 1834*789Sahrens * dataset here. 1835*789Sahrens */ 1836*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1837*789Sahrens "cannot create '%s': permission denied"), path); 1838*789Sahrens break; 1839*789Sahrens 1840*789Sahrens case EDQUOT: 1841*789Sahrens case ENOSPC: 1842*789Sahrens /* 1843*789Sahrens * The parent dataset does not have enough free space 1844*789Sahrens * to create a new dataset. 1845*789Sahrens */ 1846*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1847*789Sahrens "cannot create '%s': not enough space in '%s'"), 1848*789Sahrens path, parent); 1849*789Sahrens break; 1850*789Sahrens 1851*789Sahrens case EEXIST: 1852*789Sahrens /* 1853*789Sahrens * The target dataset already exists. We should have 1854*789Sahrens * caught this above, but there may be some unexplained 1855*789Sahrens * race condition. 1856*789Sahrens */ 1857*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1858*789Sahrens "cannot create '%s': dataset exists"), path); 1859*789Sahrens break; 1860*789Sahrens 1861*789Sahrens case EINVAL: 1862*789Sahrens /* 1863*789Sahrens * The target dataset does not support children. 1864*789Sahrens */ 1865*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1866*789Sahrens "cannot create '%s': children unsupported in '%s'"), 1867*789Sahrens path, parent); 1868*789Sahrens break; 1869*789Sahrens 1870*789Sahrens case EDOM: 1871*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "bad %s value '%s': " 1872*789Sahrens "must be power of 2 from %u to %uk"), 1873*789Sahrens zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 1874*789Sahrens blocksizestr ? blocksizestr : "<unknown>", 1875*789Sahrens (uint_t)SPA_MINBLOCKSIZE, 1876*789Sahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 1877*789Sahrens break; 1878*789Sahrens #ifdef _ILP32 1879*789Sahrens case EOVERFLOW: 1880*789Sahrens /* 1881*789Sahrens * This platform can't address a volume this big. 1882*789Sahrens */ 1883*789Sahrens if (type == ZFS_TYPE_VOLUME) { 1884*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1885*789Sahrens "cannot create '%s': " 1886*789Sahrens "max volume size is 1TB on 32-bit systems"), 1887*789Sahrens path); 1888*789Sahrens break; 1889*789Sahrens } 1890*789Sahrens #endif 1891*789Sahrens 1892*789Sahrens default: 1893*789Sahrens zfs_baderror(errno); 1894*789Sahrens } 1895*789Sahrens 1896*789Sahrens return (-1); 1897*789Sahrens } 1898*789Sahrens 1899*789Sahrens return (0); 1900*789Sahrens } 1901*789Sahrens 1902*789Sahrens /* 1903*789Sahrens * Destroys the given dataset. The caller must make sure that the filesystem 1904*789Sahrens * isn't mounted, and that there are no active dependents. 1905*789Sahrens */ 1906*789Sahrens int 1907*789Sahrens zfs_destroy(zfs_handle_t *zhp) 1908*789Sahrens { 1909*789Sahrens zfs_cmd_t zc = { 0 }; 1910*789Sahrens int ret; 1911*789Sahrens 1912*789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1913*789Sahrens 1914*789Sahrens /* 1915*789Sahrens * We use the check for 'zfs_volblocksize' instead of ZFS_TYPE_VOLUME 1916*789Sahrens * so that we do the right thing for snapshots of volumes. 1917*789Sahrens */ 1918*789Sahrens if (zhp->zfs_volblocksize != 0) { 1919*789Sahrens if (zvol_remove_link(zhp->zfs_name) != 0) 1920*789Sahrens return (-1); 1921*789Sahrens 1922*789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 1923*789Sahrens } else { 1924*789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 1925*789Sahrens } 1926*789Sahrens 1927*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_DESTROY, &zc); 1928*789Sahrens 1929*789Sahrens if (ret != 0) { 1930*789Sahrens switch (errno) { 1931*789Sahrens 1932*789Sahrens case EPERM: 1933*789Sahrens /* 1934*789Sahrens * We don't have permission to destroy this dataset. 1935*789Sahrens */ 1936*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1937*789Sahrens "cannot destroy '%s': permission denied"), 1938*789Sahrens zhp->zfs_name); 1939*789Sahrens break; 1940*789Sahrens 1941*789Sahrens case ENOENT: 1942*789Sahrens /* 1943*789Sahrens * We've hit a race condition where the dataset has been 1944*789Sahrens * destroyed since we opened it. 1945*789Sahrens */ 1946*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1947*789Sahrens "cannot destroy '%s': no such %s"), 1948*789Sahrens zhp->zfs_name, zfs_type_to_name(zhp->zfs_type)); 1949*789Sahrens break; 1950*789Sahrens 1951*789Sahrens case EBUSY: 1952*789Sahrens /* 1953*789Sahrens * Even if we destroy all children, there is a chance we 1954*789Sahrens * can hit this case if: 1955*789Sahrens * 1956*789Sahrens * - A child dataset has since been created 1957*789Sahrens * - A filesystem is mounted 1958*789Sahrens * 1959*789Sahrens * This error message is awful, but hopefully we've 1960*789Sahrens * already caught the common cases (and aborted more 1961*789Sahrens * appropriately) before calling this function. There's 1962*789Sahrens * nothing else we can do at this point. 1963*789Sahrens */ 1964*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1965*789Sahrens "cannot destroy '%s': %s is busy"), 1966*789Sahrens zhp->zfs_name, zfs_type_to_name(zhp->zfs_type)); 1967*789Sahrens break; 1968*789Sahrens 1969*789Sahrens default: 1970*789Sahrens zfs_baderror(errno); 1971*789Sahrens } 1972*789Sahrens 1973*789Sahrens return (-1); 1974*789Sahrens } 1975*789Sahrens 1976*789Sahrens remove_mountpoint(zhp); 1977*789Sahrens 1978*789Sahrens return (0); 1979*789Sahrens } 1980*789Sahrens 1981*789Sahrens /* 1982*789Sahrens * Clones the given dataset. The target must be of the same type as the source. 1983*789Sahrens */ 1984*789Sahrens int 1985*789Sahrens zfs_clone(zfs_handle_t *zhp, const char *target) 1986*789Sahrens { 1987*789Sahrens char reason[64]; 1988*789Sahrens zfs_cmd_t zc = { 0 }; 1989*789Sahrens char parent[ZFS_MAXNAMELEN]; 1990*789Sahrens int ret; 1991*789Sahrens 1992*789Sahrens assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 1993*789Sahrens 1994*789Sahrens /* validate the target name */ 1995*789Sahrens if (!zfs_validate_name(target, ZFS_TYPE_FILESYSTEM, reason, 1996*789Sahrens sizeof (reason))) { 1997*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 1998*789Sahrens "cannot create '%s': %s in filesystem name"), target, 1999*789Sahrens reason, zfs_type_to_name(ZFS_TYPE_FILESYSTEM)); 2000*789Sahrens return (-1); 2001*789Sahrens } 2002*789Sahrens 2003*789Sahrens /* validate parents exist */ 2004*789Sahrens if (check_parents(target, zhp->zfs_type) != 0) 2005*789Sahrens return (-1); 2006*789Sahrens 2007*789Sahrens (void) parent_name(target, parent, sizeof (parent)); 2008*789Sahrens 2009*789Sahrens /* do the clone */ 2010*789Sahrens if (zhp->zfs_volblocksize != 0) 2011*789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2012*789Sahrens else 2013*789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2014*789Sahrens 2015*789Sahrens (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name)); 2016*789Sahrens (void) strlcpy(zc.zc_filename, zhp->zfs_name, sizeof (zc.zc_filename)); 2017*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_CREATE, &zc); 2018*789Sahrens 2019*789Sahrens if (ret != 0) { 2020*789Sahrens switch (errno) { 2021*789Sahrens case EPERM: 2022*789Sahrens /* 2023*789Sahrens * The user doesn't have permission to create the clone. 2024*789Sahrens */ 2025*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2026*789Sahrens "cannot create '%s': permission denied"), 2027*789Sahrens target); 2028*789Sahrens break; 2029*789Sahrens 2030*789Sahrens case ENOENT: 2031*789Sahrens /* 2032*789Sahrens * The parent doesn't exist. We should have caught this 2033*789Sahrens * above, but there may a race condition that has since 2034*789Sahrens * destroyed the parent. 2035*789Sahrens * 2036*789Sahrens * At this point, we don't know whether it's the source 2037*789Sahrens * that doesn't exist anymore, or whether the target 2038*789Sahrens * dataset doesn't exist. 2039*789Sahrens */ 2040*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2041*789Sahrens "cannot create '%s': no such parent '%s'"), 2042*789Sahrens target, parent); 2043*789Sahrens break; 2044*789Sahrens 2045*789Sahrens case EDQUOT: 2046*789Sahrens case ENOSPC: 2047*789Sahrens /* 2048*789Sahrens * There is not enough space in the target dataset 2049*789Sahrens */ 2050*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2051*789Sahrens "cannot create '%s': not enough space in '%s'"), 2052*789Sahrens target, parent); 2053*789Sahrens break; 2054*789Sahrens 2055*789Sahrens case EEXIST: 2056*789Sahrens /* 2057*789Sahrens * The target already exists. 2058*789Sahrens */ 2059*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2060*789Sahrens "cannot create '%s': dataset exists"), target); 2061*789Sahrens break; 2062*789Sahrens 2063*789Sahrens case EXDEV: 2064*789Sahrens /* 2065*789Sahrens * The source and target pools differ. 2066*789Sahrens */ 2067*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2068*789Sahrens "source and target pools differ"), target); 2069*789Sahrens break; 2070*789Sahrens 2071*789Sahrens default: 2072*789Sahrens zfs_baderror(errno); 2073*789Sahrens } 2074*789Sahrens } else if (zhp->zfs_volblocksize != 0) { 2075*789Sahrens ret = zvol_create_link(target); 2076*789Sahrens } 2077*789Sahrens 2078*789Sahrens return (ret); 2079*789Sahrens } 2080*789Sahrens 2081*789Sahrens /* 2082*789Sahrens * Takes a snapshot of the given dataset 2083*789Sahrens */ 2084*789Sahrens int 2085*789Sahrens zfs_snapshot(const char *path) 2086*789Sahrens { 2087*789Sahrens char reason[64]; 2088*789Sahrens const char *delim; 2089*789Sahrens char *parent; 2090*789Sahrens zfs_handle_t *zhp; 2091*789Sahrens zfs_cmd_t zc = { 0 }; 2092*789Sahrens int ret; 2093*789Sahrens 2094*789Sahrens /* validate the snapshot name */ 2095*789Sahrens if (!zfs_validate_name(path, ZFS_TYPE_SNAPSHOT, reason, 2096*789Sahrens sizeof (reason))) { 2097*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2098*789Sahrens "cannot snapshot '%s': %s in snapshot name"), path, 2099*789Sahrens reason); 2100*789Sahrens return (-1); 2101*789Sahrens } 2102*789Sahrens 2103*789Sahrens /* make sure we have a snapshot */ 2104*789Sahrens if ((delim = strchr(path, '@')) == NULL) { 2105*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2106*789Sahrens "cannot snapshot '%s': missing '@' delim in snapshot " 2107*789Sahrens "name"), path); 2108*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2109*789Sahrens "use 'zfs create' to create a filesystem")); 2110*789Sahrens return (-1); 2111*789Sahrens } 2112*789Sahrens 2113*789Sahrens /* make sure the parent exists and is of the appropriate type */ 2114*789Sahrens parent = zfs_malloc(delim - path + 1); 2115*789Sahrens (void) strncpy(parent, path, delim - path); 2116*789Sahrens parent[delim - path] = '\0'; 2117*789Sahrens 2118*789Sahrens if ((zhp = zfs_open(parent, ZFS_TYPE_FILESYSTEM | 2119*789Sahrens ZFS_TYPE_VOLUME)) == NULL) { 2120*789Sahrens free(parent); 2121*789Sahrens return (-1); 2122*789Sahrens } 2123*789Sahrens 2124*789Sahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 2125*789Sahrens 2126*789Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME) 2127*789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2128*789Sahrens else 2129*789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2130*789Sahrens 2131*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_CREATE, &zc); 2132*789Sahrens 2133*789Sahrens if (ret == 0 && zhp->zfs_type == ZFS_TYPE_VOLUME) { 2134*789Sahrens ret = zvol_create_link(path); 2135*789Sahrens if (ret != 0) 2136*789Sahrens (void) ioctl(zfs_fd, ZFS_IOC_DESTROY, &zc); 2137*789Sahrens } 2138*789Sahrens 2139*789Sahrens if (ret != 0) { 2140*789Sahrens switch (errno) { 2141*789Sahrens case EPERM: 2142*789Sahrens /* 2143*789Sahrens * User doesn't have permission to create a snapshot 2144*789Sahrens */ 2145*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2146*789Sahrens "permission denied"), path); 2147*789Sahrens break; 2148*789Sahrens 2149*789Sahrens case EDQUOT: 2150*789Sahrens case ENOSPC: 2151*789Sahrens /* 2152*789Sahrens * Out of space in parent. 2153*789Sahrens */ 2154*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2155*789Sahrens "not enough space in '%s'"), path, parent); 2156*789Sahrens break; 2157*789Sahrens 2158*789Sahrens case EEXIST: 2159*789Sahrens /* 2160*789Sahrens * Snapshot already exists. 2161*789Sahrens */ 2162*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': " 2163*789Sahrens "snapshot exists"), path); 2164*789Sahrens break; 2165*789Sahrens 2166*789Sahrens case ENOENT: 2167*789Sahrens /* 2168*789Sahrens * Shouldn't happen because we verified the parent 2169*789Sahrens * above. But there may be a race condition where it 2170*789Sahrens * has since been removed. 2171*789Sahrens */ 2172*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': " 2173*789Sahrens "no such %s"), parent, 2174*789Sahrens zfs_type_to_name(zhp->zfs_type)); 2175*789Sahrens break; 2176*789Sahrens 2177*789Sahrens default: 2178*789Sahrens zfs_baderror(errno); 2179*789Sahrens } 2180*789Sahrens } 2181*789Sahrens 2182*789Sahrens free(parent); 2183*789Sahrens zfs_close(zhp); 2184*789Sahrens 2185*789Sahrens return (ret); 2186*789Sahrens } 2187*789Sahrens 2188*789Sahrens /* 2189*789Sahrens * Dumps a backup of tosnap, incremental from fromsnap if it isn't NULL. 2190*789Sahrens */ 2191*789Sahrens int 2192*789Sahrens zfs_backup(zfs_handle_t *zhp_to, zfs_handle_t *zhp_from) 2193*789Sahrens { 2194*789Sahrens zfs_cmd_t zc = { 0 }; 2195*789Sahrens int ret; 2196*789Sahrens 2197*789Sahrens /* do the ioctl() */ 2198*789Sahrens (void) strlcpy(zc.zc_name, zhp_to->zfs_name, sizeof (zc.zc_name)); 2199*789Sahrens if (zhp_from) { 2200*789Sahrens (void) strlcpy(zc.zc_prop_value, zhp_from->zfs_name, 2201*789Sahrens sizeof (zc.zc_name)); 2202*789Sahrens } else { 2203*789Sahrens zc.zc_prop_value[0] = '\0'; 2204*789Sahrens } 2205*789Sahrens zc.zc_cookie = STDOUT_FILENO; 2206*789Sahrens 2207*789Sahrens ret = ioctl(zfs_fd, ZFS_IOC_SENDBACKUP, &zc); 2208*789Sahrens if (ret != 0) { 2209*789Sahrens switch (errno) { 2210*789Sahrens case EPERM: 2211*789Sahrens /* 2212*789Sahrens * User doesn't have permission to do a backup 2213*789Sahrens */ 2214*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot backup '%s': " 2215*789Sahrens "permission denied"), zhp_to->zfs_name); 2216*789Sahrens break; 2217*789Sahrens 2218*789Sahrens case EXDEV: 2219*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2220*789Sahrens "cannot do incremental backup from %s:\n" 2221*789Sahrens "it is not an earlier snapshot from the " 2222*789Sahrens "same fs as %s"), 2223*789Sahrens zhp_from->zfs_name, zhp_to->zfs_name); 2224*789Sahrens break; 2225*789Sahrens 2226*789Sahrens case ENOENT: 2227*789Sahrens /* 2228*789Sahrens * Shouldn't happen because we verified the parent 2229*789Sahrens * above. But there may be a race condition where it 2230*789Sahrens * has since been removed. 2231*789Sahrens */ 2232*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot open: " 2233*789Sahrens "no such snapshot")); 2234*789Sahrens break; 2235*789Sahrens 2236*789Sahrens case EDQUOT: 2237*789Sahrens case EFBIG: 2238*789Sahrens case EIO: 2239*789Sahrens case ENOLINK: 2240*789Sahrens case ENOSPC: 2241*789Sahrens case ENOSTR: 2242*789Sahrens case ENXIO: 2243*789Sahrens case EPIPE: 2244*789Sahrens case ERANGE: 2245*789Sahrens case EFAULT: 2246*789Sahrens case EROFS: 2247*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2248*789Sahrens "cannot write backup stream: %s"), 2249*789Sahrens strerror(errno)); 2250*789Sahrens break; 2251*789Sahrens 2252*789Sahrens case EINTR: 2253*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2254*789Sahrens "backup failed: signal recieved")); 2255*789Sahrens break; 2256*789Sahrens 2257*789Sahrens default: 2258*789Sahrens zfs_baderror(errno); 2259*789Sahrens } 2260*789Sahrens } 2261*789Sahrens 2262*789Sahrens return (ret); 2263*789Sahrens } 2264*789Sahrens 2265*789Sahrens /* 2266*789Sahrens * Restores a backup of tosnap from stdin. 2267*789Sahrens */ 2268*789Sahrens int 2269*789Sahrens zfs_restore(const char *tosnap, int isprefix, int verbose, int dryrun) 2270*789Sahrens { 2271*789Sahrens zfs_cmd_t zc = { 0 }; 2272*789Sahrens time_t begin_time; 2273*789Sahrens int err, bytes; 2274*789Sahrens char *cp; 2275*789Sahrens dmu_replay_record_t drr; 2276*789Sahrens struct drr_begin *drrb = &zc.zc_begin_record; 2277*789Sahrens 2278*789Sahrens begin_time = time(NULL); 2279*789Sahrens 2280*789Sahrens /* trim off snapname, if any */ 2281*789Sahrens (void) strcpy(zc.zc_name, tosnap); 2282*789Sahrens cp = strchr(zc.zc_name, '@'); 2283*789Sahrens if (cp) 2284*789Sahrens *cp = '\0'; 2285*789Sahrens 2286*789Sahrens /* read in the BEGIN record */ 2287*789Sahrens cp = (char *)&drr; 2288*789Sahrens bytes = 0; 2289*789Sahrens do { 2290*789Sahrens err = read(STDIN_FILENO, cp, sizeof (drr) - bytes); 2291*789Sahrens cp += err; 2292*789Sahrens bytes += err; 2293*789Sahrens } while (err > 0); 2294*789Sahrens 2295*789Sahrens if (err < 0 || bytes != sizeof (drr)) { 2296*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2297*789Sahrens "Can't restore: invalid backup stream " 2298*789Sahrens "(couldn't read first record)")); 2299*789Sahrens return (-1); 2300*789Sahrens } 2301*789Sahrens 2302*789Sahrens zc.zc_begin_record = drr.drr_u.drr_begin; 2303*789Sahrens 2304*789Sahrens if (drrb->drr_magic != DMU_BACKUP_MAGIC && 2305*789Sahrens drrb->drr_magic != BSWAP_64(DMU_BACKUP_MAGIC)) { 2306*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2307*789Sahrens "Can't restore: invalid backup stream " 2308*789Sahrens "(invalid magic number)")); 2309*789Sahrens return (-1); 2310*789Sahrens } 2311*789Sahrens 2312*789Sahrens if (drrb->drr_version != DMU_BACKUP_VERSION && 2313*789Sahrens drrb->drr_version != BSWAP_64(DMU_BACKUP_VERSION)) { 2314*789Sahrens if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) 2315*789Sahrens drrb->drr_version = BSWAP_64(drrb->drr_version); 2316*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2317*789Sahrens "Can't restore: only backup version 0x%llx is supported, " 2318*789Sahrens "stream is version %llx."), 2319*789Sahrens DMU_BACKUP_VERSION, drrb->drr_version); 2320*789Sahrens return (-1); 2321*789Sahrens } 2322*789Sahrens 2323*789Sahrens /* 2324*789Sahrens * Determine name of destination snapshot. 2325*789Sahrens */ 2326*789Sahrens (void) strcpy(drrb->drr_toname, tosnap); 2327*789Sahrens if (isprefix) { 2328*789Sahrens if (strchr(tosnap, '@') != NULL) { 2329*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2330*789Sahrens "Can't restore: " 2331*789Sahrens "argument to -d must be a filesystem")); 2332*789Sahrens return (-1); 2333*789Sahrens } 2334*789Sahrens 2335*789Sahrens cp = strchr(drr.drr_u.drr_begin.drr_toname, '/'); 2336*789Sahrens if (cp == NULL) 2337*789Sahrens cp = drr.drr_u.drr_begin.drr_toname; 2338*789Sahrens else 2339*789Sahrens cp++; 2340*789Sahrens 2341*789Sahrens (void) strcat(drrb->drr_toname, "/"); 2342*789Sahrens (void) strcat(drrb->drr_toname, cp); 2343*789Sahrens } else if (strchr(tosnap, '@') == NULL) { 2344*789Sahrens /* 2345*789Sahrens * they specified just a filesystem; tack on the 2346*789Sahrens * snapname from the backup. 2347*789Sahrens */ 2348*789Sahrens cp = strchr(drr.drr_u.drr_begin.drr_toname, '@'); 2349*789Sahrens if (cp == NULL || strlen(tosnap) + strlen(cp) >= MAXNAMELEN) { 2350*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2351*789Sahrens "Can't restore: invalid backup stream " 2352*789Sahrens "(invalid snapshot name)")); 2353*789Sahrens return (-1); 2354*789Sahrens } 2355*789Sahrens (void) strcat(drrb->drr_toname, cp); 2356*789Sahrens } 2357*789Sahrens 2358*789Sahrens if (drrb->drr_fromguid) { 2359*789Sahrens zfs_handle_t *h; 2360*789Sahrens /* incremental backup stream */ 2361*789Sahrens 2362*789Sahrens /* do the ioctl to the containing fs */ 2363*789Sahrens (void) strcpy(zc.zc_name, drrb->drr_toname); 2364*789Sahrens cp = strchr(zc.zc_name, '@'); 2365*789Sahrens *cp = '\0'; 2366*789Sahrens 2367*789Sahrens /* make sure destination fs exists */ 2368*789Sahrens h = zfs_open(zc.zc_name, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2369*789Sahrens if (h == NULL) { 2370*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2371*789Sahrens "Can't restore incrememtal backup: destination\n" 2372*789Sahrens "filesystem %s does not exist"), 2373*789Sahrens zc.zc_name); 2374*789Sahrens return (-1); 2375*789Sahrens } 2376*789Sahrens /* unmount destination fs */ 2377*789Sahrens if (!dryrun) 2378*789Sahrens (void) zfs_unmount(h, NULL, 0); 2379*789Sahrens zfs_close(h); 2380*789Sahrens 2381*789Sahrens 2382*789Sahrens } else { 2383*789Sahrens /* full backup stream */ 2384*789Sahrens 2385*789Sahrens /* do the ioctl to the containing fs's parent */ 2386*789Sahrens (void) strcpy(zc.zc_name, drrb->drr_toname); 2387*789Sahrens cp = strrchr(zc.zc_name, '/'); 2388*789Sahrens if (cp == NULL) { 2389*789Sahrens cp = strchr(zc.zc_name, '@'); 2390*789Sahrens if (cp) 2391*789Sahrens *cp = '\0'; 2392*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2393*789Sahrens "Can't restore: destination fs %s already exists"), 2394*789Sahrens zc.zc_name); 2395*789Sahrens return (-1); 2396*789Sahrens } 2397*789Sahrens *cp = '\0'; 2398*789Sahrens 2399*789Sahrens /* make sure destination fs exists */ 2400*789Sahrens 2401*789Sahrens if (isprefix) { 2402*789Sahrens /* make sure prefix exists */ 2403*789Sahrens zfs_handle_t *h; 2404*789Sahrens 2405*789Sahrens /* make sure destination fs exists */ 2406*789Sahrens h = zfs_open(tosnap, ZFS_TYPE_FILESYSTEM | 2407*789Sahrens ZFS_TYPE_VOLUME); 2408*789Sahrens if (h == NULL) { 2409*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2410*789Sahrens "Can't restore:" 2411*789Sahrens "filesystem %s does not exist"), 2412*789Sahrens tosnap); 2413*789Sahrens return (-1); 2414*789Sahrens } 2415*789Sahrens 2416*789Sahrens /* create any necessary ancestors up to prefix */ 2417*789Sahrens cp = zc.zc_name + strlen(tosnap) + 1; 2418*789Sahrens while (cp = strchr(cp, '/')) { 2419*789Sahrens *cp = '\0'; 2420*789Sahrens err = ioctl(zfs_fd, ZFS_IOC_CREATE, &zc); 2421*789Sahrens if (err && err != ENOENT && err != EEXIST) { 2422*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2423*789Sahrens "Can't restore:" 2424*789Sahrens "couldn't create ancestor %s"), 2425*789Sahrens zc.zc_name); 2426*789Sahrens return (-1); 2427*789Sahrens } 2428*789Sahrens } 2429*789Sahrens } 2430*789Sahrens } 2431*789Sahrens 2432*789Sahrens (void) strcpy(zc.zc_prop_value, tosnap); 2433*789Sahrens zc.zc_cookie = STDIN_FILENO; 2434*789Sahrens zc.zc_intsz = isprefix; 2435*789Sahrens if (verbose) { 2436*789Sahrens (void) printf("%s %s backup of %s into %s\n", 2437*789Sahrens dryrun ? "would restore" : "restoring", 2438*789Sahrens drrb->drr_fromguid ? "incremental" : "full", 2439*789Sahrens drr.drr_u.drr_begin.drr_toname, 2440*789Sahrens zc.zc_begin_record.drr_toname); 2441*789Sahrens (void) fflush(stdout); 2442*789Sahrens } 2443*789Sahrens if (dryrun) 2444*789Sahrens return (0); 2445*789Sahrens err = ioctl(zfs_fd, ZFS_IOC_RECVBACKUP, &zc); 2446*789Sahrens if (err != 0) { 2447*789Sahrens switch (errno) { 2448*789Sahrens case ENODEV: 2449*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2450*789Sahrens "Can't restore: " 2451*789Sahrens "Most recent snapshot does not " 2452*789Sahrens "match incremental backup source")); 2453*789Sahrens break; 2454*789Sahrens case ETXTBSY: 2455*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2456*789Sahrens "Can't restore: " 2457*789Sahrens "Destination has been modified since " 2458*789Sahrens "most recent snapshot.\n" 2459*789Sahrens "Use 'zfs rollback' to discard changes.")); 2460*789Sahrens break; 2461*789Sahrens case EEXIST: 2462*789Sahrens if (drrb->drr_fromguid == 0) { 2463*789Sahrens /* it's the containing fs that exists */ 2464*789Sahrens cp = strchr(drrb->drr_toname, '@'); 2465*789Sahrens *cp = '\0'; 2466*789Sahrens } 2467*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2468*789Sahrens "Can't restore to %s: Destination already exists"), 2469*789Sahrens drrb->drr_toname); 2470*789Sahrens break; 2471*789Sahrens case ENOENT: 2472*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2473*789Sahrens "Can't restore: " 2474*789Sahrens "Destination does not exist")); 2475*789Sahrens break; 2476*789Sahrens case EBUSY: 2477*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2478*789Sahrens "Can't restore: " 2479*789Sahrens "Destination is in use")); 2480*789Sahrens break; 2481*789Sahrens case ENOSPC: 2482*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2483*789Sahrens "Can't restore: " 2484*789Sahrens "Out of space")); 2485*789Sahrens break; 2486*789Sahrens case EDQUOT: 2487*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2488*789Sahrens "Can't restore: " 2489*789Sahrens "Quota exceeded")); 2490*789Sahrens break; 2491*789Sahrens case EINTR: 2492*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2493*789Sahrens "Restore failed: signal recieved")); 2494*789Sahrens break; 2495*789Sahrens case EINVAL: 2496*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2497*789Sahrens "Can't restore: " 2498*789Sahrens "invalid backup stream")); 2499*789Sahrens break; 2500*789Sahrens default: 2501*789Sahrens zfs_baderror(errno); 2502*789Sahrens } 2503*789Sahrens } 2504*789Sahrens 2505*789Sahrens /* 2506*789Sahrens * Mount or recreate the /dev links for the target filesystem. 2507*789Sahrens */ 2508*789Sahrens cp = strchr(drrb->drr_toname, '@'); 2509*789Sahrens if (cp && (err == 0 || drrb->drr_fromguid)) { 2510*789Sahrens zfs_handle_t *h; 2511*789Sahrens 2512*789Sahrens *cp = '\0'; 2513*789Sahrens h = zfs_open(drrb->drr_toname, 2514*789Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2515*789Sahrens if (h) { 2516*789Sahrens if (h->zfs_type == ZFS_TYPE_FILESYSTEM) 2517*789Sahrens err = zfs_mount(h, NULL, 0); 2518*789Sahrens else 2519*789Sahrens err = zvol_create_link(h->zfs_name); 2520*789Sahrens zfs_close(h); 2521*789Sahrens } 2522*789Sahrens } 2523*789Sahrens 2524*789Sahrens /* 2525*789Sahrens * If the destination snapshot was also specified, and it was a volume, 2526*789Sahrens * make sure that the appropriate /dev link was created as well. 2527*789Sahrens */ 2528*789Sahrens if (err == 0) { 2529*789Sahrens zfs_handle_t *h; 2530*789Sahrens 2531*789Sahrens if (cp) 2532*789Sahrens *cp = '@'; 2533*789Sahrens 2534*789Sahrens h = zfs_open(drrb->drr_toname, ZFS_TYPE_SNAPSHOT | 2535*789Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2536*789Sahrens if (h) { 2537*789Sahrens if (h->zfs_volblocksize) 2538*789Sahrens err = zvol_create_link(h->zfs_name); 2539*789Sahrens zfs_close(h); 2540*789Sahrens } 2541*789Sahrens } 2542*789Sahrens 2543*789Sahrens if (err) 2544*789Sahrens return (err); 2545*789Sahrens 2546*789Sahrens if (verbose) { 2547*789Sahrens char buf1[64]; 2548*789Sahrens char buf2[64]; 2549*789Sahrens uint64_t bytes = zc.zc_cookie; 2550*789Sahrens time_t delta = time(NULL) - begin_time; 2551*789Sahrens if (delta == 0) 2552*789Sahrens delta = 1; 2553*789Sahrens zfs_nicenum(bytes, buf1, sizeof (buf1)); 2554*789Sahrens zfs_nicenum(bytes/delta, buf2, sizeof (buf1)); 2555*789Sahrens 2556*789Sahrens (void) printf("restored %sb backup in %lu seconds (%sb/sec)\n", 2557*789Sahrens buf1, delta, buf2); 2558*789Sahrens } 2559*789Sahrens return (0); 2560*789Sahrens } 2561*789Sahrens 2562*789Sahrens /* 2563*789Sahrens * Rollback the given dataset to the previous snapshot. It is up to the caller 2564*789Sahrens * to verify that there is a previous snapshot available. 2565*789Sahrens */ 2566*789Sahrens int 2567*789Sahrens zfs_rollback(zfs_handle_t *zhp) 2568*789Sahrens { 2569*789Sahrens int ret; 2570*789Sahrens zfs_cmd_t zc = { 0 }; 2571*789Sahrens 2572*789Sahrens assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM || 2573*789Sahrens zhp->zfs_type == ZFS_TYPE_VOLUME); 2574*789Sahrens 2575*789Sahrens if (zhp->zfs_type == ZFS_TYPE_VOLUME && 2576*789Sahrens zvol_remove_link(zhp->zfs_name) != 0) 2577*789Sahrens return (-1); 2578*789Sahrens 2579*789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2580*789Sahrens 2581*789Sahrens if (zhp->zfs_volblocksize != 0) 2582*789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2583*789Sahrens else 2584*789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2585*789Sahrens 2586*789Sahrens /* 2587*789Sahrens * We rely on the consumer to verify that there are no newer snapshots 2588*789Sahrens * for the given dataset. Given these constraints, we can simply pass 2589*789Sahrens * the name on to the ioctl() call. There is still an unlikely race 2590*789Sahrens * condition where the user has taken a snapshot since we verified that 2591*789Sahrens * this was the most recent. 2592*789Sahrens */ 2593*789Sahrens if ((ret = ioctl(zfs_fd, ZFS_IOC_ROLLBACK, &zc)) != 0) { 2594*789Sahrens switch (errno) { 2595*789Sahrens case EPERM: 2596*789Sahrens /* 2597*789Sahrens * The user doesn't have permission to rollback the 2598*789Sahrens * given dataset. 2599*789Sahrens */ 2600*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rollback '%s': " 2601*789Sahrens "permission denied"), zhp->zfs_name); 2602*789Sahrens break; 2603*789Sahrens 2604*789Sahrens case EDQUOT: 2605*789Sahrens case ENOSPC: 2606*789Sahrens /* 2607*789Sahrens * The parent dataset doesn't have enough space to 2608*789Sahrens * rollback to the last snapshot. 2609*789Sahrens */ 2610*789Sahrens { 2611*789Sahrens char parent[ZFS_MAXNAMELEN]; 2612*789Sahrens (void) parent_name(zhp->zfs_name, parent, 2613*789Sahrens sizeof (parent)); 2614*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 2615*789Sahrens "rollback '%s': out of space"), parent); 2616*789Sahrens } 2617*789Sahrens break; 2618*789Sahrens 2619*789Sahrens case ENOENT: 2620*789Sahrens /* 2621*789Sahrens * The dataset doesn't exist. This shouldn't happen 2622*789Sahrens * except in race conditions. 2623*789Sahrens */ 2624*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rollback '%s': " 2625*789Sahrens "no such %s"), zhp->zfs_name, 2626*789Sahrens zfs_type_to_name(zhp->zfs_type)); 2627*789Sahrens break; 2628*789Sahrens 2629*789Sahrens case EBUSY: 2630*789Sahrens /* 2631*789Sahrens * The filesystem is busy. This should have been caught 2632*789Sahrens * by the caller before getting here, but there may be 2633*789Sahrens * an unexpected problem. 2634*789Sahrens */ 2635*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rollback '%s': " 2636*789Sahrens "%s is busy"), zhp->zfs_name, 2637*789Sahrens zfs_type_to_name(zhp->zfs_type)); 2638*789Sahrens break; 2639*789Sahrens 2640*789Sahrens default: 2641*789Sahrens zfs_baderror(errno); 2642*789Sahrens } 2643*789Sahrens } else if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 2644*789Sahrens ret = zvol_create_link(zhp->zfs_name); 2645*789Sahrens } 2646*789Sahrens 2647*789Sahrens return (ret); 2648*789Sahrens } 2649*789Sahrens 2650*789Sahrens /* 2651*789Sahrens * Iterate over all dependents for a given dataset. This includes both 2652*789Sahrens * hierarchical dependents (children) and data dependents (snapshots and 2653*789Sahrens * clones). The bulk of the processing occurs in get_dependents() in 2654*789Sahrens * libzfs_graph.c. 2655*789Sahrens */ 2656*789Sahrens int 2657*789Sahrens zfs_iter_dependents(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2658*789Sahrens { 2659*789Sahrens char **dependents; 2660*789Sahrens size_t count; 2661*789Sahrens int i; 2662*789Sahrens zfs_handle_t *child; 2663*789Sahrens int ret = 0; 2664*789Sahrens 2665*789Sahrens dependents = get_dependents(zhp->zfs_name, &count); 2666*789Sahrens for (i = 0; i < count; i++) { 2667*789Sahrens if ((child = make_dataset_handle(dependents[i])) == NULL) 2668*789Sahrens continue; 2669*789Sahrens 2670*789Sahrens if ((ret = func(child, data)) != 0) 2671*789Sahrens break; 2672*789Sahrens } 2673*789Sahrens 2674*789Sahrens for (i = 0; i < count; i++) 2675*789Sahrens free(dependents[i]); 2676*789Sahrens free(dependents); 2677*789Sahrens 2678*789Sahrens return (ret); 2679*789Sahrens } 2680*789Sahrens 2681*789Sahrens /* 2682*789Sahrens * Renames the given dataset. 2683*789Sahrens */ 2684*789Sahrens int 2685*789Sahrens zfs_rename(zfs_handle_t *zhp, const char *target) 2686*789Sahrens { 2687*789Sahrens int ret; 2688*789Sahrens zfs_cmd_t zc = { 0 }; 2689*789Sahrens char reason[64]; 2690*789Sahrens char *delim; 2691*789Sahrens prop_changelist_t *cl; 2692*789Sahrens char parent[ZFS_MAXNAMELEN]; 2693*789Sahrens 2694*789Sahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2695*789Sahrens (void) strlcpy(zc.zc_prop_value, target, sizeof (zc.zc_prop_value)); 2696*789Sahrens 2697*789Sahrens /* if we have the same exact name, just return success */ 2698*789Sahrens if (strcmp(zhp->zfs_name, target) == 0) 2699*789Sahrens return (0); 2700*789Sahrens 2701*789Sahrens /* 2702*789Sahrens * Make sure the target name is valid 2703*789Sahrens */ 2704*789Sahrens if (!zfs_validate_name(target, zhp->zfs_type, reason, 2705*789Sahrens sizeof (reason))) { 2706*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2707*789Sahrens "cannot create '%s': %s in %s name"), target, reason, 2708*789Sahrens zfs_type_to_name(zhp->zfs_type)); 2709*789Sahrens return (-1); 2710*789Sahrens } 2711*789Sahrens 2712*789Sahrens if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 2713*789Sahrens if ((delim = strchr(target, '@')) == NULL) { 2714*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2715*789Sahrens "cannot rename to '%s': not a snapshot"), target); 2716*789Sahrens return (-1); 2717*789Sahrens } 2718*789Sahrens 2719*789Sahrens /* 2720*789Sahrens * Make sure we're renaming within the same dataset. 2721*789Sahrens */ 2722*789Sahrens if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 2723*789Sahrens zhp->zfs_name[delim - target] != '@') { 2724*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2725*789Sahrens "cannot rename to '%s': snapshots must be part " 2726*789Sahrens "of same dataset"), target); 2727*789Sahrens return (-1); 2728*789Sahrens } 2729*789Sahrens 2730*789Sahrens (void) strncpy(parent, target, delim - target); 2731*789Sahrens parent[delim - target] = '\0'; 2732*789Sahrens } else { 2733*789Sahrens /* validate parents */ 2734*789Sahrens if (check_parents(target, zhp->zfs_type) != 0) 2735*789Sahrens return (-1); 2736*789Sahrens 2737*789Sahrens (void) parent_name(target, parent, sizeof (parent)); 2738*789Sahrens 2739*789Sahrens /* make sure we're in the same pool */ 2740*789Sahrens verify((delim = strchr(target, '/')) != NULL); 2741*789Sahrens if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 2742*789Sahrens zhp->zfs_name[delim - target] != '/') { 2743*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2744*789Sahrens "cannot rename to '%s': " 2745*789Sahrens "datasets must be within same pool"), target); 2746*789Sahrens return (-1); 2747*789Sahrens } 2748*789Sahrens } 2749*789Sahrens 2750*789Sahrens if (getzoneid() == GLOBAL_ZONEID && 2751*789Sahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 2752*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename %s, " 2753*789Sahrens "dataset is used in a non-global zone"), zhp->zfs_name); 2754*789Sahrens return (-1); 2755*789Sahrens } 2756*789Sahrens 2757*789Sahrens if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0)) == NULL) 2758*789Sahrens return (1); 2759*789Sahrens 2760*789Sahrens if (changelist_haszonedchild(cl)) { 2761*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2762*789Sahrens "cannot rename '%s': child dataset with inherited " 2763*789Sahrens "mountpoint is used in a non-global zone"), zhp->zfs_name); 2764*789Sahrens ret = -1; 2765*789Sahrens goto error; 2766*789Sahrens } 2767*789Sahrens 2768*789Sahrens if ((ret = changelist_prefix(cl)) != 0) 2769*789Sahrens goto error; 2770*789Sahrens 2771*789Sahrens if (zhp->zfs_volblocksize != 0) 2772*789Sahrens zc.zc_objset_type = DMU_OST_ZVOL; 2773*789Sahrens else 2774*789Sahrens zc.zc_objset_type = DMU_OST_ZFS; 2775*789Sahrens 2776*789Sahrens if ((ret = ioctl(zfs_fd, ZFS_IOC_RENAME, &zc)) != 0) { 2777*789Sahrens switch (errno) { 2778*789Sahrens case EPERM: 2779*789Sahrens /* 2780*789Sahrens * The user doesn't have permission to rename the 2781*789Sahrens * given dataset. 2782*789Sahrens */ 2783*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s': " 2784*789Sahrens "permission denied"), zhp->zfs_name); 2785*789Sahrens break; 2786*789Sahrens 2787*789Sahrens case EDQUOT: 2788*789Sahrens case ENOSPC: 2789*789Sahrens /* 2790*789Sahrens * Not enough space in the parent dataset. 2791*789Sahrens */ 2792*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot " 2793*789Sahrens "rename '%s': not enough space in '%s'"), 2794*789Sahrens zhp->zfs_name, parent); 2795*789Sahrens break; 2796*789Sahrens 2797*789Sahrens case ENOENT: 2798*789Sahrens /* 2799*789Sahrens * The destination doesn't exist. 2800*789Sahrens */ 2801*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s' " 2802*789Sahrens "to '%s': destination doesn't exist"), 2803*789Sahrens zhp->zfs_name, target); 2804*789Sahrens break; 2805*789Sahrens 2806*789Sahrens case EEXIST: 2807*789Sahrens /* 2808*789Sahrens * The destination already exists. 2809*789Sahrens */ 2810*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s' " 2811*789Sahrens "to '%s': destination already exists"), 2812*789Sahrens zhp->zfs_name, target); 2813*789Sahrens break; 2814*789Sahrens 2815*789Sahrens case EBUSY: 2816*789Sahrens /* 2817*789Sahrens * The filesystem is busy. This should have been caught 2818*789Sahrens * by the caller before getting here, but there may be 2819*789Sahrens * an unexpected problem. 2820*789Sahrens */ 2821*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot rename '%s': " 2822*789Sahrens "%s is busy"), zhp->zfs_name, 2823*789Sahrens zfs_type_to_name(zhp->zfs_type)); 2824*789Sahrens break; 2825*789Sahrens 2826*789Sahrens default: 2827*789Sahrens zfs_baderror(errno); 2828*789Sahrens } 2829*789Sahrens 2830*789Sahrens /* 2831*789Sahrens * On failure, we still want to remount any filesystems that 2832*789Sahrens * were previously mounted, so we don't alter the system state. 2833*789Sahrens */ 2834*789Sahrens (void) changelist_postfix(cl); 2835*789Sahrens } else { 2836*789Sahrens changelist_rename(cl, zfs_get_name(zhp), target); 2837*789Sahrens 2838*789Sahrens ret = changelist_postfix(cl); 2839*789Sahrens } 2840*789Sahrens 2841*789Sahrens error: 2842*789Sahrens changelist_free(cl); 2843*789Sahrens return (ret); 2844*789Sahrens } 2845*789Sahrens 2846*789Sahrens /* 2847*789Sahrens * Given a zvol dataset, issue the ioctl to create the appropriate minor node, 2848*789Sahrens * poke devfsadm to create the /dev link, and then wait for the link to appear. 2849*789Sahrens */ 2850*789Sahrens int 2851*789Sahrens zvol_create_link(const char *dataset) 2852*789Sahrens { 2853*789Sahrens zfs_cmd_t zc = { 0 }; 2854*789Sahrens di_devlink_handle_t hdl; 2855*789Sahrens 2856*789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 2857*789Sahrens 2858*789Sahrens /* 2859*789Sahrens * Issue the appropriate ioctl. 2860*789Sahrens */ 2861*789Sahrens if (ioctl(zfs_fd, ZFS_IOC_CREATE_MINOR, &zc) != 0) { 2862*789Sahrens switch (errno) { 2863*789Sahrens case EPERM: 2864*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot create " 2865*789Sahrens "device links for '%s': permission denied"), 2866*789Sahrens dataset); 2867*789Sahrens break; 2868*789Sahrens 2869*789Sahrens case EEXIST: 2870*789Sahrens /* 2871*789Sahrens * Silently ignore the case where the link already 2872*789Sahrens * exists. This allows 'zfs volinit' to be run multiple 2873*789Sahrens * times without errors. 2874*789Sahrens */ 2875*789Sahrens return (0); 2876*789Sahrens 2877*789Sahrens default: 2878*789Sahrens zfs_baderror(errno); 2879*789Sahrens } 2880*789Sahrens 2881*789Sahrens return (-1); 2882*789Sahrens } 2883*789Sahrens 2884*789Sahrens /* 2885*789Sahrens * Call devfsadm and wait for the links to magically appear. 2886*789Sahrens */ 2887*789Sahrens if ((hdl = di_devlink_init(ZFS_DRIVER, DI_MAKE_LINK)) == NULL) { 2888*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, 2889*789Sahrens "cannot create device links for '%s'"), dataset); 2890*789Sahrens (void) ioctl(zfs_fd, ZFS_IOC_REMOVE_MINOR, &zc); 2891*789Sahrens return (-1); 2892*789Sahrens } else { 2893*789Sahrens (void) di_devlink_fini(&hdl); 2894*789Sahrens } 2895*789Sahrens 2896*789Sahrens return (0); 2897*789Sahrens } 2898*789Sahrens 2899*789Sahrens /* 2900*789Sahrens * Remove a minor node for the given zvol and the associated /dev links. 2901*789Sahrens */ 2902*789Sahrens int 2903*789Sahrens zvol_remove_link(const char *dataset) 2904*789Sahrens { 2905*789Sahrens zfs_cmd_t zc = { 0 }; 2906*789Sahrens 2907*789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 2908*789Sahrens 2909*789Sahrens if (ioctl(zfs_fd, ZFS_IOC_REMOVE_MINOR, &zc) != 0) { 2910*789Sahrens switch (errno) { 2911*789Sahrens case EPERM: 2912*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot remove " 2913*789Sahrens "device links for '%s': permission denied"), 2914*789Sahrens dataset); 2915*789Sahrens break; 2916*789Sahrens 2917*789Sahrens case EBUSY: 2918*789Sahrens zfs_error(dgettext(TEXT_DOMAIN, "cannot remove " 2919*789Sahrens "device links for '%s': volume is in use"), 2920*789Sahrens dataset); 2921*789Sahrens break; 2922*789Sahrens 2923*789Sahrens case ENXIO: 2924*789Sahrens /* 2925*789Sahrens * Silently ignore the case where the link no longer 2926*789Sahrens * exists, so that 'zfs volfini' can be run multiple 2927*789Sahrens * times without errors. 2928*789Sahrens */ 2929*789Sahrens return (0); 2930*789Sahrens 2931*789Sahrens default: 2932*789Sahrens zfs_baderror(errno); 2933*789Sahrens } 2934*789Sahrens 2935*789Sahrens return (-1); 2936*789Sahrens } 2937*789Sahrens 2938*789Sahrens return (0); 2939*789Sahrens } 2940