From: Qu WenRuo Date: Tue, 10 Dec 2019 08:55:00 +0000 (+0000) Subject: Snapshot create NULL pointer dereference X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2bee227a885c321eb5c5d2a3596e5cceb7b05692;p=linux Snapshot create NULL pointer dereference --YVy2ZwhygmFTft9qf4qxad0AgZTGdqI77 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: quoted-printable Hi, With reproducer, I got my new fixes for all the mess I created. Yep, that's definitely that lifespan patch caused all these problems. I got a fix for it to pass the super fast crash script, would you please try to test it? Currently the only problem is, I have observed cases where metadata balance could fall into dead loop. But since it's also reported before, so I'm not sure if it's my fix worsen the situation. And since I have only seen 3 different KASAN reports, with some not reported by you, so I'm not 100% sure if all cases are covered. Your test would help a lot to verify the fix. Thanks, Qu (cherry picked from commit d595e06eefca762e4c5937d9a83b300f7c06ff31) --- diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 26b605a49449..9ca8d11b1965 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -529,6 +529,9 @@ static int should_ignore_root(struct btrfs_root *root) if (!reloc_root) return 0; + if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state)) + return 1; + if (btrfs_root_last_snapshot(&reloc_root->root_item) == root->fs_info->running_transaction->transid - 1) return 0; @@ -4729,7 +4732,8 @@ void btrfs_reloc_pre_snapshot(struct btrfs_pending_snapshot *pending, struct btrfs_root *root = pending->root; struct reloc_control *rc = root->fs_info->reloc_ctl; - if (!root->reloc_root || !rc) + if (!root->reloc_root || !rc || test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, + &root->state)) return; if (!rc->merge_reloc_tree) @@ -4763,7 +4767,8 @@ int btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans, struct reloc_control *rc = root->fs_info->reloc_ctl; int ret; - if (!root->reloc_root || !rc) + if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state) || + !root->reloc_root || !rc) return 0; rc = root->fs_info->reloc_ctl;