linux核心md原始碼解讀 十三 raid5重試讀

來源:互聯網
上載者:User

上節我們講到條塊內讀失敗,在回呼函數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數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.