Print this page
2882 implement libzfs_core
2883 changing "canmount" property to "on" should not always remount dataset
2900 "zfs snapshot" should be able to create multiple, arbitrary snapshots at once
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Chris Siden <christopher.siden@delphix.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Bill Pijewski <wdp@joyent.com>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>


1390 #endif
1391                 /* FALLTHROUGH */
1392         default:
1393                 (void) zfs_standard_error(hdl, err, errbuf);
1394         }
1395 }
1396 
1397 /*
1398  * Given a property name and value, set the property for the given dataset.
1399  */
1400 int
1401 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
1402 {
1403         zfs_cmd_t zc = { 0 };
1404         int ret = -1;
1405         prop_changelist_t *cl = NULL;
1406         char errbuf[1024];
1407         libzfs_handle_t *hdl = zhp->zfs_hdl;
1408         nvlist_t *nvl = NULL, *realprops;
1409         zfs_prop_t prop;
1410         boolean_t do_prefix;
1411         uint64_t idx;
1412         int added_resv;
1413 
1414         (void) snprintf(errbuf, sizeof (errbuf),
1415             dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1416             zhp->zfs_name);
1417 
1418         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
1419             nvlist_add_string(nvl, propname, propval) != 0) {
1420                 (void) no_memory(hdl);
1421                 goto error;
1422         }
1423 
1424         if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
1425             zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
1426                 goto error;
1427 
1428         nvlist_free(nvl);
1429         nvl = realprops;
1430 
1431         prop = zfs_name_to_prop(propname);
1432 
1433         if (prop == ZFS_PROP_VOLSIZE) {
1434                 if ((added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1)
1435                         goto error;
1436         }
1437 
1438         if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
1439                 goto error;
1440 
1441         if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
1442                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1443                     "child dataset with inherited mountpoint is used "
1444                     "in a non-global zone"));
1445                 ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1446                 goto error;
1447         }
1448 
1449         /*
1450          * If the dataset's canmount property is being set to noauto,
1451          * then we want to prevent unmounting & remounting it.

1452          */
1453         do_prefix = !((prop == ZFS_PROP_CANMOUNT) &&
1454             (zprop_string_to_index(prop, propval, &idx,
1455             ZFS_TYPE_DATASET) == 0) && (idx == ZFS_CANMOUNT_NOAUTO));




1456 
1457         if (do_prefix && (ret = changelist_prefix(cl)) != 0)
1458                 goto error;
1459 
1460         /*
1461          * Execute the corresponding ioctl() to set this property.
1462          */
1463         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1464 
1465         if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
1466                 goto error;
1467 
1468         ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1469 
1470         if (ret != 0) {
1471                 zfs_setprop_error(hdl, prop, errno, errbuf);
1472                 if (added_resv && errno == ENOSPC) {
1473                         /* clean up the volsize property we tried to set */
1474                         uint64_t old_volsize = zfs_prop_get_int(zhp,
1475                             ZFS_PROP_VOLSIZE);


2624 int
2625 zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
2626     char *propbuf, int proplen, boolean_t literal)
2627 {
2628         int err;
2629         uint64_t propvalue;
2630 
2631         err = zfs_prop_get_written_int(zhp, propname, &propvalue);
2632 
2633         if (err)
2634                 return (err);
2635 
2636         if (literal) {
2637                 (void) snprintf(propbuf, proplen, "%llu", propvalue);
2638         } else {
2639                 zfs_nicenum(propvalue, propbuf, proplen);
2640         }
2641         return (0);
2642 }
2643 
2644 int
2645 zfs_get_snapused_int(zfs_handle_t *firstsnap, zfs_handle_t *lastsnap,
2646     uint64_t *usedp)
2647 {
2648         int err;
2649         zfs_cmd_t zc = { 0 };
2650 
2651         (void) strlcpy(zc.zc_name, lastsnap->zfs_name, sizeof (zc.zc_name));
2652         (void) strlcpy(zc.zc_value, firstsnap->zfs_name, sizeof (zc.zc_value));
2653 
2654         err = ioctl(lastsnap->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_SNAPS, &zc);
2655         if (err)
2656                 return (err);
2657 
2658         *usedp = zc.zc_cookie;
2659 
2660         return (0);
2661 }
2662 
2663 /*
2664  * Returns the name of the given zfs handle.
2665  */
2666 const char *
2667 zfs_get_name(const zfs_handle_t *zhp)
2668 {
2669         return (zhp->zfs_name);
2670 }
2671 
2672 /*
2673  * Returns the type of the given zfs handle.
2674  */
2675 zfs_type_t
2676 zfs_get_type(const zfs_handle_t *zhp)
2677 {
2678         return (zhp->zfs_type);
2679 }
2680 
2681 /*
2682  * Is one dataset name a child dataset of another?


2843         /* make sure prefix exists */
2844         cp = target + prefixlen;
2845         if (*cp != '/') {
2846                 assert(strchr(cp, '/') == NULL);
2847                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2848         } else {
2849                 *cp = '\0';
2850                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2851                 *cp = '/';
2852         }
2853         if (h == NULL)
2854                 return (-1);
2855         zfs_close(h);
2856 
2857         /*
2858          * Attempt to create, mount, and share any ancestor filesystems,
2859          * up to the prefixlen-long one.
2860          */
2861         for (cp = target + prefixlen + 1;
2862             cp = strchr(cp, '/'); *cp = '/', cp++) {
2863                 char *logstr;
2864 
2865                 *cp = '\0';
2866 
2867                 h = make_dataset_handle(hdl, target);
2868                 if (h) {
2869                         /* it already exists, nothing to do here */
2870                         zfs_close(h);
2871                         continue;
2872                 }
2873 
2874                 logstr = hdl->libzfs_log_str;
2875                 hdl->libzfs_log_str = NULL;
2876                 if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
2877                     NULL) != 0) {
2878                         hdl->libzfs_log_str = logstr;
2879                         opname = dgettext(TEXT_DOMAIN, "create");
2880                         goto ancestorerr;
2881                 }
2882 
2883                 hdl->libzfs_log_str = logstr;
2884                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2885                 if (h == NULL) {
2886                         opname = dgettext(TEXT_DOMAIN, "open");
2887                         goto ancestorerr;
2888                 }
2889 
2890                 if (zfs_mount(h, NULL, 0) != 0) {
2891                         opname = dgettext(TEXT_DOMAIN, "mount");
2892                         goto ancestorerr;
2893                 }
2894 
2895                 if (zfs_share(h) != 0) {
2896                         opname = dgettext(TEXT_DOMAIN, "share");
2897                         goto ancestorerr;
2898                 }
2899 
2900                 zfs_close(h);
2901         }
2902 
2903         return (0);


