Linux 核心中的 Device Mapper 機制

來源:互聯網
上載者:User

標籤:

本文結合具體代碼對 Linux 核心中的 device mapper 映射機制進行了介紹。Device mapper 是 Linux 2.6 核心中提供的一種從邏輯裝置到物理裝置的映射架構機制,在該機制下,使用者可以很方便的根據自己的需要制定實現儲存資源的管理原則,當前比較流行的 Linux 下的邏輯卷管理器如 LVM2(Linux Volume Manager 2 version)、EVMS(Enterprise Volume Management System)、dmraid(Device Mapper Raid Tool)等都是基於該機制實現的。理解該機制是進一步分析、理解這些卷管理器的實現及設計的基礎。通過本文也可以進一步理解 Linux 系統塊一級 IO的設計和實現。

 

Device Mapper 是 Linux2.6 核心中支援邏輯卷管理的通用裝置映射機制,它為實現用於儲存資源管理的塊裝置驅動提供了一個高度模組化的核心架構, 1。

圖1 Device Mapper的核心體系架構

在 核心中它通過一個一個模組化的 target driver 外掛程式實現對 IO 請求的過濾或者重新定向等工作,當前已經實現的 target driver 外掛程式包括軟 raid、軟加密、邏輯卷條帶、多重路徑、鏡像、快照等,圖中 linear、mirror、snapshot、multipath 表示的就是這些 target driver。Device mapper 進一步體現了在 Linux 核心設計中策略和機制分離的原則,將所有與策略相關的工作放到使用者空間完成,核心中主要提供完成這些策略所需要的機制。Device mapper 使用者空間相關部分主要負責配置具體的策略和控制邏輯,比如邏輯裝置和哪些物理裝置建立映射,怎麼建立這些映射關係等等,而具體過濾和重新導向 IO 請求的工作由核心中相關程式碼完成。因此整個 device mapper 機制由兩部分組成--核心空間的 device mapper 驅動、使用者空間的device mapper 庫以及它提供的 dmsetup 工具。在下文中,我們分核心和使用者空間兩部分進行介紹。

核心部分

Device mapper 的核心相關代碼已經作為 Linux 2.6 核心發布版的一部分整合到核心源碼中了,相關代碼在核心源碼的 driver/md/ 目錄中,其代碼檔案可以劃分為實現 device mapper 核心中基本架構的檔案和實現具體映射工作的 target driver 外掛程式檔案兩部分。文章下面的分析結果主要是基於上述源碼檔案得到的。

重要概念

Device mapper 在核心中作為一個塊裝置驅動被註冊的,它包含三個重要的對象概念,mapped device、映射表、target device。Mapped device 是一個邏輯抽象,可以理解成為核心向外提供的邏輯裝置,它通過映射表描述的映射關係和 target device 建立映射。從 Mapped device 到一個 target device 的映射表由一個多元組表示,該多元組由表示 mapped device 邏輯的起始地址、範圍、和表示在 target device 所在物理裝置的地址位移量以及target 類型等變數組成(這些地址和位移量都是以磁碟的扇區為單位的,即 512 個位元組大小)。Target device 表示的是 mapped device 所映射的物理空間段,對 mapped device 所表示的邏輯裝置來說,就是該邏輯裝置映射到的一個物理裝置。Device mapper 中這三個對象和 target driver 外掛程式一起構成了一個可迭代的裝置樹。在該樹型結構中的頂層根節點是最終作為邏輯裝置向外提供的 mapped device,葉子節點是 target device 所表示的底層物理裝置。最小的裝置樹由單個 mapped device 和 target device 組成。每個 target device 都是被mapped device 獨佔的,只能被一個 mapped device 使用。一個 mapped device 可以映射到一個或者多個 target device 上,而一個 mapped device 又可以作為它上層 mapped device的 target device 被使用,該層次在理論上可以在 device mapper 架構下無限迭代下去。

圖2 Device mapper 核心中各對象的層次關係

在 圖2 中我們可以看到 mapped device1 通過映射表和 a、b、c 三個 target device 建立了映射關係,而 target device a 又是通過 mapped device 2 演化過來,mapped device 2 通過映射表和 target device d 建立映射關係。

