Skip to content

Commit 6a921de

Browse files
naotakdave
authored andcommitted
btrfs: zoned: introduce space_info->active_total_bytes
The active_total_bytes, like the total_bytes, accounts for the total bytes of active block groups in the space_info. With an introduction of active_total_bytes, we can check if the reserved bytes can be written to the block groups without activating a new block group. The check is necessary for metadata allocation on zoned filesystem. We cannot finish a block group, which may require waiting for the current transaction, from the metadata allocation context. Instead, we need to ensure the ongoing allocation (reserved bytes) fits in active block groups. Signed-off-by: Naohiro Aota <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 393f646 commit 6a921de

File tree

4 files changed

+50
-13
lines changed

4 files changed

+50
-13
lines changed

fs/btrfs/block-group.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,8 +1051,13 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
10511051
< block_group->zone_unusable);
10521052
WARN_ON(block_group->space_info->disk_total
10531053
< block_group->length * factor);
1054+
WARN_ON(block_group->zone_is_active &&
1055+
block_group->space_info->active_total_bytes
1056+
< block_group->length);
10541057
}
10551058
block_group->space_info->total_bytes -= block_group->length;
1059+
if (block_group->zone_is_active)
1060+
block_group->space_info->active_total_bytes -= block_group->length;
10561061
block_group->space_info->bytes_readonly -=
10571062
(block_group->length - block_group->zone_unusable);
10581063
block_group->space_info->bytes_zone_unusable -=
@@ -2107,7 +2112,8 @@ static int read_one_block_group(struct btrfs_fs_info *info,
21072112
trace_btrfs_add_block_group(info, cache, 0);
21082113
btrfs_update_space_info(info, cache->flags, cache->length,
21092114
cache->used, cache->bytes_super,
2110-
cache->zone_unusable, &space_info);
2115+
cache->zone_unusable, cache->zone_is_active,
2116+
&space_info);
21112117

21122118
cache->space_info = space_info;
21132119

@@ -2177,7 +2183,7 @@ static int fill_dummy_bgs(struct btrfs_fs_info *fs_info)
21772183
}
21782184

21792185
btrfs_update_space_info(fs_info, bg->flags, em->len, em->len,
2180-
0, 0, &space_info);
2186+
0, 0, false, &space_info);
21812187
bg->space_info = space_info;
21822188
link_block_group(bg);
21832189

@@ -2558,7 +2564,7 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
25582564
trace_btrfs_add_block_group(fs_info, cache, 1);
25592565
btrfs_update_space_info(fs_info, cache->flags, size, bytes_used,
25602566
cache->bytes_super, cache->zone_unusable,
2561-
&cache->space_info);
2567+
cache->zone_is_active, &cache->space_info);
25622568
btrfs_update_global_block_rsv(fs_info);
25632569

25642570
link_block_group(cache);

fs/btrfs/space-info.c

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
295295
void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags,
296296
u64 total_bytes, u64 bytes_used,
297297
u64 bytes_readonly, u64 bytes_zone_unusable,
298-
struct btrfs_space_info **space_info)
298+
bool active, struct btrfs_space_info **space_info)
299299
{
300300
struct btrfs_space_info *found;
301301
int factor;
@@ -306,6 +306,8 @@ void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags,
306306
ASSERT(found);
307307
spin_lock(&found->lock);
308308
found->total_bytes += total_bytes;
309+
if (active)
310+
found->active_total_bytes += total_bytes;
309311
found->disk_total += total_bytes * factor;
310312
found->bytes_used += bytes_used;
311313
found->disk_used += bytes_used * factor;
@@ -369,6 +371,22 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info,
369371
return avail;
370372
}
371373

374+
static inline u64 writable_total_bytes(struct btrfs_fs_info *fs_info,
375+
struct btrfs_space_info *space_info)
376+
{
377+
/*
378+
* On regular filesystem, all total_bytes are always writable. On zoned
379+
* filesystem, there may be a limitation imposed by max_active_zones.
380+
* For metadata allocation, we cannot finish an existing active block
381+
* group to avoid a deadlock. Thus, we need to consider only the active
382+
* groups to be writable for metadata space.
383+
*/
384+
if (!btrfs_is_zoned(fs_info) || (space_info->flags & BTRFS_BLOCK_GROUP_DATA))
385+
return space_info->total_bytes;
386+
387+
return space_info->active_total_bytes;
388+
}
389+
372390
int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
373391
struct btrfs_space_info *space_info, u64 bytes,
374392
enum btrfs_reserve_flush_enum flush)
@@ -383,7 +401,7 @@ int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
383401
used = btrfs_space_info_used(space_info, true);
384402
avail = calc_available_free_space(fs_info, space_info, flush);
385403

386-
if (used + bytes < space_info->total_bytes + avail)
404+
if (used + bytes < writable_total_bytes(fs_info, space_info) + avail)
387405
return 1;
388406
return 0;
389407
}
@@ -419,7 +437,7 @@ void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info,
419437
ticket = list_first_entry(head, struct reserve_ticket, list);
420438

