From 7a12d8470e5fcdae3f8914ff52f7d19c7f9f0f3a Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Fri, 14 Sep 2018 15:49:44 +0800 Subject: [PATCH] btrfs-progs: Do metadata preallocation as long as we're not modifying extent tree In github issues, one user reports unexpected ENOSPC error if enabling datasum druing convert. After some investigation, it looks like that during ext2_saved/image creation, we could create large file extent whose size can be 128M (max data extent size). In that case, its csum block will be at least 128K. Under certain case we need to allocate extra metadata chunks to fulfill such space requirement. However we only do metadata prealloc if we're reserving extents for fs trees. (we use btrfs_root::ref_cows to determine whether we should do metadata prealloc, and that member is only set for fs trees). There is no explaination on why we only do metadata prealloc for file trees, but at least from my investigation, it could be related to avoid nested extent tree modication. At least extent reservation for csum tree shouldn't be a problem with metadata block group preallocation. So change the metadata block group preallocation check from "root->ref_cow" to "root->root_key.objectid != BTRFS_EXTENT_TREE_OBJECTID", and add some comment for it. Issue: #123 Signed-off-by: Qu Wenruo Signed-off-by: David Sterba --- extent-tree.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/extent-tree.c b/extent-tree.c index 8c9cdeff..283a6917 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -2506,7 +2506,12 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans, profile = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; } - if (root->ref_cows) { + /* + * Do metadata preallocation if we're not modifying the extent tree. + * Allocating chunk while modifying extent tree could lead to transid + * mismatch, as do_chunk_alloc() could commit transaction. + */ + if (root->root_key.objectid != BTRFS_EXTENT_TREE_OBJECTID) { if (!(profile & BTRFS_BLOCK_GROUP_METADATA)) { ret = do_chunk_alloc(trans, info, num_bytes,