]> granicus.if.org Git - zfs/commitdiff
Illumos 5870 - dmu_recv_end_check() leaks origin_head hold if error happens in drc_fo...
authorAndriy Gapon <avg@freebsd.org>
Thu, 2 Jul 2015 13:03:58 +0000 (16:03 +0300)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 6 Jul 2015 16:22:18 +0000 (09:22 -0700)
5870 dmu_recv_end_check() leaks origin_head hold if error happens in drc_force branch
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Andrew Stormont <andyjstormont@gmail.com>
Approved by: Dan McDonald <danmcd@omniti.com>

References:
  https://www.illumos.org/issues/5870
  https://github.com/illumos/illumos-gate/commit/beddaa9

Ported-by: Andriy Gapon <avg@FreeBSD.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3551

module/zfs/dmu_send.c

index d900d5cd0e5eb182e2bd6f9ac688d484248bf29e..340926785c1189efc022845b30383cecd935b51a 100644 (file)
@@ -2042,7 +2042,7 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx)
                                error = dsl_dataset_hold_obj(dp, obj, FTAG,
                                    &snap);
                                if (error != 0)
-                                       return (error);
+                                       break;
                                if (snap->ds_dir != origin_head->ds_dir)
                                        error = SET_ERROR(EINVAL);
                                if (error == 0)  {
@@ -2052,7 +2052,11 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx)
                                obj = dsl_dataset_phys(snap)->ds_prev_snap_obj;
                                dsl_dataset_rele(snap, FTAG);
                                if (error != 0)
-                                       return (error);
+                                       break;
+                       }
+                       if (error != 0) {
+                               dsl_dataset_rele(origin_head, FTAG);
+                               return (error);
                        }
                }
                error = dsl_dataset_clone_swap_check_impl(drc->drc_ds,