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数
(编辑:应用网_镇江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |