reflink
我尝试递归地创建目录的快照副本,但如果文件系统(自定义 shfs)不支持副本,它会为每个文件返回错误:
# cp -a --reflink=always /mnt/user/libvirt /mnt/user/libvirt_copy
cp: failed to clone '/mnt/user/libvirt_copy/libvirt/libvirt.img' from '/mnt/user/libvirt/libvirt.img': Operation not supported
cp: failed to clone '/mnt/user/libvirt_copy/libvirt/test.txt' from '/mnt/user/libvirt/test.txt': Operation not supported
...
由于似乎不可能cp
在第一个错误(?)时停止,这意味着对可能数千个文件的无用循环,因此我喜欢预先检查文件系统是否支持引用链接。
一种想法是搜索单个文件并进行测试复制:
if ! find /mnt/user/libvirt -type f -print -quit | xargs -I {} sh -c 'dst_path=$(dirname $(echo {} | sed "s#^/mnt/user/libvirt#/mnt/user/libvirt_copy#")); mkdir -vp $dst_path && cp -a --reflink=always {} "$dst_path"'; then
echo "Error: Filesystem does not support reflink"
exit
fi
但这留下了目录和一个空文件,之后需要清理:
# find /mnt/user/libvirt_copy/
/mnt/user/libvirt_copy/
/mnt/user/libvirt_copy/libvirt.img
# ls -lah /mnt/user/libvirt_copy/libvirt.img
-rw------- 1 root root 0 Nov 1 08:58 /mnt/user/libvirt_copy/libvirt.img
难道就没有更好的办法吗?或者也许有一个解决方案可以cp
在第一个错误时停止?
答案1
我不确定您提到的正在使用的“自定义 shfs”文件系统,但对于磁盘上的普通文件系统,应该有一个可以运行的特定于文件系统的命令来获取有关它的信息。例如,对于 XFS 文件系统,sh 脚本可以测试它是否支持引用链接功能,如下所示:
if xfs_info /yourXfsMount | grep reflink=1; then
echo "Filesystem supports reflink"
else
echo>&2 "ERROR: Filesystem does not support reflink"
exit 1
fi
答案2
如果您需要一个不依赖于特定文件系统的通用答案,我认为简单地尝试进行测试副本可能是您最好的选择。您不需要使用现有数据进行此测试,您只需要知道您尝试在哪个文件系统上进行重新链接。我认为最简单的方法是创建一个具有唯一名称的空文件,尝试复制它,然后清理它,而不是在测试中涉及任何真实数据。也许是这样的:
filesystem=/yourFilesystem
filename=${filesystem}/reflinktest-$(uuid)
filename2=${filename}-copy
touch ${filename}
cp --reflink=always ${filename} ${filename2}
result=$?
rm -f ${filename} ${filename2}
if [ ${result} -ne 0 ]; then
echo "ERROR: Filesystem ${filesystem} does not support reflink."
exit 1
fi
echo "Reflink supported"
# Proceed with your reflink copying...