2921         if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
2922                 return (-1);
2923 
2924         if ((path_copy = strdup(path)) != NULL) {
2925                 rc = create_parents(hdl, path_copy, prefix);
2926                 free(path_copy);
2927         }
2928         if (path_copy == NULL || rc != 0)
2929                 return (-1);
2930 
2931         return (0);
2932 }
2933 
2934 /*
2935  * Create a new filesystem or volume.
2936  */
2937 int
2938 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
2939     nvlist_t *props)
2940 {
2941         zfs_cmd_t zc = { 0 };
2942         int ret;
2943         uint64_t size = 0;
2944         uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
2945         char errbuf[1024];
2946         uint64_t zoned;

2947 
2948         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2949             "cannot create '%s'"), path);
2950 
2951         /* validate the path, taking care to note the extended error message */
2952         if (!zfs_validate_name(hdl, path, type, B_TRUE))
2953                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2954 
2955         /* validate parents exist */
2956         if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0)
2957                 return (-1);
2958 
2959         /*
2960          * The failure modes when creating a dataset of a different type over
2961          * one that already exists is a little strange.  In particular, if you
2962          * try to create a dataset on top of an existing dataset, the ioctl()
2963          * will return ENOENT, not EEXIST.  To prevent this from happening, we
2964          * first try to see if the dataset exists.
2965          */
2966         (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name));
2967         if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
2968                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2969                     "dataset already exists"));
2970                 return (zfs_error(hdl, EZFS_EXISTS, errbuf));
2971         }
2972 
2973         if (type == ZFS_TYPE_VOLUME)
2974                 zc.zc_objset_type = DMU_OST_ZVOL;
2975         else
2976                 zc.zc_objset_type = DMU_OST_ZFS;
2977 
2978         if (props && (props = zfs_valid_proplist(hdl, type, props,
2979             zoned, NULL, errbuf)) == 0)
2980                 return (-1);
2981 
2982         if (type == ZFS_TYPE_VOLUME) {
2983                 /*
2984                  * If we are creating a volume, the size and block size must
2985                  * satisfy a few restraints.  First, the blocksize must be a
2986                  * valid block size between SPA_{MIN,MAX}BLOCKSIZE.  Second, the
2987                  * volsize must be a multiple of the block size, and cannot be
2988                  * zero.
2989                  */
2990                 if (props == NULL || nvlist_lookup_uint64(props,
2991                     zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) {
2992                         nvlist_free(props);
2993                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2994                             "missing volume size"));
2995                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2996                 }


