diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-12-10 23:54:01 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-12-22 20:18:06 -0500 |
commit | 458e6197c37de53f7be0a837644daabb900c3036 (patch) | |
tree | 248c02467c0c1f8d84a8e6c23700620a939f3c58 /fs | |
parent | 63a0b7cb33d85aeb0df39b984c08e234db4925d1 (diff) |
f2fs: refactor bio->rw handling
This patch introduces f2fs_io_info to mitigate the complex parameter list.
struct f2fs_io_info {
enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
int rw; /* contains R/RS/W/WS */
int rw_flag; /* contains REQ_META/REQ_PRIO */
}
1. f2fs_write_data_pages
- DATA
- WRITE_SYNC is set when wbc->WB_SYNC_ALL.
2. sync_node_pages
- NODE
- WRITE_SYNC all the time
3. sync_meta_pages
- META
- WRITE_SYNC all the time
- REQ_META | REQ_PRIO all the time
** f2fs_submit_merged_bio() handles META_FLUSH.
4. ra_nat_pages, ra_sit_pages, ra_sum_pages
- META
- READ_SYNC
Cc: Fan Li <fanofcode.li@samsung.com>
Cc: Changman Lee <cm224.lee@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/f2fs/checkpoint.c | 11 | ||||
-rw-r--r-- | fs/f2fs/data.c | 85 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 22 | ||||
-rw-r--r-- | fs/f2fs/gc.c | 10 | ||||
-rw-r--r-- | fs/f2fs/node.c | 22 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 70 | ||||
-rw-r--r-- | fs/f2fs/super.c | 7 |
7 files changed, 132 insertions, 95 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index cf505eb843e8..f8c074961e0a 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -164,8 +164,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type, | |||
164 | } | 164 | } |
165 | 165 | ||
166 | if (nwritten) | 166 | if (nwritten) |
167 | f2fs_submit_merged_bio(sbi, type, nr_to_write == LONG_MAX, | 167 | f2fs_submit_merged_bio(sbi, type, WRITE); |
168 | WRITE); | ||
169 | 168 | ||
170 | return nwritten; | 169 | return nwritten; |
171 | } | 170 | } |
@@ -598,7 +597,7 @@ retry: | |||
598 | * We should submit bio, since it exists several | 597 | * We should submit bio, since it exists several |
599 | * wribacking dentry pages in the freeing inode. | 598 | * wribacking dentry pages in the freeing inode. |
600 | */ | 599 | */ |
601 | f2fs_submit_merged_bio(sbi, DATA, true, WRITE); | 600 | f2fs_submit_merged_bio(sbi, DATA, WRITE); |
602 | } | 601 | } |
603 | goto retry; | 602 | goto retry; |
604 | } | 603 | } |
@@ -804,9 +803,9 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
804 | 803 | ||
805 | trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops"); | 804 | trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops"); |
806 | 805 | ||
807 | f2fs_submit_merged_bio(sbi, DATA, true, WRITE); | 806 | f2fs_submit_merged_bio(sbi, DATA, WRITE); |
808 | f2fs_submit_merged_bio(sbi, NODE, true, WRITE); | 807 | f2fs_submit_merged_bio(sbi, NODE, WRITE); |
809 | f2fs_submit_merged_bio(sbi, META, true, WRITE); | 808 | f2fs_submit_merged_bio(sbi, META, WRITE); |
810 | 809 | ||
811 | /* | 810 | /* |
812 | * update checkpoint pack index | 811 | * update checkpoint pack index |
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index fb5e5c2627e5..ebc91778e815 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -93,37 +93,28 @@ static void f2fs_write_end_io(struct bio *bio, int err) | |||
93 | bio_put(bio); | 93 | bio_put(bio); |
94 | } | 94 | } |
95 | 95 | ||
96 | static void __submit_merged_bio(struct f2fs_sb_info *sbi, | 96 | static void __submit_merged_bio(struct f2fs_bio_info *io) |
97 | struct f2fs_bio_info *io, | ||
98 | enum page_type type, bool sync, int rw) | ||
99 | { | 97 | { |
100 | enum page_type btype = PAGE_TYPE_OF_BIO(type); | 98 | struct f2fs_io_info *fio = &io->fio; |
99 | int rw; | ||
101 | 100 | ||
102 | if (!io->bio) | 101 | if (!io->bio) |
103 | return; | 102 | return; |
104 | 103 | ||
105 | if (btype == META) | 104 | rw = fio->rw | fio->rw_flag; |
106 | rw |= REQ_META; | ||
107 | 105 | ||
108 | if (is_read_io(rw)) { | 106 | if (is_read_io(rw)) { |
109 | if (sync) | ||
110 | rw |= READ_SYNC; | ||
111 | submit_bio(rw, io->bio); | 107 | submit_bio(rw, io->bio); |
112 | trace_f2fs_submit_read_bio(sbi->sb, rw, type, io->bio); | 108 | trace_f2fs_submit_read_bio(io->sbi->sb, rw, fio->type, io->bio); |
113 | io->bio = NULL; | 109 | io->bio = NULL; |
114 | return; | 110 | return; |
115 | } | 111 | } |
116 | 112 | ||
117 | if (sync) | ||
118 | rw |= WRITE_SYNC; | ||
119 | if (type >= META_FLUSH) | ||
120 | rw |= WRITE_FLUSH_FUA; | ||
121 | |||
122 | /* | 113 | /* |
123 | * META_FLUSH is only from the checkpoint procedure, and we should wait | 114 | * META_FLUSH is only from the checkpoint procedure, and we should wait |
124 | * this metadata bio for FS consistency. | 115 | * this metadata bio for FS consistency. |
125 | */ | 116 | */ |
126 | if (type == META_FLUSH) { | 117 | if (fio->type == META_FLUSH) { |
127 | DECLARE_COMPLETION_ONSTACK(wait); | 118 | DECLARE_COMPLETION_ONSTACK(wait); |
128 | io->bio->bi_private = &wait; | 119 | io->bio->bi_private = &wait; |
129 | submit_bio(rw, io->bio); | 120 | submit_bio(rw, io->bio); |
@@ -131,12 +122,12 @@ static void __submit_merged_bio(struct f2fs_sb_info *sbi, | |||
131 | } else { | 122 | } else { |
132 | submit_bio(rw, io->bio); | 123 | submit_bio(rw, io->bio); |
133 | } | 124 | } |
134 | trace_f2fs_submit_write_bio(sbi->sb, rw, btype, io->bio); | 125 | trace_f2fs_submit_write_bio(io->sbi->sb, rw, fio->type, io->bio); |
135 | io->bio = NULL; | 126 | io->bio = NULL; |
136 | } | 127 | } |
137 | 128 | ||
138 | void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, | 129 | void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, |
139 | enum page_type type, bool sync, int rw) | 130 | enum page_type type, int rw) |
140 | { | 131 | { |
141 | enum page_type btype = PAGE_TYPE_OF_BIO(type); | 132 | enum page_type btype = PAGE_TYPE_OF_BIO(type); |
142 | struct f2fs_bio_info *io; | 133 | struct f2fs_bio_info *io; |
@@ -144,7 +135,13 @@ void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, | |||
144 | io = is_read_io(rw) ? &sbi->read_io : &sbi->write_io[btype]; | 135 | io = is_read_io(rw) ? &sbi->read_io : &sbi->write_io[btype]; |
145 | 136 | ||
146 | mutex_lock(&io->io_mutex); | 137 | mutex_lock(&io->io_mutex); |
147 | __submit_merged_bio(sbi, io, type, sync, rw); | 138 | |
139 | /* change META to META_FLUSH in the checkpoint procedure */ | ||
140 | if (type >= META_FLUSH) { | ||
141 | io->fio.type = META_FLUSH; | ||
142 | io->fio.rw = WRITE_FLUSH_FUA; | ||
143 | } | ||
144 | __submit_merged_bio(io); | ||
148 | mutex_unlock(&io->io_mutex); | 145 | mutex_unlock(&io->io_mutex); |
149 | } | 146 | } |
150 | 147 | ||
@@ -178,33 +175,33 @@ int f2fs_submit_page_bio(struct f2fs_sb_info *sbi, struct page *page, | |||
178 | } | 175 | } |
179 | 176 | ||
180 | void f2fs_submit_page_mbio(struct f2fs_sb_info *sbi, struct page *page, | 177 | void f2fs_submit_page_mbio(struct f2fs_sb_info *sbi, struct page *page, |
181 | block_t blk_addr, enum page_type type, int rw) | 178 | block_t blk_addr, struct f2fs_io_info *fio) |
182 | { | 179 | { |
183 | enum page_type btype = PAGE_TYPE_OF_BIO(type); | 180 | enum page_type btype = PAGE_TYPE_OF_BIO(fio->type); |
184 | struct block_device *bdev = sbi->sb->s_bdev; | 181 | struct block_device *bdev = sbi->sb->s_bdev; |
185 | struct f2fs_bio_info *io; | 182 | struct f2fs_bio_info *io; |
186 | int bio_blocks; | 183 | int bio_blocks; |
187 | 184 | ||
188 | io = is_read_io(rw) ? &sbi->read_io : &sbi->write_io[btype]; | 185 | io = is_read_io(fio->rw) ? &sbi->read_io : &sbi->write_io[btype]; |
189 | 186 | ||
190 | verify_block_addr(sbi, blk_addr); | 187 | verify_block_addr(sbi, blk_addr); |
191 | 188 | ||
192 | mutex_lock(&io->io_mutex); | 189 | mutex_lock(&io->io_mutex); |
193 | 190 | ||
194 | if (!is_read_io(rw)) | 191 | if (!is_read_io(fio->rw)) |
195 | inc_page_count(sbi, F2FS_WRITEBACK); | 192 | inc_page_count(sbi, F2FS_WRITEBACK); |
196 | 193 | ||
197 | if (io->bio && (io->last_block_in_bio != blk_addr - 1 || | 194 | if (io->bio && (io->last_block_in_bio != blk_addr - 1 || |
198 | io->rw_flag != rw)) | 195 | io->fio.rw != fio->rw)) |
199 | __submit_merged_bio(sbi, io, type, false, io->rw_flag); | 196 | __submit_merged_bio(io); |
200 | alloc_new: | 197 | alloc_new: |
201 | if (io->bio == NULL) { | 198 | if (io->bio == NULL) { |
202 | bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); | 199 | bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); |
203 | io->bio = __bio_alloc(bdev, bio_blocks); | 200 | io->bio = __bio_alloc(bdev, bio_blocks); |
204 | io->bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); | 201 | io->bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); |
205 | io->bio->bi_end_io = is_read_io(rw) ? f2fs_read_end_io : | 202 | io->bio->bi_end_io = is_read_io(fio->rw) ? f2fs_read_end_io : |
206 | f2fs_write_end_io; | 203 | f2fs_write_end_io; |
207 | io->rw_flag = rw; | 204 | io->fio = *fio; |
208 | /* | 205 | /* |
209 | * The end_io will be assigned at the sumbission phase. | 206 | * The end_io will be assigned at the sumbission phase. |
210 | * Until then, let bio_add_page() merge consecutive IOs as much | 207 | * Until then, let bio_add_page() merge consecutive IOs as much |
@@ -214,14 +211,14 @@ alloc_new: | |||
214 | 211 | ||
215 | if (bio_add_page(io->bio, page, PAGE_CACHE_SIZE, 0) < | 212 | if (bio_add_page(io->bio, page, PAGE_CACHE_SIZE, 0) < |
216 | PAGE_CACHE_SIZE) { | 213 | PAGE_CACHE_SIZE) { |
217 | __submit_merged_bio(sbi, io, type, false, rw); | 214 | __submit_merged_bio(io); |
218 | goto alloc_new; | 215 | goto alloc_new; |
219 | } | 216 | } |
220 | 217 | ||
221 | io->last_block_in_bio = blk_addr; | 218 | io->last_block_in_bio = blk_addr; |
222 | 219 | ||
223 | mutex_unlock(&io->io_mutex); | 220 | mutex_unlock(&io->io_mutex); |
224 | trace_f2fs_submit_page_mbio(page, rw, type, blk_addr); | 221 | trace_f2fs_submit_page_mbio(page, fio->rw, fio->type, blk_addr); |
225 | } | 222 | } |
226 | 223 | ||
227 | /* | 224 | /* |
@@ -643,10 +640,10 @@ static int f2fs_read_data_pages(struct file *file, | |||
643 | return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro); | 640 | return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro); |
644 | } | 641 | } |
645 | 642 | ||
646 | int do_write_data_page(struct page *page, struct writeback_control *wbc) | 643 | int do_write_data_page(struct page *page, struct f2fs_io_info *fio) |
647 | { | 644 | { |
648 | struct inode *inode = page->mapping->host; | 645 | struct inode *inode = page->mapping->host; |
649 | block_t old_blk_addr, new_blk_addr; | 646 | block_t old_blkaddr, new_blkaddr; |
650 | struct dnode_of_data dn; | 647 | struct dnode_of_data dn; |
651 | int err = 0; | 648 | int err = 0; |
652 | 649 | ||
@@ -655,10 +652,10 @@ int do_write_data_page(struct page *page, struct writeback_control *wbc) | |||
655 | if (err) | 652 | if (err) |
656 | return err; | 653 | return err; |
657 | 654 | ||
658 | old_blk_addr = dn.data_blkaddr; | 655 | old_blkaddr = dn.data_blkaddr; |
659 | 656 | ||
660 | /* This page is already truncated */ | 657 | /* This page is already truncated */ |
661 | if (old_blk_addr == NULL_ADDR) | 658 | if (old_blkaddr == NULL_ADDR) |
662 | goto out_writepage; | 659 | goto out_writepage; |
663 | 660 | ||
664 | set_page_writeback(page); | 661 | set_page_writeback(page); |
@@ -667,15 +664,13 @@ int do_write_data_page(struct page *page, struct writeback_control *wbc) | |||
667 | * If current allocation needs SSR, | 664 | * If current allocation needs SSR, |
668 | * it had better in-place writes for updated data. | 665 | * it had better in-place writes for updated data. |
669 | */ | 666 | */ |
670 | if (unlikely(old_blk_addr != NEW_ADDR && | 667 | if (unlikely(old_blkaddr != NEW_ADDR && |
671 | !is_cold_data(page) && | 668 | !is_cold_data(page) && |
672 | need_inplace_update(inode))) { | 669 | need_inplace_update(inode))) { |
673 | rewrite_data_page(F2FS_SB(inode->i_sb), page, | 670 | rewrite_data_page(page, old_blkaddr, fio); |
674 | old_blk_addr, wbc); | ||
675 | } else { | 671 | } else { |
676 | write_data_page(inode, page, &dn, | 672 | write_data_page(page, &dn, &new_blkaddr, fio); |
677 | old_blk_addr, &new_blk_addr, wbc); | 673 | update_extent_cache(new_blkaddr, &dn); |
678 | update_extent_cache(new_blk_addr, &dn); | ||
679 | } | 674 | } |
680 | out_writepage: | 675 | out_writepage: |
681 | f2fs_put_dnode(&dn); | 676 | f2fs_put_dnode(&dn); |
@@ -693,6 +688,11 @@ static int f2fs_write_data_page(struct page *page, | |||
693 | unsigned offset; | 688 | unsigned offset; |
694 | bool need_balance_fs = false; | 689 | bool need_balance_fs = false; |
695 | int err = 0; | 690 | int err = 0; |
691 | struct f2fs_io_info fio = { | ||
692 | .type = DATA, | ||
693 | .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC: WRITE, | ||
694 | .rw_flag = 0, | ||
695 | }; | ||
696 | 696 | ||
697 | if (page->index < end_index) | 697 | if (page->index < end_index) |
698 | goto write; | 698 | goto write; |
@@ -721,10 +721,10 @@ write: | |||
721 | if (S_ISDIR(inode->i_mode)) { | 721 | if (S_ISDIR(inode->i_mode)) { |
722 | dec_page_count(sbi, F2FS_DIRTY_DENTS); | 722 | dec_page_count(sbi, F2FS_DIRTY_DENTS); |
723 | inode_dec_dirty_dents(inode); | 723 | inode_dec_dirty_dents(inode); |
724 | err = do_write_data_page(page, wbc); | 724 | err = do_write_data_page(page, &fio); |
725 | } else { | 725 | } else { |
726 | f2fs_lock_op(sbi); | 726 | f2fs_lock_op(sbi); |
727 | err = do_write_data_page(page, wbc); | 727 | err = do_write_data_page(page, &fio); |
728 | f2fs_unlock_op(sbi); | 728 | f2fs_unlock_op(sbi); |
729 | need_balance_fs = true; | 729 | need_balance_fs = true; |
730 | } | 730 | } |
@@ -734,7 +734,7 @@ write: | |||
734 | goto redirty_out; | 734 | goto redirty_out; |
735 | 735 | ||
736 | if (wbc->for_reclaim) | 736 | if (wbc->for_reclaim) |
737 | f2fs_submit_merged_bio(sbi, DATA, true, WRITE); | 737 | f2fs_submit_merged_bio(sbi, DATA, WRITE); |
738 | 738 | ||
739 | clear_cold_data(page); | 739 | clear_cold_data(page); |
740 | out: | 740 | out: |
@@ -786,7 +786,8 @@ static int f2fs_write_data_pages(struct address_space *mapping, | |||
786 | ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping); | 786 | ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping); |
787 | if (locked) | 787 | if (locked) |
788 | mutex_unlock(&sbi->writepages); | 788 | mutex_unlock(&sbi->writepages); |
789 | f2fs_submit_merged_bio(sbi, DATA, wbc->sync_mode == WB_SYNC_ALL, WRITE); | 789 | |
790 | f2fs_submit_merged_bio(sbi, DATA, WRITE); | ||
790 | 791 | ||
791 | remove_dirty_dir_inode(inode); | 792 | remove_dirty_dir_inode(inode); |
792 | 793 | ||
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index b1df239ba421..022ce324b166 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -364,11 +364,18 @@ enum page_type { | |||
364 | META_FLUSH, | 364 | META_FLUSH, |
365 | }; | 365 | }; |
366 | 366 | ||
367 | struct f2fs_io_info { | ||
368 | enum page_type type; /* contains DATA/NODE/META/META_FLUSH */ | ||
369 | int rw; /* contains R/RS/W/WS */ | ||
370 | int rw_flag; /* contains REQ_META/REQ_PRIO */ | ||
371 | }; | ||
372 | |||
367 | #define is_read_io(rw) (((rw) & 1) == READ) | 373 | #define is_read_io(rw) (((rw) & 1) == READ) |
368 | struct f2fs_bio_info { | 374 | struct f2fs_bio_info { |
375 | struct f2fs_sb_info *sbi; /* f2fs superblock */ | ||
369 | struct bio *bio; /* bios to merge */ | 376 | struct bio *bio; /* bios to merge */ |
370 | sector_t last_block_in_bio; /* last block number */ | 377 | sector_t last_block_in_bio; /* last block number */ |
371 | int rw_flag; /* rw flag for all pages */ | 378 | struct f2fs_io_info fio; /* store buffered io info. */ |
372 | struct mutex io_mutex; /* mutex for bio */ | 379 | struct mutex io_mutex; /* mutex for bio */ |
373 | }; | 380 | }; |
374 | 381 | ||
@@ -1098,10 +1105,9 @@ struct page *get_sum_page(struct f2fs_sb_info *, unsigned int); | |||
1098 | void write_meta_page(struct f2fs_sb_info *, struct page *); | 1105 | void write_meta_page(struct f2fs_sb_info *, struct page *); |
1099 | void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int, | 1106 | void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int, |
1100 | block_t, block_t *); | 1107 | block_t, block_t *); |
1101 | void write_data_page(struct inode *, struct page *, struct dnode_of_data*, | 1108 | void write_data_page(struct page *, struct dnode_of_data *, block_t *, |
1102 | block_t, block_t *, struct writeback_control *); | 1109 | struct f2fs_io_info *); |
1103 | void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t, | 1110 | void rewrite_data_page(struct page *, block_t, struct f2fs_io_info *); |
1104 | struct writeback_control *); | ||
1105 | void recover_data_page(struct f2fs_sb_info *, struct page *, | 1111 | void recover_data_page(struct f2fs_sb_info *, struct page *, |
1106 | struct f2fs_summary *, block_t, block_t); | 1112 | struct f2fs_summary *, block_t, block_t); |
1107 | void rewrite_node_page(struct f2fs_sb_info *, struct page *, | 1113 | void rewrite_node_page(struct f2fs_sb_info *, struct page *, |
@@ -1142,17 +1148,17 @@ void destroy_checkpoint_caches(void); | |||
1142 | /* | 1148 | /* |
1143 | * data.c | 1149 | * data.c |
1144 | */ | 1150 | */ |
1145 | void f2fs_submit_merged_bio(struct f2fs_sb_info *, enum page_type, bool, int); | 1151 | void f2fs_submit_merged_bio(struct f2fs_sb_info *, enum page_type, int); |
1146 | int f2fs_submit_page_bio(struct f2fs_sb_info *, struct page *, block_t, int); | 1152 | int f2fs_submit_page_bio(struct f2fs_sb_info *, struct page *, block_t, int); |
1147 | void f2fs_submit_page_mbio(struct f2fs_sb_info *, struct page *, block_t, | 1153 | void f2fs_submit_page_mbio(struct f2fs_sb_info *, struct page *, block_t, |
1148 | enum page_type, int); | 1154 | struct f2fs_io_info *); |
1149 | int reserve_new_block(struct dnode_of_data *); | 1155 | int reserve_new_block(struct dnode_of_data *); |
1150 | int f2fs_reserve_block(struct dnode_of_data *, pgoff_t); | 1156 | int f2fs_reserve_block(struct dnode_of_data *, pgoff_t); |
1151 | void update_extent_cache(block_t, struct dnode_of_data *); | 1157 | void update_extent_cache(block_t, struct dnode_of_data *); |
1152 | struct page *find_data_page(struct inode *, pgoff_t, bool); | 1158 | struct page *find_data_page(struct inode *, pgoff_t, bool); |
1153 | struct page *get_lock_data_page(struct inode *, pgoff_t); | 1159 | struct page *get_lock_data_page(struct inode *, pgoff_t); |
1154 | struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool); | 1160 | struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool); |
1155 | int do_write_data_page(struct page *, struct writeback_control *); | 1161 | int do_write_data_page(struct page *, struct f2fs_io_info *); |
1156 | 1162 | ||
1157 | /* | 1163 | /* |
1158 | * gc.c | 1164 | * gc.c |
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index c68fba5ffadb..69c18e399014 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -520,8 +520,10 @@ static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, | |||
520 | 520 | ||
521 | static void move_data_page(struct inode *inode, struct page *page, int gc_type) | 521 | static void move_data_page(struct inode *inode, struct page *page, int gc_type) |
522 | { | 522 | { |
523 | struct writeback_control wbc = { | 523 | struct f2fs_io_info fio = { |
524 | .sync_mode = 1, | 524 | .type = DATA, |
525 | .rw = WRITE_SYNC, | ||
526 | .rw_flag = 0, | ||
525 | }; | 527 | }; |
526 | 528 | ||
527 | if (gc_type == BG_GC) { | 529 | if (gc_type == BG_GC) { |
@@ -540,7 +542,7 @@ static void move_data_page(struct inode *inode, struct page *page, int gc_type) | |||
540 | inode_dec_dirty_dents(inode); | 542 | inode_dec_dirty_dents(inode); |
541 | } | 543 | } |
542 | set_cold_data(page); | 544 | set_cold_data(page); |
543 | do_write_data_page(page, &wbc); | 545 | do_write_data_page(page, &fio); |
544 | clear_cold_data(page); | 546 | clear_cold_data(page); |
545 | } | 547 | } |
546 | out: | 548 | out: |
@@ -634,7 +636,7 @@ next_iput: | |||
634 | goto next_step; | 636 | goto next_step; |
635 | 637 | ||
636 | if (gc_type == FG_GC) { | 638 | if (gc_type == FG_GC) { |
637 | f2fs_submit_merged_bio(sbi, DATA, true, WRITE); | 639 | f2fs_submit_merged_bio(sbi, DATA, WRITE); |
638 | 640 | ||
639 | /* | 641 | /* |
640 | * In the case of FG_GC, it'd be better to reclaim this victim | 642 | * In the case of FG_GC, it'd be better to reclaim this victim |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 6c6ef772cf01..3565caf97005 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -92,6 +92,12 @@ static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid) | |||
92 | struct page *page; | 92 | struct page *page; |
93 | pgoff_t index; | 93 | pgoff_t index; |
94 | int i; | 94 | int i; |
95 | struct f2fs_io_info fio = { | ||
96 | .type = META, | ||
97 | .rw = READ_SYNC, | ||
98 | .rw_flag = REQ_META | REQ_PRIO | ||
99 | }; | ||
100 | |||
95 | 101 | ||
96 | for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) { | 102 | for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) { |
97 | if (unlikely(nid >= nm_i->max_nid)) | 103 | if (unlikely(nid >= nm_i->max_nid)) |
@@ -106,11 +112,11 @@ static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid) | |||
106 | f2fs_put_page(page, 1); | 112 | f2fs_put_page(page, 1); |
107 | continue; | 113 | continue; |
108 | } | 114 | } |
109 | f2fs_submit_page_mbio(sbi, page, index, META, READ); | 115 | f2fs_submit_page_mbio(sbi, page, index, &fio); |
110 | mark_page_accessed(page); | 116 | mark_page_accessed(page); |
111 | f2fs_put_page(page, 0); | 117 | f2fs_put_page(page, 0); |
112 | } | 118 | } |
113 | f2fs_submit_merged_bio(sbi, META, true, READ); | 119 | f2fs_submit_merged_bio(sbi, META, READ); |
114 | } | 120 | } |
115 | 121 | ||
116 | static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n) | 122 | static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n) |
@@ -1136,8 +1142,7 @@ continue_unlock: | |||
1136 | } | 1142 | } |
1137 | 1143 | ||
1138 | if (wrote) | 1144 | if (wrote) |
1139 | f2fs_submit_merged_bio(sbi, NODE, wbc->sync_mode == WB_SYNC_ALL, | 1145 | f2fs_submit_merged_bio(sbi, NODE, WRITE); |
1140 | WRITE); | ||
1141 | return nwritten; | 1146 | return nwritten; |
1142 | } | 1147 | } |
1143 | 1148 | ||
@@ -1574,6 +1579,11 @@ static int ra_sum_pages(struct f2fs_sb_info *sbi, struct list_head *pages, | |||
1574 | { | 1579 | { |
1575 | struct page *page; | 1580 | struct page *page; |
1576 | int page_idx = start; | 1581 | int page_idx = start; |
1582 | struct f2fs_io_info fio = { | ||
1583 | .type = META, | ||
1584 | .rw = READ_SYNC, | ||
1585 | .rw_flag = REQ_META | REQ_PRIO | ||
1586 | }; | ||
1577 | 1587 | ||
1578 | for (; page_idx < start + nrpages; page_idx++) { | 1588 | for (; page_idx < start + nrpages; page_idx++) { |
1579 | /* alloc temporal page for read node summary info*/ | 1589 | /* alloc temporal page for read node summary info*/ |
@@ -1594,9 +1604,9 @@ static int ra_sum_pages(struct f2fs_sb_info *sbi, struct list_head *pages, | |||
1594 | } | 1604 | } |
1595 | 1605 | ||
1596 | list_for_each_entry(page, pages, lru) | 1606 | list_for_each_entry(page, pages, lru) |
1597 | f2fs_submit_page_mbio(sbi, page, page->index, META, READ); | 1607 | f2fs_submit_page_mbio(sbi, page, page->index, &fio); |
1598 | 1608 | ||
1599 | f2fs_submit_merged_bio(sbi, META, true, READ); | 1609 | f2fs_submit_merged_bio(sbi, META, READ); |
1600 | return 0; | 1610 | return 0; |
1601 | } | 1611 | } |
1602 | 1612 | ||
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index e5dc41114867..0b2e8ceec983 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -856,15 +856,14 @@ static int __get_segment_type(struct page *page, enum page_type p_type) | |||
856 | 856 | ||
857 | static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, | 857 | static 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, struct f2fs_io_info *fio) |
860 | struct writeback_control *wbc) | ||
861 | { | 860 | { |
862 | struct sit_info *sit_i = SIT_I(sbi); | 861 | struct sit_info *sit_i = SIT_I(sbi); |
863 | struct curseg_info *curseg; | 862 | struct curseg_info *curseg; |
864 | unsigned int old_cursegno; | 863 | unsigned int old_cursegno; |
865 | int type, rw = WRITE; | 864 | int type; |
866 | 865 | ||
867 | type = __get_segment_type(page, p_type); | 866 | type = __get_segment_type(page, fio->type); |
868 | curseg = CURSEG_I(sbi, type); | 867 | curseg = CURSEG_I(sbi, type); |
869 | 868 | ||
870 | mutex_lock(&curseg->curseg_mutex); | 869 | mutex_lock(&curseg->curseg_mutex); |
@@ -897,55 +896,60 @@ static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, | |||
897 | locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); | 896 | locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); |
898 | mutex_unlock(&sit_i->sentry_lock); | 897 | mutex_unlock(&sit_i->sentry_lock); |
899 | 898 | ||
900 | if (p_type == NODE) | 899 | if (fio->type == NODE) |
901 | fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg)); | 900 | fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg)); |
902 | 901 | ||
903 | /* writeout dirty page into bdev */ | 902 | /* writeout dirty page into bdev */ |
904 | if (wbc->sync_mode == WB_SYNC_ALL) | 903 | f2fs_submit_page_mbio(sbi, page, *new_blkaddr, fio); |
905 | rw |= WRITE_SYNC; | ||
906 | f2fs_submit_page_mbio(sbi, page, *new_blkaddr, p_type, rw); | ||
907 | 904 | ||
908 | mutex_unlock(&curseg->curseg_mutex); | 905 | mutex_unlock(&curseg->curseg_mutex); |
909 | } | 906 | } |
910 | 907 | ||
911 | void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) | 908 | void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) |
912 | { | 909 | { |
910 | struct f2fs_io_info fio = { | ||
911 | .type = META, | ||
912 | .rw = WRITE_SYNC, | ||
913 | .rw_flag = REQ_META | REQ_PRIO | ||
914 | }; | ||
915 | |||
913 | set_page_writeback(page); | 916 | set_page_writeback(page); |
914 | f2fs_submit_page_mbio(sbi, page, page->index, META, WRITE); | 917 | f2fs_submit_page_mbio(sbi, page, page->index, &fio); |
915 | } | 918 | } |
916 | 919 | ||
917 | void write_node_page(struct f2fs_sb_info *sbi, struct page *page, | 920 | void write_node_page(struct f2fs_sb_info *sbi, struct page *page, |
918 | unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr) | 921 | unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr) |
919 | { | 922 | { |
920 | struct f2fs_summary sum; | 923 | struct f2fs_summary sum; |
921 | struct writeback_control wbc = { | 924 | struct f2fs_io_info fio = { |
922 | .sync_mode = 1, | 925 | .type = NODE, |
926 | .rw = WRITE_SYNC, | ||
927 | .rw_flag = 0 | ||
923 | }; | 928 | }; |
929 | |||
924 | set_summary(&sum, nid, 0, 0); | 930 | set_summary(&sum, nid, 0, 0); |
925 | do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE, &wbc); | 931 | do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, &fio); |
926 | } | 932 | } |
927 | 933 | ||
928 | void write_data_page(struct inode *inode, struct page *page, | 934 | void write_data_page(struct page *page, struct dnode_of_data *dn, |
929 | struct dnode_of_data *dn, block_t old_blkaddr, | 935 | block_t *new_blkaddr, struct f2fs_io_info *fio) |
930 | block_t *new_blkaddr, struct writeback_control *wbc) | ||
931 | { | 936 | { |
932 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 937 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
933 | struct f2fs_summary sum; | 938 | struct f2fs_summary sum; |
934 | struct node_info ni; | 939 | struct node_info ni; |
935 | 940 | ||
936 | f2fs_bug_on(old_blkaddr == NULL_ADDR); | 941 | f2fs_bug_on(dn->data_blkaddr == NULL_ADDR); |
937 | get_node_info(sbi, dn->nid, &ni); | 942 | get_node_info(sbi, dn->nid, &ni); |
938 | set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); | 943 | set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); |
939 | 944 | ||
940 | do_write_page(sbi, page, old_blkaddr, | 945 | do_write_page(sbi, page, dn->data_blkaddr, new_blkaddr, &sum, fio); |
941 | new_blkaddr, &sum, DATA, wbc); | ||
942 | } | 946 | } |
943 | 947 | ||
944 | void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page, | 948 | void rewrite_data_page(struct page *page, block_t old_blkaddr, struct f2fs_io_info *fio) |
945 | block_t old_blk_addr, struct writeback_control *wbc) | ||
946 | { | 949 | { |
947 | int rw = wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE; | 950 | struct inode *inode = page->mapping->host; |
948 | f2fs_submit_page_mbio(sbi, page, old_blk_addr, DATA, rw); | 951 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
952 | f2fs_submit_page_mbio(sbi, page, old_blkaddr, fio); | ||
949 | } | 953 | } |
950 | 954 | ||
951 | void recover_data_page(struct f2fs_sb_info *sbi, | 955 | void recover_data_page(struct f2fs_sb_info *sbi, |
@@ -1004,6 +1008,11 @@ void rewrite_node_page(struct f2fs_sb_info *sbi, | |||
1004 | unsigned int segno, old_cursegno; | 1008 | unsigned int segno, old_cursegno; |
1005 | block_t next_blkaddr = next_blkaddr_of_node(page); | 1009 | block_t next_blkaddr = next_blkaddr_of_node(page); |
1006 | unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr); | 1010 | unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr); |
1011 | struct f2fs_io_info fio = { | ||
1012 | .type = NODE, | ||
1013 | .rw = WRITE_SYNC, | ||
1014 | .rw_flag = 0 | ||
1015 | }; | ||
1007 | 1016 | ||
1008 | curseg = CURSEG_I(sbi, type); | 1017 | curseg = CURSEG_I(sbi, type); |
1009 | 1018 | ||
@@ -1032,8 +1041,8 @@ void rewrite_node_page(struct f2fs_sb_info *sbi, | |||
1032 | 1041 | ||
1033 | /* rewrite node page */ | 1042 | /* rewrite node page */ |
1034 | set_page_writeback(page); | 1043 | set_page_writeback(page); |
1035 | f2fs_submit_page_mbio(sbi, page, new_blkaddr, NODE, WRITE_SYNC); | 1044 | f2fs_submit_page_mbio(sbi, page, new_blkaddr, &fio); |
1036 | f2fs_submit_merged_bio(sbi, NODE, true, WRITE); | 1045 | f2fs_submit_merged_bio(sbi, NODE, WRITE); |
1037 | refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); | 1046 | refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); |
1038 | 1047 | ||
1039 | locate_dirty_segment(sbi, old_cursegno); | 1048 | locate_dirty_segment(sbi, old_cursegno); |
@@ -1048,7 +1057,7 @@ void f2fs_wait_on_page_writeback(struct page *page, | |||
1048 | { | 1057 | { |
1049 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); | 1058 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); |
1050 | if (PageWriteback(page)) { | 1059 | if (PageWriteback(page)) { |
1051 | f2fs_submit_merged_bio(sbi, type, sync, WRITE); | 1060 | f2fs_submit_merged_bio(sbi, type, WRITE); |
1052 | wait_on_page_writeback(page); | 1061 | wait_on_page_writeback(page); |
1053 | } | 1062 | } |
1054 | } | 1063 | } |
@@ -1580,6 +1589,11 @@ static int ra_sit_pages(struct f2fs_sb_info *sbi, int start, int nrpages) | |||
1580 | block_t blk_addr, prev_blk_addr = 0; | 1589 | block_t blk_addr, prev_blk_addr = 0; |
1581 | int sit_blk_cnt = SIT_BLK_CNT(sbi); | 1590 | int sit_blk_cnt = SIT_BLK_CNT(sbi); |
1582 | int blkno = start; | 1591 | int blkno = start; |
1592 | struct f2fs_io_info fio = { | ||
1593 | .type = META, | ||
1594 | .rw = READ_SYNC, | ||
1595 | .rw_flag = REQ_META | REQ_PRIO | ||
1596 | }; | ||
1583 | 1597 | ||
1584 | for (; blkno < start + nrpages && blkno < sit_blk_cnt; blkno++) { | 1598 | for (; blkno < start + nrpages && blkno < sit_blk_cnt; blkno++) { |
1585 | 1599 | ||
@@ -1600,13 +1614,13 @@ repeat: | |||
1600 | continue; | 1614 | continue; |
1601 | } | 1615 | } |
1602 | 1616 | ||
1603 | f2fs_submit_page_mbio(sbi, page, blk_addr, META, READ_SYNC); | 1617 | f2fs_submit_page_mbio(sbi, page, blk_addr, &fio); |
1604 | 1618 | ||
1605 | mark_page_accessed(page); | 1619 | mark_page_accessed(page); |
1606 | f2fs_put_page(page, 0); | 1620 | f2fs_put_page(page, 0); |
1607 | } | 1621 | } |
1608 | 1622 | ||
1609 | f2fs_submit_merged_bio(sbi, META, true, READ); | 1623 | f2fs_submit_merged_bio(sbi, META, READ); |
1610 | return blkno - start; | 1624 | return blkno - start; |
1611 | } | 1625 | } |
1612 | 1626 | ||
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 68df44afd14b..1674f2f9970d 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -885,8 +885,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
885 | spin_lock_init(&sbi->stat_lock); | 885 | spin_lock_init(&sbi->stat_lock); |
886 | 886 | ||
887 | mutex_init(&sbi->read_io.io_mutex); | 887 | mutex_init(&sbi->read_io.io_mutex); |
888 | for (i = 0; i < NR_PAGE_TYPE; i++) | 888 | sbi->read_io.sbi = sbi; |
889 | sbi->read_io.bio = NULL; | ||
890 | for (i = 0; i < NR_PAGE_TYPE; i++) { | ||
889 | mutex_init(&sbi->write_io[i].io_mutex); | 891 | mutex_init(&sbi->write_io[i].io_mutex); |
892 | sbi->write_io[i].sbi = sbi; | ||
893 | sbi->write_io[i].bio = NULL; | ||
894 | } | ||
890 | 895 | ||
891 | init_rwsem(&sbi->cp_rwsem); | 896 | init_rwsem(&sbi->cp_rwsem); |
892 | init_waitqueue_head(&sbi->cp_wait); | 897 | init_waitqueue_head(&sbi->cp_wait); |