Skip to content

Commit 502b09d

Browse files
committed
Fix available space accounting for special/dedup
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. Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com> Closes #18190
1 parent cdf89f4 commit 502b09d

File tree

6 files changed

+60
-36
lines changed

6 files changed

+60
-36
lines changed

include/sys/metaslab.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,12 @@ boolean_t metaslab_class_throttle_unreserve(metaslab_class_t *, int, int,
117117
void metaslab_class_evict_old(metaslab_class_t *, uint64_t);
118118
const char *metaslab_class_get_name(metaslab_class_t *);
119119
uint64_t metaslab_class_get_alloc(metaslab_class_t *);
120+
uint64_t metaslab_class_get_dalloc(metaslab_class_t *);
120121
uint64_t metaslab_class_get_space(metaslab_class_t *);
121122
uint64_t metaslab_class_get_dspace(metaslab_class_t *);
122123
uint64_t metaslab_class_get_deferred(metaslab_class_t *);
123124

124-
void metaslab_space_update(vdev_t *, metaslab_class_t *,
125-
int64_t, int64_t, int64_t);
125+
void metaslab_space_update(metaslab_group_t *, int64_t, int64_t, int64_t);
126126

127127
metaslab_group_t *metaslab_group_create(metaslab_class_t *, vdev_t *);
128128
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
@@ -199,10 +199,12 @@ struct metaslab_class {
199199

200200
uint64_t mc_alloc_groups; /* # of allocatable groups */
201201

202-
uint64_t mc_alloc; /* total allocated space */
203-
uint64_t mc_deferred; /* total deferred frees */
202+
uint64_t mc_alloc; /* allocated space */
203+
uint64_t mc_dalloc; /* deflated allocated space */
204+
uint64_t mc_deferred; /* deferred frees */
205+
uint64_t mc_ddeferred; /* deflated deferred frees */
204206
uint64_t mc_space; /* total space (alloc + free) */
205-
uint64_t mc_dspace; /* total deflated space */
207+
uint64_t mc_dspace; /* deflated total space */
206208
uint64_t mc_histogram[ZFS_RANGE_TREE_HISTOGRAM_SIZE];
207209

208210
/*

module/zfs/metaslab.c

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,9 @@ metaslab_class_destroy(metaslab_class_t *mc)
457457
spa_t *spa = mc->mc_spa;
458458

459459
ASSERT0(mc->mc_alloc);
460+
ASSERT0(mc->mc_dalloc);
460461
ASSERT0(mc->mc_deferred);
462+
ASSERT0(mc->mc_ddeferred);
461463
ASSERT0(mc->mc_space);
462464
ASSERT0(mc->mc_dspace);
463465

@@ -573,8 +575,10 @@ metaslab_class_balance(metaslab_class_t *mc, boolean_t onsync)
573575
* relative to average. Bigger vdevs should get more to
574576
* fill up at the same time as smaller ones.
575577
*/
576-
if (mc->mc_space > 0 && vs->vs_space > 0) {
577-
ratio = vs->vs_space / (mc->mc_space / (mc->mc_groups *
578+
uint64_t mc_space = atomic_load_64(&mc->mc_space);
579+
uint64_t vs_space = atomic_load_64(&vs->vs_space);
580+
if (mc_space > 0 && vs_space > 0) {
581+
ratio = vs_space / (mc_space / (mc->mc_groups *
578582
256) + 1);
579583
mg_aliquot = mg_aliquot * ratio / 256;
580584
}
@@ -595,18 +599,20 @@ metaslab_class_balance(metaslab_class_t *mc, boolean_t onsync)
595599
* queue depth, stronger enforcing the free space balance.
596600
*/
597601
if (metaslab_bias_enabled &&
598-
mc->mc_space > 0 && vs->vs_space > 0) {
599-
uint64_t vs_free = vs->vs_space > vs->vs_alloc ?
600-
vs->vs_space - vs->vs_alloc : 0;
601-
uint64_t mc_free = mc->mc_space > mc->mc_alloc ?
602-
mc->mc_space - mc->mc_alloc : 0;
602+
mc_space > 0 && vs_space > 0) {
603+
uint64_t mc_alloc = atomic_load_64(&mc->mc_alloc);
604+
uint64_t vs_alloc = atomic_load_64(&vs->vs_alloc);
605+
uint64_t vs_free = vs_space > vs_alloc ?
606+
vs_space - vs_alloc : 0;
607+
uint64_t mc_free = mc_space > mc_alloc ?
608+
mc_space - mc_alloc : 0;
603609
/*
604610
* vs_fr is 16 bit fixed-point free space fraction.
605611
* mc_fr is 8 bit fixed-point free space fraction.
606612
* ratio as their quotient is 8 bit fixed-point.
607613
*/
608-
uint_t vs_fr = vs_free / (vs->vs_space / 65536 + 1);
609-
uint_t mc_fr = mc_free / (mc->mc_space / 256 + 1);
614+
uint_t vs_fr = vs_free / (vs_space / 65536 + 1);
615+
uint_t mc_fr = mc_free / (mc_space / 256 + 1);
610616
ratio = vs_fr / (mc_fr + 1);
611617
mg->mg_aliquot = mg_aliquot * ratio / 256;
612618
/* From 2.5x at 25% full to 1x at 75%. */
@@ -693,10 +699,13 @@ metaslab_class_rotate(metaslab_group_t *mg, int allocator, uint64_t psize,
693699

694700
static void
695701
metaslab_class_space_update(metaslab_class_t *mc, int64_t alloc_delta,
696-
int64_t defer_delta, int64_t space_delta, int64_t dspace_delta)
702+
int64_t dalloc_delta, int64_t deferred_delta, int64_t ddeferred_delta,
703+
int64_t space_delta, int64_t dspace_delta)
697704
{
698705
atomic_add_64(&mc->mc_alloc, alloc_delta);
699-
atomic_add_64(&mc->mc_deferred, defer_delta);
706+
atomic_add_64(&mc->mc_dalloc, dalloc_delta);
707+
atomic_add_64(&mc->mc_deferred, deferred_delta);
708+
atomic_add_64(&mc->mc_ddeferred, ddeferred_delta);
700709
atomic_add_64(&mc->mc_space, space_delta);
701710
atomic_add_64(&mc->mc_dspace, dspace_delta);
702711
}
@@ -710,25 +719,34 @@ metaslab_class_get_name(metaslab_class_t *mc)
710719
uint64_t
711720
metaslab_class_get_alloc(metaslab_class_t *mc)
712721
{
713-
return (mc->mc_alloc);
722+
return (atomic_load_64(&mc->mc_alloc));
723+
}
724+
725+
uint64_t
726+
metaslab_class_get_dalloc(metaslab_class_t *mc)
727+
{
728+
return (spa_deflate(mc->mc_spa) ? atomic_load_64(&mc->mc_dalloc) :
729+
atomic_load_64(&mc->mc_alloc));
714730
}
715731

716732
uint64_t
717733
metaslab_class_get_deferred(metaslab_class_t *mc)
718734
{
719-
return (mc->mc_deferred);
735+
return (spa_deflate(mc->mc_spa) ? atomic_load_64(&mc->mc_ddeferred) :
736+
atomic_load_64(&mc->mc_deferred));
720737
}
721738

722739
uint64_t
723740
metaslab_class_get_space(metaslab_class_t *mc)
724741
{
725-
return (mc->mc_space);
742+
return (atomic_load_64(&mc->mc_space));
726743
}
727744

728745
uint64_t
729746
metaslab_class_get_dspace(metaslab_class_t *mc)
730747
{
731-
return (spa_deflate(mc->mc_spa) ? mc->mc_dspace : mc->mc_space);
748+
return (spa_deflate(mc->mc_spa) ? atomic_load_64(&mc->mc_dspace) :
749+
atomic_load_64(&mc->mc_space));
732750
}
733751

734752
void
@@ -2841,16 +2859,21 @@ metaslab_set_selected_txg(metaslab_t *msp, uint64_t txg)
28412859
}
28422860

28432861
void
2844-
metaslab_space_update(vdev_t *vd, metaslab_class_t *mc, int64_t alloc_delta,
2862+
metaslab_space_update(metaslab_group_t *mg, int64_t alloc_delta,
28452863
int64_t defer_delta, int64_t space_delta)
28462864
{
2865+
vdev_t *vd = mg->mg_vd;
2866+
int64_t dalloc_delta = vdev_deflated_space(vd, alloc_delta);
2867+
int64_t ddefer_delta = vdev_deflated_space(vd, defer_delta);
2868+
int64_t dspace_delta = vdev_deflated_space(vd, space_delta);
2869+
28472870
vdev_space_update(vd, alloc_delta, defer_delta, space_delta);
28482871

28492872
ASSERT3P(vd->vdev_spa->spa_root_vdev, ==, vd->vdev_parent);
28502873
ASSERT(vd->vdev_ms_count != 0);
28512874

2852-
metaslab_class_space_update(mc, alloc_delta, defer_delta, space_delta,
2853-
vdev_deflated_space(vd, space_delta));
2875+
metaslab_class_space_update(mg->mg_class, alloc_delta, dalloc_delta,
2876+
defer_delta, ddefer_delta, space_delta, dspace_delta);
28542877
}
28552878

28562879
int
@@ -2962,8 +2985,7 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object,
29622985
*/
29632986
if (txg <= TXG_INITIAL) {
29642987
metaslab_sync_done(ms, 0);
2965-
metaslab_space_update(vd, mg->mg_class,
2966-
metaslab_allocated_space(ms), 0, 0);
2988+
metaslab_space_update(mg, metaslab_allocated_space(ms), 0, 0);
29672989
}
29682990

29692991
if (txg != 0) {
@@ -3025,9 +3047,8 @@ metaslab_fini(metaslab_t *msp)
30253047
* subtracted.
30263048
*/
30273049
if (!msp->ms_new) {
3028-
metaslab_space_update(vd, mg->mg_class,
3029-
-metaslab_allocated_space(msp), 0, -msp->ms_size);
3030-
3050+
metaslab_space_update(mg, -metaslab_allocated_space(msp), 0,
3051+
-msp->ms_size);
30313052
}
30323053
space_map_close(msp->ms_sm);
30333054
msp->ms_sm = NULL;
@@ -4537,7 +4558,7 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
45374558

45384559
if (msp->ms_new) {
45394560
/* this is a new metaslab, add its capacity to the vdev */
4540-
metaslab_space_update(vd, mg->mg_class, 0, 0, msp->ms_size);
4561+
metaslab_space_update(mg, 0, 0, msp->ms_size);
45414562

45424563
/* there should be no allocations nor frees at this point */
45434564
VERIFY0(msp->ms_allocated_this_txg);
@@ -4566,8 +4587,7 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
45664587
} else {
45674588
defer_delta -= zfs_range_tree_space(*defer_tree);
45684589
}
4569-
metaslab_space_update(vd, mg->mg_class, alloc_delta + defer_delta,
4570-
defer_delta, 0);
4590+
metaslab_space_update(mg, alloc_delta + defer_delta, defer_delta, 0);
45714591

45724592
if (spa_syncing_log_sm(spa) == NULL) {
45734593
/*

module/zfs/spa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7120,6 +7120,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
71207120
spa->spa_removing_phys.sr_removing_vdev = -1;
71217121
spa->spa_removing_phys.sr_prev_indirect_vdev = -1;
71227122
spa->spa_indirect_vdevs_loaded = B_TRUE;
7123+
spa->spa_deflate = (version >= SPA_VERSION_RAIDZ_DEFLATE);
71237124

71247125
/*
71257126
* Create "The Godfather" zio to hold all async IOs
@@ -7249,7 +7250,6 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
72497250

72507251
/* Newly created pools with the right version are always deflated. */
72517252
if (version >= SPA_VERSION_RAIDZ_DEFLATE) {
7252-
spa->spa_deflate = TRUE;
72537253
if (zap_add(spa->spa_meta_objset,
72547254
DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_DEFLATE,
72557255
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
@@ -2031,7 +2031,10 @@ spa_update_dspace(spa_t *spa)
20312031
ASSERT3U(spa->spa_rdspace, >=, spa->spa_nonallocating_dspace);
20322032
spa->spa_rdspace -= spa->spa_nonallocating_dspace;
20332033
}
2034-
spa->spa_dspace = spa->spa_rdspace + ddt_get_dedup_dspace(spa) +
2034+
spa->spa_dspace = spa->spa_rdspace +
2035+
metaslab_class_get_dalloc(spa_special_class(spa)) +
2036+
metaslab_class_get_dalloc(spa_dedup_class(spa)) +
2037+
ddt_get_dedup_dspace(spa) +
20352038
brt_get_dspace(spa);
20362039
}
20372040

0 commit comments

Comments
 (0)