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_dir.c
          +++ new/usr/src/uts/common/fs/zfs/dsl_dir.c
↓ open down ↓ 833 lines elided ↑ open up ↑
 834  834          dsl_pool_willuse_space(dd->dd_pool, space, tx);
 835  835          dsl_dir_willuse_space_impl(dd, space, tx);
 836  836  }
 837  837  
 838  838  /* call from syncing context when we actually write/free space for this dd */
 839  839  void
 840  840  dsl_dir_diduse_space(dsl_dir_t *dd, dd_used_t type,
 841  841      int64_t used, int64_t compressed, int64_t uncompressed, dmu_tx_t *tx)
 842  842  {
 843  843          int64_t accounted_delta;
      844 +
      845 +        /*
      846 +         * dsl_dataset_set_refreservation_sync_impl() calls this with
      847 +         * dd_lock held, so that it can atomically update
      848 +         * ds->ds_reserved and the dsl_dir accounting, so that
      849 +         * dsl_dataset_check_quota() can see dataset and dir accounting
      850 +         * consistently.
      851 +         */
 844  852          boolean_t needlock = !MUTEX_HELD(&dd->dd_lock);
 845  853  
 846  854          ASSERT(dmu_tx_is_syncing(tx));
 847  855          ASSERT(type < DD_USED_NUM);
 848  856  
      857 +        dmu_buf_will_dirty(dd->dd_dbuf, tx);
      858 +
 849  859          if (needlock)
 850  860                  mutex_enter(&dd->dd_lock);
 851  861          accounted_delta = parent_delta(dd, dd->dd_phys->dd_used_bytes, used);
 852  862          ASSERT(used >= 0 || dd->dd_phys->dd_used_bytes >= -used);
 853  863          ASSERT(compressed >= 0 ||
 854  864              dd->dd_phys->dd_compressed_bytes >= -compressed);
 855  865          ASSERT(uncompressed >= 0 ||
 856  866              dd->dd_phys->dd_uncompressed_bytes >= -uncompressed);
 857      -        dmu_buf_will_dirty(dd->dd_dbuf, tx);
 858  867          dd->dd_phys->dd_used_bytes += used;
 859  868          dd->dd_phys->dd_uncompressed_bytes += uncompressed;
 860  869          dd->dd_phys->dd_compressed_bytes += compressed;
 861  870  
 862  871          if (dd->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) {
 863  872                  ASSERT(used > 0 ||
 864  873                      dd->dd_phys->dd_used_breakdown[type] >= -used);
 865  874                  dd->dd_phys->dd_used_breakdown[type] += used;
 866  875  #ifdef DEBUG
 867  876                  dd_used_t t;
↓ open down ↓ 12 lines elided ↑ open up ↑
 880  889                  dsl_dir_transfer_space(dd->dd_parent,
 881  890                      used - accounted_delta,
 882  891                      DD_USED_CHILD_RSRV, DD_USED_CHILD, tx);
 883  892          }
 884  893  }
 885  894  
 886  895  void
 887  896  dsl_dir_transfer_space(dsl_dir_t *dd, int64_t delta,
 888  897      dd_used_t oldtype, dd_used_t newtype, dmu_tx_t *tx)
 889  898  {
 890      -        boolean_t needlock = !MUTEX_HELD(&dd->dd_lock);
 891      -
 892  899          ASSERT(dmu_tx_is_syncing(tx));
 893  900          ASSERT(oldtype < DD_USED_NUM);
 894  901          ASSERT(newtype < DD_USED_NUM);
 895  902  
 896  903          if (delta == 0 || !(dd->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN))
 897  904                  return;
 898  905  
 899      -        if (needlock)
 900      -                mutex_enter(&dd->dd_lock);
      906 +        dmu_buf_will_dirty(dd->dd_dbuf, tx);
      907 +        mutex_enter(&dd->dd_lock);
 901  908          ASSERT(delta > 0 ?
 902  909              dd->dd_phys->dd_used_breakdown[oldtype] >= delta :
 903  910              dd->dd_phys->dd_used_breakdown[newtype] >= -delta);
 904  911          ASSERT(dd->dd_phys->dd_used_bytes >= ABS(delta));
 905      -        dmu_buf_will_dirty(dd->dd_dbuf, tx);
 906  912          dd->dd_phys->dd_used_breakdown[oldtype] -= delta;
 907  913          dd->dd_phys->dd_used_breakdown[newtype] += delta;
 908      -        if (needlock)
 909      -                mutex_exit(&dd->dd_lock);
      914 +        mutex_exit(&dd->dd_lock);
 910  915  }
 911  916  
 912  917  typedef struct dsl_dir_set_qr_arg {
 913  918          const char *ddsqra_name;
 914  919          zprop_source_t ddsqra_source;
 915  920          uint64_t ddsqra_value;
 916  921  } dsl_dir_set_qr_arg_t;
 917  922  
 918  923  static int
 919  924  dsl_dir_set_quota_check(void *arg, dmu_tx_t *tx)
↓ open down ↓ 440 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX