Commit a9cfee0e authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim

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: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent ca7efd71
...@@ -26,12 +26,16 @@ ...@@ -26,12 +26,16 @@
static struct kmem_cache *ino_entry_slab; static struct kmem_cache *ino_entry_slab;
struct kmem_cache *f2fs_inode_entry_slab; struct kmem_cache *f2fs_inode_entry_slab;
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io) void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
unsigned char reason)
{ {
f2fs_build_fault_attr(sbi, 0, 0); f2fs_build_fault_attr(sbi, 0, 0);
set_ckpt_flags(sbi, CP_ERROR_FLAG); set_ckpt_flags(sbi, CP_ERROR_FLAG);
if (!end_io) if (!end_io) {
f2fs_flush_merged_writes(sbi); f2fs_flush_merged_writes(sbi);
f2fs_handle_stop(sbi, reason);
}
} }
/* /*
...@@ -122,7 +126,7 @@ struct page *f2fs_get_meta_page_retry(struct f2fs_sb_info *sbi, pgoff_t index) ...@@ -122,7 +126,7 @@ struct page *f2fs_get_meta_page_retry(struct f2fs_sb_info *sbi, pgoff_t index)
if (PTR_ERR(page) == -EIO && if (PTR_ERR(page) == -EIO &&
++count <= DEFAULT_RETRY_IO_COUNT) ++count <= DEFAULT_RETRY_IO_COUNT)
goto retry; goto retry;
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_META_PAGE);
} }
return page; return page;
} }
......
...@@ -333,7 +333,8 @@ static void f2fs_write_end_io(struct bio *bio) ...@@ -333,7 +333,8 @@ static void f2fs_write_end_io(struct bio *bio)
mempool_free(page, sbi->write_io_dummy); mempool_free(page, sbi->write_io_dummy);
if (unlikely(bio->bi_status)) if (unlikely(bio->bi_status))
f2fs_stop_checkpoint(sbi, true); f2fs_stop_checkpoint(sbi, true,
STOP_CP_REASON_WRITE_FAIL);
continue; continue;
} }
...@@ -349,7 +350,8 @@ static void f2fs_write_end_io(struct bio *bio) ...@@ -349,7 +350,8 @@ static void f2fs_write_end_io(struct bio *bio)
if (unlikely(bio->bi_status)) { if (unlikely(bio->bi_status)) {
mapping_set_error(page->mapping, -EIO); mapping_set_error(page->mapping, -EIO);
if (type == F2FS_WB_CP_DATA) if (type == F2FS_WB_CP_DATA)
f2fs_stop_checkpoint(sbi, true); f2fs_stop_checkpoint(sbi, true,
STOP_CP_REASON_WRITE_FAIL);
} }
f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) &&
......
...@@ -3556,6 +3556,7 @@ int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly); ...@@ -3556,6 +3556,7 @@ int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly);
int f2fs_quota_sync(struct super_block *sb, int type); int f2fs_quota_sync(struct super_block *sb, int type);
loff_t max_file_blocks(struct inode *inode); loff_t max_file_blocks(struct inode *inode);
void f2fs_quota_off_umount(struct super_block *sb); void f2fs_quota_off_umount(struct super_block *sb);
void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason);
int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
int f2fs_sync_fs(struct super_block *sb, int sync); int f2fs_sync_fs(struct super_block *sb, int sync);
int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi); int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
...@@ -3715,7 +3716,8 @@ static inline bool f2fs_need_rand_seg(struct f2fs_sb_info *sbi) ...@@ -3715,7 +3716,8 @@ static inline bool f2fs_need_rand_seg(struct f2fs_sb_info *sbi)
/* /*
* checkpoint.c * checkpoint.c
*/ */
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io); void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
unsigned char reason);
void f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi); void f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi);
struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index); struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index); struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
......
...@@ -2145,7 +2145,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ...@@ -2145,7 +2145,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
if (ret) { if (ret) {
if (ret == -EROFS) { if (ret == -EROFS) {
ret = 0; ret = 0;
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
trace_f2fs_shutdown(sbi, in, ret); trace_f2fs_shutdown(sbi, in, ret);
} }
...@@ -2158,7 +2159,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ...@@ -2158,7 +2159,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
ret = freeze_bdev(sb->s_bdev); ret = freeze_bdev(sb->s_bdev);
if (ret) if (ret)
goto out; goto out;
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
thaw_bdev(sb->s_bdev); thaw_bdev(sb->s_bdev);
break; break;
...@@ -2167,16 +2168,16 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ...@@ -2167,16 +2168,16 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
ret = f2fs_sync_fs(sb, 1); ret = f2fs_sync_fs(sb, 1);
if (ret) if (ret)
goto out; goto out;
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
break; break;
case F2FS_GOING_DOWN_NOSYNC: case F2FS_GOING_DOWN_NOSYNC:
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
break; break;
case F2FS_GOING_DOWN_METAFLUSH: case F2FS_GOING_DOWN_METAFLUSH:
f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_META_IO); f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_META_IO);
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
break; break;
case F2FS_GOING_DOWN_NEED_FSCK: case F2FS_GOING_DOWN_NEED_FSCK:
......
...@@ -74,7 +74,8 @@ static int gc_thread_func(void *data) ...@@ -74,7 +74,8 @@ static int gc_thread_func(void *data)
if (time_to_inject(sbi, FAULT_CHECKPOINT)) { if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
f2fs_show_injection_info(sbi, FAULT_CHECKPOINT); f2fs_show_injection_info(sbi, FAULT_CHECKPOINT);
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_FAULT_INJECT);
} }
if (!sb_start_write_trylock(sbi->sb)) { if (!sb_start_write_trylock(sbi->sb)) {
...@@ -1712,7 +1713,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, ...@@ -1712,7 +1713,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SSA and SIT", f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SSA and SIT",
segno, type, GET_SUM_TYPE((&sum->footer))); segno, type, GET_SUM_TYPE((&sum->footer)));
set_sbi_flag(sbi, SBI_NEED_FSCK); set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_CORRUPTED_SUMMARY);
goto skip; goto skip;
} }
......
...@@ -713,7 +713,8 @@ void f2fs_update_inode_page(struct inode *inode) ...@@ -713,7 +713,8 @@ void f2fs_update_inode_page(struct inode *inode)
cond_resched(); cond_resched();
goto retry; goto retry;
} else if (err != -ENOENT) { } else if (err != -ENOENT) {
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_UPDATE_INODE);
} }
return; return;
} }
......
...@@ -376,7 +376,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) ...@@ -376,7 +376,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
{ {
if (time_to_inject(sbi, FAULT_CHECKPOINT)) { if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
f2fs_show_injection_info(sbi, FAULT_CHECKPOINT); f2fs_show_injection_info(sbi, FAULT_CHECKPOINT);
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT);
} }
/* balance_fs_bg is able to be pending */ /* balance_fs_bg is able to be pending */
...@@ -694,7 +694,8 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi) ...@@ -694,7 +694,8 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi)
} while (ret && --count); } while (ret && --count);
if (ret) { if (ret) {
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_FLUSH_FAIL);
break; break;
} }
......
...@@ -3846,6 +3846,26 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) ...@@ -3846,6 +3846,26 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
return err; return err;
} }
void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason)
{
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
int err;
f2fs_bug_on(sbi, reason >= MAX_STOP_REASON);
f2fs_down_write(&sbi->sb_lock);
if (raw_super->s_stop_reason[reason] < ((1 << BITS_PER_BYTE) - 1))
raw_super->s_stop_reason[reason]++;
err = f2fs_commit_super(sbi, false);
if (err)
f2fs_err(sbi, "f2fs_commit_super fails to record reason:%u err:%d",
reason, err);
f2fs_up_write(&sbi->sb_lock);
}
static int f2fs_scan_devices(struct f2fs_sb_info *sbi) static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
{ {
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
......
...@@ -73,6 +73,20 @@ struct f2fs_device { ...@@ -73,6 +73,20 @@ struct f2fs_device {
__le32 total_segments; __le32 total_segments;
} __packed; } __packed;
/* reason of stop_checkpoint */
enum stop_cp_reason {
STOP_CP_REASON_SHUTDOWN,
STOP_CP_REASON_FAULT_INJECT,
STOP_CP_REASON_META_PAGE,
STOP_CP_REASON_WRITE_FAIL,
STOP_CP_REASON_CORRUPTED_SUMMARY,
STOP_CP_REASON_UPDATE_INODE,
STOP_CP_REASON_FLUSH_FAIL,
STOP_CP_REASON_MAX,
};
#define MAX_STOP_REASON 32
struct f2fs_super_block { struct f2fs_super_block {
__le32 magic; /* Magic Number */ __le32 magic; /* Magic Number */
__le16 major_ver; /* Major Version */ __le16 major_ver; /* Major Version */
...@@ -116,7 +130,8 @@ struct f2fs_super_block { ...@@ -116,7 +130,8 @@ struct f2fs_super_block {
__u8 hot_ext_count; /* # of hot file extension */ __u8 hot_ext_count; /* # of hot file extension */
__le16 s_encoding; /* Filename charset encoding */ __le16 s_encoding; /* Filename charset encoding */
__le16 s_encoding_flags; /* Filename charset encoding flags */ __le16 s_encoding_flags; /* Filename charset encoding flags */
__u8 reserved[306]; /* valid reserved region */ __u8 s_stop_reason[MAX_STOP_REASON]; /* stop checkpoint reason */
__u8 reserved[274]; /* valid reserved region */
__le32 crc; /* checksum of superblock */ __le32 crc; /* checksum of superblock */
} __packed; } __packed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment