From: Jens Axboe <axboe@kernel.dk>
To: linux-fsdevel@vger.kernel.org
Cc: viro@zeniv.linux.org.uk, akpm@linux-foundation.org,
Jens Axboe <axboe@kernel.dk>
Subject: [PATCH 2/4] mpage: mpage_readpages() should submit IO as read-ahead
Date: Wed, 20 Jun 2018 19:07:23 -0600 [thread overview]
Message-ID: <20180621010725.17813-3-axboe@kernel.dk> (raw)
In-Reply-To: <20180621010725.17813-1-axboe@kernel.dk>
a_ops->readpages() is only ever used for read-ahead, yet we don't
flag the IO being submitted as such. Fix that up. Any file system
that uses mpage_readpages() as its ->readpages() implementation
will now get this right.
Since we're passing in whether the IO is read-ahead or not, we
don't need to pass in the 'gfp' separately, as it is dependent
on the IO being read-ahead. Kill off that member.
Add some documentation notes on ->readpages() being purely for
read-ahead.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
fs/f2fs/data.c | 5 +++++
fs/mpage.c | 29 +++++++++++++++++++----------
include/linux/fs.h | 4 ++++
3 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 8f931d699287..b7c9b58acf3e 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1421,6 +1421,11 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
/*
* This function was originally taken from fs/mpage.c, and customized for f2fs.
* Major change was from block_size == page_size in f2fs by default.
+ *
+ * Note that the aops->readpages() function is ONLY used for read-ahead. If
+ * this function ever deviates from doing just read-ahead, it should either
+ * use ->readpage() or do the necessary surgery to decouple ->readpages()
+ * readom read-ahead.
*/
static int f2fs_mpage_readpages(struct address_space *mapping,
struct list_head *pages, struct page *page,
diff --git a/fs/mpage.c b/fs/mpage.c
index 0ecac5c410f4..b0f9de977526 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -137,11 +137,11 @@ struct mpage_readpage_args {
struct bio *bio;
struct page *page;
unsigned nr_pages;
+ bool is_readahead;
sector_t last_block_in_bio;
struct buffer_head map_bh;
unsigned long first_logical_block;
get_block_t *get_block;
- gfp_t gfp;
};
/*
@@ -170,8 +170,18 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
struct block_device *bdev = NULL;
int length;
int fully_mapped = 1;
+ int op_flags;
unsigned nblocks;
unsigned relative_block;
+ gfp_t gfp;
+
+ if (args->is_readahead) {
+ op_flags = REQ_RAHEAD;
+ gfp = readahead_gfp_mask(page->mapping);
+ } else {
+ op_flags = 0;
+ gfp = mapping_gfp_constraint(page->mapping, GFP_KERNEL);
+ }
if (page_has_buffers(page))
goto confused;
@@ -283,7 +293,7 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
* This page will go to BIO. Do we need to send this BIO off first?
*/
if (args->bio && (args->last_block_in_bio != blocks[0] - 1))
- args->bio = mpage_bio_submit(REQ_OP_READ, 0, args->bio);
+ args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
alloc_new:
if (args->bio == NULL) {
@@ -293,14 +303,14 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
goto out;
}
args->bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9),
- min_t(int, args->nr_pages, BIO_MAX_PAGES), args->gfp);
+ min_t(int, args->nr_pages, BIO_MAX_PAGES), gfp);
if (args->bio == NULL)
goto confused;
}
length = first_hole << blkbits;
if (bio_add_page(args->bio, page, length, 0) < length) {
- args->bio = mpage_bio_submit(REQ_OP_READ, 0, args->bio);
+ args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
goto alloc_new;
}
@@ -308,7 +318,7 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
nblocks = map_bh->b_size >> blkbits;
if ((buffer_boundary(map_bh) && relative_block == nblocks) ||
(first_hole != blocks_per_page))
- args->bio = mpage_bio_submit(REQ_OP_READ, 0, args->bio);
+ args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
else
args->last_block_in_bio = blocks[blocks_per_page - 1];
out:
@@ -316,7 +326,7 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
confused:
if (args->bio)
- args->bio = mpage_bio_submit(REQ_OP_READ, 0, args->bio);
+ args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
if (!PageUptodate(page))
block_read_full_page(page, args->get_block);
else
@@ -374,7 +384,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
{
struct mpage_readpage_args args = {
.get_block = get_block,
- .gfp = readahead_gfp_mask(mapping),
+ .is_readahead = true,
};
unsigned page_idx;
@@ -385,7 +395,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
list_del(&page->lru);
if (!add_to_page_cache_lru(page, mapping,
page->index,
- args.gfp)) {
+ readahead_gfp_mask(mapping))) {
args.page = page;
args.nr_pages = nr_pages - page_idx;
args.bio = do_mpage_readpage(&args);
@@ -394,7 +404,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
}
BUG_ON(!list_empty(pages));
if (args.bio)
- mpage_bio_submit(REQ_OP_READ, 0, args.bio);
+ mpage_bio_submit(REQ_OP_READ, REQ_RAHEAD, args.bio);
return 0;
}
EXPORT_SYMBOL(mpage_readpages);
@@ -408,7 +418,6 @@ int mpage_readpage(struct page *page, get_block_t get_block)
.page = page,
.nr_pages = 1,
.get_block = get_block,
- .gfp = mapping_gfp_constraint(page->mapping, GFP_KERNEL),
};
args.bio = do_mpage_readpage(&args);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5c91108846db..b45c34a9b28d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -341,6 +341,10 @@ struct address_space_operations {
/* Set a page dirty. Return true if this dirtied it */
int (*set_page_dirty)(struct page *page);
+ /*
+ * Reads in the requested pages. Unlike ->readpage(), this is
+ * PURELY used for read-ahead!.
+ */
int (*readpages)(struct file *filp, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages);
--
2.17.1
next prev parent reply other threads:[~2018-06-21 1:07 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-21 1:07 [PATCH v4 0/4] Submit ->readpages() IO as read-ahead Jens Axboe
2018-06-21 1:07 ` [PATCH 1/4] mpage: add argument structure for do_mpage_readpage() Jens Axboe
2018-06-21 1:07 ` Jens Axboe [this message]
2018-06-21 17:27 ` [PATCH 2/4] mpage: mpage_readpages() should submit IO as read-ahead Randy Dunlap
2018-06-21 17:29 ` Jens Axboe
2018-06-21 18:47 ` Jaegeuk Kim
2018-06-21 19:18 ` Jens Axboe
2018-06-21 19:32 ` Jaegeuk Kim
2018-06-21 19:32 ` Jens Axboe
2018-06-21 1:07 ` [PATCH 3/4] btrfs: readpages() " Jens Axboe
2018-06-21 1:07 ` [PATCH 4/4] ext4: " Jens Axboe
-- strict thread matches above, loose matches on Subject: below --
2018-05-30 14:42 [PATCHSET v3 0/4] Submit ->readpages() " Jens Axboe
2018-05-30 14:42 ` [PATCH 2/4] mpage: mpage_readpages() should submit " Jens Axboe
2018-05-29 22:17 [PATCHSET v2 0/4] Submit ->readpages() " Jens Axboe
2018-05-29 22:17 ` [PATCH 2/4] mpage: mpage_readpages() should submit " Jens Axboe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180621010725.17813-3-axboe@kernel.dk \
--to=axboe@kernel.dk \
--cc=akpm@linux-foundation.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).