mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-27 12:57:53 +00:00
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>
This commit is contained in:
parent
ca7efd71c3
commit
a9cfee0ef9
9 changed files with 65 additions and 17 deletions
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
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)
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
} 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)
|
||||||
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 {
|
||||||
__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 {
|
||||||
__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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue