Skip to content

Commit a30a3d2

Browse files
josefbacikkdave
authored andcommitted
btrfs: take overcommit into account in inc_block_group_ro
inc_block_group_ro does a calculation to see if we have enough room left over if we mark this block group as read only in order to see if it's ok to mark the block group as read only. The problem is this calculation _only_ works for data, where our used is always less than our total. For metadata we will overcommit, so this will almost always fail for metadata. Fix this by exporting btrfs_can_overcommit, and then see if we have enough space to remove the remaining free space in the block group we are trying to mark read only. If we do then we can mark this block group as read only. Reviewed-by: Qu Wenruo <[email protected]> Signed-off-by: Josef Bacik <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent a7a63ac commit a30a3d2

File tree

3 files changed

+39
-19
lines changed

3 files changed

+39
-19
lines changed

fs/btrfs/block-group.c

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,6 @@ static int inc_block_group_ro(struct btrfs_block_group *cache, int force)
11911191
{
11921192
struct btrfs_space_info *sinfo = cache->space_info;
11931193
u64 num_bytes;
1194-
u64 sinfo_used;
11951194
int ret = -ENOSPC;
11961195

11971196
spin_lock(&sinfo->lock);
@@ -1205,29 +1204,45 @@ static int inc_block_group_ro(struct btrfs_block_group *cache, int force)
12051204

12061205
num_bytes = cache->length - cache->reserved - cache->pinned -
12071206
cache->bytes_super - cache->used;
1208-
sinfo_used = btrfs_space_info_used(sinfo, true);
12091207

12101208
/*
1211-
* sinfo_used + num_bytes should always <= sinfo->total_bytes.
1212-
*
1213-
* Here we make sure if we mark this bg RO, we still have enough
1214-
* free space as buffer.
1209+
* Data never overcommits, even in mixed mode, so do just the straight
1210+
* check of left over space in how much we have allocated.
12151211
*/
1216-
if (force || (sinfo_used + num_bytes <= sinfo->total_bytes)) {
1212+
if (force) {
1213+
ret = 0;
1214+
} else if (sinfo->flags & BTRFS_BLOCK_GROUP_DATA) {
1215+
u64 sinfo_used = btrfs_space_info_used(sinfo, true);
1216+
1217+
/*
1218+
* Here we make sure if we mark this bg RO, we still have enough
1219+
* free space as buffer.
1220+
*/
1221+
if (sinfo_used + num_bytes <= sinfo->total_bytes)
1222+
ret = 0;
1223+
} else {
1224+
/*
1225+
* We overcommit metadata, so we need to do the
1226+
* btrfs_can_overcommit check here, and we need to pass in
1227+
* BTRFS_RESERVE_NO_FLUSH to give ourselves the most amount of
1228+
* leeway to allow us to mark this block group as read only.
1229+
*/
1230+
if (btrfs_can_overcommit(cache->fs_info, sinfo, num_bytes,
1231+
BTRFS_RESERVE_NO_FLUSH))
1232+
ret = 0;
1233+
}
1234+
1235+
if (!ret) {
12171236
sinfo->bytes_readonly += num_bytes;
12181237
cache->ro++;
12191238
list_add_tail(&cache->ro_list, &sinfo->ro_bgs);
1220-
ret = 0;
12211239
}
12221240
out:
12231241
spin_unlock(&cache->lock);
12241242
spin_unlock(&sinfo->lock);
12251243
if (ret == -ENOSPC && btrfs_test_opt(cache->fs_info, ENOSPC_DEBUG)) {
12261244
btrfs_info(cache->fs_info,
12271245
"unable to make block group %llu ro", cache->start);
1228-
btrfs_info(cache->fs_info,
1229-
"sinfo_used=%llu bg_num_bytes=%llu",
1230-
sinfo_used, num_bytes);
12311246
btrfs_dump_space_info(cache->fs_info, cache->space_info, 0, 0);
12321247
}
12331248
return ret;

fs/btrfs/space-info.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,9 @@ static inline u64 calc_global_rsv_need_space(struct btrfs_block_rsv *global)
159159
return (global->size << 1);
160160
}
161161

162-
static int can_overcommit(struct btrfs_fs_info *fs_info,
163-
struct btrfs_space_info *space_info, u64 bytes,
164-
enum btrfs_reserve_flush_enum flush)
162+
int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
163+
struct btrfs_space_info *space_info, u64 bytes,
164+
enum btrfs_reserve_flush_enum flush)
165165
{
166166
u64 profile;
167167
u64 avail;
@@ -226,7 +226,8 @@ void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info,
226226

227227
/* Check and see if our ticket can be satisified now. */
228228
if ((used + ticket->bytes <= space_info->total_bytes) ||
229-
can_overcommit(fs_info, space_info, ticket->bytes, flush)) {
229+
btrfs_can_overcommit(fs_info, space_info, ticket->bytes,
230+
flush)) {
230231
btrfs_space_info_update_bytes_may_use(fs_info,
231232
space_info,
232233
ticket->bytes);
@@ -639,13 +640,14 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info,
639640
return to_reclaim;
640641

641642
to_reclaim = min_t(u64, num_online_cpus() * SZ_1M, SZ_16M);
642-
if (can_overcommit(fs_info, space_info, to_reclaim,
643-
BTRFS_RESERVE_FLUSH_ALL))
643+
if (btrfs_can_overcommit(fs_info, space_info, to_reclaim,
644+
BTRFS_RESERVE_FLUSH_ALL))
644645
return 0;
645646

646647
used = btrfs_space_info_used(space_info, true);
647648

648-
if (can_overcommit(fs_info, space_info, SZ_1M, BTRFS_RESERVE_FLUSH_ALL))
649+
if (btrfs_can_overcommit(fs_info, space_info, SZ_1M,
650+
BTRFS_RESERVE_FLUSH_ALL))
649651
expected = div_factor_fine(space_info->total_bytes, 95);
650652
else
651653
expected = div_factor_fine(space_info->total_bytes, 90);
@@ -1004,7 +1006,7 @@ static int __reserve_metadata_bytes(struct btrfs_fs_info *fs_info,
10041006
*/
10051007
if (!pending_tickets &&
10061008
((used + orig_bytes <= space_info->total_bytes) ||
1007-
can_overcommit(fs_info, space_info, orig_bytes, flush))) {
1009+
btrfs_can_overcommit(fs_info, space_info, orig_bytes, flush))) {
10081010
btrfs_space_info_update_bytes_may_use(fs_info, space_info,
10091011
orig_bytes);
10101012
ret = 0;

fs/btrfs/space-info.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ int btrfs_reserve_metadata_bytes(struct btrfs_root *root,
127127
enum btrfs_reserve_flush_enum flush);
128128
void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info,
129129
struct btrfs_space_info *space_info);
130+
int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
131+
struct btrfs_space_info *space_info, u64 bytes,
132+
enum btrfs_reserve_flush_enum flush);
130133

131134
static inline void btrfs_space_info_free_bytes_may_use(
132135
struct btrfs_fs_info *fs_info,

0 commit comments

Comments
 (0)