todo

  • 为什么文件系统不默认提供每个目录的空间使用量呢?
    • 多文件系统嵌套, 还是需要用户自己去df挂载的位置里去找所在目录在哪个分区里, 然后分区大小多少, 为什么不能直接显示出当前目录使用量及这个文件系统根的容量呢?
    • subvolume btrfs子文件系统支持
    • 说到这个,df默认为啥没有什么超时机制呢?卡在显示所有上? 可能df只提供基本查询, 自己有超时需求自己处理?
  • 文件系统配额, 如果不开启的话, 怎么知道这个文件系统究竟有多少空间可以用呢?
  • 文件系统写满时, 到底是哪层做的错误返回?
    • 分配器提供的吧?
    • 所以对于分布式块设备上建的文件系统, 得是支持扩容的文件系统?
  • 文件系统中的原子事务如何实现? 幂等性如何保障
  • extent技术
  • 隐藏的预留容量, 超级块

与块设备相比

问题原因 * 如何找到你想要的信息 * 如何保证一个用户不会读取另一个用户的数据 * 如何得知哪些块是空闲的, 等等

文件是上面这些问题的抽象解决.

文件系统概念[^3]

  • 主要为存储设备提供一致的访问和管理方式.
    • 数据以文件的形式存在
  • 文件以树形目录进行组织.
  • 较为复杂, 扩展性相比现在新增的对象存储较差一些.(各公司自研的应该还好)
    • 文件系统的复杂性导致可扩展性未能跟上互联网的高速发展, 极大简化了的对象存储及时填补了空确.
    • 不过因为对象存储缺乏树状结构, 也不支持原子重命名操作, 跟文件系统差异较大.

关键优化问题

存储大量小文件时, 一次文件多次读取元数据信息的"长尾效应"

  • 比如Haystack通过合并多个小文件成一个大文件, 通过减少文件数量的方式解决

文件系统架构对比[^3]

MPI 并行文件系统

JuiceFS

TODO:JuiceFS 只需要专注元数据的管理,也大大降低了元数据服务的复杂度(GFS 和 MooseFS 的 master 要同时解决元数据的存储和数据块的健康管理)。

盘古

NebulasFS(360)

  • master和datanode

多文件系统关联

  • 挂载时
    • 分配一个新的inode指向新的文件系统的data block.
    • 挂载完成后,将在/proc/self/{mounts,mountstats,mountinfo}这三个文件中写入挂载记录和相关的挂载信息,并会将/proc/self/mounts中的信息同步到/etc/mtab文件中,当然,如果挂载时加了-n参数,将不会同步到/etc/mtab。[^3]

FUSE

  • 用户-内核通信协议
    • splice
    • 零拷贝技术
  • 内核FUSE队列
  • 缓存写回

实现

文件系统布局

引导块

超级块

  • 文件系统的大小
  • 文件系统中的数据块数
  • 指示文件系统状态的标志
  • 分配组大小

空闲空间块

  • bitmap位图
  • bit vector 位向量
  • 链表 #### 碎片 #### inode ### 分配 思想
  • 有效利用文件空间
  • 快速访问文件 #### 连续分配
  • CD-ROM
    • 满的时候, 标记-1之类的. #### 链表分配
  • 随机访问难 #### 使用内存表进行链表分配
  • 引入索引的概念
  • FAT(File Application Table)
    • 整个链表都在内存中, 表占用空间较大(1T盘 1KB的块, 需要至少3-4个字节的管理, 需要3GB左右的内存)
    • 满的时候, 直接链表最后断开就行了. #### inode
  • 只有文件打开时, inode才在内存中, 解决FAT的问题
  • inode在初始化文件系统时就给定了, 多大的块设置一个inode.
  • 128字节整数倍
  • /etc/mk2fs.conf
  • inode_ratio, 多大的块分配一个inode号
  • ext4预留了inode用于比如/proc/, lost+found
  • 问题:
    • 文件知道自己的inode之后, inode存储了什么东西,可以让他找到对应的所有块? [^3]
      • inode中保存了块的文件指针
      • ext2/ext3 最多15个指针, 前12个直接寻址, 第13-15个分别一级,二级,三级间接寻址
        • 一个4K block可以放4096/4=1024个指针. 即1024^3+ 1024^2 + 1024^1+12 = 1.1G个块指针, * 4K= 4T左右的大小
      • ext4 使用了extent的方案
    • 满的时候, 最后一个磁盘地址不指向数据块, 而是指向一个包含额外磁盘块地址的地址 ### 目录的实现 ### 共享文件
  • 有向无环图
  • 硬链接
  • 软链接
  • 问题:
    • 复制时如果不对符号链接进行区分, 会带来重复写入问题

日志结构文件系统(Log structured File System, LFS)

  • 性能问题
  • 背景:
    • 不断增长的内存
    • 顺序I/O强于随机I/O
    • 现有低效率的文件系统
    • 文件系统不支持RAID(虚拟化)
    • 由于Page cache存在, 读性能基本不是问题
  • 数据结构
    • Inode
    • Inode Map
    • Segment
    • Segment Usage Table ### 日志文件系统
  • 防止掉电/崩溃问题
  • 幂等性
  • 引入原子事务

虚拟文件系统

  • VFS
  • 对用户进程的上层接口POSIX接口
  • 下层接口, 各文件系统提供的.
  • vnode

文件系统的管理和优化

磁盘空间管理

  • 分段管理
  • 分页管理 #### 块大小 #### 记录空闲块
  • 位图(bitmap)
  • 磁盘块链表
  • 问题
    • 在内存中保留一个半满的指针块, 这样既处理文件的创建和删除, 又不会为空闲表进行磁盘IO
    • 磁盘处理一些列临时文件, 不需要进行任何磁盘IO

磁盘配额

  • 硬限制
  • 软限制
    • 用于实现警告和用户权限控制的计数 ### 文件系统备份
  • 场景
    • 从灾害中恢复
    • 从错误的操作中恢复
      • 删除->回收站
  • 设计
    • 备份整个文件系统还是只备份一部分文件
    • 增量转储
    • 压缩
      • 备份过程中出错, 压缩文件是直接损坏还是可以纠正?
    • 正在使用的文件系统如何备份
      • 设置时间点? 瞬时快照

物理转储和逻辑转储

  • 物理转储
    • 全量备份
  • 坏块转储
  • 逻辑转储
    • 维持一个inode为索引的bitmap, 修改过的文件被标记
  • 空洞问题的处理 ### 文件系统的一致性
  • 因为系统调用并不是原子事务的, 写操作复杂, 完全存在不一致可能性.
  • fsck
  • sfc(windows)
  • 块的一致性检查
  • 文件的一致性检查
  • 空闲块和已使用的块的表的对照
    • 块丢失(missing block)
    • 块重复
      • 空闲表中重复
        • 直接标记就行
      • 不同文件使用了这个块
        • 分配一个磁盘快, 把他插入到文件里, 比如文本文件打开中, 出现掉电, 中间插入乱码是不是就是这个做法?
      • 已使用和空闲表中均出现(就是删除过程只执行了一半)
        • 应该也是优先分配一个新块, 插入到文件里
  • 检查目录系统, 维护计数器表
    • 检查inode数量与目录的关系

文件系统性能

高速缓存

  • block cache
  • buffer cache
  • 逻辑上属于磁盘, 实际通过内存来提供支持
  • 页面置换算法

块提前读

  • 考虑顺序读取, 进行预读取
  • 好像在磁盘驱动那层也有这个设计? 所以其实多层都提供了这样的功能?

减少磁盘臂运动

  • 块簇
    • 以连续块簇来跟踪磁盘存储区.
    • 分配时尽量分配在同一个柱面上
    • 解决一个连续内容被分配在2个柱面上带来的寻道次数翻倍
  • 读文件至少2次磁盘访问
    • 访问inode
    • 访问块
    • 原本inode放在磁盘开始位置, 所以inode到块的平均距离是柱面组的一半
    • 改到中间

磁盘碎片整理

  • 删除文件, 回收磁盘块.
  • defrag, 移动文件, 使空闲块连续分布
  • ext2/ext3选择磁盘块的方式, 导致不怎么需要处理磁盘碎片整理[^2]
    • 日文件系统分配策略上并不完全连续分布
    • ext的延迟写入技术
    • 主要是FAT

文件

文件命名

  • 名字
    • unix 大小写敏感
    • MS-DOS 大小写不敏感
  • 扩展名
    • unix 无感知
      • 但是目前是不是也像window一样了
    • windows 能够在操作系统层面设置不同扩展名对应的程序

文件结构

目前都是字节序列, 用使用者自己进行定位. 这样的话其实和操作裸块也有点像吧? 的确

不知道有没有采用树等结构化关系的, 感觉更适合更上层的应用自己抉择.

文件类型

  • 文件
    • 由内核处理
  • 目录
  • 字符特殊文件
    • 串行I/O设备
  • 块特殊文件
    • 由设备驱动程序处理

操作系统至少能识别自己的可执行文件. 所以文件系统和操作系统还是有一些绑定关系的?

文件访问

文件属性

文件操作

  • create
  • delete
  • open
  • close
  • read
  • write
  • append
  • seed
  • get attributes
  • set attributes
  • rename

目录

一级目录系统

  • 根目录

层次文件目录

路径名

目录操作

  • create
  • delete
  • opendir
  • closedir
  • readdir
  • rename
  • link
  • unlink

FUSE支持

Reference

  1. 简直不要太硬了!一文带你彻底理解文件系统 - 程序员cxuan - 博客园
  2. (80 条消息) 为什么NTFS系统容易产生碎片而ext系列则不会? - 知乎
  3. ext文件系统机制原理剖析 | 骏马金龙
  4. 分布式文件系统架构对比-InfoQ
  5. 分布式文件系统浅谈 - 知乎