@@ -164,6 +164,7 @@ enum {
164
164
Opt_discard_unit ,
165
165
Opt_memory_mode ,
166
166
Opt_age_extent_cache ,
167
+ Opt_errors ,
167
168
Opt_err ,
168
169
};
169
170
@@ -243,6 +244,7 @@ static match_table_t f2fs_tokens = {
243
244
{Opt_discard_unit , "discard_unit=%s" },
244
245
{Opt_memory_mode , "memory=%s" },
245
246
{Opt_age_extent_cache , "age_extent_cache" },
247
+ {Opt_errors , "errors=%s" },
246
248
{Opt_err , NULL },
247
249
};
248
250
@@ -1268,6 +1270,25 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
1268
1270
case Opt_age_extent_cache :
1269
1271
set_opt (sbi , AGE_EXTENT_CACHE );
1270
1272
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 ;
1271
1292
default :
1272
1293
f2fs_err (sbi , "Unrecognized mount option \"%s\" or missing value" ,
1273
1294
p );
@@ -1622,6 +1643,9 @@ static void f2fs_put_super(struct super_block *sb)
1622
1643
f2fs_destroy_node_manager (sbi );
1623
1644
f2fs_destroy_segment_manager (sbi );
1624
1645
1646
+ /* flush s_error_work before sbi destroy */
1647
+ flush_work (& sbi -> s_error_work );
1648
+
1625
1649
f2fs_destroy_post_read_wq (sbi );
1626
1650
1627
1651
kvfree (sbi -> ckpt );
@@ -2052,6 +2076,13 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
2052
2076
else if (F2FS_OPTION (sbi ).memory_mode == MEMORY_MODE_LOW )
2053
2077
seq_printf (seq , ",memory=%s" , "low" );
2054
2078
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
+
2055
2086
return 0 ;
2056
2087
}
2057
2088
@@ -2080,6 +2111,7 @@ static void default_options(struct f2fs_sb_info *sbi)
2080
2111
}
2081
2112
F2FS_OPTION (sbi ).bggc_mode = BGGC_MODE_ON ;
2082
2113
F2FS_OPTION (sbi ).memory_mode = MEMORY_MODE_NORMAL ;
2114
+ F2FS_OPTION (sbi ).errors = MOUNT_ERRORS_CONTINUE ;
2083
2115
2084
2116
sbi -> sb -> s_flags &= ~SB_INLINECRYPT ;
2085
2117
@@ -2281,6 +2313,9 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
2281
2313
if (err )
2282
2314
goto restore_opts ;
2283
2315
2316
+ /* flush outstanding errors before changing fs state */
2317
+ flush_work (& sbi -> s_error_work );
2318
+
2284
2319
/*
2285
2320
* Previous and new state of filesystem is RO,
2286
2321
* so skip checking GC and FLUSH_MERGE conditions.
@@ -3926,45 +3961,60 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
3926
3961
return err ;
3927
3962
}
3928
3963
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 )
3930
3975
{
3931
3976
struct f2fs_super_block * raw_super = F2FS_RAW_SUPER (sbi );
3977
+ unsigned long flags ;
3932
3978
int err ;
3933
3979
3934
3980
f2fs_down_write (& sbi -> sb_lock );
3935
3981
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 );
3938
3985
3939
3986
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
+
3943
3988
f2fs_up_write (& sbi -> sb_lock );
3989
+ if (err )
3990
+ f2fs_err (sbi , "f2fs_commit_super fails to record err:%d" , err );
3944
3991
}
3945
3992
3946
3993
void f2fs_save_errors (struct f2fs_sb_info * sbi , unsigned char flag )
3947
3994
{
3948
- spin_lock (& sbi -> error_lock );
3995
+ unsigned long flags ;
3996
+
3997
+ spin_lock_irqsave (& sbi -> error_lock , flags );
3949
3998
if (!test_bit (flag , (unsigned long * )sbi -> errors )) {
3950
3999
set_bit (flag , (unsigned long * )sbi -> errors );
3951
4000
sbi -> error_dirty = true;
3952
4001
}
3953
- spin_unlock (& sbi -> error_lock );
4002
+ spin_unlock_irqrestore (& sbi -> error_lock , flags );
3954
4003
}
3955
4004
3956
4005
static bool f2fs_update_errors (struct f2fs_sb_info * sbi )
3957
4006
{
4007
+ unsigned long flags ;
3958
4008
bool need_update = false;
3959
4009
3960
- spin_lock (& sbi -> error_lock );
4010
+ spin_lock_irqsave (& sbi -> error_lock , flags );
3961
4011
if (sbi -> error_dirty ) {
3962
4012
memcpy (F2FS_RAW_SUPER (sbi )-> s_errors , sbi -> errors ,
3963
4013
MAX_F2FS_ERRORS );
3964
4014
sbi -> error_dirty = false;
3965
4015
need_update = true;
3966
4016
}
3967
- spin_unlock (& sbi -> error_lock );
4017
+ spin_unlock_irqrestore (& sbi -> error_lock , flags );
3968
4018
3969
4019
return need_update ;
3970
4020
}
@@ -3988,6 +4038,66 @@ void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error)
3988
4038
f2fs_up_write (& sbi -> sb_lock );
3989
4039
}
3990
4040
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
+
3991
4101
static int f2fs_scan_devices (struct f2fs_sb_info * sbi )
3992
4102
{
3993
4103
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)
4218
4328
sb -> s_fs_info = sbi ;
4219
4329
sbi -> raw_super = raw_super ;
4220
4330
4331
+ INIT_WORK (& sbi -> s_error_work , f2fs_record_error_work );
4221
4332
memcpy (sbi -> errors , raw_super -> s_errors , MAX_F2FS_ERRORS );
4333
+ memcpy (sbi -> stop_reason , raw_super -> s_stop_reason , MAX_STOP_REASON );
4222
4334
4223
4335
/* precompute checksum seed for metadata */
4224
4336
if (f2fs_sb_has_inode_chksum (sbi ))
@@ -4615,6 +4727,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
4615
4727
f2fs_destroy_segment_manager (sbi );
4616
4728
stop_ckpt_thread :
4617
4729
f2fs_stop_ckpt_thread (sbi );
4730
+ /* flush s_error_work before sbi destroy */
4731
+ flush_work (& sbi -> s_error_work );
4618
4732
f2fs_destroy_post_read_wq (sbi );
4619
4733
free_devices :
4620
4734
destroy_device_list (sbi );
0 commit comments