ext4: reduce stack usage in ext4_mpage_readpages()

This function is very similar to do_mpage_readpage() and a similar
approach to that taken in commit 12ac5a65cb 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>
This commit is contained in:
Matthew Wilcox (Oracle) 2024-07-18 23:29:59 +01:00 committed by Theodore Ts'o
parent f5cacdc6f2
commit e37c9e173b

View File

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