]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: remove folio ordered flag and subpage bitmap
authorQu Wenruo <wqu@suse.com>
Tue, 12 May 2026 22:36:38 +0000 (08:06 +0930)
committerDavid Sterba <dsterba@suse.com>
Mon, 8 Jun 2026 13:53:32 +0000 (15:53 +0200)
Btrfs has an internal flag/subpage bitmap called ordered, which is to
indicate that a block has corresponding ordered extent covering it.

However this requires extra synchronization between the inode ordered
tree, and the folio flag/subpage bitmap, not to mention we need to
maintain the extra folio flag with subpage bitmap.

As a step to align btrfs_folio_state more closely to iomap_folio_state,
remove the btrfs specific ordered flag/bitmap.

This will also save us 64 bytes for the bitmap of a huge folio.

Since we're here, also update the ASCII graph of the bitmap, as there
are only 3 sub-bitmaps now, show all sub-bitmaps directly.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/fs.h
fs/btrfs/inode.c
fs/btrfs/subpage.c
fs/btrfs/subpage.h

index 231a73b5489c0a241289ba5095ad28fcc97747fa..8cf1e4c5105f491fe5d4dc9e3874994775f29f12 100644 (file)
@@ -250,8 +250,6 @@ static void process_one_folio(struct btrfs_fs_info *fs_info,
        ASSERT(end + 1 - start != 0 && end + 1 - start < U32_MAX);
        len = end + 1 - start;
 
-       if (page_ops & PAGE_SET_ORDERED)
-               btrfs_folio_clamp_set_ordered(fs_info, folio, start, len);
        if (page_ops & PAGE_START_WRITEBACK) {
                btrfs_folio_clamp_clear_dirty(fs_info, folio, start, len);
                btrfs_folio_clamp_set_writeback(fs_info, folio, start, len);
@@ -530,7 +528,6 @@ static void end_bbio_data_write(struct btrfs_bio *bbio)
                u32 len = fi.length;
 
                bio_size += len;
-               btrfs_folio_clear_ordered(fs_info, folio, start, len);
                btrfs_folio_clear_writeback(fs_info, folio, start, len);
        }
 
@@ -1629,7 +1626,6 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
                        u64 start = page_start + (start_bit << fs_info->sectorsize_bits);
                        u32 len = (end_bit - start_bit) << fs_info->sectorsize_bits;
 
-                       btrfs_folio_clear_ordered(fs_info, folio, start, len);
                        btrfs_mark_ordered_io_finished(inode, start, len, false);
                }
                return ret;
@@ -1707,7 +1703,6 @@ static int submit_one_sector(struct btrfs_inode *inode,
                 * ordered extent.
                 */
                btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize);
-               btrfs_folio_clear_ordered(fs_info, folio, filepos, sectorsize);
                btrfs_folio_set_writeback(fs_info, folio, filepos, sectorsize);
                btrfs_folio_clear_writeback(fs_info, folio, filepos, sectorsize);
 
@@ -1756,7 +1751,6 @@ static int submit_one_sector(struct btrfs_inode *inode,
                                     sectorsize, filepos - folio_pos(folio), 0);
        if (unlikely(queued < sectorsize)) {
                btrfs_folio_clear_writeback(fs_info, folio, filepos, sectorsize);
-               btrfs_folio_clear_ordered(fs_info, folio, filepos, sectorsize);
                btrfs_mark_ordered_io_finished(inode, filepos, fs_info->sectorsize,
                                               false);
                return -EUCLEAN;
@@ -1821,7 +1815,6 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode,
                        spin_unlock(&inode->ordered_tree_lock);
                        btrfs_put_ordered_extent(ordered);
 
-                       btrfs_folio_clear_ordered(fs_info, folio, cur, fs_info->sectorsize);
                        btrfs_mark_ordered_io_finished(inode, cur, fs_info->sectorsize, true);
                        /*
                         * This range is beyond i_size, thus we don't need to
index 899db1215602c76a4794c01bae01669032ff8c63..8c58b114f5b3e354e1be93bc4412757b857546ce 100644 (file)
@@ -55,7 +55,6 @@ enum {
        /* Page starts writeback, clear dirty bit and set writeback bit */
        ENUM_BIT(PAGE_START_WRITEBACK),
        ENUM_BIT(PAGE_END_WRITEBACK),
-       ENUM_BIT(PAGE_SET_ORDERED),
 };
 
 /*
index 1725611a3450317595fcc3b35dcd77cb7bf8ee40..d3b439fd611f7848fb5b1b7743c28810b0dce42f 100644 (file)
@@ -1198,14 +1198,6 @@ static inline void btrfs_force_shutdown(struct btrfs_fs_info *fs_info)
        }
 }
 
-/*
- * We use folio flag owner_2 to indicate there is an ordered extent with
- * unfinished IO.
- */
-#define folio_test_ordered(folio)      folio_test_owner_2(folio)
-#define folio_set_ordered(folio)       folio_set_owner_2(folio)
-#define folio_clear_ordered(folio)     folio_clear_owner_2(folio)
-
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
 
 #define EXPORT_FOR_TESTS
