From: David Sterba Date: Thu, 25 Jun 2020 10:35:28 +0000 (+0200) Subject: btrfs: allow use of global block reserve for balance item deletion X-Git-Tag: Ubuntu-5.4.0-49.53~656 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=34428da66d1e822700963c45856144c09e7a7854;p=mirror_ubuntu-focal-kernel.git btrfs: allow use of global block reserve for balance item deletion BugLink: https://bugs.launchpad.net/bugs/1892899 commit 3502a8c0dc1bd4b4970b59b06e348f22a1c05581 upstream. On a filesystem with exhausted metadata, but still enough to start balance, it's possible to hit this error: [324402.053842] BTRFS info (device loop0): 1 enospc errors during balance [324402.060769] BTRFS info (device loop0): balance: ended with status: -28 [324402.172295] BTRFS: error (device loop0) in reset_balance_state:3321: errno=-28 No space left It fails inside reset_balance_state and turns the filesystem to read-only, which is unnecessary and should be fixed too, but the problem is caused by lack for space when the balance item is deleted. This is a one-time operation and from the same rank as unlink that is allowed to use the global block reserve. So do the same for the balance item. Status of the filesystem (100GiB) just after the balance fails: $ btrfs fi df mnt Data, single: total=80.01GiB, used=38.58GiB System, single: total=4.00MiB, used=16.00KiB Metadata, single: total=19.99GiB, used=19.48GiB GlobalReserve, single: total=512.00MiB, used=50.11MiB CC: stable@vger.kernel.org # 4.4+ Reviewed-by: Johannes Thumshirn Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kamal Mostafa Signed-off-by: Kelsey Skunberg --- diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 1e6e3c1d97df..a9c84595fb24 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -3283,7 +3283,7 @@ static int insert_balance_item(struct btrfs_fs_info *fs_info, if (!path) return -ENOMEM; - trans = btrfs_start_transaction(root, 0); + trans = btrfs_start_transaction_fallback_global_rsv(root, 0); if (IS_ERR(trans)) { btrfs_free_path(path); return PTR_ERR(trans);