3008                                 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3009                         }
3010                 }
3011 
3012                 if (size == 0) {
3013                         nvlist_free(props);
3014                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3015                             "volume size cannot be zero"));
3016                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3017                 }
3018 
3019                 if (size % blocksize != 0) {
3020                         nvlist_free(props);
3021                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3022                             "volume size must be a multiple of volume block "
3023                             "size"));
3024                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3025                 }
3026         }
3027 
3028         if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0)
3029                 return (-1);
3030         nvlist_free(props);
3031 
3032         /* create the dataset */
3033         ret = zfs_ioctl(hdl, ZFS_IOC_CREATE, &zc);
3034 
3035         zcmd_free_nvlists(&zc);
3036 
3037         /* check for failure */
3038         if (ret != 0) {
3039                 char parent[ZFS_MAXNAMELEN];
3040                 (void) parent_name(path, parent, sizeof (parent));
3041 
3042                 switch (errno) {
3043                 case ENOENT:
3044                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3045                             "no such parent '%s'"), parent);
3046                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
3047 
3048                 case EINVAL:
3049                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3050                             "parent '%s' is not a filesystem"), parent);
3051                         return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3052 
3053                 case EDOM:
3054                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3055                             "volume block size must be power of 2 from "


3153 
3154         if (nvlist_next_nvpair(dd.nvl, NULL) == NULL) {
3155                 ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
3156                     dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
3157                     zhp->zfs_name, snapname);
3158         } else {
3159                 ret = zfs_destroy_snaps_nvl(zhp, dd.nvl, defer);
3160         }
3161         nvlist_free(dd.nvl);
3162         return (ret);
3163 }
3164 
3165 /*
3166  * Destroys all the snapshots named in the nvlist.  They must be underneath
3167  * the zhp (either snapshots of it, or snapshots of its descendants).
3168  */
3169 int
3170 zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
3171 {
3172         int ret;
3173         zfs_cmd_t zc = { 0 };
3174 
3175         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3176         if (zcmd_write_src_nvlist(zhp->zfs_hdl, &zc, snaps) != 0)
3177                 return (-1);
3178         zc.zc_defer_destroy = defer;
3179 
3180         ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS_NVL, &zc);
3181         if (ret != 0) {


3182                 char errbuf[1024];



3183 
3184                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3185                     "cannot destroy snapshots in %s"), zc.zc_name);
3186 
3187                 switch (errno) {
3188                 case EEXIST:
3189                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,

3190                             "snapshot is cloned"));
3191                         return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf));
3192 

3193                 default:
3194                         return (zfs_standard_error(zhp->zfs_hdl, errno,
3195                             errbuf));


3196                 }
3197         }
3198 
3199         return (0);
3200 }
3201 
3202 /*
3203  * Clones the given dataset.  The target must be of the same type as the source.
3204  */
3205 int
3206 zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
3207 {
3208         zfs_cmd_t zc = { 0 };
3209         char parent[ZFS_MAXNAMELEN];
3210         int ret;
3211         char errbuf[1024];
3212         libzfs_handle_t *hdl = zhp->zfs_hdl;
3213         zfs_type_t type;
3214         uint64_t zoned;
3215 
3216         assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
3217 
3218         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3219             "cannot create '%s'"), target);
3220 
3221         /* validate the target/clone name */
3222         if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
3223                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3224 
3225         /* validate parents exist */
3226         if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
3227                 return (-1);
3228 
3229         (void) parent_name(target, parent, sizeof (parent));
3230 
3231         /* do the clone */



3232         if (ZFS_IS_VOLUME(zhp)) {
3233                 zc.zc_objset_type = DMU_OST_ZVOL;
3234                 type = ZFS_TYPE_VOLUME;
3235         } else {
3236                 zc.zc_objset_type = DMU_OST_ZFS;
3237                 type = ZFS_TYPE_FILESYSTEM;
3238         }
3239 
3240         if (props) {
3241                 if ((props = zfs_valid_proplist(hdl, type, props, zoned,
3242                     zhp, errbuf)) == NULL)
3243                         return (-1);
3244 
3245                 if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
3246                         nvlist_free(props);
3247                         return (-1);
3248                 }
3249 

3250                 nvlist_free(props);
3251         }
3252 
3253         (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name));
3254         (void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value));
3255         ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_CREATE, &zc);
3256 
3257         zcmd_free_nvlists(&zc);
3258 
3259         if (ret != 0) {
3260                 switch (errno) {
3261 
3262                 case ENOENT:
3263                         /*
3264                          * The parent doesn't exist.  We should have caught this
3265                          * above, but there may a race condition that has since
3266                          * destroyed the parent.
3267                          *
3268                          * At this point, we don't know whether it's the source
3269                          * that doesn't exist anymore, or whether the target
3270                          * dataset doesn't exist.
3271                          */
3272                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3273                             "no such parent '%s'"), parent);
3274                         return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
3275 
3276                 case EXDEV:
3277                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,


3322         ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
3323 
3324         if (ret != 0) {
3325                 int save_errno = errno;
3326 
3327                 switch (save_errno) {
3328                 case EEXIST:
3329                         /* There is a conflicting snapshot name. */
3330                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3331                             "conflicting snapshot '%s' from parent '%s'"),
3332                             zc.zc_string, parent);
3333                         return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3334 
3335                 default:
3336                         return (zfs_standard_error(hdl, save_errno, errbuf));
3337                 }
3338         }
3339         return (ret);
3340 }
3341 






















