概要
本文将包括如下内容:NAS文件系统常见概念,如inode、dentry、文件锁的描述;文件系统概念模型示例;文件系统IO路径;关键流程等内容
NAS服务器提供文件服务,支持NFS协议或SMB协议等挂载。文件系统用于存储文件的数据和元数据,通过计算节点挂载访问。以传统的目录树形式管理文件的数据和元数据。支持多个计算节点同时访问,进行数据共享和高并发读写。NAS中文件系统概念位置如下:
文件系统常见概念
-
inode 索引节点(Index Node)
要理解inode,要从文件存储说起,硬盘的最小存储单位是扇区(Sector),块(Block)由多个扇区组成,是文件存储的最小单元,一个文件可能会占用多个Block。块的最常见的大小是4Kb,约为8个连续的扇区(每个扇区存储512字节)。
文件数据都存储在块(Block)中,显然还需要一个空间来存储文件的元数据(MetaData),如:某个文件被分成几块、每一块的地址、文件owner,创建时间,权限,大小等。这种存储文件元信息的区域就叫inode。每个文件都指向一个inode,存储文件的元信息。
每个inode都有一个号码,Linux/Unix操作系统不使用文件名来区分文件,而是使用inode号码区分不同的文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。用户通过文件名打开文件的操作,实际上系统内部处理为:首先,系统找到这个文件名对应的inode号码;其次,通过inode号码,获取inode信息;最后,根据inode信息,找到文件数据所在的block读出数据。可以使用stat命令可以查看文件的inode信息,ls -i 查看inode号。
inode包含文件的元信息,具体有以下内容:
*文件的字节数
*文件拥有者的User ID
*文件的Group ID
*文件的读、写、执行权限
*文件的时间截,共有三个:ctime创建时间,mtime文件内容上一次修改的时间,atime文件最后一次访问的时间。
*链接数,即有多少文件名指向这个inode
*文件数据block的位置 -
文件锁
1.建议锁(advisory lock)
需要不同进程共同遵守先加锁再操作文件才能生效。
例:进程A加锁,进程B加锁就会阻塞或者失败。如果进程B不遵守约定,直接对文件操作,操作也可以生效。
2.强制锁(mandatory lock)
强制性锁使内核对每一个open、read、write系统调用都进行检查,检查调用进程对正在访问的文件是否违背了某一把锁的作用。
只要一个进程加了锁,其他进程不管是否加锁都会阻塞。
如进程A加了0-5字节的范围锁,进程B无法对0-5字节的进行读写操作。
3.阻塞锁/非阻塞锁:
阻塞锁:进程没有获取到锁会被阻塞,等其他进程释放锁后进程才可继续执行。
非阻塞锁:进程没有获取到锁,接口会直接返回失败,进程不会被阻塞。 -
Dentry/Entry 目录项(directory enrty)
每个文件除了有一个索引节点inode数据结构外,还有一个目录项dentry数据结构。dentry 结构中有指针指向相应的inode结构。
dentry 跟inode的关系/区别:
dentry用来实现名称和 inode 之间的映射,有一个目录缓存用来保存最近使用的 dentry。dentry 还维护目录和文件之间的关系,从而支持在文件系统中移动。
dentry记录着文件名、上级目录,下级目录等信息,从而形成我们看到的树状结构;有关文件的组织和管理的信息放在inode中。
文件系统概念模型
上图为打散的文件系统虚拟概念与对应盘上的物理概念。每个集群有多个文件系统,每个的fs有多个dtree(特殊的dir),每个dtree下有多个目录,目录下有多个文件,每个文件有对应的归属。volumn:结构/非结构化,内部空间来源抽象为volumn。
FSP 与Shard概念对应,(多个文件组成一个partition集合),以shard为单位,归属在某一个vnode,vnode会归属到一个node(即服务器)。
整体从对外部可见的虚拟概念,层层拆分,再以拆分的零散单元,汇聚到存储节点的某一个node上。
文件系统IO模型
上层(主机)传入数据,经过文件系统处理,得到相关信息,通过文件系统的信息,下层(存储池)处理后得到在盘上的起始位置和内部偏移,从而读出或者写入数据。
文件系统上层协议
虚拟文件系统实现关键流程
以下为自定义文件系统的基本结构与关键流程
文件系统以虚拟文件系统(对用户提供统一的调用接口,屏蔽底层fs的差异)为上层接口。
基本结构:
-
file_system_type 文件系统信息定义
owner、name、mount、kill_sb(umount触发,释放fs中申请的资源) -
inode_operations 定义对inode的操作,任何对象都会有
create 文件创建
lookup 用于目录项缓存
mkdir 先走lookup
rmdir 文件夹删除
unlink 文件删除 -
file_operations 文件操作
至少需要read,write,其他如open等可增加 -
file_operations 目录操作
read 复用文件操作read结构体
iterate_shared ll或cd触发
llseek 定位文件位置
关键流程:
- 文件系统加载到内核中
加载到内核之后才能用这个文件系统挂载目录,利用内核模块加载函数,触发文件系统注册;module_init > register_filesystem 将自定义文件系统注册到内核中。 - 将文件系统mount到挂载目录
创建挂载目录的inode对象,作为根节点对象 - 创建文件
- ll命令
- 文件内容读取
- 文件删除
需要判断是否有进程占用