[ Sasha's backport helper bot ] Hi, The upstream commit SHA1 provided is correct: bb3868033a4cccff7be57e9145f2117cbdc91c11 WARNING: Author mismatch between patch and upstream commit: Backport author: bin.lan.cn@xxxxxxxxxxxxxxxxx Commit author: Filipe Manana <fdmanana@xxxxxxxx> Status in newer kernel trees: 6.12.y | Present (exact SHA1) 6.11.y | Present (exact SHA1) 6.6.y | Not found Note: The patch differs from the upstream commit: --- 1: bb3868033a4cc ! 1: 7b3a3b03bd7a2 btrfs: do not BUG_ON() when freeing tree block after error @@ Metadata ## Commit message ## btrfs: do not BUG_ON() when freeing tree block after error + [ Upstream commit bb3868033a4cccff7be57e9145f2117cbdc91c11 ] + When freeing a tree block, at btrfs_free_tree_block(), if we fail to create a delayed reference we don't deal with the error and just do a BUG_ON(). The error most likely to happen is -ENOMEM, and we have a @@ Commit message Signed-off-by: Filipe Manana <fdmanana@xxxxxxxx> Reviewed-by: David Sterba <dsterba@xxxxxxxx> Signed-off-by: David Sterba <dsterba@xxxxxxxx> + [ Resolve minor conflicts ] + Signed-off-by: Bin Lan <bin.lan.cn@xxxxxxxxxxxxx> ## fs/btrfs/ctree.c ## -@@ fs/btrfs/ctree.c: int btrfs_force_cow_block(struct btrfs_trans_handle *trans, +@@ fs/btrfs/ctree.c: static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, atomic_inc(&cow->refs); rcu_assign_pointer(root->node, cow); @@ fs/btrfs/ctree.c: int btrfs_force_cow_block(struct btrfs_trans_handle *trans, } else { WARN_ON(trans->transid != btrfs_header_generation(parent)); ret = btrfs_tree_mod_log_insert_key(parent, parent_slot, -@@ fs/btrfs/ctree.c: int btrfs_force_cow_block(struct btrfs_trans_handle *trans, +@@ fs/btrfs/ctree.c: static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, return ret; } } @@ fs/btrfs/ctree.c: int btrfs_force_cow_block(struct btrfs_trans_handle *trans, @@ fs/btrfs/ctree.c: static noinline int balance_level(struct btrfs_trans_handle *trans, free_extent_buffer(mid); - root_sub_used_bytes(root); + root_sub_used(root, mid->len); - btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1); + ret = btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1); /* once for the root ptr */ @@ fs/btrfs/ctree.c: static noinline int balance_level(struct btrfs_trans_handle *t @@ fs/btrfs/ctree.c: static noinline int balance_level(struct btrfs_trans_handle *trans, goto out; } - root_sub_used_bytes(root); + root_sub_used(root, right->len); - btrfs_free_tree_block(trans, btrfs_root_id(root), right, -- 0, 1); -+ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), -+ right, 0, 1); ++ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), right, + 0, 1); free_extent_buffer_stale(right); right = NULL; + if (ret < 0) { @@ fs/btrfs/ctree.c: static noinline int balance_level(struct btrfs_trans_handle *t @@ fs/btrfs/ctree.c: static noinline int balance_level(struct btrfs_trans_handle *trans, goto out; } - root_sub_used_bytes(root); + root_sub_used(root, mid->len); - btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1); + ret = btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1); free_extent_buffer_stale(mid); @@ fs/btrfs/ctree.c: static noinline int insert_new_root(struct btrfs_trans_handle free_extent_buffer(c); return ret; @@ fs/btrfs/ctree.c: static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, - root_sub_used_bytes(root); + root_sub_used(root, leaf->len); atomic_inc(&leaf->refs); - btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1); @@ fs/btrfs/extent-tree.c: static noinline int check_ref_cleanup(struct btrfs_trans + u64 parent, int last_ref) { struct btrfs_fs_info *fs_info = trans->fs_info; - struct btrfs_block_group *bg; + struct btrfs_ref generic_ref = { 0 }; @@ fs/btrfs/extent-tree.c: void btrfs_free_tree_block(struct btrfs_trans_handle *trans, - btrfs_init_tree_ref(&generic_ref, btrfs_header_level(buf), 0, false); + if (root_id != BTRFS_TREE_LOG_OBJECTID) { btrfs_ref_tree_mod(fs_info, &generic_ref); ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, NULL); - BUG_ON(ret); /* -ENOMEM */ @@ fs/btrfs/extent-tree.c: void btrfs_free_tree_block(struct btrfs_trans_handle *tr + return ret; } - if (!last_ref) -- return; -+ return 0; - - if (btrfs_header_generation(buf) != trans->transid) - goto out; + if (last_ref && btrfs_header_generation(buf) == trans->transid) { @@ fs/btrfs/extent-tree.c: void btrfs_free_tree_block(struct btrfs_trans_handle *trans, - * matter anymore. - */ - clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags); + */ + clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags); + } + return 0; } @@ fs/btrfs/extent-tree.c: static noinline int walk_up_proc(struct btrfs_trans_hand ## fs/btrfs/extent-tree.h ## @@ fs/btrfs/extent-tree.h: struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, + int level, u64 hint, u64 empty_size, - u64 reloc_src_root, enum btrfs_lock_nesting nest); -void btrfs_free_tree_block(struct btrfs_trans_handle *trans, - u64 root_id, @@ fs/btrfs/free-space-tree.c: int btrfs_delete_free_space_tree(struct btrfs_fs_inf + } return btrfs_commit_transaction(trans); - } + ## fs/btrfs/ioctl.c ## @@ fs/btrfs/ioctl.c: static noinline int create_subvol(struct mnt_idmap *idmap, --- Results of testing on various branches: | Branch | Patch Apply | Build Test | |---------------------------|-------------|------------| | stable/linux-6.6.y | Success | Success |