Skip to content

Commit ba53ba5

Browse files
amotinbehlendorf
authored andcommitted
Fix available space accounting for special/dedup (#18222)
Currently, spa_dspace (base to calculate dataset AVAIL) only includes the normal allocation class capacity, but dd_used_bytes tracks space allocated across all classes. Since we don't want to report free space of other classes as available (we can't promise new allocations will be able to use it), report only allocated space, similar to how we report space saved by dedup and block cloning. Since we need deflated space here, make allocation classes track deflated allocated space also. While here, make mc_deferred also deflated, matching its use contexts. Also while there, use atomic_load() to read the allocation class stats. Reviewed-by: Rob Norris <robn@despairlabs.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com> Closes #18190 Closes #18222
1 parent deb372b commit ba53ba5

6 files changed

Lines changed: 61 additions & 33 deletions

File tree

include/sys/metaslab.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,12 @@ boolean_t metaslab_class_throttle_reserve(metaslab_class_t *, int, int,
114114
void metaslab_class_throttle_unreserve(metaslab_class_t *, int, int, zio_t *);
115115
void metaslab_class_evict_old(metaslab_class_t *, uint64_t);
116116
uint64_t metaslab_class_get_alloc(metaslab_class_t *);
117+
uint64_t metaslab_class_get_dalloc(metaslab_class_t *);
117118
uint64_t metaslab_class_get_space(metaslab_class_t *);
118119
uint64_t metaslab_class_get_dspace(metaslab_class_t *);
119120
uint64_t metaslab_class_get_deferred(metaslab_class_t *);
120121

121-
void metaslab_space_update(vdev_t *, metaslab_class_t *,
122-
int64_t, int64_t, int64_t);
122+
void metaslab_space_update(metaslab_group_t *, int64_t, int64_t, int64_t);
123123

124124
metaslab_group_t *metaslab_group_create(metaslab_class_t *, vdev_t *, int);
125125
void metaslab_group_destroy(metaslab_group_t *);

include/sys/metaslab_impl.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,12 @@ struct metaslab_class {
197197

198198
uint64_t mc_alloc_groups; /* # of allocatable groups */
199199

200-
uint64_t mc_alloc; /* total allocated space */
201-
uint64_t mc_deferred; /* total deferred frees */
200+
uint64_t mc_alloc; /* allocated space */
201+
uint64_t mc_dalloc; /* deflated allocated space */
202+
uint64_t mc_deferred; /* deferred frees */
203+
uint64_t mc_ddeferred; /* deflated deferred frees */
202204
uint64_t mc_space; /* total space (alloc + free) */
203-
uint64_t mc_dspace; /* total deflated space */
205+
uint64_t mc_dspace; /* deflated total space */
204206
uint64_t mc_histogram[ZFS_RANGE_TREE_HISTOGRAM_SIZE];
205207

206208
/*

module/zfs/metaslab.c

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -443,10 +443,12 @@ metaslab_class_destroy(metaslab_class_t *mc)
443443
{
444444
spa_t *spa = mc->mc_spa;
445445

446-
ASSERT(mc->mc_alloc == 0);
447-
ASSERT(mc->mc_deferred == 0);
448-
ASSERT(mc->mc_space == 0);
449-
ASSERT(mc->mc_dspace == 0);
446+
ASSERT0(mc->mc_alloc);
447+
ASSERT0(mc->mc_dalloc);
448+
ASSERT0(mc->mc_deferred);
449+
ASSERT0(mc->mc_ddeferred);
450+
ASSERT0(mc->mc_space);
451+
ASSERT0(mc->mc_dspace);
450452

451453
for (int i = 0; i < spa->spa_alloc_count; i++) {
452454
metaslab_class_allocator_t *mca = &mc->mc_allocator[i];
@@ -487,36 +489,48 @@ metaslab_class_validate(metaslab_class_t *mc)
487489

488490
static void
489491
metaslab_class_space_update(metaslab_class_t *mc, int64_t alloc_delta,
490-
int64_t defer_delta, int64_t space_delta, int64_t dspace_delta)
492+
int64_t dalloc_delta, int64_t deferred_delta, int64_t ddeferred_delta,
493+
int64_t space_delta, int64_t dspace_delta)
491494
{
492495
atomic_add_64(&mc->mc_alloc, alloc_delta);
493-
atomic_add_64(&mc->mc_deferred, defer_delta);
496+
atomic_add_64(&mc->mc_dalloc, dalloc_delta);
497+
atomic_add_64(&mc->mc_deferred, deferred_delta);
498+
atomic_add_64(&mc->mc_ddeferred, ddeferred_delta);
494499
atomic_add_64(&mc->mc_space, space_delta);
495500
atomic_add_64(&mc->mc_dspace, dspace_delta);
496501
}
497502

498503
uint64_t
499504
metaslab_class_get_alloc(metaslab_class_t *mc)
500505
{
501-
return (mc->mc_alloc);
506+
return (atomic_load_64(&mc->mc_alloc));
507+
}
508+
509+
uint64_t
510+
metaslab_class_get_dalloc(metaslab_class_t *mc)
511+
{
512+
return (spa_deflate(mc->mc_spa) ? atomic_load_64(&mc->mc_dalloc) :
513+
atomic_load_64(&mc->mc_alloc));
502514
}
503515

504516
uint64_t
505517
metaslab_class_get_deferred(metaslab_class_t *mc)
506518
{
507-
return (mc->mc_deferred);
519+
return (spa_deflate(mc->mc_spa) ? atomic_load_64(&mc->mc_ddeferred) :
520+
atomic_load_64(&mc->mc_deferred));
508521
}
509522

510523
uint64_t
511524
metaslab_class_get_space(metaslab_class_t *mc)
512525
{
513-
return (mc->mc_space);
526+
return (atomic_load_64(&mc->mc_space));
514527
}
515528

516529
uint64_t
517530
metaslab_class_get_dspace(metaslab_class_t *mc)
518531
{
519-
return (spa_deflate(mc->mc_spa) ? mc->mc_dspace : mc->mc_space);
532+
return (spa_deflate(mc->mc_spa) ? atomic_load_64(&mc->mc_dspace) :
533+
atomic_load_64(&mc->mc_space));
520534
}
521535

522536
void
@@ -2698,16 +2712,21 @@ metaslab_set_selected_txg(metaslab_t *msp, uint64_t txg)
26982712
}
26992713

27002714
void
2701-
metaslab_space_update(vdev_t *vd, metaslab_class_t *mc, int64_t alloc_delta,
2715+
metaslab_space_update(metaslab_group_t *mg, int64_t alloc_delta,
27022716
int64_t defer_delta, int64_t space_delta)
27032717
{
2718+
vdev_t *vd = mg->mg_vd;
2719+
int64_t dalloc_delta = vdev_deflated_space(vd, alloc_delta);
2720+
int64_t ddefer_delta = vdev_deflated_space(vd, defer_delta);
2721+
int64_t dspace_delta = vdev_deflated_space(vd, space_delta);
2722+
27042723
vdev_space_update(vd, alloc_delta, defer_delta, space_delta);
27052724

27062725
ASSERT3P(vd->vdev_spa->spa_root_vdev, ==, vd->vdev_parent);
27072726
ASSERT(vd->vdev_ms_count != 0);
27082727

2709-
metaslab_class_space_update(mc, alloc_delta, defer_delta, space_delta,
2710-
vdev_deflated_space(vd, space_delta));
2728+
metaslab_class_space_update(mg->mg_class, alloc_delta, dalloc_delta,
2729+
defer_delta, ddefer_delta, space_delta, dspace_delta);
27112730
}
27122731

27132732
int
@@ -2819,8 +2838,7 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object,
28192838
*/
28202839
if (txg <= TXG_INITIAL) {
28212840
metaslab_sync_done(ms, 0);
2822-
metaslab_space_update(vd, mg->mg_class,
2823-
metaslab_allocated_space(ms), 0, 0);
2841+
metaslab_space_update(mg, metaslab_allocated_space(ms), 0, 0);
28242842
}
28252843

28262844
if (txg != 0) {
@@ -2882,9 +2900,8 @@ metaslab_fini(metaslab_t *msp)
28822900
* subtracted.
28832901
*/
28842902
if (!msp->ms_new) {
2885-
metaslab_space_update(vd, mg->mg_class,
2886-
-metaslab_allocated_space(msp), 0, -msp->ms_size);
2887-
2903+
metaslab_space_update(mg, -metaslab_allocated_space(msp), 0,
2904+
-msp->ms_size);
28882905
}
28892906
space_map_close(msp->ms_sm);
28902907
msp->ms_sm = NULL;
@@ -4392,7 +4409,7 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
43924409

43934410
if (msp->ms_new) {
43944411
/* this is a new metaslab, add its capacity to the vdev */
4395-
metaslab_space_update(vd, mg->mg_class, 0, 0, msp->ms_size);
4412+
metaslab_space_update(mg, 0, 0, msp->ms_size);
43964413

43974414
/* there should be no allocations nor frees at this point */
43984415
VERIFY0(msp->ms_allocated_this_txg);
@@ -4421,8 +4438,7 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
44214438
} else {
44224439
defer_delta -= zfs_range_tree_space(*defer_tree);
44234440
}
4424-
metaslab_space_update(vd, mg->mg_class, alloc_delta + defer_delta,
4425-
defer_delta, 0);
4441+
metaslab_space_update(mg, alloc_delta + defer_delta, defer_delta, 0);
44264442

44274443
if (spa_syncing_log_sm(spa) == NULL) {
44284444
/*
@@ -5339,8 +5355,16 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize,
53395355
*/
53405356
if (mca->mca_aliquot == 0 && metaslab_bias_enabled) {
53415357
vdev_stat_t *vs = &vd->vdev_stat;
5342-
int64_t vs_free = vs->vs_space - vs->vs_alloc;
5343-
int64_t mc_free = mc->mc_space - mc->mc_alloc;
5358+
uint64_t vs_space =
5359+
atomic_load_64(&vs->vs_space);
5360+
uint64_t mc_space =
5361+
atomic_load_64(&mc->mc_space);
5362+
uint64_t mc_alloc =
5363+
atomic_load_64(&mc->mc_alloc);
5364+
uint64_t vs_alloc =
5365+
atomic_load_64(&vs->vs_alloc);
5366+
int64_t vs_free = vs_space - vs_alloc;
5367+
int64_t mc_free = mc_space - mc_alloc;
53445368
int64_t ratio;
53455369

53465370
/*

module/zfs/spa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6949,6 +6949,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
69496949
spa->spa_removing_phys.sr_removing_vdev = -1;
69506950
spa->spa_removing_phys.sr_prev_indirect_vdev = -1;
69516951
spa->spa_indirect_vdevs_loaded = B_TRUE;
6952+
spa->spa_deflate = (version >= SPA_VERSION_RAIDZ_DEFLATE);
69526953

69536954
/*
69546955
* Create "The Godfather" zio to hold all async IOs
@@ -7078,7 +7079,6 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
70787079

70797080
/* Newly created pools with the right version are always deflated. */
70807081
if (version >= SPA_VERSION_RAIDZ_DEFLATE) {
7081-
spa->spa_deflate = TRUE;
70827082
if (zap_add(spa->spa_meta_objset,
70837083
DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_DEFLATE,
70847084
sizeof (uint64_t), 1, &spa->spa_deflate, tx) != 0) {

module/zfs/spa_log_spacemap.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,10 +1255,9 @@ spa_ld_log_sm_data(spa_t *spa)
12551255
zfs_range_tree_space(m->ms_unflushed_allocs) -
12561256
zfs_range_tree_space(m->ms_unflushed_frees);
12571257

1258-
vdev_t *vd = m->ms_group->mg_vd;
1259-
metaslab_space_update(vd, m->ms_group->mg_class,
1258+
metaslab_space_update(m->ms_group,
12601259
zfs_range_tree_space(m->ms_unflushed_allocs), 0, 0);
1261-
metaslab_space_update(vd, m->ms_group->mg_class,
1260+
metaslab_space_update(m->ms_group,
12621261
-zfs_range_tree_space(m->ms_unflushed_frees), 0, 0);
12631262

12641263
ASSERT0(m->ms_weight & METASLAB_ACTIVE_MASK);

module/zfs/spa_misc.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,10 @@ spa_update_dspace(spa_t *spa)
19881988
ASSERT3U(spa->spa_rdspace, >=, spa->spa_nonallocating_dspace);
19891989
spa->spa_rdspace -= spa->spa_nonallocating_dspace;
19901990
}
1991-
spa->spa_dspace = spa->spa_rdspace + ddt_get_dedup_dspace(spa) +
1991+
spa->spa_dspace = spa->spa_rdspace +
1992+
metaslab_class_get_dalloc(spa_special_class(spa)) +
1993+
metaslab_class_get_dalloc(spa_dedup_class(spa)) +
1994+
ddt_get_dedup_dspace(spa) +
19921995
brt_get_dspace(spa);
19931996
}
19941997

0 commit comments

Comments
 (0)