linux内核md源代码解读 十一 raid5d - Linux系统
正是有了上一篇的读写基础,我们才开始看raid5d的代码。raid5d不是读写的入口,也不是读写处理的地方,只是简简单单的中转站或者叫做交通枢纽。这个枢纽具有制高点的作用,就像美国在新加坡的基地,直接就控制了太平洋和印度洋的交通枢纽。
4626 /*
4627 * This is our raid5 kernel thread.
4628 *
4629 * We scan the hash table for stripes which can be handled now.
4630 * During the scan, completed stripes are saved for us by the interrupt
4631 * handler, so that they will not have to wait for our next wakeup.
4632 */
4633 static void raid5d(struct mddev *mddev)
4634 {
4635 struct r5conf *conf = mddev->private;
4636 int handled;
4637 struct blk_plug plug;
4638
4639 pr_debug("+++ raid5d activen");
4640
4641 md_check_recovery(mddev);
4642
4643 blk_start_plug(&plug);
4644 handled = 0;
4645 spin_lock_irq(&conf->device_lock);
4646 while (1) {
4647 struct bio *bio;
4648 int batch_size;
4649
4650 if (
4651 !list_empty(&conf->bitmap_list)) {
4652 /* Now is a good time to flush some bitmap updates */
4653 conf->seq_flush++;
4654 spin_unlock_irq(&conf->device_lock);
4655 bitmap_unplug(mddev->bitmap);
4656 spin_lock_irq(&conf->device_lock);
4657 conf->seq_write = conf->seq_flush;
4658 activate_bit_delay(conf);
4659 }
4641行,md_check_recovery这个函数前面看过了,用来检查触发同步 4643行,blk_start_plug和4688行blk_finish_plug是一对,用于合并请求。 4646行,这里为什么要来个大循环呢?刚开始看4629行注释可能有点迷糊,可是看到这个循环就知道原来讲的是这里,4629行注释说我们不必等到下次唤醒raid5线程,可以继续处理stripes,因为可能有stripes已经在中断处理函数里处理完成返回了。 4651行,判断阵列对应的bitmap_list是否为空,如果这个链表不为空则进入分支。bitmap跟条带处理有什么关系呢?这个问题就比较有历史性了。对于raid5阵列来说,最可怕的事情莫过于在写的过程中异常掉电,这就意味阵列不知道哪些数据是一致的,哪些是不一致的?这就是safemode干的事情,用来记录阵列数据是否一致。然而数据不一致导致的代码是全盘同步,这个是raid5最头疼的问题。好了,现在有bitmap了可以解决这个问题啦,太happy啦。那bitmap是如何解决这个问题的呢?bitmap说你写每个条带的时候我都记录一下,写完成就清除一下。如果异常掉电就只要同步掉电时未写完成的条带就可以啦。娃哈哈太happy了!!!但是请别高兴的太早,bitmap也不是一个好侍候的爷,bitmap必须要在写条带之前写完成,这里的写完成就是要Write Through即同步写。这下悲催了,bitmap的写过程太慢了,完全拖垮了raid5的性能。于是有了这个的bitmap_list,raid5说,bitmap老弟你批量写吧,有点类似bio的合并请求。但是这也只能部分弥补bitmap带来的负面性能作用。 4655行,下发bitmap批量写请求。 4658行,将等待bitmap写的条带下发。 4660 raid5_activate_delayed(conf); 4660行,看函数名就是激活延迟条带的意思。那么为什么要延迟条带的处理呢?按照块设备常用的手段,延迟处理是为了合并请求,这里也是同样的道理。那么条带什么时候做延迟处理呢?我们跟进raid5_activate_delayed函数:
3691static void raid5_activate_delayed(struct r5conf *conf)
3692{
3693 if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
3694 while (!list_empty(&conf->delayed_list)) {
3695 struct list_head *l = conf->delayed_list.next;
3696 struct stripe_head *sh;
3697 sh = list_entry(l, struct stripe_head, lru);
3698 list_del_init(l);
3699 clear_bit(STRIPE_DELAYED, &sh->state);
3700 if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
3701 atomic_inc(&conf->preread_active_stripes);
3702 list_add_tail(&sh->lru, &conf->hold_list);
3703 }
3704 }
3705}
3693行,这里控制预读数量。 3694行,遍历阵列延迟处理链表 3695行,获取阵列延迟处理链表表头 3697行,获取阵列延迟处理链表第一个条带 3698行,从阵列延迟处理链表取出一个条带 3700行,设置预读标志 3702行,添加到预读链表中
(编辑:佛山站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

