FICLONE 与 FICLONERANGE 与 copy_file_range 的差异(用于写入时复制支持)

Alb*_*ert 5 linux file-copying

我想知道复制文件的有效方法(在Linux上,在支持写时复制(COW)的FS上)。\n具体来说,我希望我的实现如果可能的话使用写时复制,但否则回退到其他有效的变体。具体来说,我还关心服务器端复制(由SMBNFS等支持),以及零复制(即如果可能的话绕过 CPU 或内存)。

\n

(这个问题并不是特定于任何编程语言。它可以是 C 或 C++,也可以是任何其他语言,如 Python、Go 或任何与操作系统系统调用绑定的语言,或者有任何方法进行系统调用。如果这让您感到困惑你只需回答C即可。)

\n

看起来ioctl_ficlonerangeioctl_ficlone(即ioctl使用FICLONEFICLONERANGE支持写时复制(COW)。具体FICLONE由 GNU 使用cp此处,via --reflink)。

\n

然后还有copy_file_range,它似乎也支持 COW 和服务器端复制。\n( LWN about copy_file_range。)

\n

听起来好像copy_file_range更通用(例如,它支持服务器端复制;不确定是否支持FICLONE)。

\n

但是,copy_file_range似乎存在一些问题。\n例如 保罗·艾格特在这里评论道:

\n
\n

[copy_file_range] 的手册页表示它使用 size_t (而不是 off_t)来计算要复制的字节数,这对于文件复制 API 来说是一个奇怪的选择。

\n
\n

是否存在FICLONE比 更好/不同的情况copy_file_range

\n

是否存在FICLONE比 更好/不同的情况FICLONERANGE

\n

具体来说,假设底层 FS 支持此功能,并假设您要复制文件。我询问这些函数对以下功能的支持:

\n\n

它们 ( FICLONE, FICLONERANGE, copy_file_range) 总是执行完全相同的操作吗?(假设底层 FS 支持写时复制和/或服务器端复制。)

\n

或者在某些情况下使用copy_file_range代替是有意义的FICLONE?(例如,COW 只能与 一起使用copy_file_range,但不能与 一起使用FICLONE。或者反过来。或者这永远不会发生?)

\n

或者以不同的方式表述同一问题:总是copy_file_range可以的,或者在某些情况下我想用它FICLONE来代替?

\n

为什么 GNUcp使用FICLONE而不使用copy_file_range?(有技术原因,还是这只是历史原因?)

\n

相关:GNUcp最初默认情况下不使用reflink(请参阅GNU coreutils 维护者 P\xc3\xa1draig Brady 的评论)。\n但是,最近更改了(此提交错误报告 24400),即 COW 行为现在是默认的(如果可能的) (--reflink=auto)。

\n

有关 Python for COW 支持的相关问题

\n

Python 开发人员关于 FICLONE 与 copy_file_range 的相关讨论。即,这似乎是一个有效的问题,并且尚不完全清楚是否使用FICLONEcopy_file_range

\n

有关在文件之间复制数据的方法选择的相关 Syncthing 文档,以及有关高效文件复制的 Syncthing 问题copy_file_range和其他问题,例如使用 COW 支持。\n它还表明,目前还不清楚是否FICLONE会执行与 相同的操作copy_file_range,因此他们的解决方案是尝试所有这些,然后按以下顺序回退到下一个:\nioctl(使用 FICLONE)、copy_file_range、sendfile、duplicate_extents、standard。

\n

Go 开发人员关于 .\n的使用的copy_file_range相关问题。\n听起来他们似乎同意 .copy_file_range总是比 . 更受青睐sendfile

\n

(问题从这里复制,但我不明白这怎么太不集中了。这个问题非常集中,询问一个非常具体的事情(FICLONE和copy_file_range是否表现相同),并且应该非常清楚。我提出了这个问题以多种不同的方式,使问题更加清晰。这个问题也经过了非常深入的研究,并且对于社区来说,所有参考文献都应该非常有价值。如果我能找到这样的问题,我会非常高兴当我开始研究 FICLONE 和 copy_file_range 之间的差异时,这本身就是一个问题,即使没有答案。)

\n

Alb*_*ert 6

请参阅有关、、和的Linux vfs 文档copy_file_rangeremap_file_rangeFICLONERANGEFICLONEFIDEDUPERANGE

然后看 vfs_copy_file_rangeremap_file_range如果可能的话,这首先尝试调用。

FICLONE调用ioctl_file_clone此处)和FICLONERANGE调用ioctl_file_clone_rangeioctl_file_clone_range调用更通用的ioctl_file_clone此处)。 ioctl_file_clone调用vfs_clone_file_range此处)。 vfs_clone_file_range调用do_clone_file_range和 that 调用remap_file_range此处)。

即回答了问题。copy_file_range更通用,并且无论如何都会首先在内部尝试调用(即与/remap_file_range相同)。FICLONEFICLONERANGE

我认为copy_file_range系统调用比不过稍微新一些FICLONE,即它可能copy_file_range在您的内核中不可用,但FICLONE确实可用。

无论如何,如果copy_file_range可以的话,应该是最好的解决方案。

Syncthing 完成的顺序(ioctl(使用 FICLONE)、copy_file_range、sendfile、duplicate_extents、standard)是有意义的。