Print this page
5056 ZFS deadlock on db_mtx and dn_holds
Reviewed by: Will Andrews <willa@spectralogic.com>
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>


 594                 embedok = B_FALSE;
 595         }
 596 
 597         DMU_SET_FEATUREFLAGS(drr->drr_u.drr_begin.drr_versioninfo,
 598             featureflags);
 599 
 600         drr->drr_u.drr_begin.drr_creation_time =
 601             dsl_dataset_phys(ds)->ds_creation_time;
 602         drr->drr_u.drr_begin.drr_type = dmu_objset_type(os);
 603         if (is_clone)
 604                 drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE;
 605         drr->drr_u.drr_begin.drr_toguid = dsl_dataset_phys(ds)->ds_guid;
 606         if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
 607                 drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CI_DATA;
 608 
 609         if (fromzb != NULL) {
 610                 drr->drr_u.drr_begin.drr_fromguid = fromzb->zbm_guid;
 611                 fromtxg = fromzb->zbm_creation_txg;
 612         }
 613         dsl_dataset_name(ds, drr->drr_u.drr_begin.drr_toname);
 614         if (!dsl_dataset_is_snapshot(ds)) {
 615                 (void) strlcat(drr->drr_u.drr_begin.drr_toname, "@--head--",
 616                     sizeof (drr->drr_u.drr_begin.drr_toname));
 617         }
 618 
 619         dsp = kmem_zalloc(sizeof (dmu_sendarg_t), KM_SLEEP);
 620 
 621         dsp->dsa_drr = drr;
 622         dsp->dsa_vp = vp;
 623         dsp->dsa_outfd = outfd;
 624         dsp->dsa_proc = curproc;
 625         dsp->dsa_os = os;
 626         dsp->dsa_off = off;
 627         dsp->dsa_toguid = dsl_dataset_phys(ds)->ds_guid;
 628         ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0);
 629         dsp->dsa_pending_op = PENDING_NONE;
 630         dsp->dsa_incremental = (fromzb != NULL);
 631         dsp->dsa_featureflags = featureflags;
 632 
 633         mutex_enter(&ds->ds_sendstream_lock);
 634         list_insert_head(&ds->ds_sendstreams, dsp);


 801                 err = dmu_send_impl(FTAG, dp, ds, NULL, B_FALSE,
 802                     embedok, large_block_ok, outfd, vp, off);
 803         }
 804         if (owned)
 805                 dsl_dataset_disown(ds, FTAG);
 806         else
 807                 dsl_dataset_rele(ds, FTAG);
 808         return (err);
 809 }
 810 
 811 int
 812 dmu_send_estimate(dsl_dataset_t *ds, dsl_dataset_t *fromds, uint64_t *sizep)
 813 {
 814         dsl_pool_t *dp = ds->ds_dir->dd_pool;
 815         int err;
 816         uint64_t size;
 817 
 818         ASSERT(dsl_pool_config_held(dp));
 819 
 820         /* tosnap must be a snapshot */
 821         if (!dsl_dataset_is_snapshot(ds))
 822                 return (SET_ERROR(EINVAL));
 823 
 824         /*
 825          * fromsnap must be an earlier snapshot from the same fs as tosnap,
 826          * or the origin's fs.
 827          */
 828         if (fromds != NULL && !dsl_dataset_is_before(ds, fromds, 0))
 829                 return (SET_ERROR(EXDEV));
 830 
 831         /* Get uncompressed size estimate of changed data. */
 832         if (fromds == NULL) {
 833                 size = dsl_dataset_phys(ds)->ds_uncompressed_bytes;
 834         } else {
 835                 uint64_t used, comp;
 836                 err = dsl_dataset_space_written(fromds, ds,
 837                     &used, &comp, &size);
 838                 if (err != 0)
 839                         return (err);
 840         }
 841 


1048                 if (error != 0) {
1049                         dsl_dataset_rele(ds, FTAG);
1050                         return (error);
1051                 }
1052 
1053                 error = dsl_fs_ss_limit_check(ds->ds_dir, 1,
1054                     ZFS_PROP_SNAPSHOT_LIMIT, NULL, drba->drba_cred);
1055                 if (error != 0) {
1056                         dsl_dataset_rele(ds, FTAG);
1057                         return (error);
1058                 }
1059 
1060                 if (drba->drba_origin != NULL) {
1061                         dsl_dataset_t *origin;
1062                         error = dsl_dataset_hold(dp, drba->drba_origin,
1063                             FTAG, &origin);
1064                         if (error != 0) {
1065                                 dsl_dataset_rele(ds, FTAG);
1066                                 return (error);
1067                         }
1068                         if (!dsl_dataset_is_snapshot(origin)) {
1069                                 dsl_dataset_rele(origin, FTAG);
1070                                 dsl_dataset_rele(ds, FTAG);
1071                                 return (SET_ERROR(EINVAL));
1072                         }
1073                         if (dsl_dataset_phys(origin)->ds_guid != fromguid) {
1074                                 dsl_dataset_rele(origin, FTAG);
1075                                 dsl_dataset_rele(ds, FTAG);
1076                                 return (SET_ERROR(ENODEV));
1077                         }
1078                         dsl_dataset_rele(origin, FTAG);
1079                 }
1080                 dsl_dataset_rele(ds, FTAG);
1081                 error = 0;
1082         }
1083         return (error);
1084 }
1085 
1086 static void
1087 dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
1088 {




 594                 embedok = B_FALSE;
 595         }
 596 
 597         DMU_SET_FEATUREFLAGS(drr->drr_u.drr_begin.drr_versioninfo,
 598             featureflags);
 599 
 600         drr->drr_u.drr_begin.drr_creation_time =
 601             dsl_dataset_phys(ds)->ds_creation_time;
 602         drr->drr_u.drr_begin.drr_type = dmu_objset_type(os);
 603         if (is_clone)
 604                 drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE;
 605         drr->drr_u.drr_begin.drr_toguid = dsl_dataset_phys(ds)->ds_guid;
 606         if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
 607                 drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CI_DATA;
 608 
 609         if (fromzb != NULL) {
 610                 drr->drr_u.drr_begin.drr_fromguid = fromzb->zbm_guid;
 611                 fromtxg = fromzb->zbm_creation_txg;
 612         }
 613         dsl_dataset_name(ds, drr->drr_u.drr_begin.drr_toname);
 614         if (!ds->ds_is_snapshot) {
 615                 (void) strlcat(drr->drr_u.drr_begin.drr_toname, "@--head--",
 616                     sizeof (drr->drr_u.drr_begin.drr_toname));
 617         }
 618 
 619         dsp = kmem_zalloc(sizeof (dmu_sendarg_t), KM_SLEEP);
 620 
 621         dsp->dsa_drr = drr;
 622         dsp->dsa_vp = vp;
 623         dsp->dsa_outfd = outfd;
 624         dsp->dsa_proc = curproc;
 625         dsp->dsa_os = os;
 626         dsp->dsa_off = off;
 627         dsp->dsa_toguid = dsl_dataset_phys(ds)->ds_guid;
 628         ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0);
 629         dsp->dsa_pending_op = PENDING_NONE;
 630         dsp->dsa_incremental = (fromzb != NULL);
 631         dsp->dsa_featureflags = featureflags;
 632 
 633         mutex_enter(&ds->ds_sendstream_lock);
 634         list_insert_head(&ds->ds_sendstreams, dsp);


 801                 err = dmu_send_impl(FTAG, dp, ds, NULL, B_FALSE,
 802                     embedok, large_block_ok, outfd, vp, off);
 803         }
 804         if (owned)
 805                 dsl_dataset_disown(ds, FTAG);
 806         else
 807                 dsl_dataset_rele(ds, FTAG);
 808         return (err);
 809 }
 810 
 811 int
 812 dmu_send_estimate(dsl_dataset_t *ds, dsl_dataset_t *fromds, uint64_t *sizep)
 813 {
 814         dsl_pool_t *dp = ds->ds_dir->dd_pool;
 815         int err;
 816         uint64_t size;
 817 
 818         ASSERT(dsl_pool_config_held(dp));
 819 
 820         /* tosnap must be a snapshot */
 821         if (!ds->ds_is_snapshot)
 822                 return (SET_ERROR(EINVAL));
 823 
 824         /*
 825          * fromsnap must be an earlier snapshot from the same fs as tosnap,
 826          * or the origin's fs.
 827          */
 828         if (fromds != NULL && !dsl_dataset_is_before(ds, fromds, 0))
 829                 return (SET_ERROR(EXDEV));
 830 
 831         /* Get uncompressed size estimate of changed data. */
 832         if (fromds == NULL) {
 833                 size = dsl_dataset_phys(ds)->ds_uncompressed_bytes;
 834         } else {
 835                 uint64_t used, comp;
 836                 err = dsl_dataset_space_written(fromds, ds,
 837                     &used, &comp, &size);
 838                 if (err != 0)
 839                         return (err);
 840         }
 841 


1048                 if (error != 0) {
1049                         dsl_dataset_rele(ds, FTAG);
1050                         return (error);
1051                 }
1052 
1053                 error = dsl_fs_ss_limit_check(ds->ds_dir, 1,
1054                     ZFS_PROP_SNAPSHOT_LIMIT, NULL, drba->drba_cred);
1055                 if (error != 0) {
1056                         dsl_dataset_rele(ds, FTAG);
1057                         return (error);
1058                 }
1059 
1060                 if (drba->drba_origin != NULL) {
1061                         dsl_dataset_t *origin;
1062                         error = dsl_dataset_hold(dp, drba->drba_origin,
1063                             FTAG, &origin);
1064                         if (error != 0) {
1065                                 dsl_dataset_rele(ds, FTAG);
1066                                 return (error);
1067                         }
1068                         if (!origin->ds_is_snapshot) {
1069                                 dsl_dataset_rele(origin, FTAG);
1070                                 dsl_dataset_rele(ds, FTAG);
1071                                 return (SET_ERROR(EINVAL));
1072                         }
1073                         if (dsl_dataset_phys(origin)->ds_guid != fromguid) {
1074                                 dsl_dataset_rele(origin, FTAG);
1075                                 dsl_dataset_rele(ds, FTAG);
1076                                 return (SET_ERROR(ENODEV));
1077                         }
1078                         dsl_dataset_rele(origin, FTAG);
1079                 }
1080                 dsl_dataset_rele(ds, FTAG);
1081                 error = 0;
1082         }
1083         return (error);
1084 }
1085 
1086 static void
1087 dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
1088 {