加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_镇江站长网 (https://www.0511zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

linux内核md源代码解读 十三 raid5重试读 - Linux系统

发布时间:2014-03-24 10:16:01 所属栏目:Linux 来源:站长网
导读:上节我们讲到条块内读失败,在回调函数raid5_align_endio中将请求加入阵列重试链表,在唤醒raid5d线程之后,raid5d线程将该请求调用retry_aligned_read函数进行
上节我们讲到条块内读失败,在回调函数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数

(编辑:应用网_镇江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!