index e72ea6ea7d959147fd6dddbdbb517e6e912024cd..973a89301baaa7846cc17e90f34df9bcbbf2de12 100644 (file)
@@ -401,28 +401,6 @@ void btrfs_inode_unlock(struct btrfs_inode *inode, unsigned int ilock_flags)
 static inline void btrfs_cleanup_ordered_extents(struct btrfs_inode *inode,
                                                 u64 offset, u64 bytes)
 {
-       pgoff_t index = offset >> PAGE_SHIFT;
-       const pgoff_t end_index = (offset + bytes - 1) >> PAGE_SHIFT;
-       struct folio *folio;
-
-       while (index <= end_index) {
-               folio = filemap_get_folio(inode->vfs_inode.i_mapping, index);
-               if (IS_ERR(folio)) {
-                       index++;
-                       continue;
-               }
-
-               index = folio_next_index(folio);
-               /*
-                * Here we just clear all Ordered bits for every page in the
-                * range, then btrfs_mark_ordered_io_finished() will handle
-                * the ordered extent accounting for the range.
-                */
-               btrfs_folio_clamp_clear_ordered(inode->root->fs_info, folio,
-                                               offset, bytes);
-               folio_put(folio);
-       }
-
        return btrfs_mark_ordered_io_finished(inode, offset, bytes, false);
 }
 
@@ -1406,7 +1384,6 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
         * setup for writepage.
         */
        page_ops = ((flags & COW_FILE_RANGE_KEEP_LOCKED) ? 0 : PAGE_UNLOCK);
