Skip to content

Commit a169a62

Browse files
ahrensbehlendorf
authored andcommitted
Illumos #4046
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> Approved by: Garrett D'Amore <garrett@damore.org> References: https://www.illumos.org/issues/4046 illumos/illumos-gate@b62969f Ported-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Issue #1775 Porting notes: 1. This commit removed dsl_dataset_namelen in Illumos, but that appears to have been removed from ZFSOnLinux in an earlier commit.
1 parent 8ce0af0 commit a169a62

File tree

2 files changed

+14
-13
lines changed

2 files changed

+14
-13
lines changed

module/zfs/dsl_dataset.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,8 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
102102
used, compressed, uncompressed);
103103
return;
104104
}
105-
dmu_buf_will_dirty(ds->ds_dbuf, tx);
106105

107-
mutex_enter(&ds->ds_dir->dd_lock);
106+
dmu_buf_will_dirty(ds->ds_dbuf, tx);
108107
mutex_enter(&ds->ds_lock);
109108
delta = parent_delta(ds, used);
110109
ds->ds_phys->ds_referenced_bytes += used;
@@ -116,7 +115,6 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
116115
compressed, uncompressed, tx);
117116
dsl_dir_transfer_space(ds->ds_dir, used - delta,
118117
DD_USED_REFRSRV, DD_USED_HEAD, tx);
119-
mutex_exit(&ds->ds_dir->dd_lock);
120118
}
121119

122120
int
@@ -153,7 +151,6 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
153151
dprintf_bp(bp, "freeing ds=%llu", ds->ds_object);
154152
dsl_free(tx->tx_pool, tx->tx_txg, bp);
155153

156-
mutex_enter(&ds->ds_dir->dd_lock);
157154
mutex_enter(&ds->ds_lock);
158155
ASSERT(ds->ds_phys->ds_unique_bytes >= used ||
159156
!DS_UNIQUE_IS_ACCURATE(ds));
@@ -164,7 +161,6 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
164161
delta, -compressed, -uncompressed, tx);
165162
dsl_dir_transfer_space(ds->ds_dir, -used - delta,
166163
DD_USED_REFRSRV, DD_USED_HEAD, tx);
167-
mutex_exit(&ds->ds_dir->dd_lock);
168164
} else {
169165
dprintf_bp(bp, "putting on dead list: %s", "");
170166
if (async) {

module/zfs/dsl_dir.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -846,11 +846,21 @@ dsl_dir_diduse_space(dsl_dir_t *dd, dd_used_t type,
846846
int64_t used, int64_t compressed, int64_t uncompressed, dmu_tx_t *tx)
847847
{
848848
int64_t accounted_delta;
849+
850+
/*
851+
* dsl_dataset_set_refreservation_sync_impl() calls this with
852+
* dd_lock held, so that it can atomically update
853+
* ds->ds_reserved and the dsl_dir accounting, so that
854+
* dsl_dataset_check_quota() can see dataset and dir accounting
855+
* consistently.
856+
*/
849857
boolean_t needlock = !MUTEX_HELD(&dd->dd_lock);
850858

851859
ASSERT(dmu_tx_is_syncing(tx));
852860
ASSERT(type < DD_USED_NUM);
853861

862+
dmu_buf_will_dirty(dd->dd_dbuf, tx);
863+
854864
if (needlock)
855865
mutex_enter(&dd->dd_lock);
856866
accounted_delta = parent_delta(dd, dd->dd_phys->dd_used_bytes, used);
@@ -859,7 +869,6 @@ dsl_dir_diduse_space(dsl_dir_t *dd, dd_used_t type,
859869
dd->dd_phys->dd_compressed_bytes >= -compressed);
860870
ASSERT(uncompressed >= 0 ||
861871
dd->dd_phys->dd_uncompressed_bytes >= -uncompressed);
862-
dmu_buf_will_dirty(dd->dd_dbuf, tx);
863872
dd->dd_phys->dd_used_bytes += used;
864873
dd->dd_phys->dd_uncompressed_bytes += uncompressed;
865874
dd->dd_phys->dd_compressed_bytes += compressed;
@@ -894,26 +903,22 @@ void
894903
dsl_dir_transfer_space(dsl_dir_t *dd, int64_t delta,
895904
dd_used_t oldtype, dd_used_t newtype, dmu_tx_t *tx)
896905
{
897-
boolean_t needlock = !MUTEX_HELD(&dd->dd_lock);
898-
899906
ASSERT(dmu_tx_is_syncing(tx));
900907
ASSERT(oldtype < DD_USED_NUM);
901908
ASSERT(newtype < DD_USED_NUM);
902909

903910
if (delta == 0 || !(dd->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN))
904911
return;
905912

906-
if (needlock)
907-
mutex_enter(&dd->dd_lock);
913+
dmu_buf_will_dirty(dd->dd_dbuf, tx);
914+
mutex_enter(&dd->dd_lock);
908915
ASSERT(delta > 0 ?
909916
dd->dd_phys->dd_used_breakdown[oldtype] >= delta :
910917
dd->dd_phys->dd_used_breakdown[newtype] >= -delta);
911918
ASSERT(dd->dd_phys->dd_used_bytes >= ABS(delta));
912-
dmu_buf_will_dirty(dd->dd_dbuf, tx);
913919
dd->dd_phys->dd_used_breakdown[oldtype] -= delta;
914920
dd->dd_phys->dd_used_breakdown[newtype] += delta;
915-
if (needlock)
916-
mutex_exit(&dd->dd_lock);
921+
mutex_exit(&dd->dd_lock);
917922
}
918923

919924
typedef struct dsl_dir_set_qr_arg {

0 commit comments

Comments
 (0)