复制时Linux的按写复制有什么问题



警告:本文适用于Linux上在复制时支持reflink的所有CoW文件系统。 目前,这些是:BTRFS,XFS和OCFS2。

请不要选择哪种FS更好:Btrfs,XFS,Reiser4,NILFS2,ZFS或一些未提及的FS。

背景知识


  • 2001年7月21日-Namesys发布了Reiser4公告 。 DARPA赞助了这项开发。
  • 2003年11月20日-Namesys发布了一些Reiser4基准测试
  • 2004年8月24日-Namesys公开发布Reiser4
  • 2004年9月14日-ZFS公告。
  • 2005年11月16日-ZFS包含在OpenSolaris build 27中。
  • 2006年9月-Hans Reiser因杀害妻子Nina Reiser而被捕。 Namesys结束的开始
  • 2007年6月12日-Chris Mason(前Namesys员工) 宣布了Btrfs
  • 2011年9月22日-ZFSonLinux中出现了要求实现reflink的票证。
  • 2012年-Btrfs被公认为稳定的Oracle Linux和SUSE Linux Enterprise
  • 2013年1月21日-在Linux内核的源代码中使用Btrfs删除了实验标签
  • 2019年5月-Btrfs从RHEL 8中删除(隐藏的政治原因怀疑是Oracle提倡的Btrfs)

CoW文件系统中的复制期望


当Reiser4在2001年发布时,我对写时复制感到鼓舞和热情。 试想一下,我们可以轻松轻松地拥有任意数量的不同项目的副本,并且实际上磁盘只会存储它们之间的差异!

此外,复制速度会不适当地提高。 由于在复制时只会创建到旧文件的reflink链接。 当写入这样的新文件时,将自动分配更改数据的扇区。 结果,对于文件的公共部分,我们将具有相同的扇区,而在不同的扇区中将记录不同的部分。

然后,它似乎是创建共享主机帐户的灵丹妙药,现在它是轻型虚拟机和容器的最佳解决方案。 毕竟,我们不能浪费相同文件的空间,同时允许用户轻松地更改它们。

但是,汉斯·立瑟(Hans Riser)自杀并杀死了他的妻子,其核心思想(很可能是出于政治原因)没有包括在内。 毕竟,故事取决于特定的人吗?

ZFS是根据与Linux不兼容的许可证发布的,因此未包含在内核中。 因此,很长时间以来,Linux中对ZFS的引入速度一直减慢。

之后,我开始等待Btrfs。 宣布发布仅6年后,Linux内核开发人员就认为它是稳定的。

在那之后,我不着急使用Cow系统,因为写时复制范例本身意味着增加了碎片,因为每次数据更改都会写入新位置。

对于HDD,碎片会降低性能,因为重新放置读头块的过程非常漫长。

因此,我个人将btrfs的执行推迟到我的计算机上,直到它们切换到SSD。

我注意到SSD也不喜欢碎片化,众所周知,对于SSD来说,线性写入/读取的速度可能比随机存取快数十倍。

但是,碎片化SSD的性能不如HDD出色。

那么,使用CoW的复制速度如何?


最后,时间到了。 当SSD变得足够可靠时,我开始使用may和main的CoW文件系统。 更具体地说,是Btrfs和Nilfs2。

掌握了快照的令人兴奋的可能性,有一段时间,我忘记了2000年代对超快速文件复制的期望。

一段时间后,我决定进行测试。 令我非常失望的是,复制时我发现CoW的速度没有任何提高。 这是SATA SSD上的结果:

time cp -a /usr /usr1 real 0m15,572s user 0m0,240s sys 0m4,739s 

原来,要使用CoW,您需要指定一个特殊的密钥。

 time cp -a --reflink=auto /usr /usr2 real 0m3,166s user 0m0,178s sys 0m2,891s 

只有在这种情况下,我们才能看到5倍的优势。 顺便说一句,优势的大小会随着文件长度的增加而无限增长。 我复制的/usr文件夹主要是小文件。

令我惊讶的是,为什么默认情况下未使用CoW文件系统的关键优势。 的确,为此她被创造了!

在这种情况下,我在Btrfs部分测试了复制。 但是,使用支持reflink的任何其他CoW文件系统,您都会得到类似的结果。

有什么问题,比利?


问题出在cp中。 默认情况下,复制时不使用CoW。 虽然可以。

您可以说-我不使用cp。 但是,在Linux的幕后,几乎所有地方都在使用它。 许多程序在需要复制某些内容时使用cp而不是“ bikes”。

为什么coreutils开发人员做出这样一个模棱两可的决定,而该决定却超出了CoW文件系统优势的一半?

事实证明,负责GNU coreutils开发的PádraigBrady决定了。

这是他的逻辑

  1. 缺省情况下,cp不使用CoW,因为有人会使用复制来增加在破坏文件系统后将文件保存到磁盘的可能性。
  2. 在性能方面,如果存在某种对延迟敏感的过程,则可能希望在复制过程中创建主记录,因此,如果以后发生这种情况,则在重新放置硬盘驱动器的磁头时可能会出现延迟。 请注意,从版本8.24 coreutils开始,mv默认使用reflink选项。

PádraigBrady用英语回答文字
它不是默认值,因为出于健壮性的原因,可能希望进行复制以防止数据损坏。 同样出于性能原因,您可能希望写入在复制时进行,而不是在CoW文件上进行一些对延迟敏感的过程,并且由于写入而延迟到机械磁盘的不同部分,因此可能会延迟写入。 请注意,默认情况下,从coreutils v8.24起,mv将进行重新链接,因为它没有上述约束。