3342 /*
3343  * Takes a snapshot of the given dataset.

3344  */
3345 int
3346 zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
3347     nvlist_t *props)
3348 {
3349         const char *delim;
3350         char parent[ZFS_MAXNAMELEN];
3351         zfs_handle_t *zhp;
3352         zfs_cmd_t zc = { 0 };
3353         int ret;
3354         char errbuf[1024];


3355 
3356         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3357             "cannot snapshot '%s'"), path);




3358 
3359         /* validate the target name */
3360         if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))




3361                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));


3362 
3363         if (props) {
3364                 if ((props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
3365                     props, B_FALSE, NULL, errbuf)) == NULL)
3366                         return (-1);

3367 
3368                 if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
3369                         nvlist_free(props);
3370                         return (-1);










3371                 }







3372 
3373                 nvlist_free(props);




3374         }
3375 
3376         /* make sure the parent exists and is of the appropriate type */
3377         delim = strchr(path, '@');
3378         (void) strncpy(parent, path, delim - path);
3379         parent[delim - path] = '\0';











3380 
3381         if ((zhp = zfs_open(hdl, parent, ZFS_TYPE_FILESYSTEM |











3382             ZFS_TYPE_VOLUME)) == NULL) {
3383                 zcmd_free_nvlists(&zc);
3384                 return (-1);
3385         }
3386 
3387         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3388         (void) strlcpy(zc.zc_value, delim+1, sizeof (zc.zc_value));
3389         if (ZFS_IS_VOLUME(zhp))
3390                 zc.zc_objset_type = DMU_OST_ZVOL;
3391         else
3392                 zc.zc_objset_type = DMU_OST_ZFS;
3393         zc.zc_cookie = recursive;
3394         ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SNAPSHOT, &zc);
3395 
3396         zcmd_free_nvlists(&zc);
3397 
3398         /*
3399          * if it was recursive, the one that actually failed will be in
3400          * zc.zc_name.
3401          */
3402         if (ret != 0) {
3403                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3404                     "cannot create snapshot '%s@%s'"), zc.zc_name, zc.zc_value);
3405                 (void) zfs_standard_error(hdl, errno, errbuf);
3406         }
3407 


3408         zfs_close(zhp);
3409 
3410         return (ret);
3411 }
3412 
3413 /*
3414  * Destroy any more recent snapshots.  We invoke this callback on any dependents
3415  * of the snapshot first.  If the 'cb_dependent' member is non-zero, then this
3416  * is a dependent and we should just destroy it without checking the transaction
3417  * group.
3418  */
3419 typedef struct rollback_data {
3420         const char      *cb_target;             /* the snapshot */
3421         uint64_t        cb_create;              /* creation time reference */
3422         boolean_t       cb_error;
3423         boolean_t       cb_dependent;
3424         boolean_t       cb_force;
3425 } rollback_data_t;
3426 
3427 static int
3428 rollback_destroy(zfs_handle_t *zhp, void *data)
3429 {
3430         rollback_data_t *cbp = data;
3431 
3432         if (!cbp->cb_dependent) {
3433                 if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 &&
3434                     zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
3435                     zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
3436                     cbp->cb_create) {
3437                         char *logstr;
3438 
3439                         cbp->cb_dependent = B_TRUE;
3440                         cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
3441                             rollback_destroy, cbp);
3442                         cbp->cb_dependent = B_FALSE;
3443 
3444                         logstr = zhp->zfs_hdl->libzfs_log_str;
3445                         zhp->zfs_hdl->libzfs_log_str = NULL;
3446                         cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
3447                         zhp->zfs_hdl->libzfs_log_str = logstr;
3448                 }
3449         } else {
3450                 /* We must destroy this clone; first unmount it */
3451                 prop_changelist_t *clp;
3452 
3453                 clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
3454                     cbp->cb_force ? MS_FORCE: 0);
3455                 if (clp == NULL || changelist_prefix(clp) != 0) {
3456                         cbp->cb_error = B_TRUE;
3457                         zfs_close(zhp);
3458                         return (0);
3459                 }
3460                 if (zfs_destroy(zhp, B_FALSE) != 0)
3461                         cbp->cb_error = B_TRUE;
3462                 else
3463                         changelist_remove(clp, zhp->zfs_name);
3464                 (void) changelist_postfix(clp);
3465                 changelist_free(clp);
3466         }
3467 




