]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ext4: replace ext4_writepage_trans_blocks()
authorZhang Yi <yi.zhang@huawei.com>
Mon, 7 Jul 2025 14:08:12 +0000 (22:08 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 Aug 2025 14:49:41 +0000 (16:49 +0200)
commit 57661f28756c59510e31543520b5b8f5e591f384 upstream.

After ext4 supports large folios, the semantics of reserving credits in
pages is no longer applicable. In most scenarios, reserving credits in
extents is sufficient. Therefore, introduce ext4_chunk_trans_extent()
to replace ext4_writepage_trans_blocks(). move_extent_per_page() is the
only remaining location where we are still processing extents in pages.

Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20250707140814.542883-10-yi.zhang@huaweicloud.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/move_extent.c
fs/ext4/xattr.c

index fe3366e98493b8f3fd3b93a1f5e8f7dccc4573c1..9ac0a7d4fa0cd7b54ff9966310f6ddf4d8d69d09 100644 (file)
@@ -3064,9 +3064,9 @@ extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length);
 extern void ext4_set_inode_flags(struct inode *, bool init);
 extern int ext4_alloc_da_blocks(struct inode *inode);
 extern void ext4_set_aops(struct inode *inode);
-extern int ext4_writepage_trans_blocks(struct inode *);
 extern int ext4_normal_submit_inode_data_buffers(struct jbd2_inode *jinode);
 extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks);
+extern int ext4_chunk_trans_extent(struct inode *inode, int nrblocks);
 extern int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
                                  int pextents);
 extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
index b543a46fc809621081e990adc80a2d4a5330608d..f0f1554586978aa775c53bf82bf78185abed1b3f 100644 (file)
@@ -5171,7 +5171,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
                                credits = depth + 2;
                        }
 
-                       restart_credits = ext4_writepage_trans_blocks(inode);
+                       restart_credits = ext4_chunk_trans_extent(inode, 0);
                        err = ext4_datasem_ensure_credits(handle, inode, credits,
                                        restart_credits, 0);
                        if (err) {
@@ -5431,7 +5431,7 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
 
        truncate_pagecache(inode, start);
 
-       credits = ext4_writepage_trans_blocks(inode);
+       credits = ext4_chunk_trans_extent(inode, 0);
        handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
@@ -5527,7 +5527,7 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
 
        truncate_pagecache(inode, start);
 
-       credits = ext4_writepage_trans_blocks(inode);
+       credits = ext4_chunk_trans_extent(inode, 0);
        handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
index 05313c8ffb9cc72f883656a555ba0e2d26958711..38874d62f88c44675b7b911f7438159387879cf2 100644 (file)
@@ -570,7 +570,7 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
                return 0;
        }
 
-       needed_blocks = ext4_writepage_trans_blocks(inode);
+       needed_blocks = ext4_chunk_trans_extent(inode, 1);
 
        ret = ext4_get_inode_loc(inode, &iloc);
        if (ret)
@@ -1874,7 +1874,7 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline)
        };
 
 
-       needed_blocks = ext4_writepage_trans_blocks(inode);
+       needed_blocks = ext4_chunk_trans_extent(inode, 1);
        handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
@@ -1994,7 +1994,7 @@ int ext4_convert_inline_data(struct inode *inode)
                        return 0;
        }
 
-       needed_blocks = ext4_writepage_trans_blocks(inode);
+       needed_blocks = ext4_chunk_trans_extent(inode, 1);
 
        iloc.bh = NULL;
        error = ext4_get_inode_loc(inode, &iloc);
index 786c708cb92295ffefafd59b5bb5b86e0a2910b1..3df0796a30104e3a682f5482ce07d5a7990e8504 100644 (file)
@@ -1296,7 +1296,8 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
         * Reserve one block more for addition to orphan list in case
         * we allocate blocks but write fails for some reason
         */
-       needed_blocks = ext4_writepage_trans_blocks(inode) + 1;
+       needed_blocks = ext4_chunk_trans_extent(inode,
+                       ext4_journal_blocks_per_folio(inode)) + 1;
        index = pos >> PAGE_SHIFT;
 
        if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
@@ -4464,7 +4465,7 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
                return ret;
 
        if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
-               credits = ext4_writepage_trans_blocks(inode);
+               credits = ext4_chunk_trans_extent(inode, 2);
        else
                credits = ext4_blocks_for_truncate(inode);
        handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
@@ -4613,7 +4614,7 @@ int ext4_truncate(struct inode *inode)
        }
 
        if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
-               credits = ext4_writepage_trans_blocks(inode);
+               credits = ext4_chunk_trans_extent(inode, 1);
        else
                credits = ext4_blocks_for_truncate(inode);
 
@@ -6256,25 +6257,19 @@ int ext4_meta_trans_blocks(struct inode *inode, int lblocks, int pextents)
 }
 
 /*
- * Calculate the total number of credits to reserve to fit
- * the modification of a single pages into a single transaction,
- * which may include multiple chunks of block allocations.
- *
- * This could be called via ext4_write_begin()
- *
- * We need to consider the worse case, when
- * one new block per extent.
+ * Calculate the journal credits for modifying the number of blocks
+ * in a single extent within one transaction. 'nrblocks' is used only
+ * for non-extent inodes. For extent type inodes, 'nrblocks' can be
+ * zero if the exact number of blocks is unknown.
  */
-int ext4_writepage_trans_blocks(struct inode *inode)
+int ext4_chunk_trans_extent(struct inode *inode, int nrblocks)
 {
-       int bpp = ext4_journal_blocks_per_folio(inode);
        int ret;
 
-       ret = ext4_meta_trans_blocks(inode, bpp, bpp);
-
+       ret = ext4_meta_trans_blocks(inode, nrblocks, 1);
        /* Account for data blocks for journalled mode */
        if (ext4_should_journal_data(inode))
-               ret += bpp;
+               ret += nrblocks;
        return ret;
 }
 
@@ -6652,10 +6647,12 @@ static int ext4_block_page_mkwrite(struct inode *inode, struct folio *folio,
        handle_t *handle;
        loff_t size;
        unsigned long len;
+       int credits;
        int ret;
 
-       handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE,
-                                   ext4_writepage_trans_blocks(inode));
+       credits = ext4_chunk_trans_extent(inode,
+                       ext4_journal_blocks_per_folio(inode));
+       handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, credits);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
index 1f8493a56e8f6a9aef0091e421c1f6de631ca2f1..adae3caf175a932667d1100dbe973e6b755979c3 100644 (file)
@@ -280,7 +280,8 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
         */
 again:
        *err = 0;
-       jblocks = ext4_writepage_trans_blocks(orig_inode) * 2;
+       jblocks = ext4_meta_trans_blocks(orig_inode, block_len_in_page,
+                                        block_len_in_page) * 2;
        handle = ext4_journal_start(orig_inode, EXT4_HT_MOVE_EXTENTS, jblocks);
        if (IS_ERR(handle)) {
                *err = PTR_ERR(handle);
index 8d15acbacc20356b82a8d7c5f34bf654a8d2518c..3fb93247330d10c79ef7fe73d0820664ef8669e2 100644 (file)
@@ -962,7 +962,7 @@ int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode,
         * so we need to reserve credits for this eventuality
         */
        if (inode && ext4_has_inline_data(inode))
-               credits += ext4_writepage_trans_blocks(inode) + 1;
+               credits += ext4_chunk_trans_extent(inode, 1) + 1;
 
        /* We are done if ea_inode feature is not enabled. */
        if (!ext4_has_feature_ea_inode(sb))