aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorFan Li <fanofcode.li@samsung.com>2013-12-09 03:09:00 -0500
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-12-22 20:18:06 -0500
commit63a0b7cb33d85aeb0df39b984c08e234db4925d1 (patch)
tree75de6dbf2311e606124221d11344bc3ad8e2ebfa /fs/f2fs
parent6bacf52fb58aeb3e89d9a62970b85a5570aa8ace (diff)
f2fs: merge pages with the same sync_mode flag
Previously f2fs submits most of write requests using WRITE_SYNC, but f2fs_write_data_pages submits last write requests by sync_mode flags callers pass. This causes a performance problem since continuous pages with different sync flags can't be merged in cfq IO scheduler(thanks yu chao for pointing it out), and synchronous requests often take more time. This patch makes the following modifies to DATA writebacks: 1. every page will be written back using the sync mode caller pass. 2. only pages with the same sync mode can be merged in one bio request. These changes are restricted to DATA pages.Other types of writebacks are modified To remain synchronous. In my test with tiotest, f2fs sequence write performance is improved by about 7%-10% , and this patch has no obvious impact on other performance tests. Signed-off-by: Fan Li <fanofcode.li@samsung.com> Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/data.c18
-rw-r--r--fs/f2fs/f2fs.h8
-rw-r--r--fs/f2fs/gc.c6
-rw-r--r--fs/f2fs/segment.c27
4 files changed, 37 insertions, 22 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 5607393198df..fb5e5c2627e5 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -194,8 +194,9 @@ void f2fs_submit_page_mbio(struct f2fs_sb_info *sbi, struct page *page,
194 if (!is_read_io(rw)) 194 if (!is_read_io(rw))
195 inc_page_count(sbi, F2FS_WRITEBACK); 195 inc_page_count(sbi, F2FS_WRITEBACK);
196 196
197 if (io->bio && io->last_block_in_bio != blk_addr - 1) 197 if (io->bio && (io->last_block_in_bio != blk_addr - 1 ||
198 __submit_merged_bio(sbi, io, type, true, rw); 198 io->rw_flag != rw))
199 __submit_merged_bio(sbi, io, type, false, io->rw_flag);
199alloc_new: 200alloc_new:
200 if (io->bio == NULL) { 201 if (io->bio == NULL) {
201 bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); 202 bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
@@ -203,6 +204,7 @@ alloc_new:
203 io->bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); 204 io->bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
204 io->bio->bi_end_io = is_read_io(rw) ? f2fs_read_end_io : 205 io->bio->bi_end_io = is_read_io(rw) ? f2fs_read_end_io :
205 f2fs_write_end_io; 206 f2fs_write_end_io;
207 io->rw_flag = rw;
206 /* 208 /*
207 * The end_io will be assigned at the sumbission phase. 209 * The end_io will be assigned at the sumbission phase.
208 * Until then, let bio_add_page() merge consecutive IOs as much 210 * Until then, let bio_add_page() merge consecutive IOs as much
@@ -212,7 +214,7 @@ alloc_new:
212 214
213 if (bio_add_page(io->bio, page, PAGE_CACHE_SIZE, 0) < 215 if (bio_add_page(io->bio, page, PAGE_CACHE_SIZE, 0) <
214 PAGE_CACHE_SIZE) { 216 PAGE_CACHE_SIZE) {
215 __submit_merged_bio(sbi, io, type, true, rw); 217 __submit_merged_bio(sbi, io, type, false, rw);
216 goto alloc_new; 218 goto alloc_new;
217 } 219 }
218 220
@@ -641,7 +643,7 @@ static int f2fs_read_data_pages(struct file *file,
641 return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro); 643 return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro);
642} 644}
643 645
644int do_write_data_page(struct page *page) 646int do_write_data_page(struct page *page, struct writeback_control *wbc)
645{ 647{
646 struct inode *inode = page->mapping->host; 648 struct inode *inode = page->mapping->host;
647 block_t old_blk_addr, new_blk_addr; 649 block_t old_blk_addr, new_blk_addr;
@@ -669,10 +671,10 @@ int do_write_data_page(struct page *page)
669 !is_cold_data(page) && 671 !is_cold_data(page) &&
670 need_inplace_update(inode))) { 672 need_inplace_update(inode))) {
671 rewrite_data_page(F2FS_SB(inode->i_sb), page, 673 rewrite_data_page(F2FS_SB(inode->i_sb), page,
672 old_blk_addr); 674 old_blk_addr, wbc);
673 } else { 675 } else {
674 write_data_page(inode, page, &dn, 676 write_data_page(inode, page, &dn,
675 old_blk_addr, &new_blk_addr); 677 old_blk_addr, &new_blk_addr, wbc);
676 update_extent_cache(new_blk_addr, &dn); 678 update_extent_cache(new_blk_addr, &dn);
677 } 679 }
678out_writepage: 680out_writepage:
@@ -719,10 +721,10 @@ write:
719 if (S_ISDIR(inode->i_mode)) { 721 if (S_ISDIR(inode->i_mode)) {
720 dec_page_count(sbi, F2FS_DIRTY_DENTS); 722 dec_page_count(sbi, F2FS_DIRTY_DENTS);
721 inode_dec_dirty_dents(inode); 723 inode_dec_dirty_dents(inode);
722 err = do_write_data_page(page); 724 err = do_write_data_page(page, wbc);
723 } else { 725 } else {
724 f2fs_lock_op(sbi); 726 f2fs_lock_op(sbi);
725 err = do_write_data_page(page); 727 err = do_write_data_page(page, wbc);
726 f2fs_unlock_op(sbi); 728 f2fs_unlock_op(sbi);
727 need_balance_fs = true; 729 need_balance_fs = true;
728 } 730 }
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index dca18b3bcc62..b1df239ba421 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -368,6 +368,7 @@ enum page_type {
368struct f2fs_bio_info { 368struct f2fs_bio_info {
369 struct bio *bio; /* bios to merge */ 369 struct bio *bio; /* bios to merge */
370 sector_t last_block_in_bio; /* last block number */ 370 sector_t last_block_in_bio; /* last block number */
371 int rw_flag; /* rw flag for all pages */
371 struct mutex io_mutex; /* mutex for bio */ 372 struct mutex io_mutex; /* mutex for bio */
372}; 373};
373 374
@@ -1098,8 +1099,9 @@ void write_meta_page(struct f2fs_sb_info *, struct page *);
1098void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int, 1099void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
1099 block_t, block_t *); 1100 block_t, block_t *);
1100void write_data_page(struct inode *, struct page *, struct dnode_of_data*, 1101void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
1101 block_t, block_t *); 1102 block_t, block_t *, struct writeback_control *);
1102void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t); 1103void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t,
1104 struct writeback_control *);
1103void recover_data_page(struct f2fs_sb_info *, struct page *, 1105void recover_data_page(struct f2fs_sb_info *, struct page *,
1104 struct f2fs_summary *, block_t, block_t); 1106 struct f2fs_summary *, block_t, block_t);
1105void rewrite_node_page(struct f2fs_sb_info *, struct page *, 1107void rewrite_node_page(struct f2fs_sb_info *, struct page *,
@@ -1150,7 +1152,7 @@ void update_extent_cache(block_t, struct dnode_of_data *);
1150struct page *find_data_page(struct inode *, pgoff_t, bool); 1152struct page *find_data_page(struct inode *, pgoff_t, bool);
1151struct page *get_lock_data_page(struct inode *, pgoff_t); 1153struct page *get_lock_data_page(struct inode *, pgoff_t);
1152struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool); 1154struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
1153int do_write_data_page(struct page *); 1155int do_write_data_page(struct page *, struct writeback_control *);
1154 1156
1155/* 1157/*
1156 * gc.c 1158 * gc.c
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 29ceb9d71c8c..c68fba5ffadb 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -520,6 +520,10 @@ static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
520 520
521static void move_data_page(struct inode *inode, struct page *page, int gc_type) 521static void move_data_page(struct inode *inode, struct page *page, int gc_type)
522{ 522{
523 struct writeback_control wbc = {
524 .sync_mode = 1,
525 };
526
523 if (gc_type == BG_GC) { 527 if (gc_type == BG_GC) {
524 if (PageWriteback(page)) 528 if (PageWriteback(page))
525 goto out; 529 goto out;
@@ -536,7 +540,7 @@ static void move_data_page(struct inode *inode, struct page *page, int gc_type)
536 inode_dec_dirty_dents(inode); 540 inode_dec_dirty_dents(inode);
537 } 541 }
538 set_cold_data(page); 542 set_cold_data(page);
539 do_write_data_page(page); 543 do_write_data_page(page, &wbc);
540 clear_cold_data(page); 544 clear_cold_data(page);
541 } 545 }
542out: 546out:
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index ca9adf5914cc..e5dc41114867 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -856,12 +856,13 @@ static int __get_segment_type(struct page *page, enum page_type p_type)
856 856
857static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, 857static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
858 block_t old_blkaddr, block_t *new_blkaddr, 858 block_t old_blkaddr, block_t *new_blkaddr,
859 struct f2fs_summary *sum, enum page_type p_type) 859 struct f2fs_summary *sum, enum page_type p_type,
860 struct writeback_control *wbc)
860{ 861{
861 struct sit_info *sit_i = SIT_I(sbi); 862 struct sit_info *sit_i = SIT_I(sbi);
862 struct curseg_info *curseg; 863 struct curseg_info *curseg;
863 unsigned int old_cursegno; 864 unsigned int old_cursegno;
864 int type; 865 int type, rw = WRITE;
865 866
866 type = __get_segment_type(page, p_type); 867 type = __get_segment_type(page, p_type);
867 curseg = CURSEG_I(sbi, type); 868 curseg = CURSEG_I(sbi, type);
@@ -900,7 +901,9 @@ static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
900 fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg)); 901 fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg));
901 902
902 /* writeout dirty page into bdev */ 903 /* writeout dirty page into bdev */
903 f2fs_submit_page_mbio(sbi, page, *new_blkaddr, p_type, WRITE); 904 if (wbc->sync_mode == WB_SYNC_ALL)
905 rw |= WRITE_SYNC;
906 f2fs_submit_page_mbio(sbi, page, *new_blkaddr, p_type, rw);
904 907
905 mutex_unlock(&curseg->curseg_mutex); 908 mutex_unlock(&curseg->curseg_mutex);
906} 909}
@@ -915,13 +918,16 @@ void write_node_page(struct f2fs_sb_info *sbi, struct page *page,
915 unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr) 918 unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr)
916{ 919{
917 struct f2fs_summary sum; 920 struct f2fs_summary sum;
921 struct writeback_control wbc = {
922 .sync_mode = 1,
923 };
918 set_summary(&sum, nid, 0, 0); 924 set_summary(&sum, nid, 0, 0);
919 do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE); 925 do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE, &wbc);
920} 926}
921 927
922void write_data_page(struct inode *inode, struct page *page, 928void write_data_page(struct inode *inode, struct page *page,
923 struct dnode_of_data *dn, block_t old_blkaddr, 929 struct dnode_of_data *dn, block_t old_blkaddr,
924 block_t *new_blkaddr) 930 block_t *new_blkaddr, struct writeback_control *wbc)
925{ 931{
926 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); 932 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
927 struct f2fs_summary sum; 933 struct f2fs_summary sum;
@@ -932,13 +938,14 @@ void write_data_page(struct inode *inode, struct page *page,
932 set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); 938 set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
933 939
934 do_write_page(sbi, page, old_blkaddr, 940 do_write_page(sbi, page, old_blkaddr,
935 new_blkaddr, &sum, DATA); 941 new_blkaddr, &sum, DATA, wbc);
936} 942}
937 943
938void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page, 944void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page,
939 block_t old_blk_addr) 945 block_t old_blk_addr, struct writeback_control *wbc)
940{ 946{
941 f2fs_submit_page_mbio(sbi, page, old_blk_addr, DATA, WRITE); 947 int rw = wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE;
948 f2fs_submit_page_mbio(sbi, page, old_blk_addr, DATA, rw);
942} 949}
943 950
944void recover_data_page(struct f2fs_sb_info *sbi, 951void recover_data_page(struct f2fs_sb_info *sbi,
@@ -1025,7 +1032,7 @@ void rewrite_node_page(struct f2fs_sb_info *sbi,
1025 1032
1026 /* rewrite node page */ 1033 /* rewrite node page */
1027 set_page_writeback(page); 1034 set_page_writeback(page);
1028 f2fs_submit_page_mbio(sbi, page, new_blkaddr, NODE, WRITE); 1035 f2fs_submit_page_mbio(sbi, page, new_blkaddr, NODE, WRITE_SYNC);
1029 f2fs_submit_merged_bio(sbi, NODE, true, WRITE); 1036 f2fs_submit_merged_bio(sbi, NODE, true, WRITE);
1030 refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); 1037 refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
1031 1038
@@ -1593,7 +1600,7 @@ repeat:
1593 continue; 1600 continue;
1594 } 1601 }
1595 1602
1596 f2fs_submit_page_mbio(sbi, page, blk_addr, META, READ); 1603 f2fs_submit_page_mbio(sbi, page, blk_addr, META, READ_SYNC);
1597 1604
1598 mark_page_accessed(page); 1605 mark_page_accessed(page);
1599 f2fs_put_page(page, 0); 1606 f2fs_put_page(page, 0);