OverlayFS介绍


OverlayFS介绍

OverlayFS has a workdir option, beside two other directories lowerdir and upperdir, which needs to be an empty directory.

Unfortunately the kernel documentation of overlayfs does not talk much about the purpose of this option.

The "workdir" needs to be an empty directory on the same filesystem as upperdir.

For readonly overlays the workdir might be ommittet among the upperdir. This give me the clue that it has to do with writing the merged files.

Please explain what's happening in the workdir when files are written or changed in the merged directory. Why is the writable upperdir not enough?

My guess: When a lower file is to be modified, it is copied (a non-atomic operation) to workdir and then atomically moved into the right place in upper. Thus, other processes will either open the (complete) lower file or (after the switch) the complete upper file, never a halfway-done file. – Marcel Waldvogel Mar 8 at 14:33

The workdir option is required, and used to prepare files before they are switched to the overlay destination in an atomic action (the workdir needs to be on the same filesystem as the upperdir).

Source: http://windsock.io/the-overlay-filesystem/

I would hazard a guess that "the overlay destination" means upperdir.

So... certain files (maybe "whiteout" files?) are non-atomically created and configured in workdirand then atomically moved into upperdir.

OverlayFS有一个workdir选项,另外两个目录lowerdir和upperdir需要是空目录。

不幸的是,overlayfs的内核文档并没有详细介绍这个选项的用途。

“workdir”必须是与upperdir位于同一文件系统上的空目录。

对于只读覆盖,workdir可能是upperdir中最合适的。这给了我一个线索,它与编写合并文件有关。

请解释在合并目录中写入或更改文件时workdir中发生的情况。为什么可写的upperdir不够?

我的猜测是:当修改较低的文件时,它会被复制(非原子操作)到workdir,然后原子地移动到较高位置的正确位置。因此,其他进程要么打开(完整的)下部文件,要么(切换后)打开(完整的)上部文件,而不是半途而废的文件Marcel Waldfogel 3月8日14:33

workdir选项是必需的,用于在原子操作中将文件切换到覆盖目标之前准备文件(workdir需要与upperdir位于同一文件系统上)。

资料来源:http://windsock.io/the-overlay-filesystem/

我猜“覆盖目的地”的意思是upperdir。

所以某些文件(可能是“白化”文件?)在WorkDir中以非原子方式创建和配置,然后以原子方式移动到upperdir。

1. OverlayFS介绍

OverlayFS是一种堆叠文件系统,它依赖并建立在其它的文件系统智商,不直接参与磁盘空间结构的划分,仅将原来文件系统中不同目录和文件进行“合并”。

因此OverlayFS更像是一个粘合剂,输出多个文件系统目录的“合集”。

1.1 OverlayFS应用

1.1.1 Overlay Driver

1.1.2 Overlay Driver2

2. OverlayFS分析

2.1 内核配置打开OverlayFS

File systems->Overlay filesystem support

2.2 OverlayFS架构分析

使能CONFIG_OVERLAY_FS之后,OverlayFS相关代码如下:

fs/overlayfs/
├── copy_up.c
├── dir.c
├── inode.c
├── Kconfig
├── Makefile
├── overlayfs.h
├── readdir.c
└── super.c

相关帮助文件在Documentation/filesystems/overlayfs.txt。

3. OverlayFS挂载

挂载一个overlay文件系统,可以通过mount -t overlay -o overlay 来实现。

是最终overlay的挂载点。

其中overlay的options有如下:

  • lowerdir=:指定用户需要挂载的lower层目录,lower层支持多个目录,用“:”间隔,优先级依次降低。最多支持500层。
  • upperdir=:指定用户需要挂载的upper层目录,upper层优先级高于所有的lower层目录。
  • workdir=:指定文件系统挂载后用于存放临时和间接文件的工作基础目录。
  • default_permissions:
  • redirect_dir=on/off:开启或关闭redirect directory特性,开启后可支持merged目录和纯lower层目录的rename/renameat系统调用。
  • index=on/off:开启或关闭index特性,开启后可避免hardlink copyup broken问题。

