我的应用程序架构要求我在同一分区挂载 2 个文件夹并在它们之间移动 2 个文件。我有以下挂载:
/drive2/folder1 on /var/www/myapp/folder1 type none (rw,bind)
/drive2/folder2 on /var/www/myapp/folder2 type none (rw,bind)
问题在于在 2 个文件夹之间移动文件/var/www/myapp/folder1
。/var/www/myapp/folder2
1Gb 文件大约需要 10 秒:
mv /var/www/myapp/folder1/test /var/www/myapp/folder2/
而且它会产生大量磁盘活动。但是,当我在/drive2/folder1
和之间移动同一个文件时/drive2/folder2
,移动它只需不到一秒钟的时间。
有人能帮我解决这个问题吗?
答案1
在文件系统之间移动时,文件会被复制到目标,然后在源上删除。在本地文件系统上移动时,只会更新文件系统表,这需要的时间要少得多。显然,使用绑定挂载,mv 会将这两个点视为单独的文件系统。
我在本地系统上设置了类似的挂载并运行strace mv folder1/1gb folder2/
。
lstat("folder1/1gb", {st_mode=S_IFREG|0644, st_size=1000000000, ...}) = 0
lstat("folder2/1gb", 0x7fff30fd1e20) = -1 ENOENT (No such file or directory)
rename("folder1/1gb", "folder2/1gb") = -1 EXDEV (Invalid cross-device link)
unlink("folder2/1gb") = -1 ENOENT (No such file or directory)
open("folder1/1gb", O_RDONLY|O_NOFOLLOW) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1000000000, ...}) = 0
open("folder2/1gb", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 32768) = 32768
write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 32768) = 32768
......
由于文件夹 1 和文件夹 2 实际上位于同一文件系统上,因此重命名系统调用失败,并报告错误,指出目标位于单独的设备上。除了修改内核和/或核心库之外,我怀疑您无法做太多事情来改变这种情况。
答案2
我假设您需要单独绑定安装这些文件夹,因为 /drive2 上还有其他文件夹,并且您的应用程序由于使用了类似 chroot 的东西而无法使用符号链接。
如果您可以在 /drive2 和 folder1 及 folder2 之间添加另一个目录,则可以实现相同的目的,而不会影响性能。然后,您只需要绑定挂载该文件夹。
$ ls /drive2/myapp
folder1 folder2
然后你的绑定挂载将是
/drive2/myapp on /var/www/myapp/myapp type none (rw,bind)
现在你的动作将再次即时
mv /var/www/myapp/myapp/folder1/test /var/www/myapp/myapp/folder2/