Print this page
*** NO COMMENTS ***
*** 848,876 ****
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_real_ds = rbsa.ds;
} else if (err == ENOENT) {
/* target fs does not exist; must be a full backup or clone */
char *cp;
/*
--- 848,870 ----
if (flags & DRR_FLAG_CLONE) {
dsl_dataset_rele(ds, dmu_recv_tag);
return (EINVAL);
}
/* 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) {
dsl_dataset_rele(ds, dmu_recv_tag);
return (err);
}
! 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,906 ****
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_newfs = B_TRUE;
}
return (err);
}
--- 890,900 ----
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_real_ds = rbsa.ds;
drc->drc_newfs = B_TRUE;
}
return (err);
}
*** 1526,1539 ****
*/
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);
--- 1520,1529 ----
*** 1598,1629 ****
static int
dmu_recv_existing_end(dmu_recv_cookie_t *drc)
{
struct recvendsyncarg resa;
! dsl_dataset_t *ds = drc->drc_logical_ds;
int err, myerr;
/*
* 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);
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;
--- 1588,1622 ----
static int
dmu_recv_existing_end(dmu_recv_cookie_t *drc)
{
struct recvendsyncarg resa;
! 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);
! err = dsl_dataset_clone_swap(drc->drc_real_ds, ds, drc->drc_force);
if (err)
goto out;
resa.creation_time = drc->drc_drrb->drr_creation_time;
resa.toguid = drc->drc_drrb->drr_toguid;
resa.tosnap = drc->drc_tosnap;
*** 1633,1643 ****
/* 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);
--- 1626,1635 ----
*** 1646,1656 ****
static int
dmu_recv_new_end(dmu_recv_cookie_t *drc)
{
struct recvendsyncarg resa;
! dsl_dataset_t *ds = drc->drc_logical_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()
--- 1638,1648 ----
static int
dmu_recv_new_end(dmu_recv_cookie_t *drc)
{
struct recvendsyncarg resa;
! 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,1686 ****
}
int
dmu_recv_end(dmu_recv_cookie_t *drc)
{
! if (drc->drc_logical_ds != drc->drc_real_ds)
return (dmu_recv_existing_end(drc));
else
return (dmu_recv_new_end(drc));
}
--- 1669,1678 ----
}
int
dmu_recv_end(dmu_recv_cookie_t *drc)
{
! if (!drc->drc_newfs)
return (dmu_recv_existing_end(drc));
else
return (dmu_recv_new_end(drc));
}