我們進一步看一下上述三個對象在代碼中的具體實現,dm.c 檔案定義的 mapped_device 結構用於表示 mapped device,它主要包括該 mapped device 相關的鎖,註冊的請求隊列和一些記憶體池以及指向它所對應映射表的指標等域。Mapped device 對應的映射表是由 dm_table.c 檔案中定義的 dm_table 結構表示的,該結構中包含一個 dm_target結構數組,dm_target 結構具體描述了 mapped_device 到它某個 target device 的映射關係。而在 dm_table 結構中將這些 dm_target 按照 B 樹的方式組織起來方便 IO 請求映射時的尋找操作。Dm_target 結構具體記錄該結構對應 target device 所映射的 mapped device 邏輯地區的開始地址和範圍,同時還包含指向具體 target device 相關操作的 target_type 結構的指標。Target_type 結構主要包含了 target device 對應的 target driver 外掛程式的名字、定義的構建和刪除該類型target device的方法、該類target device對應的IO請求重新對應和結束IO的方法等。而表示具體的target device的域是dm_target中的private域,該指標指向mapped device所映射的具體target device對應的結構。表示target device的具體結構由於不同的target 類型而不同,比如最簡單的線性映射target類型對應target device的結構是dm-linear.c檔案中定義的linear_c結構。其定義如下:

struct linear_c {struct dm_dev *dev;sector_t start;};

該target device的定義相當簡單,就只包括了表示對應物理裝置的dm_dev結構指標和在該物理裝置中以扇區為單位的位移地址start。上述幾個資料結構關係3所示:

圖3 device mapper中幾個重要資料結構的關係

核心中建立過程

在下面我們結合具體的代碼簡要介紹下在核心中建立一個mapped device的過程:

1、 根據核心向使用者空間提供的ioctl 介面傳來的參數,用dm-ioctl.c檔案中的dev_create函數建立相應的mapped device結構。這個過程很簡單,主要是向核心申請必要的記憶體資源,包括mapped device和為進行IO操作預申請的記憶體池,通過核心提供的blk_queue_make_request函數註冊該mapped device對應的請求隊列dm_request。並將該mapped device作為磁碟塊裝置註冊到核心中。

2、 調用dm_hash_insert將建立好的mapped device插入到device mapper中的一個全域hash表中,該表中儲存了核心中當前建立的所有mapped device。

3、 使用者空間命令通過ioctl調用table_load函數,該函數根據使用者空間傳來的參數構建指定mapped device的映射表和所映射的target device。該函數先構建相應的dm_table、dm_target結構,再調用dm-table.c中的dm_table_add_target函 數根據使用者傳入的參數初始化這些結構,並且根據參數所指定的target類型,調用相應的target類型的構建函數ctr在記憶體中構建target device對應的結構,然後再根據所建立的dm_target結構更新dm_table中維護的B樹。上述過程完畢後,再將建立好的dm_table添 加到mapped device的全域hash表對應的hash_cell結構中。

4、 最後通過ioctl調用do_resume函數建立mapped device和映射表之間的綁定關係,事實上該過程就是通過dm_swap_table函數將當前dm_table結構指標值賦予 mapped_device相應的map域中,然後再修改mapped_device表示目前狀態的域。

通過上述的4個主要步驟,device mapper在核心中就建立一個可以提供給使用者使用的mapped device邏輯塊裝置。

IO流

Device mapper本質功能就是根據映射關係和target driver描述的IO處理規則,將IO請求從邏輯裝置mapped device轉寄相應的target device上。Device mapper處理所有從核心中塊一級IO子系統的generic_make_request和submit_bio介面中定向到mapped device的所有塊讀寫IO請求。IO請求在device mapper的裝置樹中通過請求轉寄從上到下地進行處理。當一個bio請求在裝置樹中的mapped deivce向下層轉寄時,一個或者多個bio的複製被建立並發送給下層target device。然後相同的過程在裝置樹的每一個層次上重複,只要裝置樹足夠大理論上這種轉寄過程可以無限進行下去。在裝置樹上某個層次中,target driver結束某個bio請求後,將表示結束該bio請求的事件上報給它上層的mapped device,該過程在各個層次上進行直到該事件最終上傳到根mapped device的為止,然後device mapper結束根mapped device上原始bio請求,結束整個IO請求過程。

