对于 Windows, tr_sys_path_rename
可以使用标志MOVEFILE_COPY_ALLOWED
而不是它自己的来自util.c:tr_moveFile
的内置“读取和复制”循环
然后 Linux 版本可以使用更现代的copy_file_range
而不是循环遍历每个。
也许是这样的:
size_t tr_sys_file_copy(tr_sys_file_t infile, tr_sys_file_t outfile, size_t len, tr_error** error )
{
TR_ASSERT(outfile != NULL);
TR_ASSERT(infile != NULL);
bool ret = false;
unsigned int flags = 0;
size_t res;
res = copy_file_range(infile, NULL, outfile, NULL, &len, flags);
if (res) {
return res;
}
else {
set_system_error(error, errno);
return res;
}
}
也许是:
tr_sys_file_copy_fallback(tr_sys_file_t infile, tr_sys_file_t outfile, size_t len, tr_error** error ) {
TR_ASSERT(outfile != NULL);
TR_ASSERT(infile != NULL);
uint64_t bytesLeft = len;
size_t const buflen = 1024 * 128; /* 128 KiB buffer */
tr_sys_path_info info;
while (bytesLeft > 0)
{
uint64_t const bytesThisPass = MIN(bytesLeft, buflen);
uint64_t numRead;
uint64_t bytesWritten;
if (!tr_sys_file_read(infile, buf, bytesThisPass, &numRead, error))
{
break;
}
if (!tr_sys_file_write(outfile, buf, numRead, &bytesWritten, error))
{
break;
}
TR_ASSERT(numRead == bytesWritten);
TR_ASSERT(bytesWritten <= bytesLeft);
bytesLeft -= bytesWritten;
}
return bytesLeft;
}
然后 Linux 版本可以使用更现代的 copy_file_range 而不是循环遍历每个。
这不能仅通过一次调用(或在简单循环中)来完成:
If file_in is a sparse file, then copy_file_range() may expand any
holes existing in the requested range. Users may benefit from calling
copy_file_range() in a loop, and using the lseek(2) SEEK_DATA and
SEEK_HOLE operations to find the locations of data segments.
(男人 copy_file_range)
理想情况下,我们应该确保正确锁定并在单独的线程中使用 sendfile()。
这与当前的“移动文件”代码几乎相同
rename
失败。 这也不会保留稀疏部分,所以我没有
更换时考虑这个问题。
在Sun,2019年7月14日在下午10时41 andreygursky [email protected]写道:
>
然后 Linux 版本可以使用更现代的 copy_file_range 而不是循环遍历每个。
这不能仅通过一次调用(或在简单循环中)来完成:
If file_in is a sparse file, then copy_file_range() may expand any holes existing in the requested range. Users may benefit from calling copy_file_range() in a loop, and using the lseek(2) SEEK_DATA and SEEK_HOLE operations to find the locations of data segments.
(男人 copy_file_range)
理想情况下,我们应该确保正确锁定并在单独的线程中使用 sendfile()。
—
您收到此消息是因为您创作了该线程。
直接回复此邮件,在 GitHub 上查看,或将线程静音。
这也不会保留稀疏部分,所以我没有
更换时考虑这个问题。
它缺少对普通文件的预分配。
是的。 那个也是。 “移动文件”的当前不良行为足以在某些设置中导致荒谬的负载。 如果可能的话,glibc copy_file_range 中的后备解决方案似乎也是一个更好的实现。
我玩过这个。 跨平台方式很难做到正确:似乎没有任何用于内核副本的 POSIX 接口。 但我认为每个操作系统都需要特殊的外壳,因为随着文件系统在副本上变得更有效率,我们希望自动访问这些功能。
我已经在 MacOSX 和 FreeBSD 上启动并运行了一个基本实现,但我需要设置更多系统来测试它。
我认为这项工作与使文件异步移动是正交的。 一方不应该妨碍另一方。 对于志愿者项目,范围蔓延是生产力的敌人。
更改在这里: https ://github.com/transmission/transmission/compare/master...RobCrowston :kernelcopy-wip
简而言之,我创建了一个名为 tr_sys_path_copy() 的新抽象。 (我使用副本而不是移动,因为当我们将其设为异步操作时,可能需要在复制完成后将原始文件保留一段不确定的时间以关闭其他线程中的文件句柄。)
到目前为止,我已经在 MacOS 10.15.1、Windows Server 2016、Linux 5.0 (Ubuntu 19.05)、Linux 5.3 (Arch 2019-12-03)、FreeBSD 12.1 上编译并运行了新的测试 (transmission-test-copy) (使用用户空间回退)和 FreeBSD 13。在每种情况下,我都使用调试器验证我们正在进行适当的系统调用。 不幸的是,由于一些不相关的 libevent 问题,我无法在 OpenBSD 6.5、NetBSD 8.1 或 Solaris 10 上构建代码,但我不确定这些是否是 libtransmission 支持的平台。 无论如何,此更改不应影响这些平台。
还是要做:
欢迎反馈。
+1 使数据移动异步。 在文件系统之间移动大种子会锁定整个应用程序。
最有用的评论
+1 使数据移动异步。 在文件系统之间移动大种子会锁定整个应用程序。