下面将lower和upper进行overlay,挂载到merge目录,临时workdir为work目录。

  mount -t overlay -o lowerdir=lower,upperdir=upper,workdir=work overlay merge

 如下同样将lower和upper进行overlay到merge,但是merge为只读属性。

mount -t overlay -o lowerdir=upper:lower overlay merge

4. OverlayFS使用

在使用如上mount进行OverlayFS合并之后,遵循如下规则:

  • lowerdir和upperdir两个目录存在同名文件时,lowerdir的文件将会被隐藏,用户只能看到upperdir的文件。
  • lowerdir低优先级的同目录同名文件将会被隐藏。
  • 如果存在同名目录,那么lowerdir和upperdir目录中的内容将会合并。
  • 当用户修改mergedir中来自upperdir的数据时,数据将直接写入upperdir中原来目录中,删除文件也同理。
  • 当用户修改mergedir中来自lowerdir的数据时,lowerdir中内容均不会发生任何改变。因为lowerdir是只读的,用户想修改来自lowerdir数据时,overlayfs会首先拷贝一份lowerdir中文件副本到upperdir中。后续修改或删除将会在upperdir下的副本中进行,lowerdir中原文件将会被隐藏。
  • 如果某一个目录单纯来自lowerdir或者lowerdir和upperdir合并,默认无法进行rename系统调用。但是可以通过mv重命名。如果要支持rename,需要CONFIG_OVERLAY_FS_REDIRECT_DIR。

4.1 构建测试用例

通过下面的脚本构建测试用例。

#!/bin/sh

create() {
  mkdir -p lower/common-dir lower/lower-dir upper/common-dir upper/upper-dir merge work
  touch lower/common-dir/lower-file lower/lower-dir/lower-file upper/common-dir/upper-file upper/upper-dir/upper-file
  echo "From lower." > lower/common-file
  echo "From upper." > upper/common-file
  echo "From lower." > lower/lower-file
  echo "From upper." > upper/upper-file

  mount -t overlay -o lowerdir=lower,upperdir=upper,workdir=work overlay merge
  #mount -t overlay -o lowerdir=upper:lower overlay merge
}

delete() {
  umount merge
  rm -rf lower upper merge work
}

case $1 in
  create)
    create
    ;;
  delete)
    delete
    ;;
esac

通过sudo ./overlayfs_test.sh create/delete创建测试环境或者清空。

如上的脚本构建的OverlayFS结果如下:两者共同目录common-dir内容进行了合并;重复文件common-file为uppderdir中的common-file。

 目录结构如下:

├── lower
│   ├── common-dir
│   │   └── lower-file
│   ├── common-file
│   ├── lower-dir
│   │   └── lower-file
│   └── lower-file
├── merge
│   ├── common-dir
│   │   ├── lower-file
│   │   └── upper-file
│   ├── common-file
│   ├── lower-dir
│   │   └── lower-file
│   ├── lower-file
│   ├── upper-dir
│   │   └── upper-file
│   └── upper-file
├── overlayfs_test.sh
├── upper
│   ├── common-dir
│   │   └── upper-file
│   ├── common-file
│   ├── upper-dir
│   │   └── upper-file
│   └── upper-file
└── work
    └── work [error opening dir]

4.2 新增文件或目录

分别在merge下创建new-dir、new-file、common-dir/new-file、lower-dir/new-file。

1 2 sudo mkdir merge/new-dir sudo touch merge/new-file merge/common-dir/new-file merge/lower-dir/new-file

查看结果如下:

