| From 1ffe9898097f89f7083be472a0601b67b9eabd3b Mon Sep 17 00:00:00 2001 |
| From: Josef Bacik <josef@toxicpanda.com> |
| Date: Thu, 2 Apr 2020 15:51:18 -0400 |
| Subject: [PATCH] btrfs: check commit root generation in should_ignore_root |
| |
| commit 4d4225fc228e46948486d8b8207955f0c031b92e upstream. |
| |
| Previously we would set the reloc root's last snapshot to transid - 1. |
| However there was a problem with doing this, and we changed it to |
| setting the last snapshot to the generation of the commit node of the fs |
| root. |
| |
| This however broke should_ignore_root(). The assumption is that if we |
| are in a generation newer than when the reloc root was created, then we |
| would find the reloc root through normal backref lookups, and thus can |
| ignore any fs roots we find with an old enough reloc root. |
| |
| Now that the last snapshot could be considerably further in the past |
| than before, we'd end up incorrectly ignoring an fs root. Thus we'd |
| find no nodes for the bytenr we were searching for, and we'd fail to |
| relocate anything. We'd loop through the relocate code again and see |
| that there were still used space in that block group, attempt to |
| relocate those bytenr's again, fail in the same way, and just loop like |
| this forever. This is tricky in that we have to not modify the fs root |
| at all during this time, so we need to have a block group that has data |
| in this fs root that is not shared by any other root, which is why this |
| has been difficult to reproduce. |
| |
| Fixes: 054570a1dc94 ("Btrfs: fix relocation incorrectly dropping data references") |
| CC: stable@vger.kernel.org # 4.9+ |
| Reviewed-by: Filipe Manana <fdmanana@suse.com> |
| Signed-off-by: Josef Bacik <josef@toxicpanda.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c |
| index f3876884e714..b2446101d5f0 100644 |
| --- a/fs/btrfs/relocation.c |
| +++ b/fs/btrfs/relocation.c |
| @@ -527,8 +527,8 @@ static int should_ignore_root(struct btrfs_root *root) |
| if (!reloc_root) |
| return 0; |
| |
| - if (btrfs_root_last_snapshot(&reloc_root->root_item) == |
| - root->fs_info->running_transaction->transid - 1) |
| + if (btrfs_header_generation(reloc_root->commit_root) == |
| + root->fs_info->running_transaction->transid) |
| return 0; |
| /* |
| * if there is reloc tree and it was created in previous |
| -- |
| 2.7.4 |
| |