【ceph】CephFS 内部实现(三):快照
CephFS快照几个特点:
- 写时复制
- client端操作时只能针对目录,不能针对单独文件
- 从任意文件夹下开始打快照
快照实现
快照通过SnapRealm
组织成树形结构,每个有快照信息的inode节点都会有对应的SnapRealm
,没有快照信息的inode使用父节点路径上最近的SnapRealm
,根节点默认有SnapRealm
。在client端创建快照时mds会在对应的inode节点新建SnapRealm
(仅首次创建时),普通文件inode中也会出现SnapRealm
,但都是mds的cow机制创建的,client端无法直接操作。
要解决的问题
-
快照究竟是在备份什么?
快照是对当前目录及以下的子树状态进行保存,创建快照相当于对目录树中(节点以下的子目录树)每个inode进行备份,因为inode承载了文件系统的全部信息。根据MDS的元数据组织关系,对于普通文件,实际上是将dentry在dir的items
中新增一份副本,由first
,last
两个值指明对应的snap范围,并且还会对inode进行备份,备份的inode最终以omap val形式存在。对于目录,并不会在其父目录items
中新增dentry,而只是在自己的inode中新增一份inode备份,最终以meta pool中的RADOS对象形式存在(不是新增对象,每个目录只有一个对象)。 -
快照的元数据如何存在?
每个快照都有全局唯一的整数id标识,通过向MDSTableServer
申请来保证id唯一性。每个元数据都有first
,last
标识,用于标识元数据对应的snap,last
为CEPH_NOSNAP
时标识元数据为head数据。 -
在目录树中的某个节点打快照后,快照信息如何向上传递?
快照节点以上的部分和本次快照无关,因此元数据不受影响。但如果本节点是第一次打快照,则snaprealm的组织关系会发生变化。 -
在目录树中的某个节点打快照后,快照信息如何向下传递?
当父节点创建快照后,子节点是需要知道的,这样子节点才会知道去备份dentry和inode。这个通知机制是通过SnapRealm
关系树来完成的。父节点遍历自己的child snaprealms,逐个清空child snaprealm cached_seq,并向client端发送信息。
清空cached_seq可以保证在下次需要读取snap信息时snaprealm重新进行build_snap_set()
操作,进而读取到父节点的最新snap信息。
向client端发的信息主要包括三方面:- snaprealm组织关系的变化。如果是新创建的snaprealm,则涉及继承关系调整。
- 面向client的inode cap组织关系变化。每个inode cap都属于一个snaprealm管理(通过xlist结构),如果是新建的snaprealm,则涉及管理关系的移动。比如初始状态下所有cap都在根节点snaprealm中,新建snaprealm后,快照节点以下的inode cap将被移动到新snaprealm中。
- split信息。如果不是新建snaprealm,即在已有快照的节点上继续创建快照。这种情况下快照节点的子节点sanprealm需要知道父节点快照更新的消息,在mds端是通过写时复制(Copy On Write)的方式先invalidate cache seq,再在需要时build seq实现,但是对于client端无法这样做,client端维护的snap信息需要及时更新,没有cow,因此这些信息作为split信息传递给client。
写时复制
创建快照时只更新节点的snaprealm,并invalidate子节点的snaprealm cache,同时通知client最新的snap信息。整个过程并没有涉及元数据的备份,first
,last
的修改以及对于普通文件的数据进行的备份,因为这些修改是在下次对节点进行修改时才会发生的事件,因此叫做写时复制。
举两个🌰:
- 创建快照后,在目录下新建文件,这时目录发生cow:通过
journal_dirty_inode()
将目录inode进行复制(CInode::cow_old_inode()
),但并不会将目录的dentry在父目录中进行备份。 - 创建快照后,在目录下truncate一个已有的文件,这时文件发生cow:通过
journal_dirty_inode()
对文件目录进行复制(MDCache::cow_inode()
),且会在目录的items
中新增一个snaped的dentry,和cow_inode()
new出来的inode关联。对于文件数据部分的备份则是通过RADOS层的快照机制完成(mds会将文件之前的快照号传给Filer
,最终传到pg层的OSDOp中,这些快照号对应的数据将被保留)。
快照对stats的影响
由于stats信息都是根据inode统计得出的,而从client发起的请求,要么是在非快照目录下,要么是快照目录下,在非快照目录下,对于mds就是一次snapid为CEPH_NOSNAP
的请求,在快照目录下发起的请求对于mds就是一个有具体snapid的请求。因此只能分开统计快照和非快照空间使用量。如果计费的话这里会有个问题,就是快照的实际使用空间是无法从client端得到的,除非根据inode去datapool中遍历对象计算出快照的实际使用空间。
作者:宋新颖
链接:https://www.jianshu.com/p/4485601f3d4f
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。