Bio在device mapper的裝置樹進行逐層的轉寄時,最終轉寄到一個或多個葉子target節點終止。因為一個bio請求不可以跨多個target device(亦即物理空間段), 因此在每一個層次上,device mapper根據使用者預先告知的mapped device 的target映射資訊複製一個或者多個bio,將bio進行拆分後轉寄到對應的target device上。這些複製的bio先交給mapped device上對應的target driver上進行處理,根據target driver中定義的IO處理規則進行IO請求的過濾等處理,然後再提交給target device完成。上述過程在dm.c檔案中的dm_request函數中完成。Target driver可以對這些bio做如下處理:

1、 將這些bio在本驅動內部排隊等待以後進行處理;

2、 將bio重新定向到一個或多個target device上或者每個target device上的不同扇區;

3、 向device mapper返回error 狀態。

IO請求就按照上文中描述的過程在圖2中所示的裝置樹中逐層進行處理,直到IO請求結束。

小結

Device mapper在核心中向外提供了一個從邏輯裝置到物理裝置的映射架構,只要使用者在使用者空間制定好映射策略,按照自己的需要編寫處理具體IO請求的 target driver外掛程式,就可以很方便的實現一個類似LVM的邏輯卷管理器。Device mapper以ioctl的方式向外提供介面,使用者通過使用者空間的device mapper庫,向device mapper的字元裝置發送ioctl命令,完成向內的通訊。它還通過ioctl提供嚮往的事件通知機制,允許target driver將IO相關的某些事件傳送到使用者空間。

 

使用者空間部分

Device mapper在使用者空間相對簡單,主要包括device mapper庫和dmsetup工具。Device mapper庫就是對ioctl、使用者空間建立刪除device mapper邏輯裝置所需必要操作的封裝,dmsetup是一個提供給使用者直接可用的建立刪除device mapper裝置的命令列工具。因為它們的功能和流程相對簡單,在本文中對它們的細節就不介紹了,使用者空間主要負責如下工作:

1、 發現每個mapped device相關的target device;

2、 根據配置資訊建立映射表;

3、 將使用者空間構建好的映射表傳入核心,讓核心構建該mapped device對應的dm_table結構;

4、 儲存當前的映射資訊,以便未來重新構建。

以下我們主要通過執行個體來說明dmsetup的使用,同時進一步說明device mapper這種映射機制。使用者空間中最主要的工作就是構建並儲存映射表,下面給出一些映射表的例子:

1)
0 1024 linear /dev/sda 204
1024 512 linear /dev/sdb 766

1536128linear /dev/sdc 0

2)02048striped264/dev/sda1024/dev/sdb0

3)04711mirrorcore264nosync2/dev/sda2048/dev/sdb 1024

例子1中將邏輯裝置0~1023扇區、1024~1535扇區以及1536~1663三個位址範圍分別以線形映射的方式映射到/dev/sda裝置第204號扇區、/dev/sdb裝置第766號扇區和/dev/sdc裝置的第0號扇區開始的地區。

例子2中將邏輯裝置從0號扇區開始的,長度為2048個扇區的段以條帶的方式映射的到/dev/sda裝置的第1024號扇區以及/dev/sdb裝置的第0號扇區開始的地區。同時告訴核心這個條帶類型的target driver存在2個條帶裝置與邏輯裝置做映射,並且條帶的大小是64個扇區,使得驅動可以該值來拆分跨裝置的IO請求。

例子3中將邏輯裝置從0號扇區開始的,長度為4711個扇區的段以鏡像的方式映射到/dev/sda裝置的第2048個扇區以及/dev/sdb裝置的第1024號扇區開始的地區。

映射表確定後,建立、刪除邏輯裝置的操作就相對簡單,通過dmsetup如下命令就可以完成相應的操作。

dmsetup create 裝置名稱 映射表檔案/* 根據指定的映射表建立一個邏輯裝置 */

