MD(三)resync和recovery的调度(下)

    技术2024-03-27  13

    这些文章已经写了好几年了,可能已经过时了。在MSN space和QQzone几经辗转之后,我想也许这些技术文章还是放在搞技术的博客中更能帮助人。于是做了一个艰难的决定,把这些文章一篇篇搬过来!绝对是原创的。

    说完启动再来看它的结束。同样是在md_check_recovery中,但我们会发现处理结束的代码处于处理启动的代码之前。其中的逻辑其实也很好理解,无非就是先处理已经启动的线程,但是由于我在阅读这部分代码时花了点时间,所以多罗嗦几句。实际上,光是md_check_recovery中的代码实际上并没有完全结束resync和recovery,只是结束了syncd,从这段代码注释中的“double check”就可以看出来。我们还是先看看syncd是如何结束的,再看resync和recovery如何停止。结束syncd很简单,既然启动它用的是md_register_thread,那结束它用md_unregister_thread就行。每次结束syncd都要做一次检查,就是检查是否需要将spare激活。这是针对recovery的动作,所谓激活spare,就是调用各RAID中的spare_active函数来将完成recovery的spare转换为正式与其他设备同步的设备,它内部是怎么工作可以参考RAID-5。当然,如何判断recovery正常结束呢?很简单,就看在recovery是否发生了error或者syncd是否收到打断的信号,也就是recovery一直从头到尾没有出现I/O错误,也没有外界干扰。在syncd结束时还有一个重要的事情就是更新md的super_block,此时更新应该说是比较好的时机,因为此时md很可能发生了某些状态变化并需要记录到super_block中。当然什么时候需要更新super_block,那是由super_block的作用及其内容来决定,这个应该放到以后讨论。代码再接下去就是将md的resync/recovery状态设为NEEDED,这就是要做“double check”。 

    就我目前的理解而言,“double check”在resync/recovery遇到error而停止时有用,它要做一件重要的事,那就是决定是要在剩下的设备中继续做resync/recovery还是结束resync/recovery。因为将resync结束时并不只是将syncd停止就行,还有好些状态还需要修改,而在md_check_recovery中并没有改动这些状态。我现在以RAID-5的resync中遇到error的过程为例来展示这些代码的功能,recovery也有类似的过程,区别就在于recovery只需是否有spare就可以判别是否该结束了。 

    一切都从md_error开始。在md_error中,结束后我们会发现mddev->recovery有三个位被设置:ERR,INTR和NEEDED。其中NEEDED不是重点,syncd会看到ERR和INTR位被设置,于是md_do_sync结束,mddev->recovery的DONE置位。请注意,此时recovery_cp值并没有改变,也就是说他并不是MaxSector。然后RAID的守护线程被唤醒,md_check_recovery被调用,syncd被注销以后该函数也就结束了,但resync还没有结束,因为NEEDED位置1了,也就是说下一步还得由“double check”决定。

    于是md_check_recovery会被再次执行,“double check”就此开始。这次md_check_recovery并不会去注销syncd了,因为它已经被注销了。那么,md_check_recovery首先从RAID-5中移除Faulty的设备。这里我们假设没有spare设备在MD中,这样也就没有spare被加入到RAID-5中去,因为如果有spare的话,recovery会被启动,这并不是我要讨论的。到这里,我们知道syncd会再次被注册起来工作,因为没有spare加入而且mddev->recovery_cp确实小于 MaxSector。即使我们知道RAID-5现在已经少了一个设备,根本没必要resync了,但syncd的确是要起来的。syncd最终会调用RAID-5的sync_request,这个函数一看到是要做resync,但是又已经degraded了,他就“谎报军情”对MD说:“后面的sync都做完了,不用做了。”于是syncd将mddev->recovery_cp设为MaxSector,syncd工作完成。接着故事又回到md_check_recovery:第一次md_check_recovery,syncd被注销;第二次md_check_recovery,没有spare,mddev->recovery_cp已经是MaxSector,这一次resync才算真正结束了。呜呼!似乎拐了好几个弯,但愿您没都绕进去。

    最新回复(0)