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)); }