Print this page
*** NO COMMENTS ***


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,