@@ -164,6 +164,7 @@ enum {
164164 Opt_discard_unit ,
165165 Opt_memory_mode ,
166166 Opt_age_extent_cache ,
167+ Opt_errors ,
167168 Opt_err ,
168169};
169170
@@ -243,6 +244,7 @@ static match_table_t f2fs_tokens = {
243244 {Opt_discard_unit , "discard_unit=%s" },
244245 {Opt_memory_mode , "memory=%s" },
245246 {Opt_age_extent_cache , "age_extent_cache" },
247+ {Opt_errors , "errors=%s" },
246248 {Opt_err , NULL },
247249};
248250
@@ -1268,6 +1270,25 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
12681270 case Opt_age_extent_cache :
12691271 set_opt (sbi , AGE_EXTENT_CACHE );
12701272 break ;
1273+ case Opt_errors :
1274+ name = match_strdup (& args [0 ]);
1275+ if (!name )
1276+ return - ENOMEM ;
1277+ if (!strcmp (name , "remount-ro" )) {
1278+ F2FS_OPTION (sbi ).errors =
1279+ MOUNT_ERRORS_READONLY ;
1280+ } else if (!strcmp (name , "continue" )) {
1281+ F2FS_OPTION (sbi ).errors =
1282+ MOUNT_ERRORS_CONTINUE ;
1283+ } else if (!strcmp (name , "panic" )) {
1284+ F2FS_OPTION (sbi ).errors =
1285+ MOUNT_ERRORS_PANIC ;
1286+ } else {
1287+ kfree (name );
1288+ return - EINVAL ;
1289+ }
1290+ kfree (name );
1291+ break ;
12711292 default :
12721293 f2fs_err (sbi , "Unrecognized mount option \"%s\" or missing value" ,
12731294 p );
@@ -1622,6 +1643,9 @@ static void f2fs_put_super(struct super_block *sb)
16221643 f2fs_destroy_node_manager (sbi );
16231644 f2fs_destroy_segment_manager (sbi );
16241645
1646+ /* flush s_error_work before sbi destroy */
1647+ flush_work (& sbi -> s_error_work );
1648+
16251649 f2fs_destroy_post_read_wq (sbi );
16261650
16271651 kvfree (sbi -> ckpt );
@@ -2052,6 +2076,13 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
20522076 else if (F2FS_OPTION (sbi ).memory_mode == MEMORY_MODE_LOW )
20532077 seq_printf (seq , ",memory=%s" , "low" );
20542078
2079+ if (F2FS_OPTION (sbi ).errors == MOUNT_ERRORS_READONLY )
2080+ seq_printf (seq , ",errors=%s" , "remount-ro" );
2081+ else if (F2FS_OPTION (sbi ).errors == MOUNT_ERRORS_CONTINUE )
2082+ seq_printf (seq , ",errors=%s" , "continue" );
2083+ else if (F2FS_OPTION (sbi ).errors == MOUNT_ERRORS_PANIC )
2084+ seq_printf (seq , ",errors=%s" , "panic" );
2085+
20552086 return 0 ;
20562087}
20572088
@@ -2080,6 +2111,7 @@ static void default_options(struct f2fs_sb_info *sbi)
20802111 }
20812112 F2FS_OPTION (sbi ).bggc_mode = BGGC_MODE_ON ;
20822113 F2FS_OPTION (sbi ).memory_mode = MEMORY_MODE_NORMAL ;
2114+ F2FS_OPTION (sbi ).errors = MOUNT_ERRORS_CONTINUE ;
20832115
20842116 sbi -> sb -> s_flags &= ~SB_INLINECRYPT ;
20852117
@@ -2281,6 +2313,9 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
22812313 if (err )
22822314 goto restore_opts ;
22832315
2316+ /* flush outstanding errors before changing fs state */
2317+ flush_work (& sbi -> s_error_work );
2318+
22842319 /*
22852320 * Previous and new state of filesystem is RO,
22862321 * so skip checking GC and FLUSH_MERGE conditions.
@@ -3926,45 +3961,60 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
39263961 return err ;
39273962}
39283963
3929- void f2fs_handle_stop (struct f2fs_sb_info * sbi , unsigned char reason )
3964+ static void save_stop_reason (struct f2fs_sb_info * sbi , unsigned char reason )
3965+ {
3966+ unsigned long flags ;
3967+
3968+ spin_lock_irqsave (& sbi -> error_lock , flags );
3969+ if (sbi -> stop_reason [reason ] < GENMASK (BITS_PER_BYTE - 1 , 0 ))
3970+ sbi -> stop_reason [reason ]++ ;
3971+ spin_unlock_irqrestore (& sbi -> error_lock , flags );
3972+ }
3973+
3974+ static void f2fs_record_stop_reason (struct f2fs_sb_info * sbi )
39303975{
39313976 struct f2fs_super_block * raw_super = F2FS_RAW_SUPER (sbi );
3977+ unsigned long flags ;
39323978 int err ;
39333979
39343980 f2fs_down_write (& sbi -> sb_lock );
39353981
3936- if (raw_super -> s_stop_reason [reason ] < GENMASK (BITS_PER_BYTE - 1 , 0 ))
3937- raw_super -> s_stop_reason [reason ]++ ;
3982+ spin_lock_irqsave (& sbi -> error_lock , flags );
3983+ memcpy (raw_super -> s_stop_reason , sbi -> stop_reason , MAX_STOP_REASON );
3984+ spin_unlock_irqrestore (& sbi -> error_lock , flags );
39383985
39393986 err = f2fs_commit_super (sbi , false);
3940- if (err )
3941- f2fs_err (sbi , "f2fs_commit_super fails to record reason:%u err:%d" ,
3942- reason , err );
3987+
39433988 f2fs_up_write (& sbi -> sb_lock );
3989+ if (err )
3990+ f2fs_err (sbi , "f2fs_commit_super fails to record err:%d" , err );
39443991}
39453992
39463993void f2fs_save_errors (struct f2fs_sb_info * sbi , unsigned char flag )
39473994{
3948- spin_lock (& sbi -> error_lock );
3995+ unsigned long flags ;
3996+
3997+ spin_lock_irqsave (& sbi -> error_lock , flags );
39493998 if (!test_bit (flag , (unsigned long * )sbi -> errors )) {
39503999 set_bit (flag , (unsigned long * )sbi -> errors );
39514000 sbi -> error_dirty = true;
39524001 }
3953- spin_unlock (& sbi -> error_lock );
4002+ spin_unlock_irqrestore (& sbi -> error_lock , flags );
39544003}
39554004
39564005static bool f2fs_update_errors (struct f2fs_sb_info * sbi )
39574006{
4007+ unsigned long flags ;
39584008 bool need_update = false;
39594009
3960- spin_lock (& sbi -> error_lock );
4010+ spin_lock_irqsave (& sbi -> error_lock , flags );
39614011 if (sbi -> error_dirty ) {
39624012 memcpy (F2FS_RAW_SUPER (sbi )-> s_errors , sbi -> errors ,
39634013 MAX_F2FS_ERRORS );
39644014 sbi -> error_dirty = false;
39654015 need_update = true;
39664016 }
3967- spin_unlock (& sbi -> error_lock );
4017+ spin_unlock_irqrestore (& sbi -> error_lock , flags );
39684018
39694019 return need_update ;
39704020}
@@ -3988,6 +4038,66 @@ void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error)
39884038 f2fs_up_write (& sbi -> sb_lock );
39894039}
39904040
4041+ static bool system_going_down (void )
4042+ {
4043+ return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF
4044+ || system_state == SYSTEM_RESTART ;
4045+ }
4046+
4047+ void f2fs_handle_critical_error (struct f2fs_sb_info * sbi , unsigned char reason ,
4048+ bool irq_context )
4049+ {
4050+ struct super_block * sb = sbi -> sb ;
4051+ bool shutdown = reason == STOP_CP_REASON_SHUTDOWN ;
4052+ bool continue_fs = !shutdown &&
4053+ F2FS_OPTION (sbi ).errors == MOUNT_ERRORS_CONTINUE ;
4054+
4055+ set_ckpt_flags (sbi , CP_ERROR_FLAG );
4056+
4057+ if (!f2fs_hw_is_readonly (sbi )) {
4058+ save_stop_reason (sbi , reason );
4059+
4060+ if (irq_context && !shutdown )
4061+ schedule_work (& sbi -> s_error_work );
4062+ else
4063+ f2fs_record_stop_reason (sbi );
4064+ }
4065+
4066+ /*
4067+ * We force ERRORS_RO behavior when system is rebooting. Otherwise we
4068+ * could panic during 'reboot -f' as the underlying device got already
4069+ * disabled.
4070+ */
4071+ if (F2FS_OPTION (sbi ).errors == MOUNT_ERRORS_PANIC &&
4072+ !shutdown && !system_going_down () &&
4073+ !is_sbi_flag_set (sbi , SBI_IS_SHUTDOWN ))
4074+ panic ("F2FS-fs (device %s): panic forced after error\n" ,
4075+ sb -> s_id );
4076+
4077+ if (shutdown )
4078+ set_sbi_flag (sbi , SBI_IS_SHUTDOWN );
4079+
4080+ /* continue filesystem operators if errors=continue */
4081+ if (continue_fs || f2fs_readonly (sb ))
4082+ return ;
4083+
4084+ f2fs_warn (sbi , "Remounting filesystem read-only" );
4085+ /*
4086+ * Make sure updated value of ->s_mount_flags will be visible before
4087+ * ->s_flags update
4088+ */
4089+ smp_wmb ();
4090+ sb -> s_flags |= SB_RDONLY ;
4091+ }
4092+
4093+ static void f2fs_record_error_work (struct work_struct * work )
4094+ {
4095+ struct f2fs_sb_info * sbi = container_of (work ,
4096+ struct f2fs_sb_info , s_error_work );
4097+
4098+ f2fs_record_stop_reason (sbi );
4099+ }
4100+
39914101static int f2fs_scan_devices (struct f2fs_sb_info * sbi )
39924102{
39934103 struct f2fs_super_block * raw_super = F2FS_RAW_SUPER (sbi );
@@ -4218,7 +4328,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
42184328 sb -> s_fs_info = sbi ;
42194329 sbi -> raw_super = raw_super ;
42204330
4331+ INIT_WORK (& sbi -> s_error_work , f2fs_record_error_work );
42214332 memcpy (sbi -> errors , raw_super -> s_errors , MAX_F2FS_ERRORS );
4333+ memcpy (sbi -> stop_reason , raw_super -> s_stop_reason , MAX_STOP_REASON );
42224334
42234335 /* precompute checksum seed for metadata */
42244336 if (f2fs_sb_has_inode_chksum (sbi ))
@@ -4615,6 +4727,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
46154727 f2fs_destroy_segment_manager (sbi );
46164728stop_ckpt_thread :
46174729 f2fs_stop_ckpt_thread (sbi );
4730+ /* flush s_error_work before sbi destroy */
4731+ flush_work (& sbi -> s_error_work );
46184732 f2fs_destroy_post_read_wq (sbi );
46194733free_devices :
46204734 destroy_device_list (sbi );
0 commit comments