Skip to content

Commit 8cd44dd

Browse files
naotakdave
authored andcommitted
btrfs: zoned: fix zone_unusable accounting on making block group read-write again
When btrfs makes a block group read-only, it adds all free regions in the block group to space_info->bytes_readonly. That free space excludes reserved and pinned regions. OTOH, when btrfs makes the block group read-write again, it moves all the unused regions into the block group's zone_unusable. That unused region includes reserved and pinned regions. As a result, it counts too much zone_unusable bytes. Fortunately (or unfortunately), having erroneous zone_unusable does not affect the calculation of space_info->bytes_readonly, because free space (num_bytes in btrfs_dec_block_group_ro) calculation is done based on the erroneous zone_unusable and it reduces the num_bytes just to cancel the error. This behavior can be easily discovered by adding a WARN_ON to check e.g, "bg->pinned > 0" in btrfs_dec_block_group_ro(), and running fstests test case like btrfs/282. Fix it by properly considering pinned and reserved in btrfs_dec_block_group_ro(). Also, add a WARN_ON and introduce btrfs_space_info_update_bytes_zone_unusable() to catch a similar mistake. Fixes: 169e0da ("btrfs: zoned: track unusable bytes for zones") CC: [email protected] # 5.15+ Signed-off-by: Naohiro Aota <[email protected]> Reviewed-by: Josef Bacik <[email protected]> Reviewed-by: Johannes Thumshirn <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent d89c285 commit 8cd44dd

File tree

6 files changed

+23
-8
lines changed

6 files changed

+23
-8
lines changed

fs/btrfs/block-group.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,8 +1223,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
12231223
block_group->space_info->total_bytes -= block_group->length;
12241224
block_group->space_info->bytes_readonly -=
12251225
(block_group->length - block_group->zone_unusable);
1226-
block_group->space_info->bytes_zone_unusable -=
1227-
block_group->zone_unusable;
1226+
btrfs_space_info_update_bytes_zone_unusable(fs_info, block_group->space_info,
1227+
-block_group->zone_unusable);
12281228
block_group->space_info->disk_total -= block_group->length * factor;
12291229

12301230
spin_unlock(&block_group->space_info->lock);
@@ -1396,7 +1396,8 @@ static int inc_block_group_ro(struct btrfs_block_group *cache, int force)
13961396
if (btrfs_is_zoned(cache->fs_info)) {
13971397
/* Migrate zone_unusable bytes to readonly */
13981398
sinfo->bytes_readonly += cache->zone_unusable;
1399-
sinfo->bytes_zone_unusable -= cache->zone_unusable;
1399+
btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo,
1400+
-cache->zone_unusable);
14001401
cache->zone_unusable = 0;
14011402
}
14021403
cache->ro++;
@@ -3056,9 +3057,11 @@ void btrfs_dec_block_group_ro(struct btrfs_block_group *cache)
30563057
if (btrfs_is_zoned(cache->fs_info)) {
30573058
/* Migrate zone_unusable bytes back */
30583059
cache->zone_unusable =
3059-
(cache->alloc_offset - cache->used) +
3060+
(cache->alloc_offset - cache->used - cache->pinned -
3061+
cache->reserved) +
30603062
(cache->length - cache->zone_capacity);
3061-
sinfo->bytes_zone_unusable += cache->zone_unusable;
3063+
btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo,
3064+
cache->zone_unusable);
30623065
sinfo->bytes_readonly -= cache->zone_unusable;
30633066
}
30643067
num_bytes = cache->length - cache->reserved -

fs/btrfs/extent-tree.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2793,7 +2793,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
27932793
readonly = true;
27942794
} else if (btrfs_is_zoned(fs_info)) {
27952795
/* Need reset before reusing in a zoned block group */
2796-
space_info->bytes_zone_unusable += len;
2796+
btrfs_space_info_update_bytes_zone_unusable(fs_info, space_info,
2797+
len);
27972798
readonly = true;
27982799
}
27992800
spin_unlock(&cache->lock);

fs/btrfs/free-space-cache.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2723,8 +2723,10 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
27232723
* If the block group is read-only, we should account freed space into
27242724
* bytes_readonly.
27252725
*/
2726-
if (!block_group->ro)
2726+
if (!block_group->ro) {
27272727
block_group->zone_unusable += to_unusable;
2728+
WARN_ON(block_group->zone_unusable > block_group->length);
2729+
}
27282730
spin_unlock(&ctl->tree_lock);
27292731
if (!used) {
27302732
spin_lock(&block_group->lock);

fs/btrfs/space-info.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info,
316316
found->bytes_used += block_group->used;
317317
found->disk_used += block_group->used * factor;
318318
found->bytes_readonly += block_group->bytes_super;
319-
found->bytes_zone_unusable += block_group->zone_unusable;
319+
btrfs_space_info_update_bytes_zone_unusable(info, found, block_group->zone_unusable);
320320
if (block_group->length > 0)
321321
found->full = 0;
322322
btrfs_try_granting_tickets(info, found);

fs/btrfs/space-info.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ btrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \
249249

250250
DECLARE_SPACE_INFO_UPDATE(bytes_may_use, "space_info");
251251
DECLARE_SPACE_INFO_UPDATE(bytes_pinned, "pinned");
252+
DECLARE_SPACE_INFO_UPDATE(bytes_zone_unusable, "zone_unusable");
252253

253254
int btrfs_init_space_info(struct btrfs_fs_info *fs_info);
254255
void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info,

include/trace/events/btrfs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2383,6 +2383,14 @@ DEFINE_EVENT(btrfs__space_info_update, update_bytes_pinned,
23832383
TP_ARGS(fs_info, sinfo, old, diff)
23842384
);
23852385

2386+
DEFINE_EVENT(btrfs__space_info_update, update_bytes_zone_unusable,
2387+
2388+
TP_PROTO(const struct btrfs_fs_info *fs_info,
2389+
const struct btrfs_space_info *sinfo, u64 old, s64 diff),
2390+
2391+
TP_ARGS(fs_info, sinfo, old, diff)
2392+
);
2393+
23862394
DECLARE_EVENT_CLASS(btrfs_raid56_bio,
23872395

23882396
TP_PROTO(const struct btrfs_raid_bio *rbio,

0 commit comments

Comments
 (0)