]> git.baikalelectronics.ru Git - kernel.git/commitdiff
btrfs: fix space cache inconsistency after error loading it from disk
authorFilipe Manana <fdmanana@suse.com>
Thu, 4 May 2023 11:04:18 +0000 (12:04 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 May 2023 11:44:04 +0000 (12:44 +0100)
[ Upstream commit 0004ff15ea26015a0a3a6182dca3b9d1df32e2b7 ]

When loading a free space cache from disk, at __load_free_space_cache(),
if we fail to insert a bitmap entry, we still increment the number of
total bitmaps in the btrfs_free_space_ctl structure, which is incorrect
since we failed to add the bitmap entry. On error we then empty the
cache by calling __btrfs_remove_free_space_cache(), which will result
in getting the total bitmaps counter set to 1.

A failure to load a free space cache is not critical, so if a failure
happens we just rebuild the cache by scanning the extent tree, which
happens at block-group.c:caching_thread(). Yet the failure will result
in having the total bitmaps of the btrfs_free_space_ctl always bigger
by 1 then the number of bitmap entries we have. So fix this by having
the total bitmaps counter be incremented only if we successfully added
the bitmap entry.

Fixes: 63f86f1f7733 ("Btrfs: add a io_ctl struct and helpers for dealing with the space cache")
Reviewed-by: Anand Jain <anand.jain@oracle.com>
CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/btrfs/free-space-cache.c

index d2d32fed8f2e955b1af11943487c3ee6fa14a236..0cb93f73acb2d32a9a9a3daebce44d3de6ea220e 100644 (file)
@@ -784,15 +784,16 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
                        }
                        spin_lock(&ctl->tree_lock);
                        ret = link_free_space(ctl, e);
-                       ctl->total_bitmaps++;
-                       ctl->op->recalc_thresholds(ctl);
-                       spin_unlock(&ctl->tree_lock);
                        if (ret) {
+                               spin_unlock(&ctl->tree_lock);
                                btrfs_err(fs_info,
                                        "Duplicate entries in free space cache, dumping");
                                kmem_cache_free(btrfs_free_space_cachep, e);
                                goto free_cache;
                        }
+                       ctl->total_bitmaps++;
+                       ctl->op->recalc_thresholds(ctl);
+                       spin_unlock(&ctl->tree_lock);
                        list_add_tail(&e->list, &bitmaps);
                }