为什么在 btrfs 子卷之间移动文件是一项昂贵的操作?

为什么在 btrfs 子卷之间移动文件是一项昂贵的操作?

据我所知,btrfs 子卷共享相同的文件系统“存储”,因此我很惊讶地发现在不同的子卷之间移动文件是一项昂贵的操作,就像在不同的文件系统之间移动(复制+删除)一样。

我曾是尤其当有人建议采用这种解决方法时,我感到很惊讶:在子卷之间重新链接复制文件,然后删除原始文件。据说这是一种廉价的操作(仅移动元数据)。为什么不同的子卷在使用 COW 时可以共享数据块,但在应该更简单的移动数据操作中却不能共享数据块?

答案1

为什么使用 COW 时不同的子卷可以共享数据块,但在应该更简单的移动数据操作中却不能?

mv 使用重命名系统调用来尝试移动。btrfs 的内核重命名实现检测跨子卷移动并明确禁止这种操作(即使在同一个挂载点下):

/* we only allow rename subvolume link between subvolumes */
if (old_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest)
    return -EXDEV;

这可能与子卷 inode 核算以及这些操作所采用的代码路径有关。reflink-copy 实际上是在创建新的元数据(但数据本身是 CoW),这些元数据核算在新的子卷中。理论上,他们可能可以通过执行类似于 copy --reflink 后跟 rm source 的操作来让 rename “移动”元数据……只是没有人努力去做。

相关内容