關(guān)于device mapper在內(nèi)核中的架構(gòu)信息在參考文檔1,2中有很好的解釋,在這里就不過多介紹,以下將詳細(xì)的根據(jù)device mapper的代碼解釋device mapper機(jī)制。
一、 LVM簡介
LVM2是Linux 下的邏輯卷管理器,它可以對磁盤進(jìn)行分區(qū)等。但是我們這里用LVM主要是利用用戶空間的device mapper 庫以及它提供的 dmsetup 工具。
LVM的下載地址為:http://git.fedorahosted.org/git/lvm2.git。下載后在tools文件夾下會看到dmsetup.c文件,該文件即為dmsetup工具的源碼。LVM2的安裝方法為:
1. ??執(zhí)行腳本 ./configure
2. ??make device-mapper
3. ??make install?
這時(shí)ls -l /sbin/dmsetup 發(fā)現(xiàn)該命令已經(jīng)是最近編譯的。
二、DM支持RAID45
DM默認(rèn)支持linear、mirror、striped、snapshot、multipath等?target driver,并不支持raid45。但是在2.6內(nèi)核的幾個特定版本中有提供支持raid45的補(bǔ)丁:http://people.redhat.com/heinzm/sw/dm/dm-raid45/
舉例kernel-2.6.30-rc3來說。下載好內(nèi)核后,需將內(nèi)核名字更改為linux-2.6.30-rc3。然后將下載的補(bǔ)丁放在跟剛下載的內(nèi)核同目錄下,執(zhí)行命令patch -bp0 < patch名
二、 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)
1. ?mapped_device ?2. ?dm_table ??3. ?dm_target ?4. ?target_type
這四個數(shù)據(jù)結(jié)構(gòu)是dm中非常重要的數(shù)據(jù)結(jié)構(gòu),關(guān)于這四個數(shù)據(jù)結(jié)構(gòu)參考文檔1、2中已經(jīng)解釋很詳細(xì)。
5. dm_io ?6. dm_target_io ?*tio ?7. clone_info ?ci ??8.bio *clone 這些結(jié)構(gòu)將在下面介紹
三、 創(chuàng)建過程詳解:
1. ?命令:dmsetup create dm0 dm_table
其中dm_table為:0 4096000 raid45?core 2 8192 nosync ?raid4 -1 ??0 ?3 -1 /dev/sdb 0 /dev/sdc 0 /dev/sdd 0(具體參見博文:解讀device mapper raid45 創(chuàng)建參數(shù))
2. ?用戶空間即dmsetup.c函數(shù)的執(zhí)行過程如下:
1. cmd = _find_command(argv[0]) ?返回dispatch table中_create命令
2.?cmd->fn(cmd, argc--, argv++, NULL, multiple_devices) ?即執(zhí)行_create函數(shù)
3. _create->dm_task_create->dm_check_version->_check_version->dm_task_create->dm_task_run->_do_dm_ioctl->ioctl(DM_VERSION)
->dm_task_run->_create_and_load_v4->dm_task_create->dm_task_run->_do_dm_ioctl->ioctl(DM_DEV_CREATE)
->dm_task_create->dm_task_run->_do_dm_ioctl->ioctl(DM_TABLE_LOAD)
->dmt->type=DM_DEVICE_RESUME->dm_task_run->_do_dm_ioctl->ioctl(DM_DEV_SUSPEND)->case DM_DEVICE_RESUME->add_dev_node
由上可知,_create主要執(zhí)行4個ioctl操作,DM_VERSION、DM_DEV_CREATE、DM_TABLE_LOAD和DM_DEV_SUSPEND(DM_DEVICE_RESUME)。四個ioctl分別對應(yīng)內(nèi)核四個命令。在下面會分別介紹這四個命令。dm_task_create根據(jù)ioctl要執(zhí)行的命令創(chuàng)建一個dm_task結(jié)構(gòu)體。dm_task_run根據(jù)dmt->type的編號執(zhí)行ioctl命令,具體編號對應(yīng)_cmd_data_v4[]中相應(yīng)的命令。
總之感覺用戶空間的代碼風(fēng)格很亂,dm_task_create可能再次調(diào)用到dm_task_create和dm_task_run,dm_task_run中又有可能調(diào)用dm_task_create和dm_task_run。而且DM_DEVICE_RESUME這個命令不是通過dm_task_create創(chuàng)建,是直接賦值得到的。層次弄的太亂,一點(diǎn)都不清晰。
3. ?內(nèi)核空間執(zhí)行過程:
用戶空間ioctl后,內(nèi)核空間對應(yīng)執(zhí)行dm-ioctl.c中的dm_ctl_ioctl->ctl_ioctl命令。至于為什么這個ioctl對應(yīng)的是dm-ioctl.c中的dm_ctl_ioctl而不是dm.c中的dm_blk_ioctl,而且dm_blk_ioctl什么時(shí)候被調(diào)用的我還不是很清楚。ctl_ioctl執(zhí)行方法:ctl_ioctl->fn = lookup_ioctl()返回相應(yīng)函數(shù)的函數(shù)指針->copy_params()獲得函數(shù)參數(shù)->fn(param, input_param_size)執(zhí)行相應(yīng)函數(shù)。其中用戶空間的命令主要有三個,根據(jù)lookup_ioctl函數(shù)可知主要對應(yīng)dev_create,table_load,dev_suspend函數(shù)。下面分別解讀這三個函數(shù):
1. ?dev_create->dm_create->alloc_dev
->dm_hash_insert
該過程分為兩部分:a、通過函數(shù)alloc_dev創(chuàng)建相應(yīng)的mapped device結(jié)構(gòu),主要是向內(nèi)核申請必要的內(nèi)存資源,包括mapped device和為進(jìn)行IO操作預(yù)申請的內(nèi)存池,通過內(nèi)核提供的blk_queue_make_request函數(shù)注冊該mapped device對應(yīng)的請求隊(duì)列dm_request。并將該mapped device作為磁盤塊設(shè)備注冊到內(nèi)核中。b、調(diào)用dm_hash_insert將創(chuàng)建好的mapped device插入到device mapper中的一個全局hash表中,該表中保存了內(nèi)核中當(dāng)前創(chuàng)建的所有mapped device
2.?table_load->dm_table_create
->populate_table->dm_table_add_target->tgt->type->ctr()
->dm_table_complete
該函數(shù)根據(jù)用戶空間傳來的參數(shù)構(gòu)建指定mapped device的映射表和所映射的target device。該函數(shù)先構(gòu)建相應(yīng)的dm_table、dm_target結(jié)構(gòu),再調(diào)用dm-table.c中的dm_table_add_target函數(shù)根據(jù)用戶傳入的參數(shù)初始化這些結(jié)構(gòu),并且根據(jù)參數(shù)所指定的target類型,調(diào)用相應(yīng)的target類型的構(gòu)建函數(shù)ctr在內(nèi)存中構(gòu)建target device對應(yīng)的結(jié)構(gòu),然后再根據(jù)所建立的dm_target結(jié)構(gòu)更新dm_table中維護(hù)的B樹。上述過程完畢后,再將建立好的dm_table添加到mapped device的全局hash表對應(yīng)的hash_cell結(jié)構(gòu)中.
在設(shè)備創(chuàng)建時(shí),DM框架會自動創(chuàng)建對應(yīng)的struct dm_target結(jié)構(gòu),并力所能及地初始化了一些成員?,F(xiàn)在創(chuàng)建器所要做的就是完成對該結(jié)構(gòu)的初始化。那么DM框架初始化了哪些,ctr初始化又初始化哪些:參考文檔2中有詳細(xì)介紹
3.?do_resume->md = hc->md ->dm_swap_table
建立mapped device和映射表之間的綁定關(guān)系,事實(shí)上該過程就是通過dm_swap_table函數(shù)將當(dāng)前dm_table結(jié)構(gòu)指針值賦予mapped_device相應(yīng)的map域中,然后再修改mapped_device表示當(dāng)前狀態(tài)的域。
四、 DM轉(zhuǎn)發(fā)bio過程
內(nèi)核中讀寫都是以bio的形式進(jìn)行轉(zhuǎn)發(fā),對于md設(shè)備來說,bio處理所走流程為:
0 ?dm_request(struct request_queue *q, struct bio *bio) ?-->
1 ?_dm_request(q, bio) ??-->
2 ?__split_and_process_bio(md, bio) --> // md 由 q->queue_data 獲得,clone_info為與頂層bio相關(guān)的信息包括所寫md、md的映射表、需要克隆的bio和dm_io,dm_io始終指向頂層bio,提交返回時(shí)負(fù)責(zé)通知bio完成。__split_and_process_bio填充完以上信息繼續(xù)下發(fā)bio
3 ?__clone_and_map(&ci) --> ?// md、bio等信息記錄在 ci 結(jié)構(gòu)體中。首先根據(jù)ci->sector找到相應(yīng)的target,bio的處理分為三種情況:1、該bio可以由該target處理 此時(shí)單獨(dú)克隆一個bio,繼續(xù)下發(fā) 2、該bio長度跨越多個target,但是第一個bi_io_vec長度小于該target 3、正在處理的bi_io_vec(也可能是第一個)大于該target
DM構(gòu)架及其驅(qū)動一般不會是真實(shí)設(shè)備的驅(qū)動,因此只會對bio進(jìn)行處理之后再轉(zhuǎn)發(fā)出去。轉(zhuǎn)發(fā)的方法就是修改bio->bi_bdev和bio->bi_sector,單獨(dú)克隆一個bio的原因是我們不能改動上層的bio。
4 ?__map_bio(ti, clone, tio) --> ?// ti 由 ci->md 查表獲得,clone由ci->bio克隆獲得。
5 ?ti->type->map(ti, clone, &tio->info) --> //修改bio->bi_bdev和bio->bi_sector, 任何一個bio(塊設(shè)備的io請求)都要映射到最終存儲它的設(shè)備上的相應(yīng)位置,map函數(shù)就是完成這一功能.map_context在許多情況下并沒有許多作用。如果map函數(shù)將bio賦值后又分發(fā)出去,那么就返回DM_MAPIO_SUBMITTED告訴DM不要再處理了;如果map函數(shù)修改了bio的內(nèi)容,希望DM將bio按照新內(nèi)容再分發(fā),那么就返回DM_MAPIO_REMAPPED即可;如果map函數(shù)將bio加入隊(duì)列中等待后續(xù)處理,則返回DM_MAPIO_REQUEUE。DM相應(yīng)的處理代碼可以在dm.c中的__map_bio()函數(shù)中找到。對于dm-raid45.c的raid_map函數(shù)即返回DM_MAPIO_SUBMITTED。表明DM不需要做任何事情,假設(shè)target有該io的行使權(quán)。
那么我們看一下raid_map做了什么:
1. ?raid_map -->?bio->bi_sector -= ti->begin -->?bio_list_add(&rs->io.in, bio) ?--> wake_do_raid(rs)?
該函數(shù)首先重映射bio的開始扇區(qū),將該bio加入到rs的bio_list隊(duì)列中,然后喚醒守護(hù)進(jìn)程對該隊(duì)列進(jìn)行處理。守護(hù)進(jìn)程對應(yīng)do_raid函數(shù),是在raid_ctr函數(shù)調(diào)用INIT_DELAYED_WORK(&rs->io.dws_do_raid, do_raid)注冊的。
參考文檔:
1.?Linux 內(nèi)核中的 Device Mapper 機(jī)制
http://www.ibm.com/developerworks/cn/linux/l-devmapper/index.html#resources
2.?Device Mapper 代碼分析
http://blog.csdn.net/SonicLing/article/details/5460311#[1]
3.?LVM學(xué)習(xí)系列之三
http://www.doc88.com/p-675124528501.html
?
評論