就mv的速度而言,移动文件时CoW实际上没有任何好处。 在单个文件系统中,mv几乎总是非常快地工作。

再次,问题出现了人格对历史的影响。 通过以不同的方式在程序源代码中添加几个字母,您可以减慢向数以千万计的用户复制的速度(此处您需要考虑的是,现在大多数人以一种或另一种形式使用云服务,即使他们没有计算机也是如此),降低了使用驱动器的效率并增加其在全球的销售。

Pádraig参数解析


第一个论点是有道理的。 经验不足的用户实际上可以在同一文件系统上备份有价值的文件。

第二个论点。 如果您阅读有关Pádraig的滞后的更多评论,您会发现他已经想到了数据库情况,即在写入现有文件时,由于文件系统寻找可用空间可能会有所延迟。 但是对于CoW文件系统,由于CoW的性质,总是会搜索新的扇区进行记录,如Jan Kanis所指出的。 因此,我认为第二个论点是站不住脚的。

但是,在CoW系统上,写入数据库文件时确实有可能出现延迟甚至“空间不足”错误。 为避免这种情况,您需要首先创建一个空目录,并为数据库禁用CoW。

在目录/文件上禁用CoW,如下所示:

 chattr +C /dir/file chattr +C /dir/dir 

还可以选择挂载nodatacow。 它将应用于所有新创建的文件。

但是,如果我们要在默认情况下进行复制时使用CoW,该怎么办?


  1. 根本的方法是修补coreutils。 也许在您的私有存储库中创建您的包。

    修补cp.c文件:

     -x->reflink_mode = REFLINK_NEVER; +x->reflink_mode = REFLINK_AUTO; 
  2. 较不极端的解决方案是为您的外壳编写cp别名。 对于bash,例如:

    /etc/profile.d文件夹中,创建包含以下内容的cp_reflink.sh cp_reflink.sh

     #!/bin/bash alias cp='cp --reflink=auto' 

    当从外壳程序通过名称访问cp时,该解决方案几乎可以在所有情况下使用。 但是,如果在脚本中使用/ bin / cp,则别名将不起作用,并且复制将照常进行。

文件管理器和reflink


截至2019年10月31日的状态:

  • 午夜指挥官 -支持。
  • Krusader-不支持。
  • 海豚-不支持。
  • 鹦鹉螺-不支持。
  • Nemo-支持。

编程语言,系统调用和reflink


大多数编程语言不具有reflink支持。
在C语言中,许多程序员仍然使用循环和缓冲区进行复制。

sendfile系统调用不使用reflink。
cp使用带有FICLONE标志的ioctl系统调用。

我认为,如果您需要在代码中复制某些内容,建议像cp一样执行此操作,或者只调用cp --reflink=auto

结论


随着无处不在的虚拟化和SSD时代的到来,使用CoW文件系统变得非常重要。 它们对于创建快照,快速复制非常方便。 实际上,在复制时使用CoW时,我们会自动进行重复数据删除

当前,只有3种文件系统支持这种类型的副本:BTRFS,XFS和OCFS2。

我衷心希望将在ZFS和NILFS2中完成reflink支持,因为它们已经通过内部机制支持CoW。

但是,在所有Linux发行版中,复制文件时均禁用CoW,我们需要显式指定相应的密钥,或使用各种技巧,例如别名或补丁。

自Reiser4发布以来已经过去了18年,但是,到目前为止,轻量级的CoW复制还没有遍及我们的生活。

PS Docker和CoW


您知道Docker支持btrfs进行存储吗? 必须启用此选项。 默认情况下未选中它。

理论上,当不同的虚拟机使用相同的内核时,CoW文件系统是轻松虚拟化的完美补充。

在我看来,它比OverlayFS和Aufs有机得多,后者是用于模拟CoW的技术支柱。

要在Docker中使用Btrfs,您需要:

  1. 在全新安装(没有映像和虚拟机)的Docker中,将单独的Btrfs卷挂载到/var/lib/docker
  2. 向Docker启动配置文件添加选项

对于Gentoo和Calculate Linux,这是/etc/conf.d/docker

 DOCKER_OPTS="--storage-driver btrfs --data-root /var/lib/docker" 

这是所有发行版的完整说明

评论中的补充


XFS和CoW


constbsource ):在XFS上,也不总是支持CoW。 您需要使用mkfs.xfs -m reflink=1创建一个文件系统。
在创建的FS上,您无法“启用” CoW支持。 另外,在4.11以下的内核中,包含此选项会导致dmesg中出现红色警告,说明该功能是实验性的。

MacOS和CoW


MMik ):在OS X中,与cp命令类似的选项是-c

它涉及原子系统调用clonefile()的使用,该调用在文件系统中创建一个有关新文件的条目,该文件中对数据块的引用与原始文件相同。 复制文件的属性和扩展属性,访问控制列表(ACL)条目,文件所有者信息和setuid / setgid位的重置除外。 它在同一文件系统内工作,需要文件系统的支持(属性ATTR_VOL_CAPABILITIES,标志VOL_CAP_INT_CLONE)。

自OS X 10.12(Sierra)起受支持,并且仅在APFS文件系统上受支持。


致谢:


PPS将发现的错误直接发送给个人。 我为此增加业力。



您可以通过使用下面的优惠券从RUVDS订购虚拟机来试用 CoW文件系统。

Source: https://habr.com/ru/post/zh-CN473752/


All Articles