if (folio->mapping)
                lockdep_assert_held(&folio->mapping->i_private_lock);
 
-       if (fs_info->nodesize >= PAGE_SIZE) {
+       if (!btrfs_meta_is_subpage(fs_info)) {
                if (!folio_test_private(folio))
                        folio_attach_private(folio, eb);
                else
        wbc_init_bio(wbc, &bbio->bio);
        bbio->inode = BTRFS_I(eb->fs_info->btree_inode);
        bbio->file_offset = eb->start;
-       if (fs_info->nodesize < PAGE_SIZE) {
+       if (btrfs_meta_is_subpage(fs_info)) {
                struct folio *folio = eb->folios[0];
                bool ret;
 
        if (!folio_test_private(folio))
                return 0;
 
-       if (folio_to_fs_info(folio)->nodesize < PAGE_SIZE)
+       if (btrfs_meta_is_subpage(folio_to_fs_info(folio)))
                return submit_eb_subpage(folio, wbc);
 
        spin_lock(&mapping->i_private_lock);
                return;
        }
 
-       if (fs_info->nodesize >= PAGE_SIZE) {
+       if (!btrfs_meta_is_subpage(fs_info)) {
                /*
                 * We do this since we'll remove the pages after we've
                 * removed the eb from the radix tree, so we could race
         * don't try to insert two ebs for the same bytenr.  So here we always
         * return NULL and just continue.
         */
-       if (fs_info->nodesize < PAGE_SIZE)
+       if (btrfs_meta_is_subpage(fs_info))
                return NULL;
 
        /* Page not yet attached to an extent buffer */
 
 finish:
        spin_lock(&mapping->i_private_lock);
-       if (existing_folio && fs_info->nodesize < PAGE_SIZE) {
+       if (existing_folio && btrfs_meta_is_subpage(fs_info)) {
                /* We're going to reuse the existing page, can drop our folio now. */
                __free_page(folio_page(eb->folios[i], 0));
                eb->folios[i] = existing_folio;
         * The memory will be freed by attach_extent_buffer_page() or freed
         * manually if we exit earlier.
         */
-       if (fs_info->nodesize < PAGE_SIZE) {
+       if (btrfs_meta_is_subpage(fs_info)) {
                prealloc = btrfs_alloc_subpage(fs_info, BTRFS_SUBPAGE_METADATA);
                if (IS_ERR(prealloc)) {
                        ret = PTR_ERR(prealloc);
        percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len,
                                 fs_info->dirty_metadata_batch);
 
-       if (eb->fs_info->nodesize < PAGE_SIZE)
+       if (btrfs_meta_is_subpage(fs_info))
                return clear_subpage_extent_buffer_dirty(eb);
 
        num_folios = num_extent_folios(eb);
        WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags));
 
        if (!was_dirty) {
-               bool subpage = eb->fs_info->nodesize < PAGE_SIZE;
+               bool subpage = btrfs_meta_is_subpage(eb->fs_info);
 
                /*
                 * For subpage case, we can have other extent buffers in the
                 * This is special handling for metadata subpage, as regular
                 * btrfs_is_subpage() can not handle cloned/dummy metadata.
                 */
-               if (fs_info->nodesize >= PAGE_SIZE)
+               if (!btrfs_meta_is_subpage(fs_info))
                        folio_clear_uptodate(folio);
                else
                        btrfs_subpage_clear_uptodate(fs_info, folio,
                 * This is special handling for metadata subpage, as regular
                 * btrfs_is_subpage() can not handle cloned/dummy metadata.
                 */
-               if (fs_info->nodesize >= PAGE_SIZE)
+               if (!btrfs_meta_is_subpage(fs_info))
                        folio_mark_uptodate(folio);
                else
                        btrfs_subpage_set_uptodate(fs_info, folio,
        bbio->inode = BTRFS_I(eb->fs_info->btree_inode);
        bbio->file_offset = eb->start;
        memcpy(&bbio->parent_check, check, sizeof(*check));
-       if (eb->fs_info->nodesize < PAGE_SIZE) {
+       if (btrfs_meta_is_subpage(eb->fs_info)) {
                ret = bio_add_folio(&bbio->bio, eb->folios[0], eb->len,
                                    eb->start - folio_pos(eb->folios[0]));
                ASSERT(ret);
        if (test_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))
                return;
 
-       if (fs_info->nodesize < PAGE_SIZE) {
+       if (btrfs_meta_is_subpage(fs_info)) {
                folio = eb->folios[0];
                ASSERT(i == 0);
                if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio,
 {
        struct extent_buffer *eb;
 
-       if (folio_to_fs_info(folio)->nodesize < PAGE_SIZE)
+       if (btrfs_meta_is_subpage(folio_to_fs_info(folio)))
                return try_release_subpage_extent_buffer(folio);
 
        /*
 
 #include <linux/spinlock.h>
 #include <linux/atomic.h>
 #include <linux/sizes.h>
+#include "fs.h"
 
 struct address_space;
 struct folio;
-struct btrfs_fs_info;
 
 /*
  * Extra info for subpapge bitmap.
 };
 
 #if PAGE_SIZE > SZ_4K
+/*
+ * Subpage support for metadata is more complex, as we can have dummy extent
+ * buffers, where folios have no mapping to determine the owning inode.
+ *
+ * Thankfully we only need to check if node size is smaller than page size.
+ * Even with larger folio support, we will only allocate a folio as large as
+ * node size.
+ * Thus if nodesize < PAGE_SIZE, we know metadata needs need to subpage routine.
+ */
+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);
 #else
+static inline bool btrfs_meta_is_subpage(const struct btrfs_fs_info *fs_info)
+{
+       return false;
+}
 static inline bool btrfs_is_subpage(const struct btrfs_fs_info *fs_info,
                                    struct address_space *mapping)
 {