-       page_ops |= PAGE_SET_ORDERED;
 
        /*
         * Relocation relies on the relocated extents to have exactly the same
@@ -1972,8 +1949,7 @@ static int nocow_one_range(struct btrfs_inode *inode, struct folio *locked_folio
                goto error;
        extent_clear_unlock_delalloc(inode, file_pos, end, locked_folio, cached,
                                     EXTENT_LOCKED | EXTENT_DELALLOC |
-                                    EXTENT_CLEAR_DATA_RESV,
-                                    PAGE_SET_ORDERED);
+                                    EXTENT_CLEAR_DATA_RESV, 0);
        return ret;
 
 error:
@@ -7600,10 +7576,7 @@ static void btrfs_invalidate_folio(struct folio *folio, size_t offset,
                 * The range is dirty meaning it has not been submitted.
                 * Here we need to truncate the OE range as the range will never
                 * be submitted.
-                */
-               btrfs_folio_clear_ordered(fs_info, folio, cur, range_len);
-
-               /*
+                *
                 * IO on this page will never be started, so we need to account
                 * for any ordered extents now. Don't clear EXTENT_DELALLOC_NEW
                 * here, must leave that up for the ordered extent completion.
index ff68e79fe72d3d3833462dbb449a04ff5da105ad..9a178da13153d131809e000bbe699809048ceb36 100644 (file)
@@ -465,35 +465,6 @@ void btrfs_subpage_clear_writeback(const struct btrfs_fs_info *fs_info,
        spin_unlock_irqrestore(&bfs->lock, flags);
 }
 
-void btrfs_subpage_set_ordered(const struct btrfs_fs_info *fs_info,
-                              struct folio *folio, u64 start, u32 len)
-{
-       struct btrfs_folio_state *bfs = folio_get_private(folio);
-       unsigned int start_bit = subpage_calc_start_bit(fs_info, folio,
-                                                       ordered, start, len);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bfs->lock, flags);
-       bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits);
-       folio_set_ordered(folio);
-       spin_unlock_irqrestore(&bfs->lock, flags);
-}
-
-void btrfs_subpage_clear_ordered(const struct btrfs_fs_info *fs_info,
-                                struct folio *folio, u64 start, u32 len)
-{
-       struct btrfs_folio_state *bfs = folio_get_private(folio);
-       unsigned int start_bit = subpage_calc_start_bit(fs_info, folio,
-                                                       ordered, start, len);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bfs->lock, flags);
-       bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits);
-       if (subpage_test_bitmap_all_zero(fs_info, folio, ordered))
-               folio_clear_ordered(folio);
-       spin_unlock_irqrestore(&bfs->lock, flags);
-}
-
 /*
  * Unlike set/clear which is dependent on each page status, for test all bits
  * are tested in the same way.
@@ -517,7 +488,6 @@ bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info, \
 IMPLEMENT_BTRFS_SUBPAGE_TEST_OP(uptodate);
 IMPLEMENT_BTRFS_SUBPAGE_TEST_OP(dirty);
 IMPLEMENT_BTRFS_SUBPAGE_TEST_OP(writeback);
-IMPLEMENT_BTRFS_SUBPAGE_TEST_OP(ordered);
 
 /*
  * Note that, in selftests (extent-io-tests), we can have empty fs_info passed
@@ -613,8 +583,6 @@ IMPLEMENT_BTRFS_PAGE_OPS(dirty, folio_mark_dirty, folio_clear_dirty_for_io,
                         folio_test_dirty);
 IMPLEMENT_BTRFS_PAGE_OPS(writeback, folio_start_writeback, folio_end_writeback,
                         folio_test_writeback);
-IMPLEMENT_BTRFS_PAGE_OPS(ordered, folio_set_ordered, folio_clear_ordered,
-                        folio_test_ordered);
 
 #define GET_SUBPAGE_BITMAP(fs_info, folio, name, dst)                  \
 {                                                                      \
@@ -727,7 +695,6 @@ void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
        unsigned long uptodate_bitmap;
        unsigned long dirty_bitmap;
        unsigned long writeback_bitmap;
-       unsigned long ordered_bitmap;
        unsigned long flags;
 
        ASSERT(folio_test_private(folio) && folio_get_private(folio));
@@ -738,17 +705,15 @@ void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
        GET_SUBPAGE_BITMAP(fs_info, folio, uptodate, &uptodate_bitmap);
        GET_SUBPAGE_BITMAP(fs_info, folio, dirty, &dirty_bitmap);
        GET_SUBPAGE_BITMAP(fs_info, folio, writeback, &writeback_bitmap);
-       GET_SUBPAGE_BITMAP(fs_info, folio, ordered, &ordered_bitmap);
        spin_unlock_irqrestore(&bfs->lock, flags);
 
        dump_page(folio_page(folio, 0), "btrfs folio state dump");
        btrfs_warn(fs_info,
-"start=%llu len=%u page=%llu, bitmaps uptodate=%*pbl dirty=%*pbl writeback=%*pbl ordered=%*pbl",
+"start=%llu len=%u page=%llu, bitmaps uptodate=%*pbl dirty=%*pbl writeback=%*pbl",
                    start, len, folio_pos(folio),
                    blocks_per_folio, &uptodate_bitmap,
                    blocks_per_folio, &dirty_bitmap,
-                   blocks_per_folio, &writeback_bitmap,
-                   blocks_per_folio, &ordered_bitmap);
+                   blocks_per_folio, &writeback_bitmap);
 }
 
 void btrfs_get_subpage_dirty_bitmap(struct btrfs_fs_info *fs_info,
index ccdb817381dd5f66d1ec2c2fe8e47e5f75692016..b30eb4abae64753a5a4bd550d2ea51f42a49fbd7 100644 (file)
@@ -14,15 +14,15 @@ struct folio;
 /*
  * Extra info for subpage bitmap.
  *
- * For subpage we pack all uptodate/dirty/writeback/ordered bitmaps into
+ * For subpage we pack all uptodate/dirty/writeback bitmaps into
  * one larger bitmap.
  *
  * This structure records how they are organized in the bitmap:
  *
- * /- uptodate          /- dirty        /- ordered
+ * /- uptodate          /- dirty        /- writeback
  * |                   |               |
  * v                   v               v
- * |u|u|u|u|........|u|u|d|d|.......|d|d|o|o|.......|o|o|
+ * |u|u|u|u|........|u|u|d|d|.......|d|d|w|w|.......|w|w|
  * |< sectors_per_page >|
  *
  * Unlike regular macro-like enums, here we do not go upper-case names, as
@@ -40,11 +40,6 @@ enum {
         */
        btrfs_bitmap_nr_writeback,
 
-       /*
-        * The ordered flags shows if the range has an ordered extent.
-        */
-       btrfs_bitmap_nr_ordered,
-
        btrfs_bitmap_nr_max
 };
 
@@ -169,7 +164,6 @@ bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffe
 DECLARE_BTRFS_SUBPAGE_OPS(uptodate);
 DECLARE_BTRFS_SUBPAGE_OPS(dirty);
 DECLARE_BTRFS_SUBPAGE_OPS(writeback);
-DECLARE_BTRFS_SUBPAGE_OPS(ordered);
 
 /*
  * Helper for error cleanup, where a folio will have its dirty flag cleared,