Linux 版本的 Time Machine: NILFS 2

NILFS 本意是给闪存存储设备用的,但也能用在普通的机械磁盘上。NILFS 最大的特点是可以“持续”的做 snapshot,这个“持续”指自动的、秒级的,对应用性能没有影响,而 LVM、ZFS、BTRFS 这些支持快照的文件系统,快照是要人为触发的,做快照时对应用性能是有影响的。

这是 Debian 上的一次 NILFS 体验之旅:

$ sudo apt install nilfs-tools
$ cat /etc/nilfs_cleanerd.conf

$ dd if=/dev/zero of=fs.img bs=1M count=200
$ mkfs -t nilfs2 -L some-label fs.img
$ sudo mount fs.img /mnt
$ grep nilfs /proc/mounts
$ nilfs-tune -l /dev/loop0

$ sudo cp -r /etc /mnt
$ sudo cp -r /etc /mnt/a
$ lscp
$ sudo chcp ss /dev/loop0 2
$ mkdir snapshot-2
$ sudo mount -r -o cp=2/dev/loop0 snapshot-2

$ sudo rmcp 1

老版的 NILFS 据说有个 bug,磁盘空间用完后删除不了,因为无法建快照了,但好像新版解决了,我没能复现100%占用后不能删除,我用root操作的,所以保留空间也能用完,但还是能删除的。”问题”在于删除后磁盘可用空间还是零,这其实不是真的问题,只是需要nilfs-clean -p 1s -r 告诉nilfs-cleanerd不要保留一秒以前的checkpoint,它默认总是保留一小时以内的checkpoint。

NILFS 的snapshot其实是特殊标记的checkpoint(用chcp命令改标记),snapshot不能被rmcp,估计也不能被gc,只有snapshot才能被只读挂载(任意没删除的checkpoint可以先chcp换成snapshot再挂载),这个设计也符合预期,默认一小时以前的checkpoint会被gc掉,如果觉得某个版本重要,可以标记成snapshot。

另外观察到checkpoint自动创建是秒级的,不会每一次写入就生成checkpoint,这也可以理解,毫秒级checkpoint一般没必要。

checkpoint还分重要的和不重要的,大概是写入停顿时出来重要的checkpoint,lscp默认只显示重要的checkpoint,这个设计很贴心。

需要注意的是 NILFS 的快照是只读的,不能写入,不支持“回滚”文件系统修改(除非你把 snapshot 挂载后 rsync 全复制一份出来),NILFS 主要是用来防止误删误改文件,以及对文件系统做审计用途。