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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dsl_destroy.c
          +++ new/usr/src/uts/common/fs/zfs/dsl_destroy.c
↓ open down ↓ 43 lines elided ↑ open up ↑
  44   44  typedef struct dmu_snapshots_destroy_arg {
  45   45          nvlist_t *dsda_snaps;
  46   46          nvlist_t *dsda_successful_snaps;
  47   47          boolean_t dsda_defer;
  48   48          nvlist_t *dsda_errlist;
  49   49  } dmu_snapshots_destroy_arg_t;
  50   50  
  51   51  int
  52   52  dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer)
  53   53  {
  54      -        if (!dsl_dataset_is_snapshot(ds))
       54 +        if (!ds->ds_is_snapshot)
  55   55                  return (SET_ERROR(EINVAL));
  56   56  
  57   57          if (dsl_dataset_long_held(ds))
  58   58                  return (SET_ERROR(EBUSY));
  59   59  
  60   60          /*
  61   61           * Only allow deferred destroy on pools that support it.
  62   62           * NOTE: deferred destroy is only supported on snapshots.
  63   63           */
  64   64          if (defer) {
↓ open down ↓ 282 lines elided ↑ open up ↑
 347  347          }
 348  348          dsl_deadlist_close(&ds->ds_deadlist);
 349  349          dsl_deadlist_free(mos, dsl_dataset_phys(ds)->ds_deadlist_obj, tx);
 350  350          dmu_buf_will_dirty(ds->ds_dbuf, tx);
 351  351          dsl_dataset_phys(ds)->ds_deadlist_obj = 0;
 352  352  
 353  353          /* Collapse range in clone heads */
 354  354          dsl_dataset_remove_clones_key(ds,
 355  355              dsl_dataset_phys(ds)->ds_creation_txg, tx);
 356  356  
 357      -        if (dsl_dataset_is_snapshot(ds_next)) {
      357 +        if (ds_next->ds_is_snapshot) {
 358  358                  dsl_dataset_t *ds_nextnext;
 359  359  
 360  360                  /*
 361  361                   * Update next's unique to include blocks which
 362  362                   * were previously shared by only this snapshot
 363  363                   * and it.  Those blocks will be born after the
 364  364                   * prev snap and before this snap, and will have
 365  365                   * died after the next snap and before the one
 366  366                   * after that (ie. be on the snap after next's
 367  367                   * deadlist).
↓ open down ↓ 229 lines elided ↑ open up ↑
 597  597          const char *ddha_name;
 598  598  } dsl_destroy_head_arg_t;
 599  599  
 600  600  int
 601  601  dsl_destroy_head_check_impl(dsl_dataset_t *ds, int expected_holds)
 602  602  {
 603  603          int error;
 604  604          uint64_t count;
 605  605          objset_t *mos;
 606  606  
 607      -        ASSERT(!dsl_dataset_is_snapshot(ds));
 608      -        if (dsl_dataset_is_snapshot(ds))
      607 +        ASSERT(!ds->ds_is_snapshot);
      608 +        if (ds->ds_is_snapshot)
 609  609                  return (SET_ERROR(EINVAL));
 610  610  
 611  611          if (refcount_count(&ds->ds_longholds) != expected_holds)
 612  612                  return (SET_ERROR(EBUSY));
 613  613  
 614  614          mos = ds->ds_dir->dd_pool->dp_meta_objset;
 615  615  
 616  616          /*
 617  617           * Can't delete a head dataset if there are snapshots of it.
 618  618           * (Except if the only snapshots are from the branch we cloned
↓ open down ↓ 353 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX