@@ -295,7 +295,7 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
295295void 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+
372390int 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 );
0 commit comments