天天看点

有云存储团队公布 Ceph 中最严重数据不一致 BUG!

目前,块存储服务是ceph存储中被使用的最普遍的服务之一,通过块存储服务,可以向客户端以使用块设备一样访问ceph集群。然而,目前在使用块存储服务时,尤其是openstack与ceph对接时,如果没有严格的控制ceph端的对象大小(使用 >= 8mb对象时),将有可能导致严重的数据不一致情况,该异常由于xfs文件系统本身对fiemap的支持特性导致的。

xfs使用fiemap时,当extents数量大于1364时,通过ioctl的fs_ioc_fiemap接口,获取的extents数量上限为1364,导致超出部分extents数据获取不到。这将导致,在开启fiemap时,ceph集群进行recovery与backfill之后,产生大量数据不一致的情况,也是迄今为止ceph中影响最大的,最严重的数据不一致bug。

由于fiemap bug,碎片化对象在recovery与backfill之后(fiemap 获取不正确的数据),从而使的恢复的对象数据与原对象数据不一致。而恢复后的副本若成为主副本,则可能发生静默读错误,并且如果使用ceph策略自动修复对象(repair object之后),可能将错误数据覆盖至正确数据,数据将永远损毁。在某些情况下,还会触发对象永远处于inconsistent状态。

初始化大量extents碎片文件test,使其成为一个拥有3999个extents的碎片文件。

通过fiemap系统调用,获取这些extents

有云存储团队公布 Ceph 中最严重数据不一致 BUG!

编译g++ do_fiemap.cc -o do_fiemap

通过该程序可以打印出可以获取的到fiemap extents, do_fiemap test,通过xfs_bmap test 打印出真正的extents数量后,进行比较。

有云存储团队公布 Ceph 中最严重数据不一致 BUG!

可以看到,我们最先写了2000个extents,并通过xfs_bmap获取到了 2000个有内容的extents,但是通过fiemap系统调用,只获取到了1364个有数据的extents,所以在ceph中使用fiemap系统调用在某些情况下导致数据一致性bug。

修复方案

1)目前,在使用块存储使用场景时,通常情况下,默认使用4mb对象。在无特殊情况下,不用使用大于4mb 对象的rbd 镜像。

2)在i版以后,通过新的系统调用,seek_data, seek_hole,可以避免触发该bug,防止extents过多时使用fiemap调用产生的问题

有云存储团队公布 Ceph 中最严重数据不一致 BUG!

这组系统调用,可以让使用者通过while循环,反复的发现文件中的data 与 hole,从而组织出一个文件中真正存在的数据,能够避免产生与fiemap系统调用类似的bug,又保证了recovery或者clone时候只复制有用数据,而反复的系统调,应该会带来一定性能上的影响,请读者们自行测试。

目前,在i版本以后的ceph中,提供参数filestore_seek_data_hole,来启用该功能。当filestore_seek_data_hole 与 filestore_fiemap同时设置时,只用文件系统支持seek_data_hole,那么就会先通过seek_data_hole方式来获取文件的extents,所以在i版本以后的ceph中,应启用filestore_seek_data_hole功能来替代filestore_fiemap 功能。

3)对于已经使用8mb,16mb 甚至更大对象大小的rbd镜像,请暂时设置禁用fiemap功能,并等待后续版本修复。