1390 #endif
1391                 /* FALLTHROUGH */
1392         default:
1393                 (void) zfs_standard_error(hdl, err, errbuf);
1394         }
1395 }
1396 
1397 /*
1398  * Given a property name and value, set the property for the given dataset.
1399  */
1400 int
1401 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
1402 {
1403         zfs_cmd_t zc = { 0 };
1404         int ret = -1;
1405         prop_changelist_t *cl = NULL;
1406         char errbuf[1024];
1407         libzfs_handle_t *hdl = zhp->zfs_hdl;
1408         nvlist_t *nvl = NULL, *realprops;
1409         zfs_prop_t prop;
1410         boolean_t do_prefix = B_TRUE;

1411         int added_resv;
1412 
1413         (void) snprintf(errbuf, sizeof (errbuf),
1414             dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1415             zhp->zfs_name);
1416 
1417         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
1418             nvlist_add_string(nvl, propname, propval) != 0) {
1419                 (void) no_memory(hdl);
1420                 goto error;
1421         }
1422 
1423         if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
1424             zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
1425                 goto error;
1426 
1427         nvlist_free(nvl);
1428         nvl = realprops;
1429 
1430         prop = zfs_name_to_prop(propname);
1431 
1432         if (prop == ZFS_PROP_VOLSIZE) {
1433                 if ((added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1)
1434                         goto error;
1435         }
1436 
1437         if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
1438                 goto error;
1439 
1440         if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
1441                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1442                     "child dataset with inherited mountpoint is used "
1443                     "in a non-global zone"));
1444                 ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1445                 goto error;
1446         }
1447 
1448         /*
1449          * We don't want to unmount & remount the dataset when changing
1450          * its canmount property to 'on' or 'noauto'.  We only use
1451          * the changelist logic to unmount when setting canmount=off.
1452          */
1453         if (prop == ZFS_PROP_CANMOUNT) {
1454                 uint64_t idx;
1455                 int err = zprop_string_to_index(prop, propval, &idx,
1456                     ZFS_TYPE_DATASET);
1457                 if (err == 0 && idx != ZFS_CANMOUNT_OFF)
1458                         do_prefix = B_FALSE;
1459         }
1460 
1461         if (do_prefix && (ret = changelist_prefix(cl)) != 0)
1462                 goto error;
1463 
1464         /*
1465          * Execute the corresponding ioctl() to set this property.
1466          */
1467         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1468 
1469         if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
1470                 goto error;
1471 
1472         ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1473 
1474         if (ret != 0) {
1475                 zfs_setprop_error(hdl, prop, errno, errbuf);
1476                 if (added_resv && errno == ENOSPC) {
1477                         /* clean up the volsize property we tried to set */
1478                         uint64_t old_volsize = zfs_prop_get_int(zhp,
1479                             ZFS_PROP_VOLSIZE);


2628 int
2629 zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
2630     char *propbuf, int proplen, boolean_t literal)
2631 {
2632         int err;
2633         uint64_t propvalue;
2634 
2635         err = zfs_prop_get_written_int(zhp, propname, &propvalue);
2636 
2637         if (err)
2638                 return (err);
2639 
2640         if (literal) {
2641                 (void) snprintf(propbuf, proplen, "%llu", propvalue);
2642         } else {
2643                 zfs_nicenum(propvalue, propbuf, proplen);
2644         }
2645         return (0);
2646 }
2647 



















2648 /*
2649  * Returns the name of the given zfs handle.
2650  */
2651 const char *
2652 zfs_get_name(const zfs_handle_t *zhp)
2653 {
2654         return (zhp->zfs_name);
2655 }
2656 
2657 /*
2658  * Returns the type of the given zfs handle.
2659  */
2660 zfs_type_t
2661 zfs_get_type(const zfs_handle_t *zhp)
2662 {
2663         return (zhp->zfs_type);
2664 }
2665 
2666 /*
2667  * Is one dataset name a child dataset of another?


2828         /* make sure prefix exists */
2829         cp = target + prefixlen;
2830         if (*cp != '/') {
2831                 assert(strchr(cp, '/') == NULL);
2832                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2833         } else {
2834                 *cp = '\0';
2835                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2836                 *cp = '/';
2837         }
2838         if (h == NULL)
2839                 return (-1);
2840         zfs_close(h);
2841 
2842         /*
2843          * Attempt to create, mount, and share any ancestor filesystems,
2844          * up to the prefixlen-long one.
2845          */
2846         for (cp = target + prefixlen + 1;
2847             cp = strchr(cp, '/'); *cp = '/', cp++) {

2848 
2849                 *cp = '\0';
2850 
2851                 h = make_dataset_handle(hdl, target);
2852                 if (h) {
2853                         /* it already exists, nothing to do here */
2854                         zfs_close(h);
2855                         continue;
2856                 }
2857 


2858                 if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
2859                     NULL) != 0) {

2860                         opname = dgettext(TEXT_DOMAIN, "create");
2861                         goto ancestorerr;
2862                 }
2863 

