Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

f2fs: support recording stop_checkpoint reason into super_block

This patch supports to record stop_checkpoint error into
f2fs_super_block.s_stop_reason[].

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

authored by

Chao Yu and committed by
Jaegeuk Kim
a9cfee0e ca7efd71

+65 -17
+7 -3
fs/f2fs/checkpoint.c
··· 26 26 static struct kmem_cache *ino_entry_slab; 27 27 struct kmem_cache *f2fs_inode_entry_slab; 28 28 29 - void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io) 29 + void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io, 30 + unsigned char reason) 30 31 { 31 32 f2fs_build_fault_attr(sbi, 0, 0); 32 33 set_ckpt_flags(sbi, CP_ERROR_FLAG); 33 - if (!end_io) 34 + if (!end_io) { 34 35 f2fs_flush_merged_writes(sbi); 36 + 37 + f2fs_handle_stop(sbi, reason); 38 + } 35 39 } 36 40 37 41 /* ··· 126 122 if (PTR_ERR(page) == -EIO && 127 123 ++count <= DEFAULT_RETRY_IO_COUNT) 128 124 goto retry; 129 - f2fs_stop_checkpoint(sbi, false); 125 + f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_META_PAGE); 130 126 } 131 127 return page; 132 128 }
+4 -2
fs/f2fs/data.c
··· 333 333 mempool_free(page, sbi->write_io_dummy); 334 334 335 335 if (unlikely(bio->bi_status)) 336 - f2fs_stop_checkpoint(sbi, true); 336 + f2fs_stop_checkpoint(sbi, true, 337 + STOP_CP_REASON_WRITE_FAIL); 337 338 continue; 338 339 } 339 340 ··· 350 349 if (unlikely(bio->bi_status)) { 351 350 mapping_set_error(page->mapping, -EIO); 352 351 if (type == F2FS_WB_CP_DATA) 353 - f2fs_stop_checkpoint(sbi, true); 352 + f2fs_stop_checkpoint(sbi, true, 353 + STOP_CP_REASON_WRITE_FAIL); 354 354 } 355 355 356 356 f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) &&
+3 -1
fs/f2fs/f2fs.h
··· 3556 3556 int f2fs_quota_sync(struct super_block *sb, int type); 3557 3557 loff_t max_file_blocks(struct inode *inode); 3558 3558 void f2fs_quota_off_umount(struct super_block *sb); 3559 + void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason); 3559 3560 int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); 3560 3561 int f2fs_sync_fs(struct super_block *sb, int sync); 3561 3562 int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi); ··· 3716 3715 /* 3717 3716 * checkpoint.c 3718 3717 */ 3719 - void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io); 3718 + void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io, 3719 + unsigned char reason); 3720 3720 void f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi); 3721 3721 struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index); 3722 3722 struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
+6 -5
fs/f2fs/file.c
··· 2145 2145 if (ret) { 2146 2146 if (ret == -EROFS) { 2147 2147 ret = 0; 2148 - f2fs_stop_checkpoint(sbi, false); 2148 + f2fs_stop_checkpoint(sbi, false, 2149 + STOP_CP_REASON_SHUTDOWN); 2149 2150 set_sbi_flag(sbi, SBI_IS_SHUTDOWN); 2150 2151 trace_f2fs_shutdown(sbi, in, ret); 2151 2152 } ··· 2159 2158 ret = freeze_bdev(sb->s_bdev); 2160 2159 if (ret) 2161 2160 goto out; 2162 - f2fs_stop_checkpoint(sbi, false); 2161 + f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN); 2163 2162 set_sbi_flag(sbi, SBI_IS_SHUTDOWN); 2164 2163 thaw_bdev(sb->s_bdev); 2165 2164 break; ··· 2168 2167 ret = f2fs_sync_fs(sb, 1); 2169 2168 if (ret) 2170 2169 goto out; 2171 - f2fs_stop_checkpoint(sbi, false); 2170 + f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN); 2172 2171 set_sbi_flag(sbi, SBI_IS_SHUTDOWN); 2173 2172 break; 2174 2173 case F2FS_GOING_DOWN_NOSYNC: 2175 - f2fs_stop_checkpoint(sbi, false); 2174 + f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN); 2176 2175 set_sbi_flag(sbi, SBI_IS_SHUTDOWN); 2177 2176 break; 2178 2177 case F2FS_GOING_DOWN_METAFLUSH: 2179 2178 f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_META_IO); 2180 - f2fs_stop_checkpoint(sbi, false); 2179 + f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN); 2181 2180 set_sbi_flag(sbi, SBI_IS_SHUTDOWN); 2182 2181 break; 2183 2182 case F2FS_GOING_DOWN_NEED_FSCK:
+4 -2
fs/f2fs/gc.c
··· 74 74 75 75 if (time_to_inject(sbi, FAULT_CHECKPOINT)) { 76 76 f2fs_show_injection_info(sbi, FAULT_CHECKPOINT); 77 - f2fs_stop_checkpoint(sbi, false); 77 + f2fs_stop_checkpoint(sbi, false, 78 + STOP_CP_REASON_FAULT_INJECT); 78 79 } 79 80 80 81 if (!sb_start_write_trylock(sbi->sb)) { ··· 1713 1712 f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SSA and SIT", 1714 1713 segno, type, GET_SUM_TYPE((&sum->footer))); 1715 1714 set_sbi_flag(sbi, SBI_NEED_FSCK); 1716 - f2fs_stop_checkpoint(sbi, false); 1715 + f2fs_stop_checkpoint(sbi, false, 1716 + STOP_CP_REASON_CORRUPTED_SUMMARY); 1717 1717 goto skip; 1718 1718 } 1719 1719
+2 -1
fs/f2fs/inode.c
··· 713 713 cond_resched(); 714 714 goto retry; 715 715 } else if (err != -ENOENT) { 716 - f2fs_stop_checkpoint(sbi, false); 716 + f2fs_stop_checkpoint(sbi, false, 717 + STOP_CP_REASON_UPDATE_INODE); 717 718 } 718 719 return; 719 720 }
+3 -2
fs/f2fs/segment.c
··· 376 376 { 377 377 if (time_to_inject(sbi, FAULT_CHECKPOINT)) { 378 378 f2fs_show_injection_info(sbi, FAULT_CHECKPOINT); 379 - f2fs_stop_checkpoint(sbi, false); 379 + f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT); 380 380 } 381 381 382 382 /* balance_fs_bg is able to be pending */ ··· 694 694 } while (ret && --count); 695 695 696 696 if (ret) { 697 - f2fs_stop_checkpoint(sbi, false); 697 + f2fs_stop_checkpoint(sbi, false, 698 + STOP_CP_REASON_FLUSH_FAIL); 698 699 break; 699 700 } 700 701
+20
fs/f2fs/super.c
··· 3846 3846 return err; 3847 3847 } 3848 3848 3849 + void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason) 3850 + { 3851 + struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); 3852 + int err; 3853 + 3854 + f2fs_bug_on(sbi, reason >= MAX_STOP_REASON); 3855 + 3856 + f2fs_down_write(&sbi->sb_lock); 3857 + 3858 + if (raw_super->s_stop_reason[reason] < ((1 << BITS_PER_BYTE) - 1)) 3859 + raw_super->s_stop_reason[reason]++; 3860 + 3861 + err = f2fs_commit_super(sbi, false); 3862 + if (err) 3863 + f2fs_err(sbi, "f2fs_commit_super fails to record reason:%u err:%d", 3864 + reason, err); 3865 + 3866 + f2fs_up_write(&sbi->sb_lock); 3867 + } 3868 + 3849 3869 static int f2fs_scan_devices(struct f2fs_sb_info *sbi) 3850 3870 { 3851 3871 struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+16 -1
include/linux/f2fs_fs.h
··· 73 73 __le32 total_segments; 74 74 } __packed; 75 75 76 + /* reason of stop_checkpoint */ 77 + enum stop_cp_reason { 78 + STOP_CP_REASON_SHUTDOWN, 79 + STOP_CP_REASON_FAULT_INJECT, 80 + STOP_CP_REASON_META_PAGE, 81 + STOP_CP_REASON_WRITE_FAIL, 82 + STOP_CP_REASON_CORRUPTED_SUMMARY, 83 + STOP_CP_REASON_UPDATE_INODE, 84 + STOP_CP_REASON_FLUSH_FAIL, 85 + STOP_CP_REASON_MAX, 86 + }; 87 + 88 + #define MAX_STOP_REASON 32 89 + 76 90 struct f2fs_super_block { 77 91 __le32 magic; /* Magic Number */ 78 92 __le16 major_ver; /* Major Version */ ··· 130 116 __u8 hot_ext_count; /* # of hot file extension */ 131 117 __le16 s_encoding; /* Filename charset encoding */ 132 118 __le16 s_encoding_flags; /* Filename charset encoding flags */ 133 - __u8 reserved[306]; /* valid reserved region */ 119 + __u8 s_stop_reason[MAX_STOP_REASON]; /* stop checkpoint reason */ 120 + __u8 reserved[274]; /* valid reserved region */ 134 121 __le32 crc; /* checksum of superblock */ 135 122 } __packed; 136 123