Skip to content

Commit 6b8ed62

Browse files
jankaratytso
authored andcommitted
ext4: avoid unnecessary transaction starts during writeback
ext4_writepages() currently works in a loop like: start a transaction scan inode for pages to write map and submit these pages stop the transaction This loop results in starting transaction once more than is needed because in the last iteration we start a transaction only to scan the inode and find there are no pages to write. This can be significant increase in number of transaction starts for single-extent files or files that have all blocks already mapped. Furthermore we already know from previous iteration whether there are more pages to write or not. So propagate the information from mpage_prepare_extent_to_map() and avoid unnecessary looping in case there are no more pages to write. Signed-off-by: Jan Kara <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 6e014c6 commit 6b8ed62

File tree

1 file changed

+13
-18
lines changed

1 file changed

+13
-18
lines changed

fs/ext4/inode.c

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,7 @@ struct mpage_da_data {
15341534
struct ext4_map_blocks map;
15351535
struct ext4_io_submit io_submit; /* IO submission data */
15361536
unsigned int do_map:1;
1537+
unsigned int scanned_until_end:1;
15371538
};
15381539

15391540
static void mpage_release_unused_pages(struct mpage_da_data *mpd,
@@ -1549,6 +1550,7 @@ static void mpage_release_unused_pages(struct mpage_da_data *mpd,
15491550
if (mpd->first_page >= mpd->next_page)
15501551
return;
15511552

1553+
mpd->scanned_until_end = 0;
15521554
index = mpd->first_page;
15531555
end = mpd->next_page - 1;
15541556
if (invalidate) {
@@ -2195,7 +2197,11 @@ static int mpage_process_page_bufs(struct mpage_da_data *mpd,
21952197
if (err < 0)
21962198
return err;
21972199
}
2198-
return lblk < blocks;
2200+
if (lblk >= blocks) {
2201+
mpd->scanned_until_end = 1;
2202+
return 0;
2203+
}
2204+
return 1;
21992205
}
22002206

22012207
/*
@@ -2553,7 +2559,7 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)
25532559
nr_pages = pagevec_lookup_range_tag(&pvec, mapping, &index, end,
25542560
tag);
25552561
if (nr_pages == 0)
2556-
goto out;
2562+
break;
25572563

25582564
for (i = 0; i < nr_pages; i++) {
25592565
struct page *page = pvec.pages[i];
@@ -2608,6 +2614,7 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)
26082614
pagevec_release(&pvec);
26092615
cond_resched();
26102616
}
2617+
mpd->scanned_until_end = 1;
26112618
return 0;
26122619
out:
26132620
pagevec_release(&pvec);
@@ -2626,7 +2633,6 @@ static int ext4_writepages(struct address_space *mapping,
26262633
struct inode *inode = mapping->host;
26272634
int needed_blocks, rsv_blocks = 0, ret = 0;
26282635
struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
2629-
bool done;
26302636
struct blk_plug plug;
26312637
bool give_up_on_write = false;
26322638

@@ -2712,7 +2718,6 @@ static int ext4_writepages(struct address_space *mapping,
27122718
retry:
27132719
if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
27142720
tag_pages_for_writeback(mapping, mpd.first_page, mpd.last_page);
2715-
done = false;
27162721
blk_start_plug(&plug);
27172722

27182723
/*
@@ -2722,6 +2727,7 @@ static int ext4_writepages(struct address_space *mapping,
27222727
* started.
27232728
*/
27242729
mpd.do_map = 0;
2730+
mpd.scanned_until_end = 0;
27252731
mpd.io_submit.io_end = ext4_init_io_end(inode, GFP_KERNEL);
27262732
if (!mpd.io_submit.io_end) {
27272733
ret = -ENOMEM;
@@ -2737,7 +2743,7 @@ static int ext4_writepages(struct address_space *mapping,
27372743
if (ret < 0)
27382744
goto unplug;
27392745

2740-
while (!done && mpd.first_page <= mpd.last_page) {
2746+
while (!mpd.scanned_until_end && wbc->nr_to_write > 0) {
27412747
/* For each extent of pages we use new io_end */
27422748
mpd.io_submit.io_end = ext4_init_io_end(inode, GFP_KERNEL);
27432749
if (!mpd.io_submit.io_end) {
@@ -2772,20 +2778,9 @@ static int ext4_writepages(struct address_space *mapping,
27722778

27732779
trace_ext4_da_write_pages(inode, mpd.first_page, mpd.wbc);
27742780
ret = mpage_prepare_extent_to_map(&mpd);
2775-
if (!ret) {
2776-
if (mpd.map.m_len)
2777-
ret = mpage_map_and_submit_extent(handle, &mpd,
2781+
if (!ret && mpd.map.m_len)
2782+
ret = mpage_map_and_submit_extent(handle, &mpd,
27782783
&give_up_on_write);
2779-
else {
2780-
/*
2781-
* We scanned the whole range (or exhausted
2782-
* nr_to_write), submitted what was mapped and
2783-
* didn't find anything needing mapping. We are
2784-
* done.
2785-
*/
2786-
done = true;
2787-
}
2788-
}
27892784
/*
27902785
* Caution: If the handle is synchronous,
27912786
* ext4_journal_stop() can wait for transaction commit

0 commit comments

Comments
 (0)