aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/segment.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-07-12 20:28:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-07-12 20:28:24 -0400
commita641a88e5d6864f20b2608cb01165c756794e645 (patch)
tree5acf37ca592a87d705169174b51feb47bd253fa9 /fs/f2fs/segment.c
parent4ce9d181ebe53abbca5f450b8a2984b8c3a38f26 (diff)
parent2d008835ec2fcf6eef3285e41e62a5eabd1fe76b (diff)
Merge tag 'f2fs-for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs updates from Jaegeuk Kim: "In this round, we've introduced native swap file support which can exploit DIO, enhanced existing checkpoint=disable feature with additional mount option to tune the triggering condition, and allowed user to preallocate physical blocks in a pinned file which will be useful to avoid f2fs fragmentation in append-only workloads. In addition, we've fixed subtle quota corruption issue. Enhancements: - add swap file support which uses DIO - allocate blocks for pinned file - allow SSR and mount option to enhance checkpoint=disable - enhance IPU IOs - add more sanity checks such as memory boundary access Bug fixes: - quota corruption in very corner case of error-injected SPO case - fix root_reserved on remount and some wrong counts - add missing fsck flag Some patches were also introduced to clean up ambiguous i_flags and debugging messages codes" * tag 'f2fs-for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (33 commits) f2fs: improve print log in f2fs_sanity_check_ckpt() f2fs: avoid out-of-range memory access f2fs: fix to avoid long latency during umount f2fs: allow all the users to pin a file f2fs: support swap file w/ DIO f2fs: allocate blocks for pinned file f2fs: fix is_idle() check for discard type f2fs: add a rw_sem to cover quota flag changes f2fs: set SBI_NEED_FSCK for xattr corruption case f2fs: use generic EFSBADCRC/EFSCORRUPTED f2fs: Use DIV_ROUND_UP() instead of open-coding f2fs: print kernel message if filesystem is inconsistent f2fs: introduce f2fs_<level> macros to wrap f2fs_printk() f2fs: avoid get_valid_blocks() for cleanup f2fs: ioctl for removing a range from F2FS f2fs: only set project inherit bit for directory f2fs: separate f2fs i_flags from fs_flags and ext4 i_flags f2fs: replace ktype default_attrs with default_groups f2fs: Add option to limit required GC for checkpoint=disable f2fs: Fix accounting for unusable blocks ...
Diffstat (limited to 'fs/f2fs/segment.c')
-rw-r--r--fs/f2fs/segment.c170
1 files changed, 134 insertions, 36 deletions
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 8dee063c833f..a661ac32e829 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -546,9 +546,13 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
546 if (test_opt(sbi, DATA_FLUSH)) { 546 if (test_opt(sbi, DATA_FLUSH)) {
547 struct blk_plug plug; 547 struct blk_plug plug;
548 548
549 mutex_lock(&sbi->flush_lock);
550
549 blk_start_plug(&plug); 551 blk_start_plug(&plug);
550 f2fs_sync_dirty_inodes(sbi, FILE_INODE); 552 f2fs_sync_dirty_inodes(sbi, FILE_INODE);
551 blk_finish_plug(&plug); 553 blk_finish_plug(&plug);
554
555 mutex_unlock(&sbi->flush_lock);
552 } 556 }
553 f2fs_sync_fs(sbi->sb, true); 557 f2fs_sync_fs(sbi->sb, true);
554 stat_inc_bg_cp_count(sbi->stat_info); 558 stat_inc_bg_cp_count(sbi->stat_info);
@@ -869,11 +873,14 @@ void f2fs_dirty_to_prefree(struct f2fs_sb_info *sbi)
869 mutex_unlock(&dirty_i->seglist_lock); 873 mutex_unlock(&dirty_i->seglist_lock);
870} 874}
871 875
872int f2fs_disable_cp_again(struct f2fs_sb_info *sbi) 876block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi)
873{ 877{
878 int ovp_hole_segs =
879 (overprovision_segments(sbi) - reserved_segments(sbi));
880 block_t ovp_holes = ovp_hole_segs << sbi->log_blocks_per_seg;
874 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); 881 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
875 block_t ovp = overprovision_segments(sbi) << sbi->log_blocks_per_seg;
876 block_t holes[2] = {0, 0}; /* DATA and NODE */ 882 block_t holes[2] = {0, 0}; /* DATA and NODE */
883 block_t unusable;
877 struct seg_entry *se; 884 struct seg_entry *se;
878 unsigned int segno; 885 unsigned int segno;
879 886
@@ -887,10 +894,20 @@ int f2fs_disable_cp_again(struct f2fs_sb_info *sbi)
887 } 894 }
888 mutex_unlock(&dirty_i->seglist_lock); 895 mutex_unlock(&dirty_i->seglist_lock);
889 896
890 if (holes[DATA] > ovp || holes[NODE] > ovp) 897 unusable = holes[DATA] > holes[NODE] ? holes[DATA] : holes[NODE];
898 if (unusable > ovp_holes)
899 return unusable - ovp_holes;
900 return 0;
901}
902
903int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable)
904{
905 int ovp_hole_segs =
906 (overprovision_segments(sbi) - reserved_segments(sbi));
907 if (unusable > F2FS_OPTION(sbi).unusable_cap)
891 return -EAGAIN; 908 return -EAGAIN;
892 if (is_sbi_flag_set(sbi, SBI_CP_DISABLED_QUICK) && 909 if (is_sbi_flag_set(sbi, SBI_CP_DISABLED_QUICK) &&
893 dirty_segments(sbi) > overprovision_segments(sbi)) 910 dirty_segments(sbi) > ovp_hole_segs)
894 return -EAGAIN; 911 return -EAGAIN;
895 return 0; 912 return 0;
896} 913}
@@ -1480,6 +1497,10 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
1480 list_for_each_entry_safe(dc, tmp, pend_list, list) { 1497 list_for_each_entry_safe(dc, tmp, pend_list, list) {
1481 f2fs_bug_on(sbi, dc->state != D_PREP); 1498 f2fs_bug_on(sbi, dc->state != D_PREP);
1482 1499
1500 if (dpolicy->timeout != 0 &&
1501 f2fs_time_over(sbi, dpolicy->timeout))
1502 break;
1503
1483 if (dpolicy->io_aware && i < dpolicy->io_aware_gran && 1504 if (dpolicy->io_aware && i < dpolicy->io_aware_gran &&
1484 !is_idle(sbi, DISCARD_TIME)) { 1505 !is_idle(sbi, DISCARD_TIME)) {
1485 io_interrupted = true; 1506 io_interrupted = true;
@@ -1740,8 +1761,7 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
1740 devi = f2fs_target_device_index(sbi, blkstart); 1761 devi = f2fs_target_device_index(sbi, blkstart);
1741 if (blkstart < FDEV(devi).start_blk || 1762 if (blkstart < FDEV(devi).start_blk ||
1742 blkstart > FDEV(devi).end_blk) { 1763 blkstart > FDEV(devi).end_blk) {
1743 f2fs_msg(sbi->sb, KERN_ERR, "Invalid block %x", 1764 f2fs_err(sbi, "Invalid block %x", blkstart);
1744 blkstart);
1745 return -EIO; 1765 return -EIO;
1746 } 1766 }
1747 blkstart -= FDEV(devi).start_blk; 1767 blkstart -= FDEV(devi).start_blk;
@@ -1754,10 +1774,9 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
1754 1774
1755 if (sector & (bdev_zone_sectors(bdev) - 1) || 1775 if (sector & (bdev_zone_sectors(bdev) - 1) ||
1756 nr_sects != bdev_zone_sectors(bdev)) { 1776 nr_sects != bdev_zone_sectors(bdev)) {
1757 f2fs_msg(sbi->sb, KERN_ERR, 1777 f2fs_err(sbi, "(%d) %s: Unaligned zone reset attempted (block %x + %x)",
1758 "(%d) %s: Unaligned zone reset attempted (block %x + %x)", 1778 devi, sbi->s_ndevs ? FDEV(devi).path : "",
1759 devi, sbi->s_ndevs ? FDEV(devi).path: "", 1779 blkstart, blklen);
1760 blkstart, blklen);
1761 return -EIO; 1780 return -EIO;
1762 } 1781 }
1763 trace_f2fs_issue_reset_zone(bdev, blkstart); 1782 trace_f2fs_issue_reset_zone(bdev, blkstart);
@@ -2121,15 +2140,14 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
2121 mir_exist = f2fs_test_and_set_bit(offset, 2140 mir_exist = f2fs_test_and_set_bit(offset,
2122 se->cur_valid_map_mir); 2141 se->cur_valid_map_mir);
2123 if (unlikely(exist != mir_exist)) { 2142 if (unlikely(exist != mir_exist)) {
2124 f2fs_msg(sbi->sb, KERN_ERR, "Inconsistent error " 2143 f2fs_err(sbi, "Inconsistent error when setting bitmap, blk:%u, old bit:%d",
2125 "when setting bitmap, blk:%u, old bit:%d", 2144 blkaddr, exist);
2126 blkaddr, exist);
2127 f2fs_bug_on(sbi, 1); 2145 f2fs_bug_on(sbi, 1);
2128 } 2146 }
2129#endif 2147#endif
2130 if (unlikely(exist)) { 2148 if (unlikely(exist)) {
2131 f2fs_msg(sbi->sb, KERN_ERR, 2149 f2fs_err(sbi, "Bitmap was wrongly set, blk:%u",
2132 "Bitmap was wrongly set, blk:%u", blkaddr); 2150 blkaddr);
2133 f2fs_bug_on(sbi, 1); 2151 f2fs_bug_on(sbi, 1);
2134 se->valid_blocks--; 2152 se->valid_blocks--;
2135 del = 0; 2153 del = 0;
@@ -2150,15 +2168,14 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
2150 mir_exist = f2fs_test_and_clear_bit(offset, 2168 mir_exist = f2fs_test_and_clear_bit(offset,
2151 se->cur_valid_map_mir); 2169 se->cur_valid_map_mir);
2152 if (unlikely(exist != mir_exist)) { 2170 if (unlikely(exist != mir_exist)) {
2153 f2fs_msg(sbi->sb, KERN_ERR, "Inconsistent error " 2171 f2fs_err(sbi, "Inconsistent error when clearing bitmap, blk:%u, old bit:%d",
2154 "when clearing bitmap, blk:%u, old bit:%d", 2172 blkaddr, exist);
2155 blkaddr, exist);
2156 f2fs_bug_on(sbi, 1); 2173 f2fs_bug_on(sbi, 1);
2157 } 2174 }
2158#endif 2175#endif
2159 if (unlikely(!exist)) { 2176 if (unlikely(!exist)) {
2160 f2fs_msg(sbi->sb, KERN_ERR, 2177 f2fs_err(sbi, "Bitmap was wrongly cleared, blk:%u",
2161 "Bitmap was wrongly cleared, blk:%u", blkaddr); 2178 blkaddr);
2162 f2fs_bug_on(sbi, 1); 2179 f2fs_bug_on(sbi, 1);
2163 se->valid_blocks++; 2180 se->valid_blocks++;
2164 del = 0; 2181 del = 0;
@@ -2640,6 +2657,39 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
2640 stat_inc_seg_type(sbi, curseg); 2657 stat_inc_seg_type(sbi, curseg);
2641} 2658}
2642 2659
2660void allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
2661 unsigned int start, unsigned int end)
2662{
2663 struct curseg_info *curseg = CURSEG_I(sbi, type);
2664 unsigned int segno;
2665
2666 down_read(&SM_I(sbi)->curseg_lock);
2667 mutex_lock(&curseg->curseg_mutex);
2668 down_write(&SIT_I(sbi)->sentry_lock);
2669
2670 segno = CURSEG_I(sbi, type)->segno;
2671 if (segno < start || segno > end)
2672 goto unlock;
2673
2674 if (f2fs_need_SSR(sbi) && get_ssr_segment(sbi, type))
2675 change_curseg(sbi, type);
2676 else
2677 new_curseg(sbi, type, true);
2678
2679 stat_inc_seg_type(sbi, curseg);
2680
2681 locate_dirty_segment(sbi, segno);
2682unlock:
2683 up_write(&SIT_I(sbi)->sentry_lock);
2684
2685 if (segno != curseg->segno)
2686 f2fs_notice(sbi, "For resize: curseg of type %d: %u ==> %u",
2687 type, segno, curseg->segno);
2688
2689 mutex_unlock(&curseg->curseg_mutex);
2690 up_read(&SM_I(sbi)->curseg_lock);
2691}
2692
2643void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi) 2693void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi)
2644{ 2694{
2645 struct curseg_info *curseg; 2695 struct curseg_info *curseg;
@@ -2772,9 +2822,8 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
2772 goto out; 2822 goto out;
2773 2823
2774 if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) { 2824 if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) {
2775 f2fs_msg(sbi->sb, KERN_WARNING, 2825 f2fs_warn(sbi, "Found FS corruption, run fsck to fix.");
2776 "Found FS corruption, run fsck to fix."); 2826 return -EFSCORRUPTED;
2777 return -EIO;
2778 } 2827 }
2779 2828
2780 /* start/end segment number in main_area */ 2829 /* start/end segment number in main_area */
@@ -3197,12 +3246,17 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
3197 3246
3198 if (!IS_DATASEG(get_seg_entry(sbi, segno)->type)) { 3247 if (!IS_DATASEG(get_seg_entry(sbi, segno)->type)) {
3199 set_sbi_flag(sbi, SBI_NEED_FSCK); 3248 set_sbi_flag(sbi, SBI_NEED_FSCK);
3200 return -EFAULT; 3249 f2fs_warn(sbi, "%s: incorrect segment(%u) type, run fsck to fix.",
3250 __func__, segno);
3251 return -EFSCORRUPTED;
3201 } 3252 }
3202 3253
3203 stat_inc_inplace_blocks(fio->sbi); 3254 stat_inc_inplace_blocks(fio->sbi);
3204 3255
3205 err = f2fs_submit_page_bio(fio); 3256 if (fio->bio)
3257 err = f2fs_merge_page_bio(fio);
3258 else
3259 err = f2fs_submit_page_bio(fio);
3206 if (!err) { 3260 if (!err) {
3207 update_device_state(fio); 3261 update_device_state(fio);
3208 f2fs_update_iostat(fio->sbi, fio->io_type, F2FS_BLKSIZE); 3262 f2fs_update_iostat(fio->sbi, fio->io_type, F2FS_BLKSIZE);
@@ -3393,6 +3447,11 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
3393 seg_i = CURSEG_I(sbi, i); 3447 seg_i = CURSEG_I(sbi, i);
3394 segno = le32_to_cpu(ckpt->cur_data_segno[i]); 3448 segno = le32_to_cpu(ckpt->cur_data_segno[i]);
3395 blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]); 3449 blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]);
3450 if (blk_off > ENTRIES_IN_SUM) {
3451 f2fs_bug_on(sbi, 1);
3452 f2fs_put_page(page, 1);
3453 return -EFAULT;
3454 }
3396 seg_i->next_segno = segno; 3455 seg_i->next_segno = segno;
3397 reset_curseg(sbi, i, 0); 3456 reset_curseg(sbi, i, 0);
3398 seg_i->alloc_type = ckpt->alloc_type[i]; 3457 seg_i->alloc_type = ckpt->alloc_type[i];
@@ -3530,8 +3589,11 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
3530 3589
3531 /* sanity check for summary blocks */ 3590 /* sanity check for summary blocks */
3532 if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES || 3591 if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES ||
3533 sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES) 3592 sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES) {
3593 f2fs_err(sbi, "invalid journal entries nats %u sits %u\n",
3594 nats_in_cursum(nat_j), sits_in_cursum(sit_j));
3534 return -EINVAL; 3595 return -EINVAL;
3596 }
3535 3597
3536 return 0; 3598 return 0;
3537} 3599}
@@ -3762,7 +3824,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
3762 struct f2fs_journal *journal = curseg->journal; 3824 struct f2fs_journal *journal = curseg->journal;
3763 struct sit_entry_set *ses, *tmp; 3825 struct sit_entry_set *ses, *tmp;
3764 struct list_head *head = &SM_I(sbi)->sit_entry_set; 3826 struct list_head *head = &SM_I(sbi)->sit_entry_set;
3765 bool to_journal = true; 3827 bool to_journal = !is_sbi_flag_set(sbi, SBI_IS_RESIZEFS);
3766 struct seg_entry *se; 3828 struct seg_entry *se;
3767 3829
3768 down_write(&sit_i->sentry_lock); 3830 down_write(&sit_i->sentry_lock);
@@ -3781,7 +3843,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
3781 * entries, remove all entries from journal and add and account 3843 * entries, remove all entries from journal and add and account
3782 * them in sit entry set. 3844 * them in sit entry set.
3783 */ 3845 */
3784 if (!__has_cursum_space(journal, sit_i->dirty_sentries, SIT_JOURNAL)) 3846 if (!__has_cursum_space(journal, sit_i->dirty_sentries, SIT_JOURNAL) ||
3847 !to_journal)
3785 remove_sits_in_journal(sbi); 3848 remove_sits_in_journal(sbi);
3786 3849
3787 /* 3850 /*
@@ -4096,11 +4159,10 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
4096 4159
4097 start = le32_to_cpu(segno_in_journal(journal, i)); 4160 start = le32_to_cpu(segno_in_journal(journal, i));
4098 if (start >= MAIN_SEGS(sbi)) { 4161 if (start >= MAIN_SEGS(sbi)) {
4099 f2fs_msg(sbi->sb, KERN_ERR, 4162 f2fs_err(sbi, "Wrong journal entry on segno %u",
4100 "Wrong journal entry on segno %u", 4163 start);
4101 start);
4102 set_sbi_flag(sbi, SBI_NEED_FSCK); 4164 set_sbi_flag(sbi, SBI_NEED_FSCK);
4103 err = -EINVAL; 4165 err = -EFSCORRUPTED;
4104 break; 4166 break;
4105 } 4167 }
4106 4168
@@ -4137,11 +4199,10 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
4137 up_read(&curseg->journal_rwsem); 4199 up_read(&curseg->journal_rwsem);
4138 4200
4139 if (!err && total_node_blocks != valid_node_count(sbi)) { 4201 if (!err && total_node_blocks != valid_node_count(sbi)) {
4140 f2fs_msg(sbi->sb, KERN_ERR, 4202 f2fs_err(sbi, "SIT is corrupted node# %u vs %u",
4141 "SIT is corrupted node# %u vs %u", 4203 total_node_blocks, valid_node_count(sbi));
4142 total_node_blocks, valid_node_count(sbi));
4143 set_sbi_flag(sbi, SBI_NEED_FSCK); 4204 set_sbi_flag(sbi, SBI_NEED_FSCK);
4144 err = -EINVAL; 4205 err = -EFSCORRUPTED;
4145 } 4206 }
4146 4207
4147 return err; 4208 return err;
@@ -4232,6 +4293,39 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi)
4232 return init_victim_secmap(sbi); 4293 return init_victim_secmap(sbi);
4233} 4294}
4234 4295
4296static int sanity_check_curseg(struct f2fs_sb_info *sbi)
4297{
4298 int i;
4299
4300 /*
4301 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
4302 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
4303 */
4304 for (i = 0; i < NO_CHECK_TYPE; i++) {
4305 struct curseg_info *curseg = CURSEG_I(sbi, i);
4306 struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
4307 unsigned int blkofs = curseg->next_blkoff;
4308
4309 if (f2fs_test_bit(blkofs, se->cur_valid_map))
4310 goto out;
4311
4312 if (curseg->alloc_type == SSR)
4313 continue;
4314
4315 for (blkofs += 1; blkofs < sbi->blocks_per_seg; blkofs++) {
4316 if (!f2fs_test_bit(blkofs, se->cur_valid_map))
4317 continue;
4318out:
4319 f2fs_err(sbi,
4320 "Current segment's next free block offset is inconsistent with bitmap, logtype:%u, segno:%u, type:%u, next_blkoff:%u, blkofs:%u",
4321 i, curseg->segno, curseg->alloc_type,
4322 curseg->next_blkoff, blkofs);
4323 return -EFSCORRUPTED;
4324 }
4325 }
4326 return 0;
4327}
4328
4235/* 4329/*
4236 * Update min, max modified time for cost-benefit GC algorithm 4330 * Update min, max modified time for cost-benefit GC algorithm
4237 */ 4331 */
@@ -4327,6 +4421,10 @@ int f2fs_build_segment_manager(struct f2fs_sb_info *sbi)
4327 if (err) 4421 if (err)
4328 return err; 4422 return err;
4329 4423
4424 err = sanity_check_curseg(sbi);
4425 if (err)
4426 return err;
4427
4330 init_min_max_mtime(sbi); 4428 init_min_max_mtime(sbi);
4331 return 0; 4429 return 0;
4332} 4430}