dmsetup reload裝置名稱映射表檔案 /*為指定裝置從磁碟中讀取對應檔,重新構建映射關係*/

dmsetup remove裝置名稱/* 刪除指定的邏輯裝置 */

圖4 根據例子1中映射表在核心中建立的邏輯裝置

當使用者空間根據映射表下達建立邏輯裝置命令後,device mapper在核心中就根據傳入的參數和映射關係建立邏輯地址到物理地址的映射關係。根據映射表例子1中的映射關係建立的裝置4所示,圖中的下半部分就抽象地描繪出了按照該映射表在核心中建立的邏輯地址到物理地址的映射關係。

Device mapper的使用者空間部分對開發人員要實現自己的儲存管理工具來說是可選的,事實上,很多我們常見的邏輯卷管理器,比如LVM2、dmraid等工具都利用device mapper的提供的device mapper使用者空間庫,根據自己的管理需求建立獨立的一套管理工具,而並沒有使用它提供的dmsetup工具,甚至IBM的開源項目企業級的邏輯卷管理系統-EVMS,在實現中都沒有採用device mapper的使用者空間庫,完全根據核心中的ioctl定義實現了一套自己的函數庫。

 

Target Driver

Device mapper提供了一個統一的架構,通過target driver 外掛程式的方式允許使用者根據實際的需要指定自己的IO處理規則,因此target driver充分體現了device mapper的靈活性。在上文中我們已經不止一次的提到過target driver,也描述過target driver的功能,在這裡我們結合最簡單的linear target driver具體介紹target driver的實現。

Target driver主要定義對IO請求的處理規則,在device mapper中對target driver的操作已定義好了統一的介面,在實現中該介面由我們上文提到的target_type結構中定義,它定義了以下target driver的方法:

1、構建target device 的方法;
2、刪除target device 的方法;
3、Target的映射IO請求的方法;
4、Target結束IO請求的方法;
5、暫停target device讀寫的方法;
6、恢複target device讀寫的訪問;
7、擷取當前target device狀態的訪問;
8、Target 處理使用者訊息的方法;

使用者可以根據具體需求選擇性地實現上述方法,但一般最少要實現前3種方法,否則在device mapper下不能夠正常的工作。linear target driver就只實現了前3種方法和方法7,它完成邏輯地址空間到物理地址空間的線性映射,可以將多個物理裝置以線性串連的方式組成一個邏輯裝置,就4中描述的那樣,通過linear target driver將/dev/sda、/dev/sdb、/dev/sdc的三段連續空間組成了一個大的邏輯塊裝置。Linear target的實現很簡單,它的建立和刪除方法主要完成申請和釋放描述linear target device所用結構的記憶體資源;IO映射處理方法的實現更是簡單,如下代碼所示:

static int linear_map(struct dm_target *ti, struct bio *bio,      union map_info *map_context){struct linear_c *lc = (struct linear_c *) ti->private;bio->bi_bdev = lc->dev->bdev;bio->bi_sector = lc->start + (bio->bi_sector - ti->begin);return 1;}

該映射方法就是將發送給邏輯裝置mapped device的bio請求,根據映射關係以線性方式重新定向到linear target device所表示物理裝置的相應位置,如代碼所示具體實現方法就是修改bio的bi_bdev裝置指標為target device對應的裝置指標,並根據target device的起始地址和該bio請求在mapped device裝置上的位移值改變IO請求開始的扇區號bi_sector,從而完成IO請求的重新導向。其他target driver的實現也都大同小異,按照device mapper所定義的介面規範,結合自己需要的功能進行實現即可,這裡就不一一介紹了,有興趣的讀者可以看核心中具體的target driver代碼。

 

總結

Device Mapper是Linux作業系統中塊裝置一級提供的一種主要對應機制,現在已被多數Linux下的邏輯卷管理器所採用。在該機制下,實現使用者自訂的存 儲資源管理原則變得極其方便。理解device mapper所提供的映射機制,也是進一步理解Linux下一些常見邏輯卷管理器實現的基礎。

本文轉載於http://www.ibm.com/developerworks/cn/linux/l-devmapper/index.html

Linux 核心中的 Device Mapper 機制

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.