2864                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2865                 if (h == NULL) {
2866                         opname = dgettext(TEXT_DOMAIN, "open");
2867                         goto ancestorerr;
2868                 }
2869 
2870                 if (zfs_mount(h, NULL, 0) != 0) {
2871                         opname = dgettext(TEXT_DOMAIN, "mount");
2872                         goto ancestorerr;
2873                 }
2874 
2875                 if (zfs_share(h) != 0) {
2876                         opname = dgettext(TEXT_DOMAIN, "share");
2877                         goto ancestorerr;
2878                 }
2879 
2880                 zfs_close(h);
2881         }
2882 
2883         return (0);


2901         if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
2902                 return (-1);
2903 
2904         if ((path_copy = strdup(path)) != NULL) {
2905                 rc = create_parents(hdl, path_copy, prefix);
2906                 free(path_copy);
2907         }
2908         if (path_copy == NULL || rc != 0)
2909                 return (-1);
2910 
2911         return (0);
2912 }
2913 
2914 /*
2915  * Create a new filesystem or volume.
2916  */
2917 int
2918 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
2919     nvlist_t *props)
2920 {

2921         int ret;
2922         uint64_t size = 0;
2923         uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
2924         char errbuf[1024];
2925         uint64_t zoned;
2926         dmu_objset_type_t ost;
2927 
2928         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2929             "cannot create '%s'"), path);
2930 
2931         /* validate the path, taking care to note the extended error message */
2932         if (!zfs_validate_name(hdl, path, type, B_TRUE))
2933                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2934 
2935         /* validate parents exist */
2936         if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0)
2937                 return (-1);
2938 
2939         /*
2940          * The failure modes when creating a dataset of a different type over
2941          * one that already exists is a little strange.  In particular, if you
2942          * try to create a dataset on top of an existing dataset, the ioctl()
2943          * will return ENOENT, not EEXIST.  To prevent this from happening, we
2944          * first try to see if the dataset exists.
2945          */
2946         if (zfs_dataset_exists(hdl, path, ZFS_TYPE_DATASET)) {

2947                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2948                     "dataset already exists"));
2949                 return (zfs_error(hdl, EZFS_EXISTS, errbuf));
2950         }
2951 
2952         if (type == ZFS_TYPE_VOLUME)
2953                 ost = DMU_OST_ZVOL;
2954         else
2955                 ost = DMU_OST_ZFS;
2956 
2957         if (props && (props = zfs_valid_proplist(hdl, type, props,
2958             zoned, NULL, errbuf)) == 0)
2959                 return (-1);
2960 
2961         if (type == ZFS_TYPE_VOLUME) {
2962                 /*
2963                  * If we are creating a volume, the size and block size must
2964                  * satisfy a few restraints.  First, the blocksize must be a
2965                  * valid block size between SPA_{MIN,MAX}BLOCKSIZE.  Second, the
2966                  * volsize must be a multiple of the block size, and cannot be
2967                  * zero.
2968                  */
2969                 if (props == NULL || nvlist_lookup_uint64(props,
2970                     zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) {
2971                         nvlist_free(props);
2972                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2973                             "missing volume size"));
2974                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2975                 }


2987                                 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2988                         }
2989                 }
2990 
2991                 if (size == 0) {
2992                         nvlist_free(props);
2993                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2994                             "volume size cannot be zero"));
2995                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2996                 }
2997 
2998                 if (size % blocksize != 0) {
2999                         nvlist_free(props);
3000                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3001                             "volume size must be a multiple of volume block "
3002                             "size"));
3003                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3004                 }
3005         }
3006 




3007         /* create the dataset */
3008         ret = lzc_create(path, ost, props);
3009         nvlist_free(props);

3010 
3011         /* check for failure */
3012         if (ret != 0) {
3013                 char parent[ZFS_MAXNAMELEN];
3014                 (void) parent_name(path, parent, sizeof (parent));
3015 
3016                 switch (errno) {
3017                 case ENOENT:
3018                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3019                             "no such parent '%s'"), parent);
3020                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
3021 
3022                 case EINVAL:
3023                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3024                             "parent '%s' is not a filesystem"), parent);
3025                         return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3026 
3027                 case EDOM:
3028                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3029                             "volume block size must be power of 2 from "


