10 ext2文件系统IO流程:inode的创建、写入、读取、删除、释放子流程

在Linux文件系统中,inode就代表一个磁盘上的文件,所有磁盘文件的操作,最终都落到inode上去处理,inode的生命周期管理非常重要。但是inode的创建、写入、读取和删除,通常不是独立的流程,它是裹挟在其它的大IO流程中,比如创建文件。但是在其它流程中,inode的处理的介绍几乎是一笔带过,所以,有必要针对inode管理,总结一篇详实的材料。本文还是以ext2文件系统为例,来讲述inode生命周期的管理。

首先,你要知道inode管理的操作函数,都是在超级块结构体里声明,因为inode自己的操作表,都是和文件操作相关。好,我们一起来看一下:

// super.c

static const struct super_operations ext2_sops = {
    .alloc_inode    = ext2_alloc_inode,
    .free_inode     = ext2_free_in_core_inode,
    .write_inode    = ext2_write_inode,
    .evict_inode    = ext2_evict_inode,
    .put_super      = ext2_put_super,
    .sync_fs        = ext2_sync_fs,
    .freeze_fs      = ext2_freeze,
    .unfreeze_fs    = ext2_unfreeze,
    .statfs         = ext2_statfs,
    .remount_fs     = ext2_remount,
    .show_options   = ext2_show_options,
};
继续阅读“10 ext2文件系统IO流程:inode的创建、写入、读取、删除、释放子流程”

09 ext2文件系统IO流程:删除目录rmdir

上一篇说到ext2文件系统删除文件是逻辑删除,对应文件系统的unlink操作,其实就是解除磁盘目录项与inode关系,同时删除目录项(也是逻辑删除,与前一项合并)。那么,同样删除目录跟删除文件类似,ext2也是做了一次unlink操作。详细的删除目录流程如下:

  • ① 检查目录是否为空(除了.和..之外,是否还有其它文件),如果目录不空有文件,返回-ENOTEMPTY,无法删除(相关函数:ext2_empty_dir())
  • ② 如果目录为空,调用ext2_unlink()函数解除link
ext2删除目录流程
ext2删除目录流程
继续阅读“09 ext2文件系统IO流程:删除目录rmdir”

08 ext2文件系统IO流程:删除文件unlink

前面几篇博客讲了创建文件、创建目录、查找文件,接下来说一下ext2文件系统是如何删除文件,ext2文件系统删除文件,并没有在物理设备上擦除文件,只是做了一个unlink操作,所谓的逻辑删除。unlink的具体实现,就是解除目录项与inode关系,这样目录项就不会关联到inode,就无法查找到文件,达到了删除的目的。unlink的具体的流程如下:

  • ① 根据文件名和父目录信息,到磁盘上查找目录项(ext2_find_entry),记录对应的页面page和页地址page_addr
  • ② 解除目录项与inode连接,然后删除目录项(逻辑删除,其实是与前一个目录项合并)
  • ③ 修改inode->i_ctime,递减inode的硬链接数i->nlink,同时标记脏inode
ext2 unlink操作
ext2 unlink操作
继续阅读“08 ext2文件系统IO流程:删除文件unlink”

07 ext2文件系统IO流程:文件查找lookup

在打开文件、列举文件或者stat()操作时,用户端给的是文件路径信息,内核文件系统需要根据路径,查找到对应的inode,这样才能生成file对象,才能进行后续的读写等操作。所以,文件查找是一个基础能力,是其他文件操作的前置条件。

所谓查找文件,就是找到路径对应的dentry项,通过dentry项找到对应inode信息,有了inode才能对文件进行其他操作。文件查找时,优先在dcache缓存中查找,如果没有找到,需要到磁盘上进行遍历。

在dcache中查找,是VFS层面的基本动作,dcache如果没有找到,VFS就会调用具体文件系统的lookup()函数,到磁盘上进行遍历。以ext2文件系统为例,lookup具体流程如下:

  • ① 根据父目录inode、当前文件名,查找对应的目录项,最终查找到对应的ino(ext2_inode_by_name)
  • ② 根据ino,从磁盘上读取inode信息(ext2_iget)
  • ③ 连接dentry和inode,处理目录项的别名(d_splice_alias)
ext2文件lookup流程
ext2文件lookup流程
继续阅读“07 ext2文件系统IO流程:文件查找lookup”

06 ext2文件系统IO流程:创建目录mkdir

前一篇介绍了在目录下创建文件,我接下来们继续ext2主IO流程:创建目录。不论是创建文件还是创建目录,都是基于父目录,两者有很多相似之处,都要新建inode和目录项,然后建立inode与dentry的关系。但是创建目录操作,在写入目录项时,要多写两个目录项.(当前目录)和..(上层目录),详细流程如下:

  • 新建inode,并标记dirty,待内核同步
  • 设置操作表:i_op、i_fop、i_mapping->a_ops
  • 新建.和..两个目录项,inode指向新建的inode,并持久化
  • 在父目录的页缓存中,寻找一个空间,新建目录的目录项,inode指向新建的inode,并持久化(ext2_add_link)
  • 建立缓存dentry与inode关系
ext2创建目录
ext2创建目录
继续阅读“06 ext2文件系统IO流程:创建目录mkdir”

05 ext2文件系统IO流程:创建文件create

创建文件是文件系统的基本操作,之前在介绍Linux文件系统VFS时,说过创建文件会调用inode操作表中的create()函数,那create函数具体应该如何实现呢?

文件系统在创建文件时,VFS会调用父目录目录的create()函数,在这个函数中要完成具体的文件创建,以ext2文件系统为例,ext2注册的创建文件的函数指针是ext2_create,在ext2文件系统创建文件,一般包括以下几个步骤:

  • 新建一个inode对象
  • 设置inode的文件操作表
  • 标记inode为脏,等待写入到磁盘
  • 在父目录的页缓存中,写入目录项数据,指向新建的inode
  • 建立缓存dentry和inode关系
ext2创建文件
ext2创建文件
继续阅读“05 ext2文件系统IO流程:创建文件create”