Commit c0be8e6f authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Theodore Ts'o

ext4: Convert ext4_mpage_readpages() to work on folios

This definitely doesn't include support for large folios; there
are all kinds of assumptions about the number of buffers attached
to a folio.  But it does remove several calls to compound_head().
Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Link: https://lore.kernel.org/r/20230324180129.1220691-24-willy@infradead.orgSigned-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 0b5a2543
...@@ -3646,7 +3646,7 @@ static inline void ext4_set_de_type(struct super_block *sb, ...@@ -3646,7 +3646,7 @@ static inline void ext4_set_de_type(struct super_block *sb,
/* readpages.c */ /* readpages.c */
extern int ext4_mpage_readpages(struct inode *inode, extern int ext4_mpage_readpages(struct inode *inode,
struct readahead_control *rac, struct page *page); struct readahead_control *rac, struct folio *folio);
extern int __init ext4_init_post_read_processing(void); extern int __init ext4_init_post_read_processing(void);
extern void ext4_exit_post_read_processing(void); extern void ext4_exit_post_read_processing(void);
......
...@@ -3154,17 +3154,16 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block) ...@@ -3154,17 +3154,16 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
static int ext4_read_folio(struct file *file, struct folio *folio) static int ext4_read_folio(struct file *file, struct folio *folio)
{ {
struct page *page = &folio->page;
int ret = -EAGAIN; int ret = -EAGAIN;
struct inode *inode = page->mapping->host; struct inode *inode = folio->mapping->host;
trace_ext4_readpage(page); trace_ext4_readpage(&folio->page);
if (ext4_has_inline_data(inode)) if (ext4_has_inline_data(inode))
ret = ext4_readpage_inline(inode, folio); ret = ext4_readpage_inline(inode, folio);
if (ret == -EAGAIN) if (ret == -EAGAIN)
return ext4_mpage_readpages(inode, NULL, page); return ext4_mpage_readpages(inode, NULL, folio);
return ret; return ret;
} }
......
...@@ -218,7 +218,7 @@ static inline loff_t ext4_readpage_limit(struct inode *inode) ...@@ -218,7 +218,7 @@ static inline loff_t ext4_readpage_limit(struct inode *inode)
} }
int ext4_mpage_readpages(struct inode *inode, int ext4_mpage_readpages(struct inode *inode,
struct readahead_control *rac, struct page *page) struct readahead_control *rac, struct folio *folio)
{ {
struct bio *bio = NULL; struct bio *bio = NULL;
sector_t last_block_in_bio = 0; sector_t last_block_in_bio = 0;
...@@ -247,16 +247,15 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -247,16 +247,15 @@ int ext4_mpage_readpages(struct inode *inode,
int fully_mapped = 1; int fully_mapped = 1;
unsigned first_hole = blocks_per_page; unsigned first_hole = blocks_per_page;
if (rac) { if (rac)
page = readahead_page(rac); folio = readahead_folio(rac);
prefetchw(&page->flags); prefetchw(&folio->flags);
}
if (page_has_buffers(page)) if (folio_buffers(folio))
goto confused; goto confused;
block_in_file = next_block = block_in_file = next_block =
(sector_t)page->index << (PAGE_SHIFT - blkbits); (sector_t)folio->index << (PAGE_SHIFT - blkbits);
last_block = block_in_file + nr_pages * blocks_per_page; last_block = block_in_file + nr_pages * blocks_per_page;
last_block_in_file = (ext4_readpage_limit(inode) + last_block_in_file = (ext4_readpage_limit(inode) +
blocksize - 1) >> blkbits; blocksize - 1) >> blkbits;
...@@ -290,7 +289,7 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -290,7 +289,7 @@ int ext4_mpage_readpages(struct inode *inode,
/* /*
* Then do more ext4_map_blocks() calls until we are * Then do more ext4_map_blocks() calls until we are
* done with this page. * done with this folio.
*/ */
while (page_block < blocks_per_page) { while (page_block < blocks_per_page) {
if (block_in_file < last_block) { if (block_in_file < last_block) {
...@@ -299,10 +298,10 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -299,10 +298,10 @@ int ext4_mpage_readpages(struct inode *inode,
if (ext4_map_blocks(NULL, inode, &map, 0) < 0) { if (ext4_map_blocks(NULL, inode, &map, 0) < 0) {
set_error_page: set_error_page:
SetPageError(page); folio_set_error(folio);
zero_user_segment(page, 0, folio_zero_segment(folio, 0,
PAGE_SIZE); folio_size(folio));
unlock_page(page); folio_unlock(folio);
goto next_page; goto next_page;
} }
} }
...@@ -333,22 +332,22 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -333,22 +332,22 @@ int ext4_mpage_readpages(struct inode *inode,
} }
} }
if (first_hole != blocks_per_page) { if (first_hole != blocks_per_page) {
zero_user_segment(page, first_hole << blkbits, folio_zero_segment(folio, first_hole << blkbits,
PAGE_SIZE); folio_size(folio));
if (first_hole == 0) { if (first_hole == 0) {
if (ext4_need_verity(inode, page->index) && if (ext4_need_verity(inode, folio->index) &&
!fsverity_verify_page(page)) !fsverity_verify_page(&folio->page))
goto set_error_page; goto set_error_page;
SetPageUptodate(page); folio_mark_uptodate(folio);
unlock_page(page); folio_unlock(folio);
goto next_page; continue;
} }
} else if (fully_mapped) { } else if (fully_mapped) {
SetPageMappedToDisk(page); folio_set_mappedtodisk(folio);
} }
/* /*
* This page 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 != blocks[0] - 1 ||
...@@ -366,7 +365,7 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -366,7 +365,7 @@ int ext4_mpage_readpages(struct inode *inode,
REQ_OP_READ, GFP_KERNEL); REQ_OP_READ, GFP_KERNEL);
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, page->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 = blocks[0] << (blkbits - 9);
bio->bi_end_io = mpage_end_io; bio->bi_end_io = mpage_end_io;
if (rac) if (rac)
...@@ -374,7 +373,7 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -374,7 +373,7 @@ int ext4_mpage_readpages(struct inode *inode,
} }
length = first_hole << blkbits; length = first_hole << blkbits;
if (bio_add_page(bio, page, length, 0) < length) if (!bio_add_folio(bio, folio, length, 0))
goto submit_and_realloc; goto submit_and_realloc;
if (((map.m_flags & EXT4_MAP_BOUNDARY) && if (((map.m_flags & EXT4_MAP_BOUNDARY) &&
...@@ -384,19 +383,18 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -384,19 +383,18 @@ int ext4_mpage_readpages(struct inode *inode,
bio = NULL; bio = NULL;
} else } else
last_block_in_bio = blocks[blocks_per_page - 1]; last_block_in_bio = blocks[blocks_per_page - 1];
goto next_page; continue;
confused: confused:
if (bio) { if (bio) {
submit_bio(bio); submit_bio(bio);
bio = NULL; bio = NULL;
} }
if (!PageUptodate(page)) if (!folio_test_uptodate(folio))
block_read_full_folio(page_folio(page), ext4_get_block); block_read_full_folio(folio, ext4_get_block);
else else
unlock_page(page); folio_unlock(folio);
next_page: next_page:
if (rac) ; /* A label shall be followed by a statement until C23 */
put_page(page);
} }
if (bio) if (bio)
submit_bio(bio); submit_bio(bio);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment