]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: require strict data/metadata split for subpage checks
authorQu Wenruo <wqu@suse.com>
Wed, 29 Jan 2025 03:59:30 +0000 (14:29 +1030)
committerDavid Sterba <dsterba@suse.com>
Tue, 18 Mar 2025 19:35:42 +0000 (20:35 +0100)
Since we have btrfs_meta_is_subpage(), we should make btrfs_is_subpage()
to be data inode specific.

This change involves:

- Simplify btrfs_is_subpage()
  Now we only need to do a very simple sectorsize check against
  PAGE_SIZE.
  And since the function is pretty simple now, just make it an inline
  function.

- Add an extra ASSERT() to make sure btrfs_is_subpage() is only called
  on data inode mapping

- Migrate btree_csum_one_bio() to use btrfs_meta_folio_*() helpers
- Migrate alloc_extent_buffer() to use btrfs_meta_folio_*() helpers
- Migrate end_bbio_meta_write() to use btrfs_meta_folio_*() helpers
  Or we will trigger the ASSERT() due to calling btrfs_folio_*() on
  metadata folios.

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/disk-io.c
fs/btrfs/extent_io.c
fs/btrfs/subpage.c
fs/btrfs/subpage.h

index d55e2828280959cac0b2b986baa64cbdd1bb0999..8c31ba1b061ec811e8754a1b286ac3ffbc9681d1 100644 (file)
@@ -284,8 +284,8 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio)
 
        if (WARN_ON_ONCE(found_start != eb->start))
                return BLK_STS_IOERR;
-       if (WARN_ON(!btrfs_folio_test_uptodate(fs_info, eb->folios[0],
-                                              eb->start, eb->len)))
+       if (WARN_ON(!btrfs_meta_folio_test_uptodate(fs_info, eb->folios[0],
+                                                   eb->start, eb->len)))
                return BLK_STS_IOERR;
 
        ASSERT(memcmp_extent_buffer(eb, fs_info->fs_devices->metadata_uuid,
index 1deff394ead3ffd59c4c1b0f16534f776099fae9..580bdb0379742f665c50b6f2b69f1e7126a6b416 100644 (file)
@@ -1732,18 +1732,14 @@ static void end_bbio_meta_write(struct btrfs_bio *bbio)
        struct extent_buffer *eb = bbio->private;
        struct btrfs_fs_info *fs_info = eb->fs_info;
        struct folio_iter fi;
-       u32 bio_offset = 0;
 
        if (bbio->bio.bi_status != BLK_STS_OK)
                set_btree_ioerr(eb);
 
        bio_for_each_folio_all(fi, &bbio->bio) {
-               u64 start = eb->start + bio_offset;
                struct folio *folio = fi.folio;
-               u32 len = fi.length;
 
-               btrfs_folio_clear_writeback(fs_info, folio, start, len);
-               bio_offset += len;
+               btrfs_meta_folio_clear_writeback(fs_info, folio, eb->start, eb->len);
        }
 
        clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
@@ -3136,7 +3132,7 @@ reallocate:
                 * and free the allocated page.
                 */
                folio = eb->folios[i];
-               WARN_ON(btrfs_folio_test_dirty(fs_info, folio, eb->start, eb->len));
+               WARN_ON(btrfs_meta_folio_test_dirty(fs_info, folio, eb->start, eb->len));
 
                /*
                 * Check if the current page is physically contiguous with previous eb
@@ -3147,7 +3143,7 @@ reallocate:
                if (i && folio_page(eb->folios[i - 1], 0) + 1 != folio_page(folio, 0))
                        page_contig = false;
 
-               if (!btrfs_folio_test_uptodate(fs_info, folio, eb->start, eb->len))
+               if (!btrfs_meta_folio_test_uptodate(fs_info, folio, eb->start, eb->len))
                        uptodate = 0;
 
                /*
index f02346aff827f655cc9acbc6452701f0d2710bc7..a8a6e105e5f6c78848305af47be5ff42ed9b672d 100644 (file)
  *   This means a slightly higher tree locking latency.
  */
 
-#if PAGE_SIZE > SZ_4K
-bool btrfs_is_subpage(const struct btrfs_fs_info *fs_info, struct address_space *mapping)
-{
-       if (fs_info->sectorsize >= PAGE_SIZE)
-               return false;
-
-       /*
-        * Only data pages (either through DIO or compression) can have no
-        * mapping. And if mapping->host is data inode, it's subpage.
-        * As we have ruled our sectorsize >= PAGE_SIZE case already.
-        */
-       if (!mapping || !mapping->host || is_data_inode(BTRFS_I(mapping->host)))
-               return true;
-
-       /*
-        * Now the only remaining case is metadata, which we only go subpage
-        * routine if nodesize < PAGE_SIZE.
-        */
-       if (fs_info->nodesize < PAGE_SIZE)
-               return true;
-       return false;
-}
-#endif
-
 int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info,
                         struct folio *folio, enum btrfs_subpage_type type)
 {
index 6a2dd208eeae8c325b247afe5772145754fa589b..e10a1d308f32ee9baf133a0252a62a34110f975b 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/spinlock.h>
 #include <linux/atomic.h>
 #include <linux/sizes.h>
+#include "btrfs_inode.h"
 #include "fs.h"
 
 struct address_space;
@@ -83,7 +84,13 @@ static inline bool btrfs_meta_is_subpage(const struct btrfs_fs_info *fs_info)
 {
        return fs_info->nodesize < PAGE_SIZE;
 }
-bool btrfs_is_subpage(const struct btrfs_fs_info *fs_info, struct address_space *mapping);
+static inline bool btrfs_is_subpage(const struct btrfs_fs_info *fs_info,
+                                   struct address_space *mapping)
+{
+       if (mapping && mapping->host)
+               ASSERT(is_data_inode(BTRFS_I(mapping->host)));
+       return fs_info->sectorsize < PAGE_SIZE;
+}
 #else
 static inline bool btrfs_meta_is_subpage(const struct btrfs_fs_info *fs_info)
 {
@@ -92,6 +99,8 @@ static inline bool btrfs_meta_is_subpage(const struct btrfs_fs_info *fs_info)
 static inline bool btrfs_is_subpage(const struct btrfs_fs_info *fs_info,
                                    struct address_space *mapping)
 {
+       if (mapping && mapping->host)
+               ASSERT(is_data_inode(BTRFS_I(mapping->host)));
        return false;
 }
 #endif