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,