ZFS 如何对大文件进行写时复制

ZFS 如何对大文件进行写时复制

假设我有一个example.log在 ZFS 上调用的大文件 (8GB)。我这样做是cp example.log example.bak为了复印。然后我在原始文件中添加或修改一些字节。会发生什么?

ZFS 会复制整个 8GB 文件还是仅复制发生更改的块(以及从文件描述符指向该块的所有 inode 链)?

答案1

据我所知,FreeBSD ZFS 不支持使用 cp 进行写时复制;本机 cp 似乎没有此类轻量级副本的选项,并且--reflink在 ZFS 系统上尝试 GNU cp 时出现错误,我尝试使用错误消息“cp:无法从 'example.log' 克隆 'example.bak':操作”不支持”。

评论者提到 Solaris cp 有一个-z开关可以执行此类复制。

但是,我希望这能回答您的根本问题,即写时复制用于文件系统快照:假设您在 1000GB 可用空间中使用了 900GB,没有什么可以阻止您为该文件系统创建快照,该快照不会占用 900GB;事实上,它最初根本不会占用任何新的数据块。

创建包含 的原始文件系统的快照后 example.log,您最终会得到两个“副本”:快照中的只读版本和原始位置中的实时版本。当副本被修改时,无论是通过附加还是就地更改,会发生什么?这就是奇迹发生的地方:只有那些被更改的块才会被复制并开始耗尽空间。情况并非是一旦更改整个文件就会被复制。

答案2

cp命令将创建一个新文件,因此每个块都会有一个副本。一旦您修改了原始文件中的几个字节,ZFS 将首先将包含这些字节的数据块从磁盘复制到 RAM,将新字节应用到其中,然后将该块写入磁盘上的新位置。原始块将被释放(这里简化,但这本质上就是发生的情况)。文件的其余块保持不变。

关于您问题的 inode 部分:ZFS 没有 inode。相反,它维护“间接块”。这些是磁盘上指向文件数据的元数据块。可以有多层间接块,具体取决于文件大小和文件的块大小。指向已修改块的间接块将需要更新,但其余部分保持不变。

相关内容