| From 2d36bb2a2435a09dabc772d1d36c6f94cf28df9c Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 14 Jul 2020 09:12:20 +0800 |
| Subject: btrfs: qgroup: free per-trans reserved space when a subvolume gets |
| dropped |
| |
| From: Qu Wenruo <wqu@suse.com> |
| |
| [ Upstream commit a3cf0e4342b6af9e6b34a4b913c630fbd03a82ea ] |
| |
| [BUG] |
| Sometime fsstress could lead to qgroup warning for case like |
| generic/013: |
| |
| BTRFS warning (device dm-3): qgroup 0/259 has unreleased space, type 1 rsv 81920 |
| ------------[ cut here ]------------ |
| WARNING: CPU: 9 PID: 24535 at fs/btrfs/disk-io.c:4142 close_ctree+0x1dc/0x323 [btrfs] |
| Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 |
| RIP: 0010:close_ctree+0x1dc/0x323 [btrfs] |
| Call Trace: |
| btrfs_put_super+0x15/0x17 [btrfs] |
| generic_shutdown_super+0x72/0x110 |
| kill_anon_super+0x18/0x30 |
| btrfs_kill_super+0x17/0x30 [btrfs] |
| deactivate_locked_super+0x3b/0xa0 |
| deactivate_super+0x40/0x50 |
| cleanup_mnt+0x135/0x190 |
| __cleanup_mnt+0x12/0x20 |
| task_work_run+0x64/0xb0 |
| __prepare_exit_to_usermode+0x1bc/0x1c0 |
| __syscall_return_slowpath+0x47/0x230 |
| do_syscall_64+0x64/0xb0 |
| entry_SYSCALL_64_after_hwframe+0x44/0xa9 |
| ---[ end trace 6c341cdf9b6cc3c1 ]--- |
| BTRFS error (device dm-3): qgroup reserved space leaked |
| |
| While that subvolume 259 is no longer in that filesystem. |
| |
| [CAUSE] |
| Normally per-trans qgroup reserved space is freed when a transaction is |
| committed, in commit_fs_roots(). |
| |
| However for completely dropped subvolume, that subvolume is completely |
| gone, thus is no longer in the fs_roots_radix, and its per-trans |
| reserved qgroup will never be freed. |
| |
| Since the subvolume is already gone, leaked per-trans space won't cause |
| any trouble for end users. |
| |
| [FIX] |
| Just call btrfs_qgroup_free_meta_all_pertrans() before a subvolume is |
| completely dropped. |
| |
| Signed-off-by: Qu Wenruo <wqu@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/btrfs/extent-tree.c | 8 ++++++++ |
| 1 file changed, 8 insertions(+) |
| |
| diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c |
| index 54a64d1e18c6b..7c86188b33d43 100644 |
| --- a/fs/btrfs/extent-tree.c |
| +++ b/fs/btrfs/extent-tree.c |
| @@ -5481,6 +5481,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc) |
| } |
| } |
| |
| + /* |
| + * This subvolume is going to be completely dropped, and won't be |
| + * recorded as dirty roots, thus pertrans meta rsv will not be freed at |
| + * commit transaction time. So free it here manually. |
| + */ |
| + btrfs_qgroup_convert_reserved_meta(root, INT_MAX); |
| + btrfs_qgroup_free_meta_all_pertrans(root); |
| + |
| if (test_bit(BTRFS_ROOT_IN_RADIX, &root->state)) |
| btrfs_add_dropped_root(trans, root); |
| else |
| -- |
| 2.25.1 |
| |