linux内核奇遇记之md源代码解读之九阵列raid5同步函数sync_request
linux内核奇遇记之md源代码解读之九阵列raid5同步函数sync_request转载请注明出处:http://blog.csdn.net/liumangxiong
我们再来回顾一下整个场景:1)在运行阵列的时候调用md_wakeup_thread唤醒主线程2)主线程调用md_check_recovery检查同步
3)md_check_recovery函数中检查需要同步调用md_register_thread创建同步线程4)同步线程调用md_do_sync函数处理同步过程5)md_do_sync做同步过程的管理,一步步推同步点,记录同步完成点,调用sync_request进行各种阵列级别的同步6)sync_request做同步数据流的派发工作对于raid5阵列来说,同步是按struct stripe_head为基本单位进行派发的。打个比方,我们现在要把一个土豆炸成薯片,这时首先要把土豆切成片,再把土豆片放到油锅里炸,炸开了再捞起来装盒。那么md_do_sync的作用就相当于把土豆切片,这个切片的大小也就是STRIPE_SECTORS大小了。sync_request接收到这个土豆片之后不能立即下锅,要用struct stripe_head把它包装一下,这就类似要在土豆片外面刷一层调料。然后再调用handle_stripe进行处理并最终下发到磁盘,这就类似于把土豆片放在锅里油炸加工的过程。最后调用bitmap_cond_end_sync保存同步完成记录,这就类似回收土豆片并盒装。这里还有一个细节,就是为了周期性保存同步结果,每隔几秒钟都会等待所有同步请求返回再记录下来。这就类似于这个炸土豆的锅很小,一次只能放20片土豆,一开始我们不停的放薯片,等放满20片,我们就停下来直接到所有土豆都熟了然后一次性打捞上来,然后再放20片,重复上面的过程。理解上以上的处理机制,再看代码就非常容易了。
4480 /* Allow raid5_quiesce to complete */4481 wait_event(conf->wait_for_overlap, conf->quiesce != 2);44824483 if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))4484 return reshape_request(mddev, sector_nr, skipped);44854486 /* No need to check resync_max as we never do more than one4487 * stripe, and as resync_max will always be on a chunk boundary,4488 * if the check in md_do_sync didn't fire, there is no chance4489 * of overstepping resync_max here4490 */44914492 /* if there is too many failed drives and we are trying4493 * to resync, then assert that we are finished, because there is4494 * nothing we can do.4495 */4496 if (mddev->degraded >= conf->max_degraded &&4497 test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {4498 sector_t rv = mddev->dev_sectors - sector_nr;4499 *skipped = 1;4500 return rv;4501 }4502 if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&4503 !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&4504 !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {4505 /* we can skip this block, and probably more */4506 sync_blocks /= STRIPE_SECTORS;4507 *skipped = 1;4508 return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */4509 }45104511 bitmap_cond_end_sync(mddev->bitmap, sector_nr);45124513 sh = get_active_stripe(conf, sector_nr, 0, 1, 0);4514 if (sh == NULL) {4515 sh = get_active_stripe(conf, sector_nr, 0, 0, 0);4516 /* make sure we don't swamp the stripe cache if someone else4517 * is trying to get access4518 */4519 schedule_timeout_uninterruptible(1);4520 }4521 /* Need to check if array will still be degraded after recovery/resync4522 * We don't need to check the 'failed' flag as when that gets set,4523 * recovery aborts.4524 */4525 for (i = 0; i < conf->raid_disks; i++)4526 if (conf->disks[i].rdev == NULL)4527 still_degraded = 1;45284529 bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded);45304531 set_bit(STRIPE_SYNC_REQUESTED, &sh->state);45324533 handle_stripe(sh);4534 release_stripe(sh);45354536 return STRIPE_SECTORS;4537 }