[PATCH v4 09/12] ext4: Convert from readpages to readahead

From: Matthew Wilcox
Date: Sat Feb 01 2020 - 10:12:52 EST


From: "Matthew Wilcox (Oracle)" <willy@xxxxxxxxxxxxx>

Use the new readahead operation in ext4

Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx>
Cc: linux-ext4@xxxxxxxxxxxxxxx
---
fs/ext4/ext4.h | 5 ++---
fs/ext4/inode.c | 24 ++++++++++++------------
fs/ext4/readpage.c | 20 +++++++-------------
fs/ext4/verity.c | 16 +++++++++++-----
4 files changed, 32 insertions(+), 33 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 9a2ee2428ecc..346ad9e1403b 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3275,9 +3275,8 @@ static inline void ext4_set_de_type(struct super_block *sb,
}

/* readpages.c */
-extern int ext4_mpage_readpages(struct address_space *mapping,
- struct list_head *pages, struct page *page,
- unsigned nr_pages, bool is_readahead);
+extern int ext4_mpage_readpages(struct address_space *mapping, pgoff_t start,
+ struct page *page, unsigned nr_pages, bool is_readahead);
extern int __init ext4_init_post_read_processing(void);
extern void ext4_exit_post_read_processing(void);

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3313168b680f..e1f5864e5ecf 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3218,7 +3218,7 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
static int ext4_readpage(struct file *file, struct page *page)
{
int ret = -EAGAIN;
- struct inode *inode = page->mapping->host;
+ struct inode *inode = file_inode(file);

trace_ext4_readpage(page);

@@ -3226,23 +3226,23 @@ static int ext4_readpage(struct file *file, struct page *page)
ret = ext4_readpage_inline(inode, page);

if (ret == -EAGAIN)
- return ext4_mpage_readpages(page->mapping, NULL, page, 1,
- false);
+ return ext4_mpage_readpages(page->mapping, 0, page, 1, false);

return ret;
}

-static int
-ext4_readpages(struct file *file, struct address_space *mapping,
- struct list_head *pages, unsigned nr_pages)
+static unsigned
+ext4_readahead(struct file *file, struct address_space *mapping,
+ pgoff_t start, unsigned nr_pages)
{
struct inode *inode = mapping->host;

- /* If the file has inline data, no need to do readpages. */
+ /* If the file has inline data, no need to do readahead. */
if (ext4_has_inline_data(inode))
- return 0;
+ return nr_pages;

- return ext4_mpage_readpages(mapping, pages, NULL, nr_pages, true);
+ ext4_mpage_readpages(mapping, start, NULL, nr_pages, true);
+ return 0;
}

static void ext4_invalidatepage(struct page *page, unsigned int offset,
@@ -3587,7 +3587,7 @@ static int ext4_set_page_dirty(struct page *page)

static const struct address_space_operations ext4_aops = {
.readpage = ext4_readpage,
- .readpages = ext4_readpages,
+ .readahead = ext4_readahead,
.writepage = ext4_writepage,
.writepages = ext4_writepages,
.write_begin = ext4_write_begin,
@@ -3604,7 +3604,7 @@ static const struct address_space_operations ext4_aops = {

static const struct address_space_operations ext4_journalled_aops = {
.readpage = ext4_readpage,
- .readpages = ext4_readpages,
+ .readahead = ext4_readahead,
.writepage = ext4_writepage,
.writepages = ext4_writepages,
.write_begin = ext4_write_begin,
@@ -3620,7 +3620,7 @@ static const struct address_space_operations ext4_journalled_aops = {

static const struct address_space_operations ext4_da_aops = {
.readpage = ext4_readpage,
- .readpages = ext4_readpages,
+ .readahead = ext4_readahead,
.writepage = ext4_writepage,
.writepages = ext4_writepages,
.write_begin = ext4_da_write_begin,
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index c1769afbf799..aaeb298c8fdb 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -7,8 +7,8 @@
*
* This was originally taken from fs/mpage.c
*
- * The intent is the ext4_mpage_readpages() function here is intended
- * to replace mpage_readpages() in the general case, not just for
+ * The ext4_mpage_readahead() function here is intended to
+ * replace mpage_readahead() in the general case, not just for
* encrypted files. It has some limitations (see below), where it
* will fall back to read_block_full_page(), but these limitations
* should only be hit when page_size != block_size.
@@ -221,9 +221,8 @@ static inline loff_t ext4_readpage_limit(struct inode *inode)
return i_size_read(inode);
}

-int ext4_mpage_readpages(struct address_space *mapping,
- struct list_head *pages, struct page *page,
- unsigned nr_pages, bool is_readahead)
+int ext4_mpage_readpages(struct address_space *mapping, pgoff_t start,
+ struct page *page, unsigned nr_pages, bool is_readahead)
{
struct bio *bio = NULL;
sector_t last_block_in_bio = 0;
@@ -251,14 +250,10 @@ int ext4_mpage_readpages(struct address_space *mapping,
int fully_mapped = 1;
unsigned first_hole = blocks_per_page;

- if (pages) {
- page = lru_to_page(pages);
+ if (is_readahead) {
+ page = readahead_page(mapping, start++);

prefetchw(&page->flags);
- list_del(&page->lru);
- if (add_to_page_cache_lru(page, mapping, page->index,
- readahead_gfp_mask(mapping)))
- goto next_page;
}

if (page_has_buffers(page))
@@ -406,10 +401,9 @@ int ext4_mpage_readpages(struct address_space *mapping,
else
unlock_page(page);
next_page:
- if (pages)
+ if (is_readahead)
put_page(page);
}
- BUG_ON(pages && !list_empty(pages));
if (bio)
submit_bio(bio);
return 0;
diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c
index dc5ec724d889..40a550c0da2b 100644
--- a/fs/ext4/verity.c
+++ b/fs/ext4/verity.c
@@ -351,7 +351,6 @@ static int ext4_get_verity_descriptor(struct inode *inode, void *buf,
static void ext4_merkle_tree_readahead(struct address_space *mapping,
pgoff_t start_index, unsigned long count)
{
- LIST_HEAD(pages);
unsigned int nr_pages = 0;
struct page *page;
pgoff_t index;
@@ -360,16 +359,23 @@ static void ext4_merkle_tree_readahead(struct address_space *mapping,
for (index = start_index; index < start_index + count; index++) {
page = xa_load(&mapping->i_pages, index);
if (!page || xa_is_value(page)) {
- page = __page_cache_alloc(readahead_gfp_mask(mapping));
+ gfp_t gfp = readahead_gfp_mask(mapping);
+ page = __page_cache_alloc(gfp);
if (!page)
break;
- page->index = index;
- list_add(&page->lru, &pages);
+ if (add_to_page_cache_lru(page, mapping, index, gfp)) {
+ put_page(page);
+ break;
+ }
nr_pages++;
}
}
+
+ if (!nr_pages)
+ return;
+
blk_start_plug(&plug);
- ext4_mpage_readpages(mapping, &pages, NULL, nr_pages, true);
+ ext4_mpage_readpages(mapping, start_index, NULL, nr_pages, true);
blk_finish_plug(&plug);
}

--
2.24.1