diff mbox series

[v2] btrfs: handle free space tree rebuild in multiple transactions

Message ID 648c181a4b3d2076ee838945232e3b87b5d575e7.1734582790.git.wqu@suse.com (mailing list archive)
State New
Headers show
Series [v2] btrfs: handle free space tree rebuild in multiple transactions | expand

Commit Message

Qu Wenruo Dec. 19, 2024, 4:34 a.m. UTC
During free space tree rebuild, we're holding a transaction handler for
the whole rebuild process.

This can lead to blocked task warning, e.g. btrfs-transaction kthread
(which is already created before btrfs_start_pre_rw_mount()) can be
waked up to join and commit the current transaction.

But the free space tree rebuild process may need to go through thousands
block groups, this will block btrfs-transaction kthread for a long time.

Fix the problem by calling btrfs_should_end_transaction() after each
block group, so that we won't hold the transaction handler too long.

And since the free-space-tree rebuild can be split into
multiple transactions, we need to consider the safety when the rebuild
process is interrupted.

Thankfully since we only set the FREE_SPACE_TREE compat_ro flag without
FREE_SPACE_TREE_VALID flag, even if the rebuild is interrupted, on the
next RW mount, we will still go rebuild the free space tree, by deleting
any items we have and re-starting the rebuild from scratch.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
Changelog:
v2:
- Use btrfs_should_end_transaction() instead of batching
  Which should be more reliable than batching.
---
 fs/btrfs/free-space-tree.c | 6 ++++++
 1 file changed, 6 insertions(+)

Comments

Filipe Manana Dec. 19, 2024, 2:22 p.m. UTC | #1
On Thu, Dec 19, 2024 at 4:35 AM Qu Wenruo <wqu@suse.com> wrote:
>
> During free space tree rebuild, we're holding a transaction handler for

handler -> handle

> the whole rebuild process.
>
> This can lead to blocked task warning, e.g. btrfs-transaction kthread
> (which is already created before btrfs_start_pre_rw_mount()) can be
> waked up to join and commit the current transaction.
>
> But the free space tree rebuild process may need to go through thousands
> block groups, this will block btrfs-transaction kthread for a long time.
>
> Fix the problem by calling btrfs_should_end_transaction() after each
> block group, so that we won't hold the transaction handler too long.

handler -> handle

We could also start the transaction kthread only after building the
free space tree,
it would avoid some transaction commits, saving IO and rotation of
backup roots in
the super block.

But with the free space tree being a default for quite a while now,
and this being
more likely only on very large filesystems, it's fine.

Reviewed-by: Filipe Manana <fdmanana@suse.com>

Thanks.

>
> And since the free-space-tree rebuild can be split into
> multiple transactions, we need to consider the safety when the rebuild
> process is interrupted.
>
> Thankfully since we only set the FREE_SPACE_TREE compat_ro flag without
> FREE_SPACE_TREE_VALID flag, even if the rebuild is interrupted, on the
> next RW mount, we will still go rebuild the free space tree, by deleting
> any items we have and re-starting the rebuild from scratch.
>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
> Changelog:
> v2:
> - Use btrfs_should_end_transaction() instead of batching
>   Which should be more reliable than batching.
> ---
>  fs/btrfs/free-space-tree.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
> index 7ba50e133921..2400fa5a5be4 100644
> --- a/fs/btrfs/free-space-tree.c
> +++ b/fs/btrfs/free-space-tree.c
> @@ -1350,6 +1350,12 @@ int btrfs_rebuild_free_space_tree(struct btrfs_fs_info *fs_info)
>                         btrfs_end_transaction(trans);
>                         return ret;
>                 }
> +               if (btrfs_should_end_transaction(trans)) {
> +                       btrfs_end_transaction(trans);
> +                       trans = btrfs_start_transaction(free_space_root, 1);
> +                       if (IS_ERR(trans))
> +                               return PTR_ERR(trans);
> +               }
>                 node = rb_next(node);
>         }
>
> --
> 2.47.1
>
>
diff mbox series

Patch

diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
index 7ba50e133921..2400fa5a5be4 100644
--- a/fs/btrfs/free-space-tree.c
+++ b/fs/btrfs/free-space-tree.c
@@ -1350,6 +1350,12 @@  int btrfs_rebuild_free_space_tree(struct btrfs_fs_info *fs_info)
 			btrfs_end_transaction(trans);
 			return ret;
 		}
+		if (btrfs_should_end_transaction(trans)) {
+			btrfs_end_transaction(trans);
+			trans = btrfs_start_transaction(free_space_root, 1);
+			if (IS_ERR(trans))
+				return PTR_ERR(trans);
+		}
 		node = rb_next(node);
 	}