Btrfs: use global reserve when deleting unused block group after ENOSPC
It's possible to reach a state where the cleaner kthread isn't able to start a transaction to delete an unused block group due to lack of enough free metadata space and due to lack of unallocated device space to allocate a new metadata block group as well. If this happens try to use space from the global block group reserve just like we do for unlink operations, so that we don't reach a permanent state where starting a transaction for filesystem operations (file creation, renames, etc) keeps failing with -ENOSPC. Such an unfortunate state was observed on a machine where over a dozen unused data block groups existed and the cleaner kthread was failing to delete them due to ENOSPC error when attempting to start a transaction, and even running balance with a -dusage=0 filter failed with ENOSPC as well. Also unmounting and mounting again the filesystem didn't help. Allowing the cleaner kthread to use the global block reserve to delete the unused data block groups fixed the problem. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Jeff Mahoney <jeffm@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:

committed by
Chris Mason

parent
89b6c8d1e4
commit
8eab77ff16
@@ -10256,6 +10256,17 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct btrfs_trans_handle *
|
||||
btrfs_start_trans_remove_block_group(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
/*
|
||||
* 1 unit for adding the free space inode's orphan (located in the tree
|
||||
* of tree roots).
|
||||
*/
|
||||
return btrfs_start_transaction_fallback_global_rsv(fs_info->extent_root,
|
||||
1, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the unused_bgs list and remove any that don't have any allocated
|
||||
* space inside of them.
|
||||
@@ -10322,8 +10333,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
|
||||
* Want to do this before we do anything else so we can recover
|
||||
* properly if we fail to join the transaction.
|
||||
*/
|
||||
/* 1 for btrfs_orphan_reserve_metadata() */
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
trans = btrfs_start_trans_remove_block_group(fs_info);
|
||||
if (IS_ERR(trans)) {
|
||||
btrfs_dec_block_group_ro(root, block_group);
|
||||
ret = PTR_ERR(trans);
|
||||
|
Reference in New Issue
Block a user