421439
/* Check and see if our ticket can be satisfied now. */
422-
if ((used + ticket->bytes <= space_info->total_bytes) ||
440+
if ((used + ticket->bytes <= writable_total_bytes(fs_info, space_info)) ||
423441
btrfs_can_overcommit(fs_info, space_info, ticket->bytes,
424442
flush)) {
425443
btrfs_space_info_update_bytes_may_use(fs_info,
@@ -750,6 +768,7 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info,
750768
{
751769
u64 used;
752770
u64 avail;
771+
u64 total;
753772
u64 to_reclaim = space_info->reclaim_size;
754773

755774
lockdep_assert_held(&space_info->lock);
@@ -764,8 +783,9 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info,
764783
* space. If that's the case add in our overage so we make sure to put
765784
* appropriate pressure on the flushing state machine.
766785
*/
767-
if (space_info->total_bytes + avail < used)
768-
to_reclaim += used - (space_info->total_bytes + avail);
786+
total = writable_total_bytes(fs_info, space_info);
787+
if (total + avail < used)
788+
to_reclaim += used - (total + avail);
769789

770790
return to_reclaim;
771791
}
@@ -775,9 +795,12 @@ static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info,
775795
{
776796
u64 global_rsv_size = fs_info->global_block_rsv.reserved;
777797
u64 ordered, delalloc;
778-
u64 thresh = div_factor_fine(space_info->total_bytes, 90);
798+
u64 total = writable_total_bytes(fs_info, space_info);
799+
u64 thresh;
779800
u64 used;
780801

802+
thresh = div_factor_fine(total, 90);
803+
781804
lockdep_assert_held(&space_info->lock);
782805

783806
/* If we're just plain full then async reclaim just slows us down. */
@@ -839,8 +862,8 @@ static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info,
839862
BTRFS_RESERVE_FLUSH_ALL);
840863
used = space_info->bytes_used + space_info->bytes_reserved +
841864
space_info->bytes_readonly + global_rsv_size;
842-
if (used < space_info->total_bytes)
843-
thresh += space_info->total_bytes - used;
865+
if (used < total)
866+
thresh += total - used;
844867
thresh >>= space_info->clamp;
845868

846869
used = space_info->bytes_pinned;
@@ -1557,7 +1580,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info,
15571580
* can_overcommit() to ensure we can overcommit to continue.
15581581
*/
15591582
if (!pending_tickets &&
1560-
((used + orig_bytes <= space_info->total_bytes) ||
1583+
((used + orig_bytes <= writable_total_bytes(fs_info, space_info)) ||
15611584
btrfs_can_overcommit(fs_info, space_info, orig_bytes, flush))) {
15621585
btrfs_space_info_update_bytes_may_use(fs_info, space_info,
15631586
orig_bytes);

fs/btrfs/space-info.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ struct btrfs_space_info {
1919
u64 bytes_may_use; /* number of bytes that may be used for
2020
delalloc/allocations */
2121
u64 bytes_readonly; /* total bytes that are read only */
22+
/* Total bytes in the space, but only accounts active block groups. */
23+
u64 active_total_bytes;
2224
u64 bytes_zone_unusable; /* total bytes that are unusable until
2325
resetting the device zone */
2426

@@ -124,7 +126,7 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info);
124126
void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags,
125127
u64 total_bytes, u64 bytes_used,
126128
u64 bytes_readonly, u64 bytes_zone_unusable,
127-
struct btrfs_space_info **space_info);
129+
bool active, struct btrfs_space_info **space_info);
128130
void btrfs_update_space_info_chunk_size(struct btrfs_space_info *space_info,
129131
u64 chunk_size);
130132
struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info,

fs/btrfs/zoned.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,6 +1849,7 @@ struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info,
18491849
bool btrfs_zone_activate(struct btrfs_block_group *block_group)
18501850
{
18511851
struct btrfs_fs_info *fs_info = block_group->fs_info;
1852+
struct btrfs_space_info *space_info = block_group->space_info;
18521853
struct map_lookup *map;
18531854
struct btrfs_device *device;
18541855
u64 physical;
@@ -1860,6 +1861,7 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
18601861

18611862
map = block_group->physical_map;
18621863

1864+
spin_lock(&space_info->lock);
18631865
spin_lock(&block_group->lock);
18641866
if (block_group->zone_is_active) {
18651867
ret = true;
@@ -1888,7 +1890,10 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
18881890

18891891
/* Successfully activated all the zones */
18901892
block_group->zone_is_active = 1;
1893+
space_info->active_total_bytes += block_group->length;
18911894
spin_unlock(&block_group->lock);
1895+
btrfs_try_granting_tickets(fs_info, space_info);
1896+
spin_unlock(&space_info->lock);
18921897

18931898
/* For the active block group list */
18941899
btrfs_get_block_group(block_group);
@@ -1901,6 +1906,7 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
19011906

19021907
out_unlock:
19031908
spin_unlock(&block_group->lock);
1909+
spin_unlock(&space_info->lock);
19041910
return ret;
19051911
}
19061912

0 commit comments

Comments
 (0)