查看原文
其他

LWN:使用blksnap抓取块设备的快照!

关注了就能看到更多这么棒的文章哦~

Block-device snapshots with blksnap

By Jonathan Corbet
November 14, 2022
DeepL assisted translation
https://lwn.net/Articles/914031/

一般来说,在技术领域内只要工作过一段时间,就能清楚地意识到多么需要良好的数据备份习惯。但是,如果在备份过程中,相关的文件系统正在频繁地变动,那么很难创建出一个真正完好的备份。多年来,已经开发出各种方法来解决这个问题,比如在备份运行时直接关闭系统,或者各种快照机制。如果 Sergei Shtepa 的 blksnap patch set 能进入 mainline 的话,那么内核可能会得到另一种快照方案。

blksnap patch,完全没有文档,所以下面的内容大部分来自于对代码的分析理解也就是纯逆向工程得出的。Blksnap 是在 block 设备层来进行快照,这意味着相关设备上的任何文件系统都是完全可以透明地支持起来的。它能够将多个块设备组合起来创建出快照,所以它应该会很适用于 RAID 阵列之类的情况。目标使用场景可能是那些自动备份系统;blksnap 创建的快照被称为 "non-persistent",只要真正进行了备份之后,就会将其丢弃掉。

由于 blksnap 是在 block 层实现的,所以它必须需要一个不属于被抓取快照的设备上的空间,来存储快照文件。具体来说,可以用一些 ioctl()操作来从另一个设备上分配出一些扇区,用来存储 "difference blocks(差异数据块)",并随着时间推移会修改分配了哪些扇区。并且具备通知机制,当某个存放差异数据区域空间不足时,用户空间进程可以收到通知,从而可以继续为该区域分配更多的 block。

blksnap 使用的算法非常简单:一旦为一组块设备创建了快照(通过另一个 ioctl()操作来发起),blksnap 就会拦截对这些设备中每一个 block 进行的写入操作。如果某个 block 在快照之后第一次被写入,那么该 block 上之前的内容就会被复制到差异数据区域,并且会记录下该 block 在快照创建好后被改变的情况。这样做了之后,写操作就可以继续正常进行了。因此,block device 上的数据总是可以展示最近写入之后的情况,而差异数据区则包含了快照创建时的这些较早数据,从而可以用来根据快照恢复状态。

为了能够拦截这些对 block 设备的写入操作,Shtepa 不得不在 block 层添加了一个新的 "device filter" 机制。可以给某个设备来附加一个 filter,从而在该设备上的每个操作执行之前都被调用,使用代表这个操作的 BIO 结构来当作 filter 的一个参数。如果 filter 函数返回了 false,这个操作就不会被执行。早期版本的 patch set 中提供了将多个 filter 附加到同一个 block 设备上的不同 "位置" 的功能,但由于目前 filter 还没有其他用途,所有这部分功能被删除了。

Blksnap 使用 filter 功能来捕捉对抓取了快照的设备的写操作。当发现有写操作时,就会暂停这个操作,同时将要写的 block 的原始内容复制到差异数据区;在完成之后,才会正常提交这个写操作。

有趣的是,这组 patch set 中没有任何地方描述在快照被创建之后,人们如何访问到它。不过,看看 ioctl()接口,就可以猜到几种可能性。其一是获取与 snapshot 相关的有过改动的 block 列表,这对于某些类型的增量备份场景来说可能很有用。但 blksnap 也为每个快照都创建了一个新的、只读的设备。从该设备中读取一个 block 就会让 blksnap 查询它内部维护的有过改动的 block 的 map;如果相关的 block 已经被变更过,那么它就会从差异数据区中来读取。否则的话就直接从原始 block 设备中读取。快照设备的 major number 和 minor number 可以通过另一个 ioctl() 操作来获得;还有一个没有文档描述的 sysfs 文件可以用来参考。

内核现在并不缺乏制作快照的功能,所以人们可能会顺理成章地问为什么还需要 blksnap。它显然跟 Btrfs 等文件系统所提供的快照功能不一样,因为 blksnap 是在 block 设备层来实现的。所以 blktrace 可以用在那些本身没有快照功能的文件系统上。Btrfs 的快照与文件系统本身都是存放在同一个块设备上的,这意味着两者会互相争抢存储空间,而快照所使用的空间可能会阻止像当前活跃的文件系统中写入数据。由于 blksnap 将其快照数据存储在一个单独的设备上,所以这些数据不会妨碍正在进行的操作。在差异数据区的空间用完了的情况下,快照就会被破坏,但被快照的设备本身并不会受到影响。

在块设备层还存在一个现成的替代方案,就是 device mapper snapshot target。blksnap 提供的功能跟它在很多方面都比较相似;两者都是通过拦截写操作并将旧数据复制到另一个独立的设备上来实现的。不过,Blksnap 并不需要给要被快照的设备设置 device mapper。它还声称对其差异数据区实现了更灵活的管理,尤其是当有多个设备一起被快照的时候。

这些差异似乎已经足够了,所以到目前为止,没看到有人质疑 blksnap 是否有必要添加到内核里。该 patch set(尽管被标记为 "v1")正在进行从 7 月的第一次发布之后进行的第二次修改,其中已经包含了不少 fix。运气好的话,下一次修订没准能让我们看到一些文档,然后可能就差不多准备好可以被纳入 mainline 了。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存