接着上一篇博文,繼續分析Ext4磁盤布局中的元數據。
1.7 超級塊
超級塊記錄整個文件系統的大量信息,如數據塊個數、inode個數、支持的特性、管理信息,等待。
如果設置sparse_super特性標志,超級塊和塊組描述符表的冗余備份僅存放在編號為0或3、5、7的冪次方的塊組中。如果未設置sparse_super特性標志,冗余備份存在與所有的塊組中。以下是2.6.32.18內核中對Ext4超級塊的描述:
3.0的內核中,Ext4的超級塊加入了以下相關元數據:快照、文件系統錯誤處理相關、掛載選項、配額文件inode、超級塊校驗和等,見下圖。目前沒有深入研究這些新的元數據。
1.8 塊組描述符
一個塊組中,具有固定位置的數據結構是超級塊和塊組描述符。其他數據結構位置都可以不固定。Flex_bg機制使用這個性質將幾個塊組聚合成一個flex塊組,將flex_bg中所有位圖和inode 表放到flex_bg的第一個塊組中。詳細情況可以參考我的上一篇Ext4分析博文的Flexible 塊組(flex_bg)部分。
如果設置了meta_bg特性標志,幾個塊組結合成一個meta group。在meta_bg的情況下,在meta group中的第一個和最后兩個塊組中僅包含meta group中的塊組的塊組描述符。Flex_bg和Meta_bg互斥因而不能共同出現。
1.9 數據塊位圖與inode位圖
數據塊位圖跟蹤塊組中數據塊使用情況。Inode位圖跟蹤塊組中Inode使用情況。每個位圖一個數據塊,每一位用0或1表示一個塊組中數據塊或inode表中inode的使用情況。如果一個數據塊大小是4KB的話,那一個位圖塊可以表示4*1024*8個數據塊的使用情況,這也是單個塊組具有的最大數據塊個數。這樣可以算出一個塊組大小是128MB。當然一個位圖塊也可以表示4*1024*8個inode的使用情況,但是實際上一個塊組中即使存滿了文件,也不會用到這么多的inode,因為實際系統中基本不會出現所有文件大小都小於等於1個數據塊大小的情況。實際上一個塊組中有多少個inode,在塊組描述符中是確定的,在文件系統格式化過程中也會看到這個數值,如果沒記錯的話,大概是每4個還是8個數據塊分配一個inode空間。
1.10 Inode表
為了找到與一個文件相關的信息,必須遍歷目錄文件找到與文件相關的目錄項,然后加載inode找到該文件的元數據。Ext4在目錄項中用一位存儲了文件類型(通常存儲在inode中)的拷貝,這對性能提升有益。Inode表的大小為ext4_super_block.s_inode_size * ext4_super_block.s_inodes_per_group Bytes。
Ext4的inode的數據結構大小為156 bytes,但是Ext4的標准inode的大小是256 bytes。
1.11 查找inode
每個塊組包含ext4_super_block.s_inodes_per_group個inodes。因為0號inode不存在,可以通過如下的算式計算inode所在的塊組:
bg=(inode_num -1)/ ext4_super_block.s_inodes_per_group
inode在塊組中inode表中的索引index可以通過如下的算式計算:
index=(inode_num -1) % ext4_super_block.s_inodes_per_group
inode在inode表中的地址偏移為:
offset=index * ext4_super_block.s_inode _size
1.12 inode.i_block0[]s的內容
取決於文件類型,inode.i_blocks[]使用的方式不同。一般來說,常規文件和目錄用inode.i_blocks[]作為文件數據塊索引信息,特殊文件將inode.i_blocks[]用於特殊用途。常規文件用inode.i_blocks[]作為文件數據塊索引信息的三級索引結構會在后面直接、間接塊地址中詳細介紹。
1.13 符號鏈接
如果符號鏈接的目標字符串長度小於60字節,那么就將其存儲在inode.i_blocks[]中,inode中inode.i_blocks[]占據的大小剛好是60KB。這里要注意到的是,有些文件其內容是跟文件的元數據放在一起的,因而就沒有了數據塊。也就是說不是每個文件數據都必然占據着一個數據塊。
1.14 直接/間接塊地址
Ext2/Ext3中數據塊映射方式如下表
1.15 Extent 樹
Ext4中用extent樹代替了邏輯塊映射。使用extents,用一個struct ext4_extent結構就可以映射多個數據塊,減少元數據塊的使用。如果設置了flex_bg,甚至可以用一個extent分配一個非常大的文件。使用extent特性,inode必須設置extents flag。
Extents以樹的方式安排。Extent樹的每個節點都以一個ext4_extent_header開頭,如果節點是內部節點(ext4_extent_header.eh_depth>0),ext4_extent_header后面緊跟的是ext4_extent_header .eh_entries個索引項struct ext4_extent_idx,每個索引項指向該extent樹中一個包含更多的節點的數據塊。如果節點是葉子節點(ext4_extent_header.eh_depth==0),ext4_extent_header后面緊跟的是ext4_extent_header .eh_entries個struct ext4_extent數據結構。這些ext4_extent結構指向文件數據塊。Extent樹的根結點存儲在inode.i_blocks中,可以存儲文件的前4個extents而不需額外的元數據塊。
ext4_extent_header:
struct ext4_extent_idx:extent樹的內部節點,也稱為索引節點。
ext4_extent:extent樹的葉子節點。
1.16 Extent樹數據塊校驗和:可能加入的新元數據
由於extent樹的根在inode中,因而Extent樹數據塊指extent樹的除根據節點外的所有內部節點和葉子節點。Extent的樹根節點和葉子節點的數據塊中存儲完xt4_extent_idx和xt4_extent數據結構后至少會留下4 ((2^x%12)>=4) bytes的空間。因而可以加入一個結構struct ext4_extent_tail,其中存儲32位的校驗和。位於inode中的4個extents無需校驗和,因為inode已經做了校驗和。
1.17 目錄項
Ext4文件系統中,一個目錄差不多是一個平面文件,映射任意長度的字符串到文件系統中的一個inode。文件系統中存在多個目錄項引用同一個inode——硬鏈接,這也是硬鏈接不能鏈接其他文件系統中的文件的原因。
1.18 線性(經典)目錄
缺省地,目錄文件中包含一個線性的目錄項數組。未使用的目錄項標記為inode =0。Ext4文件系統默認地使用struct ext4_dir_entry_2記錄目錄項,除非沒有設置filetype特性標志。在沒有設置filetype特性標志的情況下,使用struct ext4_dir_entry記錄目錄項。