Print this page
4046 dsl_dataset_t ds_dir->dd_lock is highly contended
Reviewed by: Eric Schrock <eric.schrock@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dsl_dataset.c
          +++ new/usr/src/uts/common/fs/zfs/dsl_dataset.c
↓ open down ↓ 92 lines elided ↑ open up ↑
  93   93          /* It could have been compressed away to nothing */
  94   94          if (BP_IS_HOLE(bp))
  95   95                  return;
  96   96          ASSERT(BP_GET_TYPE(bp) != DMU_OT_NONE);
  97   97          ASSERT(DMU_OT_IS_VALID(BP_GET_TYPE(bp)));
  98   98          if (ds == NULL) {
  99   99                  dsl_pool_mos_diduse_space(tx->tx_pool,
 100  100                      used, compressed, uncompressed);
 101  101                  return;
 102  102          }
 103      -        dmu_buf_will_dirty(ds->ds_dbuf, tx);
 104  103  
 105      -        mutex_enter(&ds->ds_dir->dd_lock);
      104 +        dmu_buf_will_dirty(ds->ds_dbuf, tx);
 106  105          mutex_enter(&ds->ds_lock);
 107  106          delta = parent_delta(ds, used);
 108  107          ds->ds_phys->ds_referenced_bytes += used;
 109  108          ds->ds_phys->ds_compressed_bytes += compressed;
 110  109          ds->ds_phys->ds_uncompressed_bytes += uncompressed;
 111  110          ds->ds_phys->ds_unique_bytes += used;
 112  111          mutex_exit(&ds->ds_lock);
 113  112          dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
 114  113              compressed, uncompressed, tx);
 115  114          dsl_dir_transfer_space(ds->ds_dir, used - delta,
 116  115              DD_USED_REFRSRV, DD_USED_HEAD, tx);
 117      -        mutex_exit(&ds->ds_dir->dd_lock);
 118  116  }
 119  117  
 120  118  int
 121  119  dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
 122  120      boolean_t async)
 123  121  {
 124  122          if (BP_IS_HOLE(bp))
 125  123                  return (0);
 126  124  
 127  125          ASSERT(dmu_tx_is_syncing(tx));
↓ open down ↓ 14 lines elided ↑ open up ↑
 142  140  
 143  141          ASSERT(!dsl_dataset_is_snapshot(ds));
 144  142          dmu_buf_will_dirty(ds->ds_dbuf, tx);
 145  143  
 146  144          if (bp->blk_birth > ds->ds_phys->ds_prev_snap_txg) {
 147  145                  int64_t delta;
 148  146  
 149  147                  dprintf_bp(bp, "freeing ds=%llu", ds->ds_object);
 150  148                  dsl_free(tx->tx_pool, tx->tx_txg, bp);
 151  149  
 152      -                mutex_enter(&ds->ds_dir->dd_lock);
 153  150                  mutex_enter(&ds->ds_lock);
 154  151                  ASSERT(ds->ds_phys->ds_unique_bytes >= used ||
 155  152                      !DS_UNIQUE_IS_ACCURATE(ds));
 156  153                  delta = parent_delta(ds, -used);
 157  154                  ds->ds_phys->ds_unique_bytes -= used;
 158  155                  mutex_exit(&ds->ds_lock);
 159  156                  dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
 160  157                      delta, -compressed, -uncompressed, tx);
 161  158                  dsl_dir_transfer_space(ds->ds_dir, -used - delta,
 162  159                      DD_USED_REFRSRV, DD_USED_HEAD, tx);
 163      -                mutex_exit(&ds->ds_dir->dd_lock);
 164  160          } else {
 165  161                  dprintf_bp(bp, "putting on dead list: %s", "");
 166  162                  if (async) {
 167  163                          /*
 168  164                           * We are here as part of zio's write done callback,
 169  165                           * which means we're a zio interrupt thread.  We can't
 170  166                           * call dsl_deadlist_insert() now because it may block
 171  167                           * waiting for I/O.  Instead, put bp on the deferred
 172  168                           * queue and let dsl_pool_sync() finish the job.
 173  169                           */
↓ open down ↓ 410 lines elided ↑ open up ↑
 584  580                                  mutex_enter(&ds->ds_lock);
 585  581                                  (void) strcat(name, ds->ds_snapname);
 586  582                                  mutex_exit(&ds->ds_lock);
 587  583                          } else {
 588  584                                  (void) strcat(name, ds->ds_snapname);
 589  585                          }
 590  586                  }
 591  587          }
 592  588  }
 593  589  
 594      -static int
 595      -dsl_dataset_namelen(dsl_dataset_t *ds)
 596      -{
 597      -        int result;
 598      -
 599      -        if (ds == NULL) {
 600      -                result = 3;     /* "mos" */
 601      -        } else {
 602      -                result = dsl_dir_namelen(ds->ds_dir);
 603      -                VERIFY0(dsl_dataset_get_snapname(ds));
 604      -                if (ds->ds_snapname[0]) {
 605      -                        ++result;       /* adding one for the @-sign */
 606      -                        if (!MUTEX_HELD(&ds->ds_lock)) {
 607      -                                mutex_enter(&ds->ds_lock);
 608      -                                result += strlen(ds->ds_snapname);
 609      -                                mutex_exit(&ds->ds_lock);
 610      -                        } else {
 611      -                                result += strlen(ds->ds_snapname);
 612      -                        }
 613      -                }
 614      -        }
 615      -
 616      -        return (result);
 617      -}
 618      -
 619  590  void
 620  591  dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
 621  592  {
 622  593          dmu_buf_rele(ds->ds_dbuf, tag);
 623  594  }
 624  595  
 625  596  void
 626  597  dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
 627  598  {
 628  599          ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
↓ open down ↓ 2375 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX