linux内核的冒险md来源释义# 14raid5非条块读
生活随笔
收集整理的這篇文章主要介紹了
linux内核的冒险md来源释义# 14raid5非条块读
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
linux內(nèi)核的冒險(xiǎn)md來(lái)源釋義# 14raid5非條塊讀 轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/liumangxiong
假設(shè)是非條塊內(nèi)讀。那么就至少涉及到兩個(gè)條塊的讀,這就須要分別從這兩個(gè)條塊內(nèi)讀出數(shù)據(jù)。然后再湊成整個(gè)結(jié)果返回給上層。接下來(lái)我們將看到怎樣將一個(gè)完整的bio讀請(qǐng)求拆分成多個(gè)子請(qǐng)求下發(fā)到磁盤(pán),從磁盤(pán)返回之后再又一次組合成請(qǐng)求結(jié)果返回給上層的。 4097 logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1); 4098 last_sector = bi->bi_sector + (bi->bi_size>>9); 4099 bi->bi_next = NULL; 4100 bi->bi_phys_segments = 1; /* over-loaded to count active stripes */
首先計(jì)算請(qǐng)求起始位置,由于md下發(fā)到磁盤(pán)數(shù)據(jù)請(qǐng)求的最小單位為STRIPE_SECTORS,所以這里要將請(qǐng)求對(duì)齊。計(jì)算出請(qǐng)求起始位置為logical_sector?,結(jié)束位置為last_sector。4100行復(fù)用bi_phys_segments?用于計(jì)數(shù)下發(fā)條帶數(shù),這里防止意外釋放先設(shè)置為1。
在這個(gè)循環(huán)中將請(qǐng)求拆分個(gè)多個(gè)條帶,分別下發(fā)命令。
在第一次看這段代碼的時(shí)候。因?yàn)樘颐θ粵](méi)有找到重點(diǎn)在哪里。就像一個(gè)人在喧囂的城市里長(zhǎng)大,因?yàn)楸怀鞘械耐獗硭曰笕徊恢纼?nèi)心真正想追求的生活。當(dāng)真正靜下心來(lái)看的時(shí)候。最終發(fā)現(xiàn)最重要的一句在4187行,即add_stripe_bio函數(shù),從此開(kāi)始stripe不再孤單,因?yàn)橛辛薭io的附體。它已經(jīng)準(zhǔn)備好要增加了條帶處理流程,一場(chǎng)轟轟烈烈的條帶人生路由此展開(kāi)。 在4198行和4203行release_stripe_plug之后一個(gè)新的條帶正式增加了處理隊(duì)列(conf->handle_list)。 人的上半生在不斷地找入口。下半生在不斷地找出口。在這里,讀stripe找到了入口,那么出口在哪里呢?讀過(guò)LDD的同學(xué)一定知道答案,對(duì)于不使用默認(rèn)請(qǐng)求隊(duì)列的塊設(shè)備驅(qū)動(dòng)來(lái)說(shuō)。相應(yīng)的make_request函數(shù)為入口。出口就是bio_endio。接下來(lái)我們就一步步邁向這個(gè)出口。 release_stripe_plug之后首先進(jìn)入的是handle_stripe,handle_stripe調(diào)用analyse_stripe,在這個(gè)函數(shù)中設(shè)置了to_read: 3245 if (test_bit(R5_Wantfill, &dev->flags)) 3246 s->to_fill++; 3247 else if (dev->toread) 3248 s->to_read++;
回到handle_stripe函數(shù)中: 3472 if (s.to_read || s.non_overwrite 3473 || (conf->level == 6 && s.to_write && s.failed) 3474 || (s.syncing && (s.uptodate + s.compute < disks)) 3475 || s.replacing 3476 || s.expanding) 3477 handle_stripe_fill(sh, &s, disks);
to_read觸發(fā)了handle_stripe_fill,這個(gè)函數(shù)的作用就是設(shè)置須要讀取的標(biāo)志: 2696 set_bit(R5_LOCKED, &dev->flags); 2697 set_bit(R5_Wantread, &dev->flags); 2698 s->locked++;
接著又來(lái)到了ops_run_io,將讀請(qǐng)求下發(fā)到磁盤(pán)。讀請(qǐng)求的回調(diào)函數(shù)為raid5_end_read_request: 1745 if (uptodate) { 1746 set_bit(R5_UPTODATE, &sh->dev[i].flags); ... 1824 rdev_dec_pending(rdev, conf->mddev); 1825 clear_bit(R5_LOCKED, &sh->dev[i].flags); 1826 set_bit(STRIPE_HANDLE, &sh->state); 1827 release_stripe(sh);
這個(gè)函數(shù)做了兩件事情。一是設(shè)置了R5_UPTODATE標(biāo)志,還有一是調(diào)用了release_stripe又一次將條帶送回了handle_stripe處理。 帶著R5_UPTODATE標(biāo)志進(jìn)入了analyse_stripe函數(shù): 3231 if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread && 3232 !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) 3233 set_bit(R5_Wantfill, &dev->flags); 3234 3235 /* now count some things */ 3236 if (test_bit(R5_LOCKED, &dev->flags)) 3237 s->locked++; 3238 if (test_bit(R5_UPTODATE, &dev->flags)) 3239 s->uptodate++; 3240 if (test_bit(R5_Wantcompute, &dev->flags)) { 3241 s->compute++; 3242 BUG_ON(s->compute > 2); 3243 } 3244 3245 if (test_bit(R5_Wantfill, &dev->flags)) 3246 s->to_fill++;
在3255行設(shè)置了R5_Wantfill標(biāo)志。在3246行設(shè)置了to_fill,再次回來(lái)handle_stripe: 3426 if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { 3427 set_bit(STRIPE_OP_BIOFILL, &s.ops_request); 3428 set_bit(STRIPE_BIOFILL_RUN, &sh->state); 3429 }
條帶狀態(tài)設(shè)置了STRIPE_OP_BIOFILL,僅僅要設(shè)置了s.ops_request。就必須立即知道這個(gè)域相應(yīng)的處理函數(shù)為raid_run_ops,實(shí)際操作在__raid_run_ops: 1378 if (test_bit(STRIPE_OP_BIOFILL, &ops_request)) { 1379 ops_run_biofill(sh); 1380 overlap_clear++; 1381 }
相應(yīng)的處理函數(shù)是ops_run_biofill: 812static void ops_run_biofill(struct stripe_head *sh) 813{ 814 struct dma_async_tx_descriptor *tx = NULL; 815 struct async_submit_ctl submit; 816 int i; 817 818 pr_debug("%s: stripe %llu\n", __func__, 819 (unsigned long long)sh->sector); 820 821 for (i = sh->disks; i--; ) { 822 struct r5dev *dev = &sh->dev[i]; 823 if (test_bit(R5_Wantfill, &dev->flags)) { 824 struct bio *rbi; 825 spin_lock_irq(&sh->stripe_lock); 826 dev->read = rbi = dev->toread; 827 dev->toread = NULL; 828 spin_unlock_irq(&sh->stripe_lock); 829 while (rbi && rbi->bi_sector < 830 dev->sector + STRIPE_SECTORS) { 831 tx = async_copy_data(0, rbi, dev->page, 832 dev->sector, tx); 833 rbi = r5_next_bio(rbi, dev->sector); 834 } 835 } 836 } 837 838 atomic_inc(&sh->count); 839 init_async_submit(&submit, ASYNC_TX_ACK, tx, ops_complete_biofill, sh, NULL); 840 async_trigger_callback(&submit); 841}
最終見(jiàn)到廬山真面目了,不禁感慨一下代碼就是這樣裹著一層又一層,就好像神奇的生日禮物一樣要拆開(kāi)一層又一層的包裝,又像老胡同巷子走過(guò)一道又一道才干找到那個(gè)賣(mài)酒的店子。但無(wú)論怎么樣,代碼都對(duì)你毫無(wú)保留的。真誠(chéng)的。
假設(shè)你已經(jīng)練就了一目十行的火眼睛睛的話(huà),你一定看到了806行的return_io,沒(méi)錯(cuò)。這就是我之前提到的出口了: 177static void return_io(struct bio *return_bi) 178{ 179 struct bio *bi = return_bi; 180 while (bi) { 181 182 return_bi = bi->bi_next; 183 bi->bi_next = NULL; 184 bi->bi_size = 0; 185 bio_endio(bi, 0); 186 bi = return_bi; 187 } 188}
最終看到bio_endio了吧,happy吧去慶祝喝一杯吧。 狂歡夠了嗎?接下來(lái)有兩個(gè)思考題: 1)return_bi為什么不是一個(gè)bio。而有bi_next? 2)既然return_io結(jié)束了。808/809行為什么又要又一次增加到處理鏈表? 轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/liumangxiong
假設(shè)是非條塊內(nèi)讀。那么就至少涉及到兩個(gè)條塊的讀,這就須要分別從這兩個(gè)條塊內(nèi)讀出數(shù)據(jù)。然后再湊成整個(gè)結(jié)果返回給上層。接下來(lái)我們將看到怎樣將一個(gè)完整的bio讀請(qǐng)求拆分成多個(gè)子請(qǐng)求下發(fā)到磁盤(pán),從磁盤(pán)返回之后再又一次組合成請(qǐng)求結(jié)果返回給上層的。 4097 logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1); 4098 last_sector = bi->bi_sector + (bi->bi_size>>9); 4099 bi->bi_next = NULL; 4100 bi->bi_phys_segments = 1; /* over-loaded to count active stripes */
首先計(jì)算請(qǐng)求起始位置,由于md下發(fā)到磁盤(pán)數(shù)據(jù)請(qǐng)求的最小單位為STRIPE_SECTORS,所以這里要將請(qǐng)求對(duì)齊。計(jì)算出請(qǐng)求起始位置為logical_sector?,結(jié)束位置為last_sector。4100行復(fù)用bi_phys_segments?用于計(jì)數(shù)下發(fā)條帶數(shù),這里防止意外釋放先設(shè)置為1。
4102 for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { 4103 DEFINE_WAIT(w); 4104 int previous; 4105 4106 retry: 4107 previous = 0; 4108 prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); ... 4134 4135 new_sector = raid5_compute_sector(conf, logical_sector, 4136 previous, 4137 &dd_idx, NULL); 4138 pr_debug("raid456: make_request, sector %llu logical %llu\n", 4139 (unsigned long long)new_sector, 4140 (unsigned long long)logical_sector); 4141 4142 sh = get_active_stripe(conf, new_sector, previous, 4143 (bi->bi_rw&RWA_MASK), 0);
在這個(gè)循環(huán)中將請(qǐng)求拆分個(gè)多個(gè)條帶,分別下發(fā)命令。
在處理?xiàng)l帶的時(shí)候還須要做到相互排斥。不能有兩個(gè)線程在同一時(shí)候操作同一個(gè)條帶。
比方說(shuō)同步線程在同步這個(gè)條帶,raid5d在寫(xiě)這個(gè)條帶,那么就會(huì)產(chǎn)生非預(yù)期的結(jié)果。
4103行。等待隊(duì)列用于條帶訪問(wèn)相互排斥 4108行,增加等待隊(duì)列 4135行。依據(jù)陣列邏輯扇區(qū)計(jì)算出磁盤(pán)物理偏移扇區(qū),并計(jì)算相應(yīng)的數(shù)據(jù)盤(pán)號(hào)和校驗(yàn)盤(pán)號(hào) 4142行,依據(jù)磁盤(pán)物理偏移扇區(qū)獲取一個(gè)條帶 4144 if (sh) { .... 4186 if (test_bit(STRIPE_EXPANDING, &sh->state) || 4187 !add_stripe_bio(sh, bi, dd_idx, rw)) { 4188 /* Stripe is busy expanding or 4189 * add failed due to overlap. Flush everything 4190 * and wait a while 4191 */ 4192 md_wakeup_thread(mddev->thread); 4193 release_stripe(sh); 4194 schedule(); 4195 goto retry; 4196 } 4197 finish_wait(&conf->wait_for_overlap, &w); 4198 set_bit(STRIPE_HANDLE, &sh->state); 4199 clear_bit(STRIPE_DELAYED, &sh->state); 4200 if ((bi->bi_rw & REQ_SYNC) && 4201 !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) 4202 atomic_inc(&conf->preread_active_stripes); 4203 release_stripe_plug(mddev, sh); 4204 } else { 4205 /* cannot get stripe for read-ahead, just give-up */ 4206 clear_bit(BIO_UPTODATE, &bi->bi_flags); 4207 finish_wait(&conf->wait_for_overlap, &w); 4208 break; 4209 } 4210 }在第一次看這段代碼的時(shí)候。因?yàn)樘颐θ粵](méi)有找到重點(diǎn)在哪里。就像一個(gè)人在喧囂的城市里長(zhǎng)大,因?yàn)楸怀鞘械耐獗硭曰笕徊恢纼?nèi)心真正想追求的生活。當(dāng)真正靜下心來(lái)看的時(shí)候。最終發(fā)現(xiàn)最重要的一句在4187行,即add_stripe_bio函數(shù),從此開(kāi)始stripe不再孤單,因?yàn)橛辛薭io的附體。它已經(jīng)準(zhǔn)備好要增加了條帶處理流程,一場(chǎng)轟轟烈烈的條帶人生路由此展開(kāi)。 在4198行和4203行release_stripe_plug之后一個(gè)新的條帶正式增加了處理隊(duì)列(conf->handle_list)。 人的上半生在不斷地找入口。下半生在不斷地找出口。在這里,讀stripe找到了入口,那么出口在哪里呢?讀過(guò)LDD的同學(xué)一定知道答案,對(duì)于不使用默認(rèn)請(qǐng)求隊(duì)列的塊設(shè)備驅(qū)動(dòng)來(lái)說(shuō)。相應(yīng)的make_request函數(shù)為入口。出口就是bio_endio。接下來(lái)我們就一步步邁向這個(gè)出口。 release_stripe_plug之后首先進(jìn)入的是handle_stripe,handle_stripe調(diào)用analyse_stripe,在這個(gè)函數(shù)中設(shè)置了to_read: 3245 if (test_bit(R5_Wantfill, &dev->flags)) 3246 s->to_fill++; 3247 else if (dev->toread) 3248 s->to_read++;
回到handle_stripe函數(shù)中: 3472 if (s.to_read || s.non_overwrite 3473 || (conf->level == 6 && s.to_write && s.failed) 3474 || (s.syncing && (s.uptodate + s.compute < disks)) 3475 || s.replacing 3476 || s.expanding) 3477 handle_stripe_fill(sh, &s, disks);
to_read觸發(fā)了handle_stripe_fill,這個(gè)函數(shù)的作用就是設(shè)置須要讀取的標(biāo)志: 2696 set_bit(R5_LOCKED, &dev->flags); 2697 set_bit(R5_Wantread, &dev->flags); 2698 s->locked++;
接著又來(lái)到了ops_run_io,將讀請(qǐng)求下發(fā)到磁盤(pán)。讀請(qǐng)求的回調(diào)函數(shù)為raid5_end_read_request: 1745 if (uptodate) { 1746 set_bit(R5_UPTODATE, &sh->dev[i].flags); ... 1824 rdev_dec_pending(rdev, conf->mddev); 1825 clear_bit(R5_LOCKED, &sh->dev[i].flags); 1826 set_bit(STRIPE_HANDLE, &sh->state); 1827 release_stripe(sh);
這個(gè)函數(shù)做了兩件事情。一是設(shè)置了R5_UPTODATE標(biāo)志,還有一是調(diào)用了release_stripe又一次將條帶送回了handle_stripe處理。 帶著R5_UPTODATE標(biāo)志進(jìn)入了analyse_stripe函數(shù): 3231 if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread && 3232 !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) 3233 set_bit(R5_Wantfill, &dev->flags); 3234 3235 /* now count some things */ 3236 if (test_bit(R5_LOCKED, &dev->flags)) 3237 s->locked++; 3238 if (test_bit(R5_UPTODATE, &dev->flags)) 3239 s->uptodate++; 3240 if (test_bit(R5_Wantcompute, &dev->flags)) { 3241 s->compute++; 3242 BUG_ON(s->compute > 2); 3243 } 3244 3245 if (test_bit(R5_Wantfill, &dev->flags)) 3246 s->to_fill++;
在3255行設(shè)置了R5_Wantfill標(biāo)志。在3246行設(shè)置了to_fill,再次回來(lái)handle_stripe: 3426 if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { 3427 set_bit(STRIPE_OP_BIOFILL, &s.ops_request); 3428 set_bit(STRIPE_BIOFILL_RUN, &sh->state); 3429 }
條帶狀態(tài)設(shè)置了STRIPE_OP_BIOFILL,僅僅要設(shè)置了s.ops_request。就必須立即知道這個(gè)域相應(yīng)的處理函數(shù)為raid_run_ops,實(shí)際操作在__raid_run_ops: 1378 if (test_bit(STRIPE_OP_BIOFILL, &ops_request)) { 1379 ops_run_biofill(sh); 1380 overlap_clear++; 1381 }
相應(yīng)的處理函數(shù)是ops_run_biofill: 812static void ops_run_biofill(struct stripe_head *sh) 813{ 814 struct dma_async_tx_descriptor *tx = NULL; 815 struct async_submit_ctl submit; 816 int i; 817 818 pr_debug("%s: stripe %llu\n", __func__, 819 (unsigned long long)sh->sector); 820 821 for (i = sh->disks; i--; ) { 822 struct r5dev *dev = &sh->dev[i]; 823 if (test_bit(R5_Wantfill, &dev->flags)) { 824 struct bio *rbi; 825 spin_lock_irq(&sh->stripe_lock); 826 dev->read = rbi = dev->toread; 827 dev->toread = NULL; 828 spin_unlock_irq(&sh->stripe_lock); 829 while (rbi && rbi->bi_sector < 830 dev->sector + STRIPE_SECTORS) { 831 tx = async_copy_data(0, rbi, dev->page, 832 dev->sector, tx); 833 rbi = r5_next_bio(rbi, dev->sector); 834 } 835 } 836 } 837 838 atomic_inc(&sh->count); 839 init_async_submit(&submit, ASYNC_TX_ACK, tx, ops_complete_biofill, sh, NULL); 840 async_trigger_callback(&submit); 841}
最終見(jiàn)到廬山真面目了,不禁感慨一下代碼就是這樣裹著一層又一層,就好像神奇的生日禮物一樣要拆開(kāi)一層又一層的包裝,又像老胡同巷子走過(guò)一道又一道才干找到那個(gè)賣(mài)酒的店子。但無(wú)論怎么樣,代碼都對(duì)你毫無(wú)保留的。真誠(chéng)的。
并且越是復(fù)雜的代碼就越是風(fēng)情萬(wàn)種、婀娜多姿,前提是你要懂得怎樣走入她的內(nèi)心里才干體會(huì)得到。等真正體會(huì)到的時(shí)候你就會(huì)拍案叫絕,從而獲得征服的快感久久不能忘懷。在征服了這樣一個(gè)又一個(gè)風(fēng)情萬(wàn)種的代碼之后。你的追求就不再局限于肉體之上,轉(zhuǎn)而追求精神上的高度,像歐洲建筑師一樣去設(shè)計(jì)大教堂,然后花個(gè)600多年把哥特式的科隆大教堂建好,這才叫藝術(shù)。
好吧,那個(gè)時(shí)候你我都已經(jīng)不在了,但那種精神始終是你我要追求的境地。
823行,我們剛剛完畢了對(duì)磁盤(pán)的讀取,這下將讀取的數(shù)據(jù)從緩存區(qū)中復(fù)制到dev->page上,而此時(shí)dev->toread也轉(zhuǎn)移到了dev->read。這里先構(gòu)造了dma的描寫(xiě)敘述符,839和840將請(qǐng)求提交給DMA,在請(qǐng)求完畢之后會(huì)回調(diào)到839傳入的參數(shù)ops_complete_biofill: 769static void ops_complete_biofill(void *stripe_head_ref) 770{ 771 struct stripe_head *sh = stripe_head_ref; 772 struct bio *return_bi = NULL; 773 int i; 774 775 pr_debug("%s: stripe %llu\n", __func__, 776 (unsigned long long)sh->sector); 777 778 /* clear completed biofills */ 779 for (i = sh->disks; i--; ) { 780 struct r5dev *dev = &sh->dev[i]; 781 782 /* acknowledge completion of a biofill operation */ 783 /* and check if we need to reply to a read request, 784 * new R5_Wantfill requests are held off until 785 * !STRIPE_BIOFILL_RUN 786 */ 787 if (test_and_clear_bit(R5_Wantfill, &dev->flags)) { 788 struct bio *rbi, *rbi2; 789 790 BUG_ON(!dev->read); 791 rbi = dev->read; 792 dev->read = NULL; 793 while (rbi && rbi->bi_sector < 794 dev->sector + STRIPE_SECTORS) { 795 rbi2 = r5_next_bio(rbi, dev->sector); 796 if (!raid5_dec_bi_active_stripes(rbi)) { 797 rbi->bi_next = return_bi; 798 return_bi = rbi; 799 } 800 rbi = rbi2; 801 } 802 } 803 } 804 clear_bit(STRIPE_BIOFILL_RUN, &sh->state); 805 806 return_io(return_bi); 807 808 set_bit(STRIPE_HANDLE, &sh->state); 809 release_stripe(sh); 810}假設(shè)你已經(jīng)練就了一目十行的火眼睛睛的話(huà),你一定看到了806行的return_io,沒(méi)錯(cuò)。這就是我之前提到的出口了: 177static void return_io(struct bio *return_bi) 178{ 179 struct bio *bi = return_bi; 180 while (bi) { 181 182 return_bi = bi->bi_next; 183 bi->bi_next = NULL; 184 bi->bi_size = 0; 185 bio_endio(bi, 0); 186 bi = return_bi; 187 } 188}
最終看到bio_endio了吧,happy吧去慶祝喝一杯吧。 狂歡夠了嗎?接下來(lái)有兩個(gè)思考題: 1)return_bi為什么不是一個(gè)bio。而有bi_next? 2)既然return_io結(jié)束了。808/809行為什么又要又一次增加到處理鏈表? 轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/liumangxiong
版權(quán)聲明:本文博客原創(chuàng)文章。博客,未經(jīng)同意,不得轉(zhuǎn)載。
轉(zhuǎn)載于:https://www.cnblogs.com/mengfanrong/p/4713262.html
總結(jié)
以上是生活随笔為你收集整理的linux内核的冒险md来源释义# 14raid5非条块读的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 开发文档收集
- 下一篇: 分析windows宿主机Ping不通li