if (subpage)
                        folio_lock(eb->folios[0]);
                for (int i = 0; i < num_folios; i++)
-                       btrfs_folio_set_dirty(eb->fs_info, eb->folios[i],
-                                             eb->start, eb->len);
+                       btrfs_meta_folio_set_dirty(eb->fs_info, eb->folios[i],
+                                                  eb->start, eb->len);
                if (subpage)
                        folio_unlock(eb->folios[0]);
                percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes,
                if (!folio)
                        continue;
 
-               /*
-                * This is special handling for metadata subpage, as regular
-                * btrfs_is_subpage() can not handle cloned/dummy metadata.
-                */
-               if (!btrfs_meta_is_subpage(fs_info))
-                       folio_clear_uptodate(folio);
-               else
-                       btrfs_subpage_clear_uptodate(fs_info, folio,
-                                                    eb->start, eb->len);
+               btrfs_meta_folio_clear_uptodate(fs_info, folio, eb->start, eb->len);
        }
 }
 
        for (int i = 0; i < num_folios; i++) {
                struct folio *folio = eb->folios[i];
 
-               /*
-                * This is special handling for metadata subpage, as regular
-                * btrfs_is_subpage() can not handle cloned/dummy metadata.
-                */
-               if (!btrfs_meta_is_subpage(fs_info))
-                       folio_mark_uptodate(folio);
-               else
-                       btrfs_subpage_set_uptodate(fs_info, folio,
-                                                  eb->start, eb->len);
+               btrfs_meta_folio_set_uptodate(fs_info, folio, eb->start, eb->len);
        }
 }
 
 
                return folio_test_func(folio);                          \
        btrfs_subpage_clamp_range(folio, &start, &len);                 \
        return btrfs_subpage_test_##name(fs_info, folio, start, len);   \
+}                                                                      \
+void btrfs_meta_folio_set_##name(const struct btrfs_fs_info *fs_info,   \
+                                struct folio *folio, u64 start, u32 len) \
+{                                                                      \
+       if (!btrfs_meta_is_subpage(fs_info)) {                          \
+               folio_set_func(folio);                                  \
+               return;                                                 \
+       }                                                               \
+       btrfs_subpage_set_##name(fs_info, folio, start, len);           \
+}                                                                      \
+void btrfs_meta_folio_clear_##name(const struct btrfs_fs_info *fs_info, \
+                                  struct folio *folio, u64 start, u32 len) \
+{                                                                      \
+       if (!btrfs_meta_is_subpage(fs_info)) {                          \
+               folio_clear_func(folio);                                \
+               return;                                                 \
+       }                                                               \
+       btrfs_subpage_clear_##name(fs_info, folio, start, len);         \
+}                                                                      \
+bool btrfs_meta_folio_test_##name(const struct btrfs_fs_info *fs_info, \
+                                 struct folio *folio, u64 start, u32 len) \
+{                                                                      \
+       if (!btrfs_meta_is_subpage(fs_info))                            \
+               return folio_test_func(folio);                          \
+       return btrfs_subpage_test_##name(fs_info, folio, start, len);   \
 }
 IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate,
                         folio_test_uptodate);
 
  * btrfs_folio_clamp_*() are similar to btrfs_folio_*(), except the range doesn't
  * need to be inside the page. Those functions will truncate the range
  * automatically.
+ *
+ * Both btrfs_folio_*() and btrfs_folio_clamp_*() are for data folios.
+ *
+ * For metadata, one should use btrfs_meta_folio_*() helpers instead, and there
+ * is no clamp version for metadata helpers, as we either go subpage
+ * (nodesize < PAGE_SIZE) or go regular folio helpers (nodesize >= PAGE_SIZE,
+ * and our folio is never larger than nodesize).
  */
 #define DECLARE_BTRFS_SUBPAGE_OPS(name)                                        \
 void btrfs_subpage_set_##name(const struct btrfs_fs_info *fs_info,     \
 void btrfs_folio_clamp_clear_##name(const struct btrfs_fs_info *fs_info,       \
                struct folio *folio, u64 start, u32 len);                       \
 bool btrfs_folio_clamp_test_##name(const struct btrfs_fs_info *fs_info,        \
-               struct folio *folio, u64 start, u32 len);
+               struct folio *folio, u64 start, u32 len);               \
+void btrfs_meta_folio_set_##name(const struct btrfs_fs_info *fs_info,  \
+               struct folio *folio, u64 start, u32 len);               \
+void btrfs_meta_folio_clear_##name(const struct btrfs_fs_info *fs_info,        \
+               struct folio *folio, u64 start, u32 len);               \
+bool btrfs_meta_folio_test_##name(const struct btrfs_fs_info *fs_info, \
+               struct folio *folio, u64 start, u32 len);               \
 
 DECLARE_BTRFS_SUBPAGE_OPS(uptodate);
 DECLARE_BTRFS_SUBPAGE_OPS(dirty);