ceph的BlueStore中_open_db的分析

代码中经常看到的read_meta和write_meta,实际读取和写入的地址是/var/lib/ceph/osd/ceph-x/里面的block文件。

/var/lib/ceph/osd/ceph-0/里面包含的文件有block, block.db, block.wal, ceph_fsid, fsid, keyring, ready, type, whoami,其中block,block.db,block.wal是软链接,block指向数据空间,block.db指向rocksdb存放数据库的空间,block.wal指向log存放的空间。所以关于block,block.db,block.wal的打开、读写、关闭操作实际上是对应于底层的xfs来实现的。

osd进程启动后,在BlueStore模块中,如果磁盘或分区没有元数据或为空,则会执行BlueStore::mkfs,BlueStore::mkfs中会执行到_open_db,这里的db是储存BlueStore元数据的空间。通过键值对数据库的形式存储在db里。

_open_db的处理过程:

  1. 为BlueFS结构分配内存空间
  2. 分别针对BDEV_DB, BDEV_SLOW, BDEV_WAL 3个盘创建3个BlockDevice结构,在目前配置下即KernelDevice。随后对这三个BlockDevice做open操作,这里所做的主要工作是打开block,block.db,block.wal这几个文件获取句柄。开启aio线程,因为三个BlockDevice,所以开启了3个aio线程。然后把这三个BlockDevice的指针送给bluefs结构下的bdev[id],id即为BDEV_DB,BDEV_SLOW,BDEV_WAL。并创建三个IOContext,分别送给bluefs下的ioc[id]。假如没有配置block.db和block.wal,那么便只打开block这个文件作为BDEV_DB。open BlockDevice的处理流程里,代码会从read_meta(“path_block.db”,&bfn)里读取出db的路径,如果没有读出来则设置一个默认的路径,默认的路径一般是/var/lib/ceph/osd/ceph-x/block.db,找到路径后会通过stat来判断文件属性,假如没有配置block.db和block.wal,则stat返回-1,这样bluefs_shared_bdev赋值BlueFS::BDEV_DB。后面流程中会以block文件作为BDEV_DB。
  3. 分配磁盘空间,先统计盘的大小,即block,block.db,block.wal。把盘或分区空闲空间以map的形式给到bluefs下的block_all[id],并把这些分区的空闲空间交给Allocator来管理。Allocator有两种模式,BitMapAllocator和StupidAllocator,目前应用的是StupidAllocator。StupidAllocator是通过interval_set>的形式来组织的,本质上是通过b-tree的方式来管理硬盘空闲空间。在这里,还会分配一定的block中的空间给db做预留空间,倘若db空间不足,则会向block这个慢速设备中给db留的预留中分配空间。在后续程序运行过程中,这些空间还会动态的allocate和release。
  4. 三个数据空间管理结构分配完成后,便执行BlueFS::mkfs。
    1. 首先做的工作一样是分配BlueFS下所管理的硬盘空间管理结构alloc[id],alloc[id]即针对该设备创建空间管理模块Allocate::create,将block_all里的空闲数据段交给alloc[id]。之后便是结构的创建和指向工作,创建File作为log_file,log_file中的节点名为1,优先写入设备是WAL。并为这个文件分配一定的空间。这里的空间大小是4M,分配的空间存放于log_file->fnode.extents。接着创建一个FileWriter,把log_file指向FileWriter,即log_writer。最终的数据结构分布,log_writer->log_file->fnode,fnode里面包含ino=1,prefer_bdev=BDEV_WAL,extents。
    2. 从block_all里面提取出空闲空间,对log_t做op_alloc_add写入操作,把这些空闲空间以日志的形式存储起来。
    3. 刷日志
    4. 将super block写入磁盘,flush一遍磁盘,super block的内容为uuid, osd_uuid, version, block_size, log_fnode。log_fnode是一个重要的内容,在mount的时候全靠它来对数据结构做恢复。
    5. 释放所有分配的内存结构,退出。这里释放所有已分配的内存结构包括block_tall,是因为这些元数据已经刷入磁盘了,之后做mount操作的话会把这些数据重新恢复。
  5. BlueFS::mount,bluefs的mount是从磁盘中读出元数据,对元数据做恢复的过程。具体过程为
    1. 从磁盘读出super block,这个super block在BDEV_DB分区,系统已经固定了super block的offset和length,所以在之前写入的位置和长度与现在读的位置和长度是相同的。
    2. 日志的回放,创建File的类log_file,把super.log_fnode赋值给log_file->fnode。应为fnode中存在来extents,也就是fnode中记录了文件数据的位置,所以根据log_file里的extents读出存在磁盘上的元数据。随后对读出来的数据解析,恢复出数据结构。
  6. 创建一个BlueRocksEnv结构,这个结构是rocksdb对接BlueFS的中间接口的方法实现。基于BlueRocksEnv创建一个目录。目录名为db,这里是基于BlueFS文件系统创建的目录。
  7. 以db这个目录为根目录,创建rocksdb,并把上一步创建的BlueRocksEnv结构的env传送给rocksdb。
  8. 后续的操作是rocksdb的操作了,包括db->set_merge_operators,db->set_cache_size,db->init,db->create_and_open。

至此,BlueStore::mkfs下的关于_open_db这一块的处理操作便完成了。

你可能感兴趣的:(ceph的BlueStore中_open_db的分析)