使用写时复制(COW)在Python中复制文件

3

我的文件系统(FS)(特别是ZFS)支持写时复制(COW),即如果正确执行,复制操作非常便宜且恒定,实际上并不会复制底层内容。只有在我编写/修改新文件时才会复制内容。

实际上,我刚发现,ZFS-on-Linux实际上尚未为用户空间实现该功能(对吗?)。 但例如BTRFS或XFS有。 (请参见这里这里这里, 这里。)

对于(GNU)cp实用程序,您将传递--reflink = always选项 (请参见这里。) cp调用ioctl(dest_fd,FICLONE,src_fd) (请参见这里这里)。

如何在Python中实现此行为(如果可能)?

我假设“零拷贝”(例如这里的 os.sendfile)不会导致这种行为,对吗?因为查看shutil_fastcopy_sendfile实现(这里),它仍然是一个循环,围绕os.sendfile使用一些自定义字节计数(应该是块大小max(os.fstat(infd).st_size, 2 ** 23))。还是会有类似行为的吗?

写时复制(COW)是在文件级别还是块级别上进行的?

如果可能的话,我希望这个方案是通用的和跨平台的,尽管我的问题有点偏向于Linux。 关于Mac的相关问题,可以参考这里。 MacOSX的cp命令有一个-c选项可以克隆文件。
1个回答

2
在进一步搜索时,我找到了答案和相关的问题报告。 Issue 37157 (shutil: add reflink=False to file copy functions to control clone/CoW copies (use copy_file_range)) 正是关于这个问题的,它将在 Linux 上使用 FICLONE/FICLONERANGE
因此,我认为 shutil 将在即将推出的 Python 版本中支持这一功能(也许从 Python 3.9 开始)。
自 Python 3.8 起,有 os.copy_file_range,它包装了 copy_file_range(Linux)。
然而,根据问题37159(在shutil.copyfile()中使用copy_file_range()进行服务器端拷贝),Giampaolo Rodola说:

不行,[copy_file_range]不支持CoW(参见man页面)。我们可以简单地使用FICLONE(cp也是这样做的)。

然而,我不确定这是否正确,因为copy_file_range man页面上说:

copy_file_range()为文件系统提供了实现“复制加速”技术的机会,例如使用reflinks(即两个或多个inode共享指向相同写时复制磁盘块的指针)或服务器端复制(在NFS的情况下)。

问题26826(在os模块中公开新的copy_file_range()系统调用)有Giampaolo Rodola的评论:
我认为数据去重/CoW/reflink复制最好通过FICLONE实现。我猜想"cp --reflink"使用它,因为它比copy_file_range()更旧。正如问题中已经提到的那样,这在ZFS上还不起作用,请参见this issue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接