ext4文件系统初探
1、核心文件:
kernel/fs/ext4/super.c
2、几个概念
(1)
super block :VFS(虚拟文件系统)的 superblock
ext4_sb_info :内存中的 superblock
ext4_super_block:磁盘中的 superblock
关系:
(1)EXT4_SB(struct super_block *sb)可由super_block得到ext4_sb_info;
(2)ext4_super_block在ext4_sb_info结构体中有s_es进行指向,因此可以通过ext4_super_block->s_es得到ext4_super_block;
(3)由前两项克制由super_block得到ext4_super_block结构体的方式为: es = EXT4_SB(sb)->s_es;
(4)由super_block得到ext4_sb_info可通过sb->s_fs_info得到
(5)知道ext4_sb_info可通过sbi->s_sb得到super_block.
(2)super block: 记录文件系统的整体信息,包括inode/block 的总量、使用量、剩余量,以及文件系统的格式与相关信息等。
在mount时,vfs层根据实际文件系统存放在块设备上的管理信息(也可以叫做文件系统的元数据),在内存中建立一个vfs层的
struct super_block,并且加入vfs的
全局链表!
(3) super_block只存在于
内存中,它在文件系统mount时建立,在文件系统umount时删除。这里得分清楚vfs层的super_block和各实际文件系统的super
block,对于每个具体的文件系统来说,都有各自的super_block (如ext4文件系统的super_block结构是
struct ext4_super_block),它们是存于
磁盘中的!
(4)
vfs中的super_block和各个实际的文件系统的super_block的联系是vfs层的super_block的void* s_fs_info 成员指向具体文件系统的信息(ext4中的struct ext4_sb_info)。这个过程是ext4_mount --> mount_bdev --> ext4_fill_super!
(5)
struct ext4_sb_info 内存中的ext4的
super block
struct ext4_sb_info
中也保存了struct super_block和ext4_super_block指针,他们的关系:
3、ext4 运行报错函数解读:
/* 当ext4报错误的时候的处理函数,比如一些一致性错误或者是读写的IO错误。
* 在ext2上,我们把一些错误状态字存储在超级块里。但是在ext4,这不可能,因为我们可能有写入顺序限制在超级块上,这个限制将会阻止我们写入,考虑到日志将要终止的情况,我们不能依赖以后。 我们使用jbd2_journal_abort()获得的错误码来记录错误,在恢复的时候日志将会报错误,直到我们清除这个错误记录。
*/
static void ext4_handle_error(struct super_block *sb)
{
/* 首先从超级块结构体获得磁盘上存储的ext4超级块结构体 */
struct ext4_super_block *es = EXT4_SB(sb)->s_es;
/* 挂载状态标记为错误发生状态 */
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; //内存中的标志
es->s_state |= cpu_to_le16(EXT4_ERROR_FS); //磁盘中的标志
/* 如果已经是只读挂载了,我们就不必继续操作了 */
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_opt |= EXT4_MOUNT_ABORT;
if (journal)
jbd2_journal_abort(journal, -EIO);
}
/* 如果fs是标记未,如果有错误,重新挂载为只读的情况,我们就重新挂载为只读 */
if (test_opt (sb, ERRORS_RO)) {
printk (KERN_CRIT "Remounting filesystem read-only\n");
sb->s_flags |= MS_RDONLY; //会重启导致 挂载为只读
}
/* 提交超级块的修改 */
ext4_commit_super(sb, es, 1);
/* 如果挂载选项是出错就panic,打印出panic信息 */
if (test_opt(sb, ERRORS_PANIC))
panic("EXT4-fs (device %s): panic forced after error\n",
sb->s_id);
}
/* 调用上边的函数处理错误,在此之前打印出错误信息 */
void ext4_error (struct super_block * sb, const char * function,
const char * fmt, ...)
{
va_list args;
/* 先打印出错误信息 */
va_start(args, fmt);
printk(KERN_CRIT "EXT4-fs error (device %s): %s: ",sb->s_id, function);
vprintk(fmt, args);
printk("\n");
va_end(args);
/* 然后处理错误 */
ext4_handle_error(sb);
}
4、开机挂载流程:
(1)开机调用mount时,会调用到 ext4_mount
(2) ext4_fill_super ( )
函数说明: 本文件最重要的函数,填充super_block结构体以及ext4_sb_info结构体的各个字段,挂载过程中最重要的函数
(3) ext4_load_journal
函数说明:
根据日志的主次设备号来进行加载日志操作
(4) ext4_clear_journal_err
/*
* 如果我们挂载的fs记录了一个错误,我们需要把错误放到主文件系统中
*/
(5) jbd2_journal_errno
/*
* 检查状态,如果有错误,用ext4_error()或者ext4_abort()
*/