diff options
-rw-r--r-- | fs/f2fs/checkpoint.c | 6 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 1 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 17 |
3 files changed, 22 insertions, 2 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 4aa521aa9bc3..890e23d208a8 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -762,6 +762,12 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
762 | void *kaddr; | 762 | void *kaddr; |
763 | int i; | 763 | int i; |
764 | 764 | ||
765 | /* | ||
766 | * This avoids to conduct wrong roll-forward operations and uses | ||
767 | * metapages, so should be called prior to sync_meta_pages below. | ||
768 | */ | ||
769 | discard_next_dnode(sbi); | ||
770 | |||
765 | /* Flush all the NAT/SIT pages */ | 771 | /* Flush all the NAT/SIT pages */ |
766 | while (get_pages(sbi, F2FS_DIRTY_META)) | 772 | while (get_pages(sbi, F2FS_DIRTY_META)) |
767 | sync_meta_pages(sbi, META, LONG_MAX); | 773 | sync_meta_pages(sbi, META, LONG_MAX); |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 2ecac8312359..2c5a5dadae65 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -1179,6 +1179,7 @@ int f2fs_issue_flush(struct f2fs_sb_info *); | |||
1179 | void invalidate_blocks(struct f2fs_sb_info *, block_t); | 1179 | void invalidate_blocks(struct f2fs_sb_info *, block_t); |
1180 | void refresh_sit_entry(struct f2fs_sb_info *, block_t, block_t); | 1180 | void refresh_sit_entry(struct f2fs_sb_info *, block_t, block_t); |
1181 | void clear_prefree_segments(struct f2fs_sb_info *); | 1181 | void clear_prefree_segments(struct f2fs_sb_info *); |
1182 | void discard_next_dnode(struct f2fs_sb_info *); | ||
1182 | int npages_for_summary_flush(struct f2fs_sb_info *); | 1183 | int npages_for_summary_flush(struct f2fs_sb_info *); |
1183 | void allocate_new_segments(struct f2fs_sb_info *); | 1184 | void allocate_new_segments(struct f2fs_sb_info *); |
1184 | struct page *get_sum_page(struct f2fs_sb_info *, unsigned int); | 1185 | struct page *get_sum_page(struct f2fs_sb_info *, unsigned int); |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 1e264e761f71..9993f94848fc 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -335,13 +335,26 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) | |||
335 | mutex_unlock(&dirty_i->seglist_lock); | 335 | mutex_unlock(&dirty_i->seglist_lock); |
336 | } | 336 | } |
337 | 337 | ||
338 | static void f2fs_issue_discard(struct f2fs_sb_info *sbi, | 338 | static int f2fs_issue_discard(struct f2fs_sb_info *sbi, |
339 | block_t blkstart, block_t blklen) | 339 | block_t blkstart, block_t blklen) |
340 | { | 340 | { |
341 | sector_t start = SECTOR_FROM_BLOCK(sbi, blkstart); | 341 | sector_t start = SECTOR_FROM_BLOCK(sbi, blkstart); |
342 | sector_t len = SECTOR_FROM_BLOCK(sbi, blklen); | 342 | sector_t len = SECTOR_FROM_BLOCK(sbi, blklen); |
343 | blkdev_issue_discard(sbi->sb->s_bdev, start, len, GFP_NOFS, 0); | ||
344 | trace_f2fs_issue_discard(sbi->sb, blkstart, blklen); | 343 | trace_f2fs_issue_discard(sbi->sb, blkstart, blklen); |
344 | return blkdev_issue_discard(sbi->sb->s_bdev, start, len, GFP_NOFS, 0); | ||
345 | } | ||
346 | |||
347 | void discard_next_dnode(struct f2fs_sb_info *sbi) | ||
348 | { | ||
349 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); | ||
350 | block_t blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); | ||
351 | |||
352 | if (f2fs_issue_discard(sbi, blkaddr, 1)) { | ||
353 | struct page *page = grab_meta_page(sbi, blkaddr); | ||
354 | /* zero-filled page */ | ||
355 | set_page_dirty(page); | ||
356 | f2fs_put_page(page, 1); | ||
357 | } | ||
345 | } | 358 | } |
346 | 359 | ||
347 | static void add_discard_addrs(struct f2fs_sb_info *sbi, | 360 | static void add_discard_addrs(struct f2fs_sb_info *sbi, |