提交 a8366d32 编写于 作者: X Xiaoguang Wang 提交者: Joseph Qi

alios: ext4: don't submit unwritten extent while holding active jbd2 handle

In ext4_writepages(), for every iteration, mpage_prepare_extent_to_map()
will try to find 2048 pages to map and normally one bio can contain 256
pages at most. If we really found 2048 pages to map, there will be 4 bios
and 4 ext4_io_submit() calls which are called both in ext4_writepages()
and mpage_map_and_submit_extent().

But note that in mpage_map_and_submit_extent(), we hold a valid jbd2 handle,
when dioread_nolock is enabled and extent is unwritten, jbd2 commit thread
will wait this handle to finish, so wait the unwritten extent is written to
disk, this will introduce unnecessary stall time, especially longer when
the writeback operation is io throttled, need to fix this issue.

Here for this scene, we accumulate bios in ext4_io_submit's io_bio, and
only submit these bios after dropping the jbd2 handle.
Signed-off-by: NXiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
Reviewed-by: NLiu Bo <bo.liu@linux.alibaba.com>
Signed-off-by: NJoseph Qi <joseph.qi@linux.alibaba.com>
Acked-by: NCaspar Zhang <caspar@linux.alibaba.com>
上级 28df06b3
......@@ -226,9 +226,21 @@ typedef struct ext4_io_end {
struct ext4_io_submit {
struct writeback_control *io_wbc;
/*
* When dioread_nolock is enabled, we don't submit bios for unwritten
* extent while holding jbd2 handle, which can avoid jbd2 commit thread
* wait io to complete, for this case, we will link bios cover the
* extent to io_bio using bio->bi_private.
*/
struct bio *io_bio;
ext4_io_end_t *io_end;
sector_t io_next_block;
/*
* If not zero, we have an active bio and can submit this bio or add
* new bh to this bio, if zero, we'll need to allocate a new bio.
*/
int have_active_bio;
int can_submit;
};
/*
......
......@@ -2496,6 +2496,7 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
mpd->io_submit.io_end->handle = handle->h_rsv_handle;
handle->h_rsv_handle = NULL;
}
mpd->io_submit.can_submit = 0;
ext4_set_io_unwritten_flag(inode, mpd->io_submit.io_end);
}
......@@ -2921,7 +2922,9 @@ static int ext4_writepages(struct address_space *mapping,
}
/* Unlock pages we didn't use */
mpage_release_unused_pages(&mpd, give_up_on_write);
/* Submit prepared bio */
/* Submit all prepared bio */
if (!mpd.io_submit.can_submit)
mpd.io_submit.can_submit = 1;
ext4_io_submit(&mpd.io_submit);
/*
......
......@@ -346,15 +346,27 @@ static void ext4_end_bio(struct bio *bio)
void ext4_io_submit(struct ext4_io_submit *io)
{
struct bio *bio = io->io_bio;
if (bio) {
int io_op_flags = io->io_wbc->sync_mode == WB_SYNC_ALL ?
REQ_SYNC : 0;
io->io_bio->bi_write_hint = io->io_end->inode->i_write_hint;
bio_set_op_attrs(io->io_bio, REQ_OP_WRITE, io_op_flags);
submit_bio(io->io_bio);
struct bio *bio = io->io_bio, *next = NULL;
int io_op_flags = io->io_wbc->sync_mode == WB_SYNC_ALL ? REQ_SYNC : 0;
if (!io->can_submit) {
/*
* Caller tries to submit this bio, but currently we can not
* submit this bio, we set have_active_bio to zero, then caller
* will allocate a new bio.
*/
io->have_active_bio = 0;
return;
}
for (bio = io->io_bio; bio; bio = next) {
next = bio->bi_private;
bio->bi_write_hint = io->io_end->inode->i_write_hint;
bio_set_op_attrs(bio, REQ_OP_WRITE, io_op_flags);
bio->bi_private = ext4_get_io_end(io->io_end);
submit_bio(bio);
}
io->have_active_bio = 0;
io->io_bio = NULL;
}
......@@ -364,6 +376,13 @@ void ext4_io_submit_init(struct ext4_io_submit *io,
io->io_wbc = wbc;
io->io_bio = NULL;
io->io_end = NULL;
/*
* When dioread_nolock is enabled and submit unwritten extents,
* set can_submit to zero, then we'll accumulate bios for this
* extent and submit these bios after drop jdb2 handle.
*/
io->can_submit = 1;
io->have_active_bio = 0;
}
static int io_submit_init_bio(struct ext4_io_submit *io,
......@@ -378,8 +397,10 @@ static int io_submit_init_bio(struct ext4_io_submit *io,
bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
bio_set_dev(bio, bh->b_bdev);
bio->bi_end_io = ext4_end_bio;
bio->bi_private = ext4_get_io_end(io->io_end);
/* Point to previous bio if there is */
bio->bi_private = io->io_bio;
io->io_bio = bio;
io->have_active_bio = 1;
io->io_next_block = bh->b_blocknr;
return 0;
}
......@@ -391,11 +412,11 @@ static int io_submit_add_bh(struct ext4_io_submit *io,
{
int ret;
if (io->io_bio && bh->b_blocknr != io->io_next_block) {
if (io->have_active_bio && bh->b_blocknr != io->io_next_block) {
submit_and_retry:
ext4_io_submit(io);
}
if (io->io_bio == NULL) {
if (!io->have_active_bio) {
ret = io_submit_init_bio(io, bh);
if (ret)
return ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册