LWN:关闭文件系统extent的一个优化!
共 2824字,需浏览 6分钟
·
2022-07-07 21:35
关注了就能看到更多这么棒的文章哦~
Disabling an extent optimization
By Jake Edge
June 21, 2022
LSFMM
DeepL assisted translation
https://lwn.net/Articles/898029/
在 2022 年 Linux 存储、文件系统、内存管理和 BPF 峰会(LSFMM)的最后一场文件系统会议上,David Howells 主持讨论了文件系统中一个当前引出了一些问题的优化。那些 Extent-based 文件系统中包含了一些有时不能反映文件中存在的空洞(hole)的数据结构。如果对稀疏文件(sparse file, 也就是有空洞的文件)的空洞区域中进行 read 时,返回的数据必须是零,但除此之外,文件系统并没有责任去真正意识到这里是有个空洞的,这就导致了下面要讲述的问题。
Howells 首先介绍了一下这个问题,他第一次遇到的是在使用 FS-Cache 来缓存文件内容的时候,但他后来发现这个问题实际上是个更普遍的问题。如果某个 extent-based 文件系统(如 Ext4、XFS 和 Linux 的 Btrfs)上有一个文件,在两个 extent 之间有一个小空缺时,文件系统有时就会把两个 extent 合并起来,并且用 0 来填补空缺区域。这样做的目的是为了减少文件的 extent list 数量,尽管这样做会增加磁盘上的存储空间的占用量。同时也会有一些相反的情况发生,如果文件系统看到文件中有一个文件中有很多 block 都是全 0 的时候,它可以通过创建成两个 extent 把中间作为空洞,从而节省磁盘空间,不过这一点这对 Howells 来说似乎不是一个问题。
[David Howells]
困难在于,由于 extent list 可以随时改变,因此各种操作如 lseek() 用 SEEK_HOLE 和 SEEK_DATA 来寻找空洞区域的话,都会出现假阳性或者假阴性的结果。FS-Cache 是用本地缓存文件中的空洞来代表尚未从服务器上获取的数据的,所以不应该直接想当然地填充这部分区域。如果加密不是在文件系统内进行的,那么这种 merging 和 filling 操作也会对带有空洞的文件的内容的加密操作造成负面影响。他说,当内容加密是单独进行的时候,加密文件中的空洞主要是为了表明明文文件中包含 0,而不是加密文件里面包含 0;所以在加密文件中填入很多 0 的话会破坏这个文件。
对于 ext4 上的 fscrypt,他认为是没有问题的,因为它是在 ext4 内完成加密的,ext4 不允许在加密文件中出现空洞;ext4 会用适当的加密内容来填补这些空洞。Ted Ts'o 证实了这一点。Howells 希望能够对任何文件系统的内容都支持加密,但不需要浪费磁盘空间来加密明文文件中的空洞。他想知道是不是应该允许其他用例来对底层文件系统提出要求不要进行这些优化。
Ts'o 说,这个问题的核心是一个哲学问题。一些文件系统把稀疏文件当作简单的优化,他们不管这里是否有空洞,只保证说这些空洞中会返回 0。但是,FS-Cache 把这些空洞事实上作为一个数据通道(data channel)来使用了;它需要确保那些它专门放在文件中的空洞需要一直保持空洞状态。如果用户空间期望 SEEK_HOLE 和 SEEK_DATA 也是按这种方式工作的话,就可能跟文件系统的看法不一致了,毕竟文件系统认为空洞只是一种优化,他说。
几位与会者整理了一下当前的情况,其中 Btrfs 不会做这种 "optimistic filling",也就是说不会把这些小空隙填充掉从而不再当作一个空洞,所以这个问题只存在于 ext4 和 XFS 中。不过,这里的终极问题是文件系统是否有义务维护稀疏文件以及磁盘上全 0 的 block 的文件之间的语义差异,Ts'o 说。他介绍说最初的理由是,比如说有一个 32KB 的空洞,那么在磁盘里直接写入 32KB 的 0 数据,比起使用两个 extent 所必需的 seeking 以及 extent-tree 的操作要更快。
一位远程参与者指出,欧洲原子核研究中心(CERN)几年前就因为这种行为而对 AFS 报告了一些 bug。CERN 当时正在使用一个大小为 2PB 的稀疏文件,并期望其中的空洞要能够一直保持。后来其中一个 12 字节的空洞消失了,从而破坏了整个文件。AFS 的开发者解释说,CERN 所依靠的是一个文件系统无法保证的行为,但这是一个与加密(或缓存)无关的例子,表明用户确实有可能希望能禁用 hole filling 动作。
Josef Bacik 建议说可以提供一个 per-file 的 flag 来禁用这个优化。Ts'o 说,Ext4 有一个文件系统范围的解决方法,就是使用一个可调整的参数来设置文件系统中会被填充的 hole 的最大 size。默认是 8 个文件系统 block,但将其设置为 0 就可以禁用该功能。他认为 per-file flag 确实更加好;他不介意替没能参加 LSFMM 的 XFS 的开发人员来提供意见,不过毕竟无法代表他们。然而,如果受影响的文件系统都达成一致应该如何设置这个 flag,那就是最好的方案了。
Bacik 说他想在 Btrfs 中加入这个优化,所以也想实现禁用此优化的机制。Chris Mason 说他不确定这些 "bridgeable(意思就是填充两个区域之间的空隙)" 的空洞出现得有多频繁,但对于 Btrfs 来说,创建一个 4KB 的 hole 绝对是得不偿失的。Ts'o 说,在 ext4 中填补小空隙的最初需求是来自 libbfd,它会创建有很多空隙的文件,然后最终用真正的数据填补这些空隙;不这样做的话会影响 "一些愚蠢的性能测试场景,比如说内核编译就是一个例子"。
Amir Goldstein 说,XFS 已经有了一个类似的 API,但跟人们想要的并不完全相同,也许它可以被扩展一下来满足这个需求。远程接入会议的 Jan Kara 说,那个 API 是基于 ioctl()的,主要目的之一是用来设置 project ID,并且跟 ext4 公用。这个 API 可以扩展一下来设置一个 inode flag,存放在 inode 里的 chattr flags 中,禁用这个 hole filling 行为,只要那里还有可用空间的话。Bacik 说,他认为还是有空间的,Howells 也同意,因此这似乎会是今后的实现方向了。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~