.
├── lower
│   ├── common-dir
│   │   └── lower-file
│   ├── common-file
│   ├── lower-dir
│   │   └── lower-file
│   └── lower-file
├── merge
│   ├── common-dir
│   │   ├── lower-file
│   │   ├── new-file
│   │   └── upper-file
│   ├── common-file
│   ├── lower-dir
│   │   ├── lower-file
│   │   └── new-file
│   ├── lower-file
│   ├── new-dir
│   ├── new-file
│   ├── upper-dir
│   │   └── upper-file
│   └── upper-file
├── overlayfs_test.sh
├── upper
│   ├── common-dir
│   │   ├── new-file
│   │   └── upper-file
│   ├── common-file
│   ├── lower-dir
│   │   └── new-file
│   ├── new-dir
│   ├── new-file
│   ├── upper-dir
│   │   └── upper-file
│   └── upper-file
└── work
    └── work [error opening dir]

可以看出lower目录没有发生变化,在upper中新增lower-dir/new-file。其他所有的新增文件也都在upper中。

4.3 修改文件或目录

修改common-dir/lower-file、common-dir/upper-file、lower-dir/lower-file、upper-dir/upper-file、重命名lower-dir为new-dir。

vi将内容改成"new":
  merge/common-dir/upper-file
  merge/common-dir/lower-file
  merge/lower-dir/lower-file
  merge/upper-dir/upper-file
  merge/common-file

sudo mv merge/lower-dir merge/new-dir

结果如下:

.
├── lower
│   ├── common-dir
│   │   └── lower-file
│   ├── common-file
│   ├── lower-dir
│   │   └── lower-file
│   └── lower-file
├── merge
│   ├── common-dir
│   │   ├── lower-file
│   │   └── upper-file
│   ├── common-file
│   ├── lower-file
│   ├── new-dir
│   │   └── lower-file
│   ├── upper-dir
│   │   └── upper-file
│   └── upper-file
├── overlayfs_test.sh
├── upper
│   ├── common-dir
│   │   ├── lower-file
│   │   └── upper-file
│   ├── common-file
│   ├── lower-dir
│   ├── new-dir
│   │   └── lower-file
│   ├── upper-dir
│   │   └── upper-file
│   └── upper-file
└── work
    └── work [error opening dir]

同样lower中文件没有发生修改,所有修改都在upper中产生。

其中修改了upper/common-dir/upper-file、common-file、upper-dir/upper-file,新增了common-dir/lower-file、new-dir/lower-file、lower-dir。

其中new-dir/lower-file是由lower-dir/lower-file文件件重命名而来的,新增lower-dir是一个特殊文件。

c--------- 1 root root 0, 0 6月   8 14:17 upper/lower-dir

Overlayfs针对这种场景设计了一套“障眼法”——Whiteout文件。Whiteout文件在用户删除文件时创建,用于屏蔽底层的同名文件,同时该文件在merge中是不可见的,所以用户就看不到被删除的文件或目录了。

whiteout文件并非普通文件,而是主次设备号都为0的字符设备(可以通过"mknod c 0 0"命令手动创建),当用户在merge中通过ls命令(将通过readddir系统调用)检查父目录的目录项时,overlayfs会自动过过滤掉和whiteout文件自身以及和它同名的lower层文件和目录,达到了隐藏文件的目的,让用户以为文件已经被删除了。

4.4 删除文件或目录

删除所有merge中的目录和文件。

sudo rm -rf merge/*

结果如下:

.
├── lower
│   ├── common-dir
│   │   └── lower-file
│   ├── common-file
│   ├── lower-dir
│   │   └── lower-file
│   └── lower-file
├── merge
├── overlayfs_test.sh
├── upper
│   ├── common-dir
│   ├── common-file
│   ├── lower-dir
│   └── lower-file
└── work
    └── work [error opening dir]

可以看出所有upper中的目录和文件被删除了,所有lower中目录和文件都有对应的whiteout对应文件。

参考文档:《深入理解overlayfs(一):初识》、《深入理解overlayfs(二):使用与原理分析》、《OverlayFS》、《》。

  ============= End