btrfs: warn on tree blocks which are not nodesize aligned
authorQu Wenruo <wqu@suse.com>
Thu, 24 Aug 2023 06:33:36 +0000 (14:33 +0800)
committerDavid Sterba <dsterba@suse.com>
Thu, 12 Oct 2023 14:44:09 +0000 (16:44 +0200)
A long time ago, we had some metadata chunks which started at sector
boundary but not aligned to nodesize boundary.

This led to some older filesystems which can have tree blocks only
aligned to sectorsize, but not nodesize.

Later 'btrfs check' gained the ability to detect and warn about such tree
blocks, and kernel fixed the chunk allocation behavior, nowadays those
tree blocks should be pretty rare.

But in the future, if we want to migrate metadata to folio, we cannot
have such tree blocks, as filemap_add_folio() requires the page index to
be aligned with the folio number of pages.  Such unaligned tree blocks
can lead to VM_BUG_ON().

So this patch adds extra warning for those unaligned tree blocks, as a
preparation for the future folio migration.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c
fs/btrfs/fs.h

index 5698282c17877916185c7112c8417703a60380a8..5e5852a4ffb5cffb5a813c802b57a18c6be08af0 100644 (file)
@@ -3454,6 +3454,12 @@ static int check_eb_alignment(struct btrfs_fs_info *fs_info, u64 start)
                          start, fs_info->nodesize);
                return -EINVAL;
        }
+       if (!IS_ALIGNED(start, fs_info->nodesize) &&
+           !test_and_set_bit(BTRFS_FS_UNALIGNED_TREE_BLOCK, &fs_info->flags)) {
+               btrfs_warn(fs_info,
+"tree block not nodesize aligned, start %llu nodesize %u, can be resolved by a full metadata balance",
+                             start, fs_info->nodesize);
+       }
        return 0;
 }
 
index d84a390336fc1de56b3075f615faf308a83a47a8..5559c33cd53a50d078986a7e30507521087f5896 100644 (file)
@@ -139,6 +139,12 @@ enum {
         */
        BTRFS_FS_FEATURE_CHANGED,
 
+       /*
+        * Indicate that we have found a tree block which is only aligned to
+        * sectorsize, but not to nodesize.  This should be rare nowadays.
+        */
+       BTRFS_FS_UNALIGNED_TREE_BLOCK,
+
 #if BITS_PER_LONG == 32
        /* Indicate if we have error/warn message printed on 32bit systems */
        BTRFS_FS_32BIT_ERROR,