linux内核md源代码解读 十三 raid5重试读 - Linux系统
上节我们讲到条块内读失败,在回调函数raid5_align_endio中将请求加入阵列重试链表,在唤醒raid5d线程之后,raid5d线程将该请求调用retry_aligned_read函数进行重试读:
4539static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
4540{
4541 /* We may not be able to submit a whole bio at once as there
4542 * may not be enough stripe_heads available.
4543 * We cannot pre-allocate enough stripe_heads as we may need
4544 * more than exist in the cache (if we allow ever large chunks).
4545 * So we do one stripe head at a time and record in
4546 * ->bi_hw_segments how many have been done.
4547 *
4548 * We *know* that this entire raid_bio is in one chunk, so
4549 * it will be only one 'dd_idx' and only need one call to raid5_compute_sector.
4550 */
如果没有足够的struct stripe_head结构,我们没能把请求一次性提交。我们也不能提前预留足够的struct stripe_head结构,所以我们一次提交一个struct stripe_head,并将已提交记录在bio->bi_hw_segments字段里。 由于是条块内读,所以raid_bio请求区间都在一个条块内的,所以我们只需要调用一次raid5_compute_sector来计算对应磁盘下标dd_idx。 看完了以上的注释部分,我们就知道这里复用了bio->bi_hw_segment字段,用于记录已经下发的struct stripe_head数,那具体是怎么用的呢?我们来继续看代码: 4558 logical_sector = raid_bio->bi_sector & ~((sector_t)STRIPE_SECTORS-1); 4559 sector = raid5_compute_sector(conf, logical_sector, 4560 0, &dd_idx, NULL); 4561 last_sector = raid_bio->bi_sector + (raid_bio->bi_size>>9); 4558行,计算请求开始扇区对应的stripe扇区,因为读操作的基本单位是stripe大小,即一页大小 4559行,计算对应磁盘下标dd_idx,磁盘中偏移sector 4561行,请求结束扇区
4563 for (; logical_sector < last_sector;
4564 logical_sector += STRIPE_SECTORS,
4565 sector += STRIPE_SECTORS,
4566 scnt++) {
4567
4568 if (scnt < raid5_bi_processed_stripes(raid_bio))
4569 /* already done this stripe */
4570 continue;
4571
4572 sh = get_active_stripe(conf, sector, 0, 1, 0);
4573
4574 if (!sh) {
4575 /* failed to get a stripe - must wait */
4576 raid5_set_bi_processed_stripes(raid_bio, scnt);
4577 conf->retry_read_aligned = raid_bio;
4578 return handled;
4579 }
4580
4581 if (!add_stripe_bio(sh, raid_bio, dd_idx, 0)) {
4582 release_stripe(sh);
4583 raid5_set_bi_processed_stripes(raid_bio, scnt);
4584 conf->retry_read_aligned = raid_bio;
4585 return handled;
4586 }
4587
4588 set_bit(R5_ReadNoMerge, &sh->dev[dd_idx].flags);
4589 handle_stripe(sh);
4590 release_stripe(sh);
4591 handled++;
4592 }
4563行,对于条块内的每一个stripe进行操作,比如说条块为64KB,stripe为4KB,请求为整个条块,那么这里就需要循环16次。4568行,如果是已经下发请求的stripe,那么就跳过去。在上面注释里我们已经讲过,利用了bio->bi_hw_segments来表示一个请求中已经下发的stripe数量。比如说一次只下发了8个stripe,有了这里的continue那么下次再进来这个函数就继续下发后面8个stripe。4572行,获取sector对应的stripe_head4574行,如果没有申请到stripe_head,那么保存已经下发的stripe数量,将请求raid_bio保存到阵列retry_read_aligned指针里,下次唤醒raid5d里直接从该指针中获取bio,并继续下发stripe请求。4578行,返回已下发stripe个数4581行,将bio添加到stripe_head请求链表中 4582行,如果添加失败,释放stripe_head,记录下发stripe数量,保存重试读请求 4588行,设置块层不需要合并标志 4589行,处理stripe 4590行,递减stripe计数 4591行,增加处理stripe数
(编辑:佛山站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

