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

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: 1aa161e43106 ("f2fs: fix scheduling while atomic in decompression path")
Fixes: 95fa90c9e5a7 ("f2fs: support recording errors into superblock")
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
901c12d1 458c15df

+25 -4
+1 -1
fs/f2fs/compress.c
··· 744 744 745 745 /* Avoid f2fs_commit_super in irq context */ 746 746 if (!in_task) 747 - f2fs_save_errors(sbi, ERROR_FAIL_DECOMPRESSION); 747 + f2fs_handle_error_async(sbi, ERROR_FAIL_DECOMPRESSION); 748 748 else 749 749 f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION); 750 750 goto out_release;
+1
fs/f2fs/f2fs.h
··· 3563 3563 void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason, 3564 3564 bool irq_context); 3565 3565 void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error); 3566 + void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error); 3566 3567 int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); 3567 3568 int f2fs_sync_fs(struct super_block *sb, int sync); 3568 3569 int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
+23 -3
fs/f2fs/super.c
··· 3995 3995 f2fs_down_write(&sbi->sb_lock); 3996 3996 3997 3997 spin_lock_irqsave(&sbi->error_lock, flags); 3998 + if (sbi->error_dirty) { 3999 + memcpy(F2FS_RAW_SUPER(sbi)->s_errors, sbi->errors, 4000 + MAX_F2FS_ERRORS); 4001 + sbi->error_dirty = false; 4002 + } 3998 4003 memcpy(raw_super->s_stop_reason, sbi->stop_reason, MAX_STOP_REASON); 3999 4004 spin_unlock_irqrestore(&sbi->error_lock, flags); 4000 4005 ··· 4039 4034 return need_update; 4040 4035 } 4041 4036 4042 - void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error) 4037 + static void f2fs_record_errors(struct f2fs_sb_info *sbi, unsigned char error) 4043 4038 { 4044 4039 int err; 4045 - 4046 - f2fs_save_errors(sbi, error); 4047 4040 4048 4041 f2fs_down_write(&sbi->sb_lock); 4049 4042 ··· 4054 4051 error, err); 4055 4052 out_unlock: 4056 4053 f2fs_up_write(&sbi->sb_lock); 4054 + } 4055 + 4056 + void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error) 4057 + { 4058 + f2fs_save_errors(sbi, error); 4059 + f2fs_record_errors(sbi, error); 4060 + } 4061 + 4062 + void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error) 4063 + { 4064 + f2fs_save_errors(sbi, error); 4065 + 4066 + if (!sbi->error_dirty) 4067 + return; 4068 + if (!test_bit(error, (unsigned long *)sbi->errors)) 4069 + return; 4070 + schedule_work(&sbi->s_error_work); 4057 4071 } 4058 4072 4059 4073 static bool system_going_down(void)