ceph scrub流程分析




继续基于H版本代码分析。

主动触发

$ ceph osd deep-scrub 1

或者ceph pg scrub 0.1

pg是发给主osd。

定时触发

主osd

scrub_wq是关联到disk_tp这个线程池的一个ThreadPool::WorkQueue,最终线程处理队列调用的是ThreadPool::worker这个函数。

scrub_wq具体初始化流程是OSD::OSD构造函数,之后传给OSDService的构造函数,

接下来是disk_tp的初始化过程,在OSD::init()里调用了disk_tp.start();,之后的流程都是线程池初始化通用流程了。
ThreadPool::start() -> ThreadPool::start_threads() -> new WorkThread -> wt->create() -> Thread::create(0) -> Thread::try_create(0) -> pthread_create(&thread_id, thread_attr, _entry_func, (void*)this);。

其中线程的处理函数_entry_func是Thread::entry_wrapper()返回的entry()函数,这个在WorkThread里定义了:

整个scrub流程,主要包括确定时间,确定scrub对象(pg、object),获取从osd的对应信息进行比较,这些信息都是保存在scrub map里的。

副本osd

主要就是生成scrub map(OSD::handle_rep_scrub->rep_scrub_wq.queue(m)->PG::replica_scrub)和预留scrub资源(PG::sub_op_scrub_reserve),比较都是在主osd进行的(PG::scrub_compare_maps())。

replica_scrub也是调用build_scrub_map_chunk生成的map(跟主osd一样)。

scrub map比较

PGBackend::be_compare_scrubmaps会调用PGBackend::be_compare_scrub_objects进行objects级别的比较,如果有不一致则打印日志并修改pg状态为inconsistent。

scrub之后如果不一致,则要进行repair,ceph pg repair xxx.yyy,repair可能要等很久,因为scrub在执行中,要排队,可以先把scrub关掉(ceph osd noscrub、ceph osd nodeep-scrub),过段时间就会开始repair,开始repair之后就可以再次开启scrub了。