Print this page
*** NO COMMENTS ***
@@ -848,29 +848,23 @@
if (flags & DRR_FLAG_CLONE) {
dsl_dataset_rele(ds, dmu_recv_tag);
return (EINVAL);
}
- /* must not have an incremental recv already in progress */
- if (!mutex_tryenter(&ds->ds_recvlock)) {
- dsl_dataset_rele(ds, dmu_recv_tag);
- return (EBUSY);
- }
-
/* tmp clone name is: tofs/%tosnap" */
(void) snprintf(rbsa.clonelastname, sizeof (rbsa.clonelastname),
"%%%s", tosnap);
rbsa.force = force;
err = dsl_sync_task_do(ds->ds_dir->dd_pool,
recv_existing_check, recv_existing_sync, ds, &rbsa, 5);
if (err) {
- mutex_exit(&ds->ds_recvlock);
dsl_dataset_rele(ds, dmu_recv_tag);
return (err);
}
- drc->drc_logical_ds = ds;
+ drc->drc_logical_dsobj = ds->ds_object;
drc->drc_real_ds = rbsa.ds;
+ dsl_dataset_rele(ds, dmu_recv_tag);
} else if (err == ENOENT) {
/* target fs does not exist; must be a full backup or clone */
char *cp;
/*
@@ -896,11 +890,11 @@
err = dsl_sync_task_do(ds->ds_dir->dd_pool,
recv_new_check, recv_new_sync, ds->ds_dir, &rbsa, 5);
dsl_dataset_rele(ds, FTAG);
if (err)
return (err);
- drc->drc_logical_ds = drc->drc_real_ds = rbsa.ds;
+ drc->drc_real_ds = rbsa.ds;
drc->drc_newfs = B_TRUE;
}
return (err);
}
@@ -1526,14 +1520,10 @@
*/
txg_wait_synced(drc->drc_real_ds->ds_dir->dd_pool, 0);
(void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
B_FALSE);
- if (drc->drc_real_ds != drc->drc_logical_ds) {
- mutex_exit(&drc->drc_logical_ds->ds_recvlock);
- dsl_dataset_rele(drc->drc_logical_ds, dmu_recv_tag);
- }
}
kmem_free(ra.buf, ra.bufsize);
*voffp = ra.voff;
return (ra.err);
@@ -1598,32 +1588,35 @@
static int
dmu_recv_existing_end(dmu_recv_cookie_t *drc)
{
struct recvendsyncarg resa;
- dsl_dataset_t *ds = drc->drc_logical_ds;
+ dsl_dataset_t *ds;
int err, myerr;
+ dsl_pool_t *dp = drc->drc_real_ds->ds_dir->dd_pool;
+
+ rw_enter(&dp->dp_config_rwlock, RW_READER);
+ err = dsl_dataset_own_obj(dp, drc->drc_logical_dsobj, FALSE,
+ dmu_recv_tag, &ds);
+ rw_exit(&dp->dp_config_rwlock);
+
+ if (err) {
+ (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
+ B_FALSE);
+ return (EBUSY);
+ }
/*
* XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()
* expects it to have a ds_user_ptr (and zil), but clone_swap()
* can close it.
*/
txg_wait_synced(ds->ds_dir->dd_pool, 0);
- if (dsl_dataset_tryown(ds, FALSE, dmu_recv_tag)) {
- err = dsl_dataset_clone_swap(drc->drc_real_ds, ds,
- drc->drc_force);
+ err = dsl_dataset_clone_swap(drc->drc_real_ds, ds, drc->drc_force);
if (err)
goto out;
- } else {
- mutex_exit(&ds->ds_recvlock);
- dsl_dataset_rele(ds, dmu_recv_tag);
- (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
- B_FALSE);
- return (EBUSY);
- }
resa.creation_time = drc->drc_drrb->drr_creation_time;
resa.toguid = drc->drc_drrb->drr_toguid;
resa.tosnap = drc->drc_tosnap;
@@ -1633,11 +1626,10 @@
/* swap back */
(void) dsl_dataset_clone_swap(drc->drc_real_ds, ds, B_TRUE);
}
out:
- mutex_exit(&ds->ds_recvlock);
if (err == 0 && drc->drc_guid_to_ds_map != NULL)
(void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
dsl_dataset_disown(ds, dmu_recv_tag);
myerr = dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE);
ASSERT3U(myerr, ==, 0);
@@ -1646,11 +1638,11 @@
static int
dmu_recv_new_end(dmu_recv_cookie_t *drc)
{
struct recvendsyncarg resa;
- dsl_dataset_t *ds = drc->drc_logical_ds;
+ dsl_dataset_t *ds = drc->drc_real_ds;
int err;
/*
* XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()
* expects it to have a ds_user_ptr (and zil), but clone_swap()
@@ -1677,10 +1669,10 @@
}
int
dmu_recv_end(dmu_recv_cookie_t *drc)
{
- if (drc->drc_logical_ds != drc->drc_real_ds)
+ if (!drc->drc_newfs)
return (dmu_recv_existing_end(drc));
else
return (dmu_recv_new_end(drc));
}