Skip to content

Commit 6822b3f

Browse files
fdmananakdave
authored andcommitted
btrfs: do not BUG_ON after failure to migrate space during truncation
During truncation we reserve 2 metadata units when starting a transaction (reserved space goes to fs_info->trans_block_rsv) and then attempt to migrate 1 unit (min_size bytes) from fs_info->trans_block_rsv into the local block reserve. If we ever fail we trigger a BUG_ON(), which should never happen, because we reserved 2 units. However if we happen to fail for some reason, we don't need to be so dire and hit a BUG_ON(), we can just error out the truncation and, since this is highly unexpected, surround the error check with WARN_ON(), to get an informative stack trace and tag the branh as 'unlikely'. Also make the 'min_size' variable const, since it's not supposed to ever change and any accidental change could possibly make the space migration not so unlikely to fail. Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent df9f278 commit 6822b3f

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

fs/btrfs/inode.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8344,7 +8344,7 @@ static int btrfs_truncate(struct btrfs_inode *inode, bool skip_writeback)
83448344
int ret;
83458345
struct btrfs_trans_handle *trans;
83468346
u64 mask = fs_info->sectorsize - 1;
8347-
u64 min_size = btrfs_calc_metadata_size(fs_info, 1);
8347+
const u64 min_size = btrfs_calc_metadata_size(fs_info, 1);
83488348

83498349
if (!skip_writeback) {
83508350
ret = btrfs_wait_ordered_range(&inode->vfs_inode,
@@ -8401,7 +8401,15 @@ static int btrfs_truncate(struct btrfs_inode *inode, bool skip_writeback)
84018401
/* Migrate the slack space for the truncate to our reserve */
84028402
ret = btrfs_block_rsv_migrate(&fs_info->trans_block_rsv, rsv,
84038403
min_size, false);
8404-
BUG_ON(ret);
8404+
/*
8405+
* We have reserved 2 metadata units when we started the transaction and
8406+
* min_size matches 1 unit, so this should never fail, but if it does,
8407+
* it's not critical we just fail truncation.
8408+
*/
8409+
if (WARN_ON(ret)) {
8410+
btrfs_end_transaction(trans);
8411+
goto out;
8412+
}
84058413

84068414
trans->block_rsv = rsv;
84078415

@@ -8449,7 +8457,14 @@ static int btrfs_truncate(struct btrfs_inode *inode, bool skip_writeback)
84498457
btrfs_block_rsv_release(fs_info, rsv, -1, NULL);
84508458
ret = btrfs_block_rsv_migrate(&fs_info->trans_block_rsv,
84518459
rsv, min_size, false);
8452-
BUG_ON(ret); /* shouldn't happen */
8460+
/*
8461+
* We have reserved 2 metadata units when we started the
8462+
* transaction and min_size matches 1 unit, so this should never
8463+
* fail, but if it does, it's not critical we just fail truncation.
8464+
*/
8465+
if (WARN_ON(ret))
8466+
break;
8467+
84538468
trans->block_rsv = rsv;
84548469
}
84558470

0 commit comments

Comments
 (0)