3127 
3128         if (nvlist_next_nvpair(dd.nvl, NULL) == NULL) {
3129                 ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
3130                     dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
3131                     zhp->zfs_name, snapname);
3132         } else {
3133                 ret = zfs_destroy_snaps_nvl(zhp, dd.nvl, defer);
3134         }
3135         nvlist_free(dd.nvl);
3136         return (ret);
3137 }
3138 
3139 /*
3140  * Destroys all the snapshots named in the nvlist.  They must be underneath
3141  * the zhp (either snapshots of it, or snapshots of its descendants).
3142  */
3143 int
3144 zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
3145 {
3146         int ret;
3147         nvlist_t *errlist;
3148 
3149         ret = lzc_destroy_snaps(snaps, defer, &errlist);



3150 

3151         if (ret != 0) {
3152                 for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL);
3153                     pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) {
3154                         char errbuf[1024];
3155                         (void) snprintf(errbuf, sizeof (errbuf),
3156                             dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"),
3157                             nvpair_name(pair));
3158 
3159                         switch (fnvpair_value_int32(pair)) {



3160                         case EEXIST:
3161                                 zfs_error_aux(zhp->zfs_hdl,
3162                                     dgettext(TEXT_DOMAIN,
3163                                     "snapshot is cloned"));
3164                                 ret = zfs_error(zhp->zfs_hdl, EZFS_EXISTS,
3165                                     errbuf);
3166                                 break;
3167                         default:
3168                                 ret = zfs_standard_error(zhp->zfs_hdl, errno,
3169                                     errbuf);
3170                                 break;
3171                         }
3172                 }
3173         }
3174 
3175         return (ret);
3176 }
3177 
3178 /*
3179  * Clones the given dataset.  The target must be of the same type as the source.
3180  */
3181 int
3182 zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
3183 {

3184         char parent[ZFS_MAXNAMELEN];
3185         int ret;
3186         char errbuf[1024];
3187         libzfs_handle_t *hdl = zhp->zfs_hdl;

3188         uint64_t zoned;
3189 
3190         assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
3191 
3192         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3193             "cannot create '%s'"), target);
3194 
3195         /* validate the target/clone name */
3196         if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
3197                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3198 
3199         /* validate parents exist */
3200         if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
3201                 return (-1);
3202 
3203         (void) parent_name(target, parent, sizeof (parent));
3204 
3205         /* do the clone */
3206 
3207         if (props) {
3208                 zfs_type_t type;
3209                 if (ZFS_IS_VOLUME(zhp)) {

3210                         type = ZFS_TYPE_VOLUME;
3211                 } else {

3212                         type = ZFS_TYPE_FILESYSTEM;
3213                 }


3214                 if ((props = zfs_valid_proplist(hdl, type, props, zoned,
3215                     zhp, errbuf)) == NULL)
3216                         return (-1);




3217         }
3218 
3219         ret = lzc_clone(target, zhp->zfs_name, props);
3220         nvlist_free(props);







3221 
3222         if (ret != 0) {
3223                 switch (errno) {
3224 
3225                 case ENOENT:
3226                         /*
3227                          * The parent doesn't exist.  We should have caught this
3228                          * above, but there may a race condition that has since
3229                          * destroyed the parent.
3230                          *
3231                          * At this point, we don't know whether it's the source
3232                          * that doesn't exist anymore, or whether the target
3233                          * dataset doesn't exist.
3234                          */
3235                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3236                             "no such parent '%s'"), parent);
3237                         return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
3238 
3239                 case EXDEV:
3240                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,


3285         ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
3286 
3287         if (ret != 0) {
3288                 int save_errno = errno;
3289 
3290                 switch (save_errno) {
3291                 case EEXIST:
3292                         /* There is a conflicting snapshot name. */
3293                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3294                             "conflicting snapshot '%s' from parent '%s'"),
3295                             zc.zc_string, parent);
3296                         return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3297 
3298                 default:
3299                         return (zfs_standard_error(hdl, save_errno, errbuf));
3300                 }
3301         }
3302         return (ret);
3303 }
3304 
3305 typedef struct snapdata {
3306         nvlist_t *sd_nvl;
3307         const char *sd_snapname;
3308 } snapdata_t;
3309 
3310 static int
3311 zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
3312 {
3313         snapdata_t *sd = arg;
3314         char name[ZFS_MAXNAMELEN];
3315         int rv = 0;
3316 
3317         (void) snprintf(name, sizeof (name),
3318             "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
3319 
3320         fnvlist_add_boolean(sd->sd_nvl, name);
3321 
3322         rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
3323         zfs_close(zhp);
3324         return (rv);
3325 }
3326 
3327 /*
3328  * Creates snapshots.  The keys in the snaps nvlist are the snapshots to be
3329  * created.
3330  */
3331 int
3332 zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)

