btrfs-progs: properly reserve metadata space for bgt conversion

There is a bug report [1] that btrfstune failed to convert to block
group tree.  The bug report shows some very weird call trace, mostly
fail at free space tree code.

One of the concern is the failed conversion may be caused by exhausted
metadata space.  In that case, we're doing quite some metadata
operations (one transaction to convert 64 block groups in one go).

But for each transaction we have only reserved the metadata for one
block group conversion (1 block for extent tree and 1 block for block
group tree, this excludes free space and extent tree operations, as they
should go global reserve).

Although we're not 100% sure about the failed conversion, at least we
should handle the metadata reservation correctly, by properly reserve
the needed space for the batch, and reduce the batch size just in case
there isn't much metadata space left.

[1] https://lore.kernel.org/linux-btrfs/3c93d0b5-a8cb-ebe3-f8d6-76ea6340f23e@gmail.com/

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2023-10-03 10:39:18 +10:30 committed by David Sterba
parent 5ceec3bcf9
commit b874fe6dda

View File

@ -28,7 +28,7 @@
#include "tune/tune.h"
/* After this many block groups we need to commit transaction. */
#define BLOCK_GROUP_BATCH 64
#define BLOCK_GROUP_BATCH 16
int convert_to_bg_tree(struct btrfs_fs_info *fs_info)
{
@ -71,7 +71,8 @@ int convert_to_bg_tree(struct btrfs_fs_info *fs_info)
error_msg(ERROR_MSG_COMMIT_TRANS, "new bg root: %d", ret);
goto error;
}
trans = btrfs_start_transaction(fs_info->tree_root, 2);
trans = btrfs_start_transaction(fs_info->tree_root,
2 * BLOCK_GROUP_BATCH);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
errno = -ret;
@ -119,7 +120,8 @@ iterate_bgs:
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
return ret;
}
trans = btrfs_start_transaction(fs_info->tree_root, 2);
trans = btrfs_start_transaction(fs_info->tree_root,
2 * BLOCK_GROUP_BATCH);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
errno = -ret;
@ -181,7 +183,8 @@ int convert_to_extent_tree(struct btrfs_fs_info *fs_info)
error_msg(ERROR_MSG_COMMIT_TRANS, "new extent tree root: %m");
goto error;
}
trans = btrfs_start_transaction(fs_info->tree_root, 2);
trans = btrfs_start_transaction(fs_info->tree_root,
2 * BLOCK_GROUP_BATCH);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
errno = -ret;
@ -227,7 +230,8 @@ iterate_bgs:
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
return ret;
}
trans = btrfs_start_transaction(fs_info->tree_root, 2);
trans = btrfs_start_transaction(fs_info->tree_root,
2 * BLOCK_GROUP_BATCH);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
errno = -ret;