ext4: reduce stack usage in ext4_mpage_readpages()
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Thu, 18 Jul 2024 22:29:59 +0000 (23:29 +0100)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 27 Aug 2024 01:47:03 +0000 (21:47 -0400)
This function is very similar to do_mpage_readpage() and a similar
approach to that taken in commit 12ac5a65cb56 will work.  As in
do_mpage_readpage(), we only use this array for checking block contiguity
and we can do that more efficiently with a little arithmetic.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Link: https://patch.msgid.link/20240718223005.568869-1-willy@infradead.org
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/readpage.c

index 8494492582abea86ecd1b33272c349eaefbeb04e..5d3a9dc9a32d948b6bc6922685a0ba952b07ec73 100644 (file)
@@ -221,7 +221,7 @@ int ext4_mpage_readpages(struct inode *inode,
        sector_t block_in_file;
        sector_t last_block;
        sector_t last_block_in_file;
-       sector_t blocks[MAX_BUF_PER_PAGE];
+       sector_t first_block;
        unsigned page_block;
        struct block_device *bdev = inode->i_sb->s_bdev;
        int length;
@@ -263,6 +263,7 @@ int ext4_mpage_readpages(struct inode *inode,
                        unsigned map_offset = block_in_file - map.m_lblk;
                        unsigned last = map.m_len - map_offset;
 
+                       first_block = map.m_pblk + map_offset;
                        for (relative_block = 0; ; relative_block++) {
                                if (relative_block == last) {
                                        /* needed? */
@@ -271,8 +272,6 @@ int ext4_mpage_readpages(struct inode *inode,
                                }
                                if (page_block == blocks_per_page)
                                        break;
-                               blocks[page_block] = map.m_pblk + map_offset +
-                                       relative_block;
                                page_block++;
                                block_in_file++;
                        }
@@ -307,7 +306,9 @@ int ext4_mpage_readpages(struct inode *inode,
                                goto confused;          /* hole -> non-hole */
 
                        /* Contiguous blocks? */
-                       if (page_block && blocks[page_block-1] != map.m_pblk-1)
+                       if (!page_block)
+                               first_block = map.m_pblk;
+                       else if (first_block + page_block != map.m_pblk)
                                goto confused;
                        for (relative_block = 0; ; relative_block++) {
                                if (relative_block == map.m_len) {
@@ -316,7 +317,6 @@ int ext4_mpage_readpages(struct inode *inode,
                                        break;
                                } else if (page_block == blocks_per_page)
                                        break;
-                               blocks[page_block] = map.m_pblk+relative_block;
                                page_block++;
                                block_in_file++;
                        }
@@ -339,7 +339,7 @@ int ext4_mpage_readpages(struct inode *inode,
                 * This folio will go to BIO.  Do we need to send this
                 * BIO off first?
                 */
-               if (bio && (last_block_in_bio != blocks[0] - 1 ||
+               if (bio && (last_block_in_bio != first_block - 1 ||
                            !fscrypt_mergeable_bio(bio, inode, next_block))) {
                submit_and_realloc:
                        submit_bio(bio);
@@ -355,7 +355,7 @@ int ext4_mpage_readpages(struct inode *inode,
                        fscrypt_set_bio_crypt_ctx(bio, inode, next_block,
                                                  GFP_KERNEL);
                        ext4_set_bio_post_read_ctx(bio, inode, folio->index);
-                       bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9);
+                       bio->bi_iter.bi_sector = first_block << (blkbits - 9);
                        bio->bi_end_io = mpage_end_io;
                        if (rac)
                                bio->bi_opf |= REQ_RAHEAD;
@@ -371,7 +371,7 @@ int ext4_mpage_readpages(struct inode *inode,
                        submit_bio(bio);
                        bio = NULL;
                } else
-                       last_block_in_bio = blocks[blocks_per_page - 1];
+                       last_block_in_bio = first_block + blocks_per_page - 1;
                continue;
        confused:
                if (bio) {