diff options
Diffstat (limited to 'fs/f2fs/checkpoint.c')
-rw-r--r-- | fs/f2fs/checkpoint.c | 77 |
1 files changed, 52 insertions, 25 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 3842af954cd5..0955312e5ca0 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -39,7 +39,7 @@ repeat: | |||
39 | cond_resched(); | 39 | cond_resched(); |
40 | goto repeat; | 40 | goto repeat; |
41 | } | 41 | } |
42 | f2fs_wait_on_page_writeback(page, META); | 42 | f2fs_wait_on_page_writeback(page, META, true); |
43 | SetPageUptodate(page); | 43 | SetPageUptodate(page); |
44 | return page; | 44 | return page; |
45 | } | 45 | } |
@@ -56,7 +56,8 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index, | |||
56 | .sbi = sbi, | 56 | .sbi = sbi, |
57 | .type = META, | 57 | .type = META, |
58 | .rw = READ_SYNC | REQ_META | REQ_PRIO, | 58 | .rw = READ_SYNC | REQ_META | REQ_PRIO, |
59 | .blk_addr = index, | 59 | .old_blkaddr = index, |
60 | .new_blkaddr = index, | ||
60 | .encrypted_page = NULL, | 61 | .encrypted_page = NULL, |
61 | }; | 62 | }; |
62 | 63 | ||
@@ -143,7 +144,6 @@ bool is_valid_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr, int type) | |||
143 | int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, | 144 | int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, |
144 | int type, bool sync) | 145 | int type, bool sync) |
145 | { | 146 | { |
146 | block_t prev_blk_addr = 0; | ||
147 | struct page *page; | 147 | struct page *page; |
148 | block_t blkno = start; | 148 | block_t blkno = start; |
149 | struct f2fs_io_info fio = { | 149 | struct f2fs_io_info fio = { |
@@ -152,10 +152,12 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, | |||
152 | .rw = sync ? (READ_SYNC | REQ_META | REQ_PRIO) : READA, | 152 | .rw = sync ? (READ_SYNC | REQ_META | REQ_PRIO) : READA, |
153 | .encrypted_page = NULL, | 153 | .encrypted_page = NULL, |
154 | }; | 154 | }; |
155 | struct blk_plug plug; | ||
155 | 156 | ||
156 | if (unlikely(type == META_POR)) | 157 | if (unlikely(type == META_POR)) |
157 | fio.rw &= ~REQ_META; | 158 | fio.rw &= ~REQ_META; |
158 | 159 | ||
160 | blk_start_plug(&plug); | ||
159 | for (; nrpages-- > 0; blkno++) { | 161 | for (; nrpages-- > 0; blkno++) { |
160 | 162 | ||
161 | if (!is_valid_blkaddr(sbi, blkno, type)) | 163 | if (!is_valid_blkaddr(sbi, blkno, type)) |
@@ -167,27 +169,24 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, | |||
167 | NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid))) | 169 | NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid))) |
168 | blkno = 0; | 170 | blkno = 0; |
169 | /* get nat block addr */ | 171 | /* get nat block addr */ |
170 | fio.blk_addr = current_nat_addr(sbi, | 172 | fio.new_blkaddr = current_nat_addr(sbi, |
171 | blkno * NAT_ENTRY_PER_BLOCK); | 173 | blkno * NAT_ENTRY_PER_BLOCK); |
172 | break; | 174 | break; |
173 | case META_SIT: | 175 | case META_SIT: |
174 | /* get sit block addr */ | 176 | /* get sit block addr */ |
175 | fio.blk_addr = current_sit_addr(sbi, | 177 | fio.new_blkaddr = current_sit_addr(sbi, |
176 | blkno * SIT_ENTRY_PER_BLOCK); | 178 | blkno * SIT_ENTRY_PER_BLOCK); |
177 | if (blkno != start && prev_blk_addr + 1 != fio.blk_addr) | ||
178 | goto out; | ||
179 | prev_blk_addr = fio.blk_addr; | ||
180 | break; | 179 | break; |
181 | case META_SSA: | 180 | case META_SSA: |
182 | case META_CP: | 181 | case META_CP: |
183 | case META_POR: | 182 | case META_POR: |
184 | fio.blk_addr = blkno; | 183 | fio.new_blkaddr = blkno; |
185 | break; | 184 | break; |
186 | default: | 185 | default: |
187 | BUG(); | 186 | BUG(); |
188 | } | 187 | } |
189 | 188 | ||
190 | page = grab_cache_page(META_MAPPING(sbi), fio.blk_addr); | 189 | page = grab_cache_page(META_MAPPING(sbi), fio.new_blkaddr); |
191 | if (!page) | 190 | if (!page) |
192 | continue; | 191 | continue; |
193 | if (PageUptodate(page)) { | 192 | if (PageUptodate(page)) { |
@@ -196,11 +195,13 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, | |||
196 | } | 195 | } |
197 | 196 | ||
198 | fio.page = page; | 197 | fio.page = page; |
198 | fio.old_blkaddr = fio.new_blkaddr; | ||
199 | f2fs_submit_page_mbio(&fio); | 199 | f2fs_submit_page_mbio(&fio); |
200 | f2fs_put_page(page, 0); | 200 | f2fs_put_page(page, 0); |
201 | } | 201 | } |
202 | out: | 202 | out: |
203 | f2fs_submit_merged_bio(sbi, META, READ); | 203 | f2fs_submit_merged_bio(sbi, META, READ); |
204 | blk_finish_plug(&plug); | ||
204 | return blkno - start; | 205 | return blkno - start; |
205 | } | 206 | } |
206 | 207 | ||
@@ -232,13 +233,17 @@ static int f2fs_write_meta_page(struct page *page, | |||
232 | if (unlikely(f2fs_cp_error(sbi))) | 233 | if (unlikely(f2fs_cp_error(sbi))) |
233 | goto redirty_out; | 234 | goto redirty_out; |
234 | 235 | ||
235 | f2fs_wait_on_page_writeback(page, META); | ||
236 | write_meta_page(sbi, page); | 236 | write_meta_page(sbi, page); |
237 | dec_page_count(sbi, F2FS_DIRTY_META); | 237 | dec_page_count(sbi, F2FS_DIRTY_META); |
238 | |||
239 | if (wbc->for_reclaim) | ||
240 | f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, META, WRITE); | ||
241 | |||
238 | unlock_page(page); | 242 | unlock_page(page); |
239 | 243 | ||
240 | if (wbc->for_reclaim || unlikely(f2fs_cp_error(sbi))) | 244 | if (unlikely(f2fs_cp_error(sbi))) |
241 | f2fs_submit_merged_bio(sbi, META, WRITE); | 245 | f2fs_submit_merged_bio(sbi, META, WRITE); |
246 | |||
242 | return 0; | 247 | return 0; |
243 | 248 | ||
244 | redirty_out: | 249 | redirty_out: |
@@ -252,13 +257,13 @@ static int f2fs_write_meta_pages(struct address_space *mapping, | |||
252 | struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); | 257 | struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); |
253 | long diff, written; | 258 | long diff, written; |
254 | 259 | ||
255 | trace_f2fs_writepages(mapping->host, wbc, META); | ||
256 | |||
257 | /* collect a number of dirty meta pages and write together */ | 260 | /* collect a number of dirty meta pages and write together */ |
258 | if (wbc->for_kupdate || | 261 | if (wbc->for_kupdate || |
259 | get_pages(sbi, F2FS_DIRTY_META) < nr_pages_to_skip(sbi, META)) | 262 | get_pages(sbi, F2FS_DIRTY_META) < nr_pages_to_skip(sbi, META)) |
260 | goto skip_write; | 263 | goto skip_write; |
261 | 264 | ||
265 | trace_f2fs_writepages(mapping->host, wbc, META); | ||
266 | |||
262 | /* if mounting is failed, skip writing node pages */ | 267 | /* if mounting is failed, skip writing node pages */ |
263 | mutex_lock(&sbi->cp_mutex); | 268 | mutex_lock(&sbi->cp_mutex); |
264 | diff = nr_pages_to_write(sbi, META, wbc); | 269 | diff = nr_pages_to_write(sbi, META, wbc); |
@@ -269,6 +274,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping, | |||
269 | 274 | ||
270 | skip_write: | 275 | skip_write: |
271 | wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_META); | 276 | wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_META); |
277 | trace_f2fs_writepages(mapping->host, wbc, META); | ||
272 | return 0; | 278 | return 0; |
273 | } | 279 | } |
274 | 280 | ||
@@ -276,15 +282,18 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type, | |||
276 | long nr_to_write) | 282 | long nr_to_write) |
277 | { | 283 | { |
278 | struct address_space *mapping = META_MAPPING(sbi); | 284 | struct address_space *mapping = META_MAPPING(sbi); |
279 | pgoff_t index = 0, end = LONG_MAX, prev = LONG_MAX; | 285 | pgoff_t index = 0, end = ULONG_MAX, prev = ULONG_MAX; |
280 | struct pagevec pvec; | 286 | struct pagevec pvec; |
281 | long nwritten = 0; | 287 | long nwritten = 0; |
282 | struct writeback_control wbc = { | 288 | struct writeback_control wbc = { |
283 | .for_reclaim = 0, | 289 | .for_reclaim = 0, |
284 | }; | 290 | }; |
291 | struct blk_plug plug; | ||
285 | 292 | ||
286 | pagevec_init(&pvec, 0); | 293 | pagevec_init(&pvec, 0); |
287 | 294 | ||
295 | blk_start_plug(&plug); | ||
296 | |||
288 | while (index <= end) { | 297 | while (index <= end) { |
289 | int i, nr_pages; | 298 | int i, nr_pages; |
290 | nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, | 299 | nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, |
@@ -296,7 +305,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type, | |||
296 | for (i = 0; i < nr_pages; i++) { | 305 | for (i = 0; i < nr_pages; i++) { |
297 | struct page *page = pvec.pages[i]; | 306 | struct page *page = pvec.pages[i]; |
298 | 307 | ||
299 | if (prev == LONG_MAX) | 308 | if (prev == ULONG_MAX) |
300 | prev = page->index - 1; | 309 | prev = page->index - 1; |
301 | if (nr_to_write != LONG_MAX && page->index != prev + 1) { | 310 | if (nr_to_write != LONG_MAX && page->index != prev + 1) { |
302 | pagevec_release(&pvec); | 311 | pagevec_release(&pvec); |
@@ -315,6 +324,9 @@ continue_unlock: | |||
315 | goto continue_unlock; | 324 | goto continue_unlock; |
316 | } | 325 | } |
317 | 326 | ||
327 | f2fs_wait_on_page_writeback(page, META, true); | ||
328 | |||
329 | BUG_ON(PageWriteback(page)); | ||
318 | if (!clear_page_dirty_for_io(page)) | 330 | if (!clear_page_dirty_for_io(page)) |
319 | goto continue_unlock; | 331 | goto continue_unlock; |
320 | 332 | ||
@@ -334,6 +346,8 @@ stop: | |||
334 | if (nwritten) | 346 | if (nwritten) |
335 | f2fs_submit_merged_bio(sbi, type, WRITE); | 347 | f2fs_submit_merged_bio(sbi, type, WRITE); |
336 | 348 | ||
349 | blk_finish_plug(&plug); | ||
350 | |||
337 | return nwritten; | 351 | return nwritten; |
338 | } | 352 | } |
339 | 353 | ||
@@ -621,7 +635,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, | |||
621 | goto invalid_cp1; | 635 | goto invalid_cp1; |
622 | 636 | ||
623 | crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset))); | 637 | crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset))); |
624 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) | 638 | if (!f2fs_crc_valid(sbi, crc, cp_block, crc_offset)) |
625 | goto invalid_cp1; | 639 | goto invalid_cp1; |
626 | 640 | ||
627 | pre_version = cur_cp_version(cp_block); | 641 | pre_version = cur_cp_version(cp_block); |
@@ -636,7 +650,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, | |||
636 | goto invalid_cp2; | 650 | goto invalid_cp2; |
637 | 651 | ||
638 | crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset))); | 652 | crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset))); |
639 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) | 653 | if (!f2fs_crc_valid(sbi, crc, cp_block, crc_offset)) |
640 | goto invalid_cp2; | 654 | goto invalid_cp2; |
641 | 655 | ||
642 | cur_version = cur_cp_version(cp_block); | 656 | cur_version = cur_cp_version(cp_block); |
@@ -696,6 +710,10 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) | |||
696 | cp_block = (struct f2fs_checkpoint *)page_address(cur_page); | 710 | cp_block = (struct f2fs_checkpoint *)page_address(cur_page); |
697 | memcpy(sbi->ckpt, cp_block, blk_size); | 711 | memcpy(sbi->ckpt, cp_block, blk_size); |
698 | 712 | ||
713 | /* Sanity checking of checkpoint */ | ||
714 | if (sanity_check_ckpt(sbi)) | ||
715 | goto fail_no_cp; | ||
716 | |||
699 | if (cp_blks <= 1) | 717 | if (cp_blks <= 1) |
700 | goto done; | 718 | goto done; |
701 | 719 | ||
@@ -902,7 +920,7 @@ static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi) | |||
902 | if (!get_pages(sbi, F2FS_WRITEBACK)) | 920 | if (!get_pages(sbi, F2FS_WRITEBACK)) |
903 | break; | 921 | break; |
904 | 922 | ||
905 | io_schedule(); | 923 | io_schedule_timeout(5*HZ); |
906 | } | 924 | } |
907 | finish_wait(&sbi->cp_wait, &wait); | 925 | finish_wait(&sbi->cp_wait, &wait); |
908 | } | 926 | } |
@@ -921,6 +939,9 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
921 | int cp_payload_blks = __cp_payload(sbi); | 939 | int cp_payload_blks = __cp_payload(sbi); |
922 | block_t discard_blk = NEXT_FREE_BLKADDR(sbi, curseg); | 940 | block_t discard_blk = NEXT_FREE_BLKADDR(sbi, curseg); |
923 | bool invalidate = false; | 941 | bool invalidate = false; |
942 | struct super_block *sb = sbi->sb; | ||
943 | struct curseg_info *seg_i = CURSEG_I(sbi, CURSEG_HOT_NODE); | ||
944 | u64 kbytes_written; | ||
924 | 945 | ||
925 | /* | 946 | /* |
926 | * This avoids to conduct wrong roll-forward operations and uses | 947 | * This avoids to conduct wrong roll-forward operations and uses |
@@ -1008,7 +1029,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1008 | get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP)); | 1029 | get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP)); |
1009 | get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP)); | 1030 | get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP)); |
1010 | 1031 | ||
1011 | crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset)); | 1032 | crc32 = f2fs_crc32(sbi, ckpt, le32_to_cpu(ckpt->checksum_offset)); |
1012 | *((__le32 *)((unsigned char *)ckpt + | 1033 | *((__le32 *)((unsigned char *)ckpt + |
1013 | le32_to_cpu(ckpt->checksum_offset))) | 1034 | le32_to_cpu(ckpt->checksum_offset))) |
1014 | = cpu_to_le32(crc32); | 1035 | = cpu_to_le32(crc32); |
@@ -1034,6 +1055,14 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1034 | 1055 | ||
1035 | write_data_summaries(sbi, start_blk); | 1056 | write_data_summaries(sbi, start_blk); |
1036 | start_blk += data_sum_blocks; | 1057 | start_blk += data_sum_blocks; |
1058 | |||
1059 | /* Record write statistics in the hot node summary */ | ||
1060 | kbytes_written = sbi->kbytes_written; | ||
1061 | if (sb->s_bdev->bd_part) | ||
1062 | kbytes_written += BD_PART_WRITTEN(sbi); | ||
1063 | |||
1064 | seg_i->journal->info.kbytes_written = cpu_to_le64(kbytes_written); | ||
1065 | |||
1037 | if (__remain_node_summaries(cpc->reason)) { | 1066 | if (__remain_node_summaries(cpc->reason)) { |
1038 | write_node_summaries(sbi, start_blk); | 1067 | write_node_summaries(sbi, start_blk); |
1039 | start_blk += NR_CURSEG_NODE_TYPE; | 1068 | start_blk += NR_CURSEG_NODE_TYPE; |
@@ -1048,8 +1077,8 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1048 | if (unlikely(f2fs_cp_error(sbi))) | 1077 | if (unlikely(f2fs_cp_error(sbi))) |
1049 | return -EIO; | 1078 | return -EIO; |
1050 | 1079 | ||
1051 | filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX); | 1080 | filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LLONG_MAX); |
1052 | filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX); | 1081 | filemap_fdatawait_range(META_MAPPING(sbi), 0, LLONG_MAX); |
1053 | 1082 | ||
1054 | /* update user_block_counts */ | 1083 | /* update user_block_counts */ |
1055 | sbi->last_valid_block_count = sbi->total_valid_block_count; | 1084 | sbi->last_valid_block_count = sbi->total_valid_block_count; |
@@ -1112,9 +1141,7 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1112 | 1141 | ||
1113 | trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops"); | 1142 | trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops"); |
1114 | 1143 | ||
1115 | f2fs_submit_merged_bio(sbi, DATA, WRITE); | 1144 | f2fs_flush_merged_bios(sbi); |
1116 | f2fs_submit_merged_bio(sbi, NODE, WRITE); | ||
1117 | f2fs_submit_merged_bio(sbi, META, WRITE); | ||
1118 | 1145 | ||
1119 | /* | 1146 | /* |
1120 | * update checkpoint pack index | 1147 | * update checkpoint pack index |