Commit d346e098 authored by Qu Wenruo's avatar Qu Wenruo Committed by Kleber Sacilotto de Souza

btrfs: relocation: Only remove reloc rb_trees if reloc control has been initialized

BugLink: https://bugs.launchpad.net/bugs/1797563

[ Upstream commit 389305b2 ]

Invalid reloc tree can cause kernel NULL pointer dereference when btrfs
does some cleanup of the reloc roots.

It turns out that fs_info::reloc_ctl can be NULL in
btrfs_recover_relocation() as we allocate relocation control after all
reloc roots have been verified.
So when we hit: note, we haven't called set_reloc_control() thus
fs_info::reloc_ctl is still NULL.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=199833Reported-by: default avatarXu Wen <wen.xu@gatech.edu>
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Tested-by: default avatarGu Jinxiang <gujx@cn.fujitsu.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarSasha Levin <alexander.levin@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 91627a0f
...@@ -1318,18 +1318,19 @@ static void __del_reloc_root(struct btrfs_root *root) ...@@ -1318,18 +1318,19 @@ static void __del_reloc_root(struct btrfs_root *root)
struct mapping_node *node = NULL; struct mapping_node *node = NULL;
struct reloc_control *rc = root->fs_info->reloc_ctl; struct reloc_control *rc = root->fs_info->reloc_ctl;
spin_lock(&rc->reloc_root_tree.lock); if (rc) {
rb_node = tree_search(&rc->reloc_root_tree.rb_root, spin_lock(&rc->reloc_root_tree.lock);
root->node->start); rb_node = tree_search(&rc->reloc_root_tree.rb_root,
if (rb_node) { root->node->start);
node = rb_entry(rb_node, struct mapping_node, rb_node); if (rb_node) {
rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); node = rb_entry(rb_node, struct mapping_node, rb_node);
rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
}
spin_unlock(&rc->reloc_root_tree.lock);
if (!node)
return;
BUG_ON((struct btrfs_root *)node->data != root);
} }
spin_unlock(&rc->reloc_root_tree.lock);
if (!node)
return;
BUG_ON((struct btrfs_root *)node->data != root);
spin_lock(&root->fs_info->trans_lock); spin_lock(&root->fs_info->trans_lock);
list_del_init(&root->root_list); list_del_init(&root->root_list);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment