mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
f2fs: flush error flags in workqueue
In IRQ context, it wakes up workqueue to record errors into on-disk superblock fields rather than in-memory fields. Fixes:1aa161e431
("f2fs: fix scheduling while atomic in decompression path") Fixes:95fa90c9e5
("f2fs: support recording errors into superblock") Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
458c15dfbc
commit
901c12d144
3 changed files with 25 additions and 4 deletions
|
@ -744,7 +744,7 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic, bool in_task)
|
|||
|
||||
/* Avoid f2fs_commit_super in irq context */
|
||||
if (!in_task)
|
||||
f2fs_save_errors(sbi, ERROR_FAIL_DECOMPRESSION);
|
||||
f2fs_handle_error_async(sbi, ERROR_FAIL_DECOMPRESSION);
|
||||
else
|
||||
f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION);
|
||||
goto out_release;
|
||||
|
|
|
@ -3563,6 +3563,7 @@ void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag);
|
|||
void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason,
|
||||
bool irq_context);
|
||||
void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error);
|
||||
void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error);
|
||||
int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
|
||||
int f2fs_sync_fs(struct super_block *sb, int sync);
|
||||
int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
|
||||
|
|
|
@ -3995,6 +3995,11 @@ static void f2fs_record_stop_reason(struct f2fs_sb_info *sbi)
|
|||
f2fs_down_write(&sbi->sb_lock);
|
||||
|
||||
spin_lock_irqsave(&sbi->error_lock, flags);
|
||||
if (sbi->error_dirty) {
|
||||
memcpy(F2FS_RAW_SUPER(sbi)->s_errors, sbi->errors,
|
||||
MAX_F2FS_ERRORS);
|
||||
sbi->error_dirty = false;
|
||||
}
|
||||
memcpy(raw_super->s_stop_reason, sbi->stop_reason, MAX_STOP_REASON);
|
||||
spin_unlock_irqrestore(&sbi->error_lock, flags);
|
||||
|
||||
|
@ -4034,12 +4039,10 @@ static bool f2fs_update_errors(struct f2fs_sb_info *sbi)
|
|||
return need_update;
|
||||
}
|
||||
|
||||
void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error)
|
||||
static void f2fs_record_errors(struct f2fs_sb_info *sbi, unsigned char error)
|
||||
{
|
||||
int err;
|
||||
|
||||
f2fs_save_errors(sbi, error);
|
||||
|
||||
f2fs_down_write(&sbi->sb_lock);
|
||||
|
||||
if (!f2fs_update_errors(sbi))
|
||||
|
@ -4053,6 +4056,23 @@ void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error)
|
|||
f2fs_up_write(&sbi->sb_lock);
|
||||
}
|
||||
|
||||
void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error)
|
||||
{
|
||||
f2fs_save_errors(sbi, error);
|
||||
f2fs_record_errors(sbi, error);
|
||||
}
|
||||
|
||||
void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error)
|
||||
{
|
||||
f2fs_save_errors(sbi, error);
|
||||
|
||||
if (!sbi->error_dirty)
|
||||
return;
|
||||
if (!test_bit(error, (unsigned long *)sbi->errors))
|
||||
return;
|
||||
schedule_work(&sbi->s_error_work);
|
||||
}
|
||||
|
||||
static bool system_going_down(void)
|
||||
{
|
||||
return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF
|
||||
|
|
Loading…
Reference in a new issue