diff options
author | Matthew Ahrens <[email protected]> | 2013-04-10 13:54:56 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2013-10-31 14:58:09 -0700 |
commit | 7ec09286b761ee1fb85178ff55daaf8f74d935be (patch) | |
tree | 659af6f99796b74565c71b26b10a5710301e8ad9 | |
parent | 2e528b49f8a0f8f2f51536a00fdf3ea9343bf302 (diff) |
Illumos #3645, #3692
3645 dmu_send_impl: possibilty of pool hold leak
3692 Panic on zfs receive of a recursive deduplicated stream
Reviewed by: Adam Leventhal <[email protected]>
Reviewed by: Christopher Siden <[email protected]>
Reviewed by: Dan McDonald <[email protected]>
Approved by: Richard Lowe <[email protected]>
References:
https://www.illumos.org/issues/3645
https://www.illumos.org/issues/3692
illumos/illumos-gate@de8d9cff565e928d0ace86f3ea0e2b15094d61df
Ported-by: Richard Yao <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Issue #1792
Issue #1775
-rw-r--r-- | module/zfs/dmu_send.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c index 5c1a8a311..87744cb72 100644 --- a/module/zfs/dmu_send.c +++ b/module/zfs/dmu_send.c @@ -508,14 +508,14 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds, list_insert_head(&ds->ds_sendstreams, dsp); mutex_exit(&ds->ds_sendstream_lock); + dsl_dataset_long_hold(ds, FTAG); + dsl_pool_rele(dp, tag); + if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0) { err = dsp->dsa_err; goto out; } - dsl_dataset_long_hold(ds, FTAG); - dsl_pool_rele(dp, tag); - err = traverse_dataset(ds, fromtxg, TRAVERSE_PRE | TRAVERSE_PREFETCH, backup_cb, dsp); @@ -988,6 +988,7 @@ free_guid_map_onexit(void *arg) while ((gmep = avl_destroy_nodes(ca, &cookie)) != NULL) { dsl_dataset_long_rele(gmep->gme_ds, gmep); + dsl_dataset_rele(gmep->gme_ds, gmep); kmem_free(gmep, sizeof (guid_map_entry_t)); } avl_destroy(ca); @@ -1667,14 +1668,15 @@ add_ds_to_guidmap(const char *name, avl_tree_t *guid_map, uint64_t snapobj) err = dsl_pool_hold(name, FTAG, &dp); if (err != 0) return (err); - err = dsl_dataset_hold_obj(dp, snapobj, FTAG, &snapds); + gmep = kmem_alloc(sizeof (*gmep), KM_SLEEP); + err = dsl_dataset_hold_obj(dp, snapobj, gmep, &snapds); if (err == 0) { - gmep = kmem_alloc(sizeof (guid_map_entry_t), KM_SLEEP); gmep->guid = snapds->ds_phys->ds_guid; gmep->gme_ds = snapds; avl_add(guid_map, gmep); dsl_dataset_long_hold(snapds, gmep); - dsl_dataset_rele(snapds, FTAG); + } else { + kmem_free(gmep, sizeof (*gmep)); } dsl_pool_rele(dp, FTAG); |