Since the allocation info of tree log node is not recorded to the extent
tree, calculate_alloc_pointer() cannot detect the node, so the pointer can
be over a tree node.

Replaying the log call btrfs_remove_free_space() for each node in the log
tree. So, advance the pointer after the node.

Reviewed-by: Josef Bacik <jo...@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.a...@wdc.com>
---
 fs/btrfs/free-space-cache.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 19c00118917a..c4ccfcb98aed 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -2619,8 +2619,22 @@ int btrfs_remove_free_space(struct btrfs_block_group 
*block_group,
        int ret;
        bool re_search = false;
 
-       if (btrfs_is_zoned(block_group->fs_info))
+       if (btrfs_is_zoned(block_group->fs_info)) {
+               /*
+                * This can happen with conventional zones when replaying
+                * log. Since the allocation info of tree-log nodes are
+                * not recorded to the extent-tree, calculate_alloc_pointer()
+                * failed to advance the allocation pointer after last
+                * allocated tree log node blocks.
+                *
+                * This function is called from
+                * btrfs_pin_extent_for_log_replay() when replaying the
+                * log. Advance the pointer not to overwrite the tree-log nodes.
+                */
+               if (block_group->alloc_offset < offset + bytes)
+                       block_group->alloc_offset = offset + bytes;
                return 0;
+       }
 
        spin_lock(&ctl->tree_lock);
 
-- 
2.27.0

Reply via email to