ext4文件系统错误处理机制
目前内核对ext4文件系统错误处理机制分为三种:1.不处理;2.内核panic;3.错误分区remount成只读形式。
处理机制的设定是在两个地方处理的,一个是在文件系统物理分区上设置,通过设置ext4文件系统分区的超级块中的“Errors behavior”参数,可以配置错误处理方式,一般默认处理方式是Continue(不处理),具体配置通过tune2fs搞定:
oen@oen ~ $ sudo tune2fs -l /dev/sda3 | head -n 10 tune2fs 1.42.5 (29-Jul-2012)</pre> Filesystem flags: signed_directory_hash Default mount options: user_xattr acl Filesystem state: clean Errors behavior: Continue Filesystem OS type: Linux
另外一种方式则是通过配置mount参数搞定,参看man手册:
errors=continue / errors=remount-ro / errors=panic
Define the behaviour when an error is encountered. (Either ignore errors
and just mark the file system erroneous and continue, or remount the file
system read-only, or panic and halt the system.) The default is set in
the filesystem superblock, and can be changed using tune2fs(8).
mount参数通常情况下在fstab中mount参数中直接设定,一般情况下服务器环境中的系统分区都是通过mount设置错误处理参数,一般都要设定为errors=panic,如此宁可让系统重启,让双机保持系统稳定,也不能让业务进程挂死在只读分区上。
但很多情况下,没有设置挂载参数,最后文件系统错误也导致了分区只读,具体就要分析内核的实现了。
文件系统问题出错最终都要有ext4_handle_error函数处理:
static void ext4_handle_error(struct super_block *sb) { if (sb->s_flags & MS_RDONLY) return; if (!test_opt(sb, ERRORS_CONT)) { journal_t *journal = EXT4_SB(sb)->s_journal; EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; if (journal) jbd2_journal_abort(journal, -EIO); } if (test_opt(sb, ERRORS_RO)) { ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); sb->s_flags |= MS_RDONLY; } if (test_opt(sb, ERRORS_PANIC)) panic("EXT4-fs (device %s): panic forced after errorn", sb->s_id); }
在代码第6行的判断中,如果系统默认不是EXT4_ERRORS_CONTINUE(即忽略不处理错误),则将journal置为aborted状态,然后结束;如果是挂载方式是只读,则将超级块的挂载标志位为MS_RDONLY;如果是panic,则打印panic告警并复位。
虽然系统默认不处理的情况下ext4_handle_error处理函数完美结束,但系统还在正常运行,如果系统需要对问题分区写入一些文件,此时IO会走JBD,获取handle原子操作,在ext4_journal_start_sb中判断journal状态,如果是aborted,则进入ext4_abort。
journal = EXT4_SB(sb)->s_journal; if (is_journal_aborted(journal)) { ext4_abort(sb, __func__, "Detected aborted journal"); return ERR_PTR(-EROFS); }
在ext4_abort中,如果分区状态不是只读,则将其分区置为只读。
void __ext4_abort(struct super_block *sb, ) { if ((sb->s_flags & MS_RDONLY) == 0) { ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); sb->s_flags |= MS_RDONLY; EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; if (EXT4_SB(sb)->s_journal) jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); save_error_info(sb, function, line); } if (test_opt(sb, ERRORS_PANIC)) panic("EXT4-fs panic from previous errorn"); }
真正工作中,文件系统的读写次数非常高,如果挂着参数不是panic,则文件系统出现bug,内核会将其置为只读状态。
ext4文件系统错误处理机制来自于OenHan
链接为:https://oenhan.com/ext4-fs-error-handle
“在代码第6行的判断中,如果系统默认不处理,则将journal置为aborted状态,然后结束”,这里第6行“if (!test_opt(sb, ERRORS_CONT)) ”表示的是如果系统默认不是ERRORS_CONT(不处理),则将journal置为aborted状态,如果是不处理的话,则不会执行任何操作退出函数了。
@SUJERRY 多谢指正
“如果系统需要对问题分区写入一些文件,此时IO会走JBD,获取handle原子操作,在ext4_journal_start_sb中判断journal状态,如果是aborted,则进入ext4_abort。” 这里的“如果是aborted”的aborted状态是哪里置的呢?
@SUJERRY 时间太长了,不记得当时原因,有可能写错了,有兴趣可以自己研究一下