linux內核dm thin pool分析


一、簡介

Docker現在非常火熱,作為docker存儲引擎之一的dm thin pool用的比較多,thin-pool由一個metadata設備和data設備組成,thin的概念就是按需分配數據塊,刪除時也回收數據塊,提高存儲空間利用率。

a)         Dm thin pool創建命令如下:

 

//清零metadata設備的第一個page, why??因為第一個page是thin-pool的superblock, thin pool 內核模塊里是通過判斷superbock是否全0來決定是重新格式化一個thin-pool還是打開已有的thin-pool

dd if=/dev/zero of=$metadata_dev bs=4096 count=1

//創建pool, --table的參數,0為起始扇區,20971520是扇區數,這里的扇區都是512字節來算的,data_block_size --- 數據塊的大小,單位還是扇區,512字節,data_block_size最小為128,最大為2097152

low_water_mark ---當空閑數據塊個數小於water_mark時, dm thin-pool內核模塊會給用戶態daemon發送通知事件。

dmsetup create pool \

b)         --table "0 20971520 thin-pool $metadata_dev $data_dev \

  1. $data_block_size $low_water_mark"

//調用pool設備的message接口,創建thin設備,其中0是thin設備的id, 因為一個pool可以創建N個thin設備,所以需要一個id來區別開這些thin設備。

dmsetup message /dev/mapper/pool 0 "create_thin 0"

//為上面的thin設備創建/dev/dm-x 設備文件。

dmsetup create thin --table "0 2097152 thin /dev/mapper/pool 0"

 

二、thin-pool磁盤布局

a)         data設備

data設備是以data_block_size,如果是128就是128*512=64KB 划分為塊來管理的,data設備存儲的全是數據,沒有任何元數據,所以磁盤布局略。

b)         Meta設備

 

 

 

c)         如圖, meta設備的磁盤布局如上,meta設備的塊大小為4KB, 第一個塊是superblock, 代碼里定義如下:

/*

Little endian on-disk superblock and device details.

*/

struct thin_disk_superblock {

__le32 csum;    /* Checksum of superblock except for this field. */

__le32 flags;

__le64 blocknr; /* This block number, dm_block_t. */

__u8 uuid[16];

__le64 magic;

__le32 version;

__le32 time;

 

__le64 trans_id;

 

/*  

Root held by userspace transactions.

*/

__le64 held_root;

 

__u8 data_space_map_root[SPACE_MAP_ROOT_SIZE];

__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];

 

/*  

2-level btree mapping (dev_id, (dev block, time)) -> data block

*/

__le64 data_mapping_root;

/*  

Device detail root mapping dev_id -> device_details

*/

__le64 device_details_root;

__le32 data_block_size;     /* In 512-byte sectors. */

__le32 metadata_block_size; /* In 512-byte sectors. */

__le64 metadata_nr_blocks;

__le32 compat_flags;

__le32 compat_ro_flags;

__le32 incompat_flags;

} __packed;

d)         重要的字段:

l  Magic: pool設備的magic: 27022010

l  Data_space_map_root: 管理數據塊設備使用空間(使用位圖)的map_root結構

l  Metadata_space_map_root: 管理元數據塊設備使用空間(使用位圖)的map_root結構

l  Data_mapping_root: thin設備從虛擬塊地址到數據塊設備上真實地址的映射btree根塊號

l  Device_details_root: 所有thin設備的信息以btree的方式存到Device_details_root指向的根塊上

l  Data_block_size: 數據設備塊大小 =  data_block_size * 512B

l  Meta_nr_blocks: 元數據設備總塊數, 注元數據設備塊大小為4KB

 

三、尋址

從thin設備的虛擬塊地址到數據設備的實際塊地址,thin-pool的尋址邏輯如下:

a)         先用thin設備的dev_id作為key, 從data_mapping_root指向的塊所包含的btree根節點中,去查找thin設備所對應的數據映射btree的塊號

b)         再用虛擬塊號作為key從thin設備的數據映射btree里去查找實際的value, 查到的value就是數據塊設備上對應的實際塊號

c)         整個過程用偽代碼如下:

block_t find_thin_block(dev_t dev_id, block_t block)

{

block_t thin_map_root;

//從data_map_root btree中以dev_id為key查找對應的值,結果為dev_id對應的thin設備的具體btree根節點所在的塊

thin_map_root = btree_lookup(pool_data_map_root, dev_id);

//從meta設備上讀出根節點

read_block(meta_dev, thin_map_root, &thin_map_tree);

//從btree中以thin的虛擬塊block查找data設備對應的實際塊

return btree_lookup(&thin_map_tree, block);

}

 

四、空間管理

a)         整個thin-pool模塊里,所有的空間管理都是基於btree的。

b)         元數據塊設備自身的空間管理: 這個是通過以Metadata_space_map_root為根塊的btree來管理的,葉子節點存放的是管理空間的位圖,與普通位圖不同的是thin-pool的位圖是一個單元2個位,一共能表示4個狀態: 0為空閑,1為引用計數為1, 2位引用計數為2, 3表示引用計數>2, 需要從另一顆btree里去找實際的引用計數。

c)         數據塊設備空間管理: 跟元數據塊設備自身空間管理類似,數據塊設備也是一顆btree, 葉子節點指向包含管理位圖的塊,當然這些塊都是在元數據設備上的。

d)         空間釋放:當引用bitmap里的引用計數變為0時, 塊就變空閑了,這也就是thin設備的意義所在,不過,這需要上層文件系統discard的支持,thin-pool需要能知道哪些塊上層不需要了,就可以減小位圖的引用計數,釋放塊。

五、總結

thin-pool的存儲格式還是比較清晰和簡單的,總體看上面的布局結構圖就已經很清晰了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM