OverlayFS

关注
义项:Linux联合文件系统
OverlayFS

OverlayFS 是 Linux 内核提供的一种联合文件系统(union filesystem),它把一个通常可写的目录树叠加在一个或多个只读目录树之上,对外呈现为单一的合并视图,所有修改都写入可写的上层[1]。它在 2014 年被合并进 Linux 3.18 内核主线,此后成为容器与嵌入式系统中使用最广泛的层叠文件系统之一,Docker 的 overlay 与 overlay2 存储驱动即基于它构建[2]。

百科 图文
目录
  1. 定义
  2. 原理
  3. 发展历程
  4. 应用
  5. 局限
  6. 参见

定义

OverlayFS 是 Linux 内核中的一种联合文件系统,它的作用是提供一个"覆盖"式的文件系统视图:把若干个目录树叠加在一起,让使用者看到的是一个统一的目录结构[1]。参与叠加的目录被划分为上层与下层两类,下层可以有一个或多个,通常处于只读状态,甚至可以是另一个 OverlayFS 实例[3]。

严格来说,上下层指的是目录树而不是整个文件系统,因为上下两个目录树完全可能位于同一个文件系统之中,也不要求它们各自是某个文件系统的根[4]。当同一个名字在上层与下层同时存在时,上层对象可见,下层对象被隐藏;如果两者都是目录,则合并为一个目录[5]。

原理

挂载 OverlayFS 需要指定 lowerdir、upperdir 和 workdir 三类目录,典型命令为 mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,workdir=/work /merged[3]。其中 workdir 必须是位于 upperdir 同一文件系统上的空目录;下层可以为任意 Linux 支持的文件系统类型,不要求可写;上层通常可写,并且需要支持创建 trusted.* 扩展属性、在 readdir 响应中提供合法的 d_type,因此 NFS 不适合作为上层[3]。仅由两个只读文件系统组成的只读叠加则可以使用任何文件系统类型[4]。

对文件的写入通过"写时复制"(copy_up)完成:当下层的文件被以需要写权限的方式访问时,该文件先被完整复制到上层,此后的操作直接作用于上层的新副本[4]。复制时会先保证上层中存在包含它的目录,随后按原有元数据(属主、权限、时间戳、符号链接目标等)创建对象,再复制数据与扩展属性[4]。

由于下层不能被修改,删除文件必须靠上层记录:OverlayFS 使用 whiteout 与 opaque 目录来表示"此处已删除"[4]。在白头文件中,whiteout 早期以符号链接形式实现,后来的内核文档描述为设备号 0/0 的字符设备文件[4];目录则通过把 trusted.overlay.opaque 扩展属性置为 y 标记为不透明,此时下层同名目录被完全忽略[6]。

对合并目录执行 readdir 时,系统分别读取上层与下层目录,先列上层、再补下层中尚未出现过的名字,并把合并结果缓存在 struct file 中;目录打开期间对它的改动不会反映到读取结果里[6]。从多个低层叠加时,lowerdir 之间用冒号分隔,从右到左依次自底向上堆叠[4]。


graph TD

L2["lowerdir 下层目录(只读)"] --> M["merged 合并视图"]

L1["upperdir 上层目录(可写)"] --> M

W["workdir 工作目录"] -.-> L1

M --> R["文件读取:上层优先,其次下层"]

M --> Wr["文件写入:先 copy_up 到上层"]

发展历程

OverlayFS 由 Miklos Szeredi 开发。2011 年 3 月,他以一组补丁的形式把它提交到 Linux 内核邮件列表,请求并入主线,其中包含 Neil Brown 撰写的文档[7]。当时的审查意见集中在 i_op->open 接口的调用约定以及 copy_up 的加锁分析上,这些意见促成了从 v6 到 v8 之间的若干修改,包括把单一源文件拆分为多个文件[8]。

早期版本使用多套内部约定,开发过程中该文件系统曾被称为"混合联合文件系统",后正式定名为 overlay filesystem,简称 overlayfs[7]。OpenWrt 曾在内核 2.6.37 与 2.6.38 上加以移植,用于以 squashfs 作只读部分、jffs2 作可写覆盖层的路由器固件,以便在闪存容量很小的设备上提供可写根文件系统[7]。

2014 年 10 月,OverlayFS 的代码进入 Linux 3.18 的候选版本,被合并进内核主线。随着合并的完成,内核模块名由 overlayfs 改为 overlay,因此在部分文档中两个名称会交替出现[2]。

合并之后,OverlayFS 陆续补充了若干面向一致性的特性:4.10 版引入 redirect_dir,允许对目录执行改名;4.13 版引入 index,用于在复制时保留硬链接;4.16 版支持把叠加层导出到 NFS;4.12 至 4.17 版期间引入 xino,用于生成唯一对象标识;4.19 版引入 metacopy,使元数据可以单独复制[9]。这些特性默认多为关闭状态,以兼容旧内核,用户需按场景显式启用[9]。

应用

Docker 的 overlay 与 overlay2 存储驱动都建立在 OverlayFS 之上:镜像的各层作为只读的 lowerdir,容器层作为可写的 upperdir,两者叠加后通过一个称为 merged 的目录对外暴露[2]。镜像层目录之间使用硬链接引用共享数据,从而节省磁盘空间[2]。

Docker 自 1.12 版起还提供 overlay2 驱动,它在 inode 使用效率上明显优于早期的 overlay 驱动,但要求 Linux 内核 4.0 及以上[2]。早期的 overlay 驱动只支持两层,因此多层镜像无法直接对应为多层 OverlayFS,而是把每个镜像层实现为独立目录并用硬链接引用下层数据[2]。

除容器之外,叠加式文件系统最典型的用途是 Live CD 一类的场景,即用一个可写目录覆盖只读的镜像目录[1]。在嵌入式领域也有实际部署,例如以 squashfs 提供只读部分、以 jffs2 提供可写覆盖,从而在用户重置设备时无需重新刷写固件[7]。

局限

OverlayFS 在语义上并非完全符合 POSIX。内核文档列出的已知差异包括:按照 POSIX,读取应当更新 st_atime,而当文件位于下层时这一时间戳不会被更新;下层文件以只读方式打开后再以 MAP_SHARED 映射,此后的改动不会反映到内存映射中[10];此外,正在执行的下层文件被以写方式打开或被截断时,也不会像普通文件系统那样返回 ETXTBSY 错误[11]。

copy_up 会带来若干副作用。复制本质上是新建一个内容相同的文件并放到旧名字下,新文件可能位于不同的文件系统,因此 st_dev 与 st_ino 都可能变化[4]。此前打开该文件而持有旧 inode 的进程仍会看到旧数据,复制前取得的文件锁也不会作用于复制后的文件;若被复制的文件有多个硬链接,链接会被打断,改动不再传播到其他名字[4]。

OverlayFS 工作在文件级别而非块级别,因此任何 copy_up 都会复制整个文件,即使只修改其中很小的一部分;对于大文件,这会对写性能造成明显影响[12]。针对元数据的操作也存在类似开销,metacopy 特性的设计目的正是先只复制元数据、等到真正写入数据时再复制完整文件[5]。

若干操作不具备原子性。早期实现中,在 copy_up、rename、unlink、rmdir 或对 whiteout 的创建过程中发生崩溃,可能导致叠加层上的文件系统损坏,相关操作需要变为原子操作,或者至少能够检测出损坏[1]。在重命名目录方面,默认行为是对下层或合并得到的目录返回 EXDEV 错误,由用户空间自行处理;只有在启用 redirect_dir 之后,目录才会被复制到上层并设置 trusted.overlay.redirect 扩展属性,再移动到新位置[6]。

叠加层与其底层目录的一致性需要人为保证。叠加层处于挂载状态时,不允许改动底层文件系统,否则叠加层的行为未定义;在未挂载时允许对上层目录树做离线修改,而对下层目录树的离线修改只有在未使用 metacopy、index、xino 和 redirect_dir 等特性的前提下才被允许[10]。使用 volatile 选项挂载时,叠加层不保证能从崩溃中恢复,若在工作目录中发现上次残留的标记目录,再次挂载将被拒绝[5]。

在 st_ino 与 st_dev 的稳定性方面,如果未启用 xino,或者底层文件系统的 inode 号中没有足够的空闲位,OverlayFS 无法保证 stat 返回的 st_ino、st_dev 以及 readdir 返回的 d_ino 表现得和普通文件系统一致,同一叠加层内两个对象的 st_dev 可能不同,目录对象的 st_ino 甚至可能在挂载期间发生变化[10]。此外,把叠加层的各层复制到另一目录树甚至另一台机器是很常见的做法,但在启用 index 特性后,这样复制的层会因为下层根文件句柄校验失败而无法挂载[10]。

参见

  • Docker —— 其 overlay 与 overlay2 存储驱动建立在 OverlayFS 之上,用镜像层作只读下层、容器层作可写上层。

  • Linux内核 —— OverlayFS 自 3.18 版起被合并进这一内核主线。

  • 写时复制 —— OverlayFS 处理下层文件写入时采用的核心机制 copy_up 即属此类技术。

  • AUFS —— 更早的联合文件系统实现,OverlayFS 在设计上被视为它的后继者之一。

  • squashfs —— 常作为 OverlayFS 的只读下层,与可写上层配合用于嵌入式设备。

  • NFS —— 因不满足扩展属性与 d_type 要求,不适合充当 OverlayFS 的上层。

参考资料

  1. LKML: Andrew Morton: Re: [PATCH 5/9] overlay filesystem [引用日期2026-10-14]
  2. Docker and OverlayFS in practice [引用日期2026-10-14]
  3. mount [引用日期2026-10-14]
  4. softwareheritage.org 上的网页 [引用日期2026-10-14]
  5. mount [引用日期2026-10-14]
  6. overlayfs [引用日期2026-10-14]
  7. lkml.org 上的网页 [引用日期2026-10-14]
  8. [PATCH 0/7] overlay filesystem: request for inclusion [引用日期2026-10-14]
  9. Overlayfs and Containers [引用日期2026-10-14]
  10. softwareheritage.org 上的网页 [引用日期2026-10-14]
  11. softwareheritage.org 上的网页 [引用日期2026-10-14]
  12. overlayfs-driver [引用日期2026-10-14]
词条评价
词条统计

浏览次数:3 次

阅读量:0 次 · 阅读完成量:0 次

最近更新:2026-10-13T21:13:53Z

历史版本

本条目引用的词条
Docker Linux内核 写时复制 AUFS squashfs NFS