Print this page
*** NO COMMENTS ***
@@ -3225,25 +3225,36 @@
{
dsl_dataset_t *ds, *clone;
int error;
zfsvfs_t *zfsvfs;
char *clone_name;
+ boolean_t umounted = B_FALSE;
+
+ if (getzfsvfs(zc->zc_name, &zfsvfs) == 0) {
+ error = zfs_suspend_fs(zfsvfs);
+ if (error) {
+ VFS_RELE(zfsvfs->z_vfs);
+ return (error);
+ }
+
+ umounted = B_TRUE;
+ }
error = dsl_dataset_hold(zc->zc_name, FTAG, &ds);
if (error)
- return (error);
+ goto out_vfs;
/* must not be a snapshot */
if (dsl_dataset_is_snapshot(ds)) {
- dsl_dataset_rele(ds, FTAG);
- return (EINVAL);
+ error = EINVAL;
+ goto out_ds;
}
/* must have a most recent snapshot */
if (ds->ds_phys->ds_prev_snap_txg < TXG_INITIAL) {
- dsl_dataset_rele(ds, FTAG);
- return (EINVAL);
+ error = EINVAL;
+ goto out_ds;
}
/*
* Create clone of most recent snapshot.
*/
@@ -3257,27 +3268,19 @@
goto out;
/*
* Do clone swap.
*/
- if (getzfsvfs(zc->zc_name, &zfsvfs) == 0) {
- error = zfs_suspend_fs(zfsvfs);
- if (error == 0) {
- int resume_err;
-
+ if (umounted) {
if (dsl_dataset_tryown(ds, B_FALSE, FTAG)) {
error = dsl_dataset_clone_swap(clone, ds,
B_TRUE);
dsl_dataset_disown(ds, FTAG);
ds = NULL;
} else {
error = EBUSY;
}
- resume_err = zfs_resume_fs(zfsvfs, zc->zc_name);
- error = error ? error : resume_err;
- }
- VFS_RELE(zfsvfs->z_vfs);
} else {
if (dsl_dataset_tryown(ds, B_FALSE, FTAG)) {
error = dsl_dataset_clone_swap(clone, ds, B_TRUE);
dsl_dataset_disown(ds, FTAG);
ds = NULL;
@@ -3291,12 +3294,22 @@
*/
(void) dsl_dataset_destroy(clone, FTAG, B_FALSE);
out:
strfree(clone_name);
+out_ds:
if (ds)
dsl_dataset_rele(ds, FTAG);
+out_vfs:
+ if (umounted) {
+ int resume_err;
+
+ resume_err = zfs_resume_fs(zfsvfs, zc->zc_name);
+ error = error ? error : resume_err;
+ VFS_RELE(zfsvfs->z_vfs);
+ }
+
return (error);
}
/*
* inputs:
@@ -3699,11 +3712,16 @@
* dmu_recv_begin() succeeds.
*/
if (props) {
nvlist_t *errlist;
- if (dmu_objset_from_ds(drc.drc_logical_ds, &os) == 0) {
+ if (drc.drc_newfs)
+ error = dmu_objset_from_ds(drc.drc_real_ds, &os);
+ else
+ error = dmu_objset_hold(tofs, FTAG, &os);
+
+ if (error == 0) {
if (drc.drc_newfs) {
if (spa_version(os->os_spa) >=
SPA_VERSION_RECVD_PROPS)
first_recvd_props = B_TRUE;
} else if (origprops != NULL) {
@@ -3712,10 +3730,13 @@
zc->zc_obj |= ZPROP_ERR_NOCLEAR;
} else {
zc->zc_obj |= ZPROP_ERR_NOCLEAR;
}
dsl_prop_set_hasrecvd(os);
+
+ if (!drc.drc_newfs)
+ dmu_objset_rele(os, FTAG);
} else if (!drc.drc_newfs) {
zc->zc_obj |= ZPROP_ERR_NOCLEAR;
}
(void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_RECEIVED,