3210
3211 err = dmu_objset_destroy(zc->zc_name, zc->zc_defer_destroy);
3212 if (zc->zc_objset_type == DMU_OST_ZVOL && err == 0)
3213 (void) zvol_remove_minor(zc->zc_name);
3214 return (err);
3215 }
3216
3217 /*
3218 * inputs:
3219 * zc_name name of dataset to rollback (to most recent snapshot)
3220 *
3221 * outputs: none
3222 */
3223 static int
3224 zfs_ioc_rollback(zfs_cmd_t *zc)
3225 {
3226 dsl_dataset_t *ds, *clone;
3227 int error;
3228 zfsvfs_t *zfsvfs;
3229 char *clone_name;
3230
3231 error = dsl_dataset_hold(zc->zc_name, FTAG, &ds);
3232 if (error)
3233 return (error);
3234
3235 /* must not be a snapshot */
3236 if (dsl_dataset_is_snapshot(ds)) {
3237 dsl_dataset_rele(ds, FTAG);
3238 return (EINVAL);
3239 }
3240
3241 /* must have a most recent snapshot */
3242 if (ds->ds_phys->ds_prev_snap_txg < TXG_INITIAL) {
3243 dsl_dataset_rele(ds, FTAG);
3244 return (EINVAL);
3245 }
3246
3247 /*
3248 * Create clone of most recent snapshot.
3249 */
3250 clone_name = kmem_asprintf("%s/%%rollback", zc->zc_name);
3251 error = dmu_objset_clone(clone_name, ds->ds_prev, DS_FLAG_INCONSISTENT);
3252 if (error)
3253 goto out;
3254
3255 error = dsl_dataset_own(clone_name, B_TRUE, FTAG, &clone);
3256 if (error)
3257 goto out;
3258
3259 /*
3260 * Do clone swap.
3261 */
3262 if (getzfsvfs(zc->zc_name, &zfsvfs) == 0) {
3263 error = zfs_suspend_fs(zfsvfs);
3264 if (error == 0) {
3265 int resume_err;
3266
3267 if (dsl_dataset_tryown(ds, B_FALSE, FTAG)) {
3268 error = dsl_dataset_clone_swap(clone, ds,
3269 B_TRUE);
3270 dsl_dataset_disown(ds, FTAG);
3271 ds = NULL;
3272 } else {
3273 error = EBUSY;
3274 }
3275 resume_err = zfs_resume_fs(zfsvfs, zc->zc_name);
3276 error = error ? error : resume_err;
3277 }
3278 VFS_RELE(zfsvfs->z_vfs);
3279 } else {
3280 if (dsl_dataset_tryown(ds, B_FALSE, FTAG)) {
3281 error = dsl_dataset_clone_swap(clone, ds, B_TRUE);
3282 dsl_dataset_disown(ds, FTAG);
3283 ds = NULL;
3284 } else {
3285 error = EBUSY;
3286 }
3287 }
3288
3289 /*
3290 * Destroy clone (which also closes it).
3291 */
3292 (void) dsl_dataset_destroy(clone, FTAG, B_FALSE);
3293
3294 out:
3295 strfree(clone_name);
3296 if (ds)
3297 dsl_dataset_rele(ds, FTAG);
3298 return (error);
3299 }
3300
3301 /*
3302 * inputs:
3303 * zc_name old name of dataset
3304 * zc_value new name of dataset
3305 * zc_cookie recursive flag (only valid for snapshots)
3306 *
3307 * outputs: none
3308 */
3309 static int
3310 zfs_ioc_rename(zfs_cmd_t *zc)
3311 {
3312 boolean_t recursive = zc->zc_cookie & 1;
3313
3314 zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
3315 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
3316 strchr(zc->zc_value, '%'))
3317 return (EINVAL);
3684 error = dmu_objset_hold(zc->zc_string, FTAG, &origin);
3685 if (error)
3686 goto out;
3687 }
3688
3689 error = dmu_recv_begin(tofs, tosnap, zc->zc_top_ds,
3690 &zc->zc_begin_record, force, origin, &drc);
3691 if (origin)
3692 dmu_objset_rele(origin, FTAG);
3693 if (error)
3694 goto out;
3695
3696 /*
3697 * Set properties before we receive the stream so that they are applied
3698 * to the new data. Note that we must call dmu_recv_stream() if
3699 * dmu_recv_begin() succeeds.
3700 */
3701 if (props) {
3702 nvlist_t *errlist;
3703
3704 if (dmu_objset_from_ds(drc.drc_logical_ds, &os) == 0) {
3705 if (drc.drc_newfs) {
3706 if (spa_version(os->os_spa) >=
3707 SPA_VERSION_RECVD_PROPS)
3708 first_recvd_props = B_TRUE;
3709 } else if (origprops != NULL) {
3710 if (clear_received_props(os, tofs, origprops,
3711 first_recvd_props ? NULL : props) != 0)
3712 zc->zc_obj |= ZPROP_ERR_NOCLEAR;
3713 } else {
3714 zc->zc_obj |= ZPROP_ERR_NOCLEAR;
3715 }
3716 dsl_prop_set_hasrecvd(os);
3717 } else if (!drc.drc_newfs) {
3718 zc->zc_obj |= ZPROP_ERR_NOCLEAR;
3719 }
3720
3721 (void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_RECEIVED,
3722 props, &errlist);
3723 (void) nvlist_merge(errors, errlist, 0);
3724 nvlist_free(errlist);
3725 }
3726
3727 if (fit_error_list(zc, &errors) != 0 || put_nvlist(zc, errors) != 0) {
3728 /*
3729 * Caller made zc->zc_nvlist_dst less than the minimum expected
3730 * size or supplied an invalid address.
3731 */
3732 props_error = EINVAL;
3733 }
3734
3735 off = fp->f_offset;
3736 error = dmu_recv_stream(&drc, fp->f_vnode, &off, zc->zc_cleanup_fd,
|
3210
3211 err = dmu_objset_destroy(zc->zc_name, zc->zc_defer_destroy);
3212 if (zc->zc_objset_type == DMU_OST_ZVOL && err == 0)
3213 (void) zvol_remove_minor(zc->zc_name);
3214 return (err);
3215 }
3216
3217 /*
3218 * inputs:
3219 * zc_name name of dataset to rollback (to most recent snapshot)
3220 *
3221 * outputs: none
3222 */
3223 static int
3224 zfs_ioc_rollback(zfs_cmd_t *zc)
3225 {
3226 dsl_dataset_t *ds, *clone;
3227 int error;
3228 zfsvfs_t *zfsvfs;
3229 char *clone_name;
3230 boolean_t umounted = B_FALSE;
3231
3232 if (getzfsvfs(zc->zc_name, &zfsvfs) == 0) {
3233 error = zfs_suspend_fs(zfsvfs);
3234 if (error) {
3235 VFS_RELE(zfsvfs->z_vfs);
3236 return (error);
3237 }
3238
3239 umounted = B_TRUE;
3240 }
3241
3242 error = dsl_dataset_hold(zc->zc_name, FTAG, &ds);
3243 if (error)
3244 goto out_vfs;
3245
3246 /* must not be a snapshot */
3247 if (dsl_dataset_is_snapshot(ds)) {
3248 error = EINVAL;
3249 goto out_ds;
3250 }
3251
3252 /* must have a most recent snapshot */
3253 if (ds->ds_phys->ds_prev_snap_txg < TXG_INITIAL) {
3254 error = EINVAL;
3255 goto out_ds;
3256 }
3257
3258 /*
3259 * Create clone of most recent snapshot.
3260 */
3261 clone_name = kmem_asprintf("%s/%%rollback", zc->zc_name);
3262 error = dmu_objset_clone(clone_name, ds->ds_prev, DS_FLAG_INCONSISTENT);
3263 if (error)
3264 goto out;
3265
3266 error = dsl_dataset_own(clone_name, B_TRUE, FTAG, &clone);
3267 if (error)
3268 goto out;
3269
3270 /*
3271 * Do clone swap.
3272 */
3273 if (umounted) {
3274 if (dsl_dataset_tryown(ds, B_FALSE, FTAG)) {
3275 error = dsl_dataset_clone_swap(clone, ds,
3276 B_TRUE);
3277 dsl_dataset_disown(ds, FTAG);
3278 ds = NULL;
3279 } else {
3280 error = EBUSY;
3281 }
3282 } else {
3283 if (dsl_dataset_tryown(ds, B_FALSE, FTAG)) {
3284 error = dsl_dataset_clone_swap(clone, ds, B_TRUE);
3285 dsl_dataset_disown(ds, FTAG);
3286 ds = NULL;
3287 } else {
3288 error = EBUSY;
3289 }
3290 }
3291
3292 /*
3293 * Destroy clone (which also closes it).
3294 */
3295 (void) dsl_dataset_destroy(clone, FTAG, B_FALSE);
3296
3297 out:
3298 strfree(clone_name);
3299 out_ds:
3300 if (ds)
3301 dsl_dataset_rele(ds, FTAG);
3302 out_vfs:
3303 if (umounted) {
3304 int resume_err;
3305
3306 resume_err = zfs_resume_fs(zfsvfs, zc->zc_name);
3307 error = error ? error : resume_err;
3308 VFS_RELE(zfsvfs->z_vfs);
3309 }
3310
3311 return (error);
3312 }
3313
3314 /*
3315 * inputs:
3316 * zc_name old name of dataset
3317 * zc_value new name of dataset
3318 * zc_cookie recursive flag (only valid for snapshots)
3319 *
3320 * outputs: none
3321 */
3322 static int
3323 zfs_ioc_rename(zfs_cmd_t *zc)
3324 {
3325 boolean_t recursive = zc->zc_cookie & 1;
3326
3327 zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
3328 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
3329 strchr(zc->zc_value, '%'))
3330 return (EINVAL);
3697 error = dmu_objset_hold(zc->zc_string, FTAG, &origin);
3698 if (error)
3699 goto out;
3700 }
3701
3702 error = dmu_recv_begin(tofs, tosnap, zc->zc_top_ds,
3703 &zc->zc_begin_record, force, origin, &drc);
3704 if (origin)
3705 dmu_objset_rele(origin, FTAG);
3706 if (error)
3707 goto out;
3708
3709 /*
3710 * Set properties before we receive the stream so that they are applied
3711 * to the new data. Note that we must call dmu_recv_stream() if
3712 * dmu_recv_begin() succeeds.
3713 */
3714 if (props) {
3715 nvlist_t *errlist;
3716
3717 if (drc.drc_newfs)
3718 error = dmu_objset_from_ds(drc.drc_real_ds, &os);
3719 else
3720 error = dmu_objset_hold(tofs, FTAG, &os);
3721
3722 if (error == 0) {
3723 if (drc.drc_newfs) {
3724 if (spa_version(os->os_spa) >=
3725 SPA_VERSION_RECVD_PROPS)
3726 first_recvd_props = B_TRUE;
3727 } else if (origprops != NULL) {
3728 if (clear_received_props(os, tofs, origprops,
3729 first_recvd_props ? NULL : props) != 0)
3730 zc->zc_obj |= ZPROP_ERR_NOCLEAR;
3731 } else {
3732 zc->zc_obj |= ZPROP_ERR_NOCLEAR;
3733 }
3734 dsl_prop_set_hasrecvd(os);
3735
3736 if (!drc.drc_newfs)
3737 dmu_objset_rele(os, FTAG);
3738 } else if (!drc.drc_newfs) {
3739 zc->zc_obj |= ZPROP_ERR_NOCLEAR;
3740 }
3741
3742 (void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_RECEIVED,
3743 props, &errlist);
3744 (void) nvlist_merge(errors, errlist, 0);
3745 nvlist_free(errlist);
3746 }
3747
3748 if (fit_error_list(zc, &errors) != 0 || put_nvlist(zc, errors) != 0) {
3749 /*
3750 * Caller made zc->zc_nvlist_dst less than the minimum expected
3751 * size or supplied an invalid address.
3752 */
3753 props_error = EINVAL;
3754 }
3755
3756 off = fp->f_offset;
3757 error = dmu_recv_stream(&drc, fp->f_vnode, &off, zc->zc_cleanup_fd,
|