3333 {




3334         int ret;
3335         char errbuf[1024];
3336         nvpair_t *elem;
3337         nvlist_t *errors;
3338 
3339         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3340             "cannot create snapshots "));
3341 
3342         elem = NULL;
3343         while ((elem = nvlist_next_nvpair(snaps, elem)) != NULL) {
3344                 const char *snapname = nvpair_name(elem);
3345 
3346                 /* validate the target name */
3347                 if (!zfs_validate_name(hdl, snapname, ZFS_TYPE_SNAPSHOT,
3348                     B_TRUE)) {
3349                         (void) snprintf(errbuf, sizeof (errbuf),
3350                             dgettext(TEXT_DOMAIN,
3351                             "cannot create snapshot '%s'"), snapname);
3352                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3353                 }
3354         }
3355 
3356         if (props != NULL &&
3357             (props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
3358             props, B_FALSE, NULL, errbuf)) == NULL) {
3359                 return (-1);
3360         }
3361 
3362         ret = lzc_snapshot(snaps, props, &errors);
3363 
3364         if (ret != 0) {
3365                 boolean_t printed = B_FALSE;
3366                 for (elem = nvlist_next_nvpair(errors, NULL);
3367                     elem != NULL;
3368                     elem = nvlist_next_nvpair(errors, elem)) {
3369                         (void) snprintf(errbuf, sizeof (errbuf),
3370                             dgettext(TEXT_DOMAIN,
3371                             "cannot create snapshot '%s'"), nvpair_name(elem));
3372                         (void) zfs_standard_error(hdl,
3373                             fnvpair_value_int32(elem), errbuf);
3374                         printed = B_TRUE;
3375                 }
3376                 if (!printed) {
3377                         switch (ret) {
3378                         case EXDEV:
3379                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3380                                     "multiple snapshots of same "
3381                                     "fs not allowed"));
3382                                 (void) zfs_error(hdl, EZFS_EXISTS, errbuf);
3383 
3384                                 break;
3385                         default:
3386                                 (void) zfs_standard_error(hdl, ret, errbuf);
3387                         }
3388                 }
3389         }
3390 
3391         nvlist_free(props);
3392         nvlist_free(errors);
3393         return (ret);
3394 }
3395 
3396 int
3397 zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
3398     nvlist_t *props)
3399 {
3400         int ret;
3401         snapdata_t sd = { 0 };
3402         char fsname[ZFS_MAXNAMELEN];
3403         char *cp;
3404         zfs_handle_t *zhp;
3405         char errbuf[1024];
3406 
3407         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3408             "cannot snapshot %s"), path);
3409 
3410         if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
3411                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3412 
3413         (void) strlcpy(fsname, path, sizeof (fsname));
3414         cp = strchr(fsname, '@');
3415         *cp = '\0';
3416         sd.sd_snapname = cp + 1;
3417 
3418         if ((zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM |
3419             ZFS_TYPE_VOLUME)) == NULL) {

3420                 return (-1);
3421         }
3422 
3423         verify(nvlist_alloc(&sd.sd_nvl, NV_UNIQUE_NAME, 0) == 0);
3424         if (recursive) {
3425                 (void) zfs_snapshot_cb(zfs_handle_dup(zhp), &sd);
3426         } else {
3427                 fnvlist_add_boolean(sd.sd_nvl, path);














3428         }
3429 
3430         ret = zfs_snapshot_nvl(hdl, sd.sd_nvl, props);
3431         nvlist_free(sd.sd_nvl);
3432         zfs_close(zhp);

3433         return (ret);
3434 }
3435 
3436 /*
3437  * Destroy any more recent snapshots.  We invoke this callback on any dependents
3438  * of the snapshot first.  If the 'cb_dependent' member is non-zero, then this
3439  * is a dependent and we should just destroy it without checking the transaction
3440  * group.
3441  */
3442 typedef struct rollback_data {
3443         const char      *cb_target;             /* the snapshot */
3444         uint64_t        cb_create;              /* creation time reference */
3445         boolean_t       cb_error;
3446         boolean_t       cb_dependent;
3447         boolean_t       cb_force;
3448 } rollback_data_t;
3449 
3450 static int
3451 rollback_destroy(zfs_handle_t *zhp, void *data)
3452 {
3453         rollback_data_t *cbp = data;
3454 
3455         if (!cbp->cb_dependent) {
3456                 if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 &&
3457                     zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
3458                     zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
3459                     cbp->cb_create) {

3460 
3461                         cbp->cb_dependent = B_TRUE;
3462                         cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
3463                             rollback_destroy, cbp);
3464                         cbp->cb_dependent = B_FALSE;
3465 


3466                         cbp->cb_error |= zfs_destroy(zhp, B_FALSE);

3467                 }
3468         } else {
3469                 /* We must destroy this clone; first unmount it */
3470                 prop_changelist_t *clp;
3471 
3472                 clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
3473                     cbp->cb_force ? MS_FORCE: 0);
3474                 if (clp == NULL || changelist_prefix(clp) != 0) {
3475                         cbp->cb_error = B_TRUE;
3476                         zfs_close(zhp);
3477                         return (0);
3478                 }
3479                 if (zfs_destroy(zhp, B_FALSE) != 0)
3480                         cbp->cb_error = B_TRUE;
3481                 else
3482                         changelist_remove(clp, zhp->zfs_name);
3483                 (void) changelist_postfix(clp);
3484                 changelist_free(clp);
3485         }
3486