為了更好的理解在線調(diào)整大小工作機(jī)制,我們首先需要理解 ext3 和 ext4 文件系統(tǒng)的磁盤布局,對于該功能的實(shí)現(xiàn)來說,這兩個(gè)文件系統(tǒng)在磁盤上的結(jié)構(gòu)是一致的,同時(shí)為了簡化和突出重點(diǎn),對于與在線調(diào)整大小功能不相關(guān)的內(nèi)容我們將不會(huì)介紹。
Ext3 文件系統(tǒng)將其所管理的磁盤或者分區(qū)(引導(dǎo)塊除外)中的塊劃分到不同的塊組中。每個(gè)塊組大小相同,當(dāng)然最后一個(gè)塊組所管理的塊可能會(huì)少一些,其大小在文件系統(tǒng)創(chuàng)建時(shí)決定,主要取決于文件系統(tǒng)的塊大小,對于大小為4k的文件系統(tǒng)塊來說,塊組大小為 168M。每個(gè)塊組都包含一些重要的元數(shù)據(jù)信息,見圖1:
每個(gè)塊組包含一個(gè)塊位圖塊,一個(gè) inode 位圖塊,一個(gè)或多個(gè)塊用于描述 inode 表和用于存儲(chǔ)文件數(shù)據(jù)的數(shù)據(jù)塊,除此之外,還有可能包含超級塊和所有塊組描述符表(取決于塊組號和文件系統(tǒng)創(chuàng)建時(shí)使用的參數(shù))。下面將對這些元數(shù)據(jù)作一些簡要介紹。
塊位圖用于描述該塊組所管理的塊的分配狀態(tài)。如果某個(gè)塊對應(yīng)的位未置位,那么代表該塊未分配,可以用于存儲(chǔ)數(shù)據(jù);否則,代表該塊已經(jīng)用于存儲(chǔ)數(shù)據(jù)或者該塊不能夠使用(譬如該塊物理上不存在)。由于塊位圖僅占一個(gè)塊,因此這也就決定了塊組的大小。
Inode位圖用于描述該塊組所管理的inode的分配狀態(tài)。我們知道inode是用于描述文件的元數(shù)據(jù),每個(gè)inode對應(yīng)文件系統(tǒng)中唯一的一個(gè)號,如果inode位圖中相應(yīng)位置位,那么代表該inode已經(jīng)分配出去;否則可以使用。由于其僅占用一個(gè)塊,因此這也限制了一個(gè)塊組中所能夠使用的最大inode數(shù)量。
Inode表用于存儲(chǔ)inode信息。它占用一個(gè)或多個(gè)塊(為了有效的利用空間,多個(gè)inode存儲(chǔ)在一個(gè)塊中),其大小取決于文件系統(tǒng)創(chuàng)建時(shí)的參數(shù),由于inode位圖的限制,決定了其最大所占用的空間。
超級塊用于存儲(chǔ)文件系統(tǒng)全局的配置參數(shù)(譬如:塊大小,總的塊數(shù)和inode數(shù))和動(dòng)態(tài)信息(譬如:當(dāng)前空閑塊數(shù)和inode數(shù)),其處于文件系統(tǒng)開始位置的1k處,所占大小為1k。為了系統(tǒng)的健壯性,最初每個(gè)塊組都有超級塊和組描述符表(以下將用GDT)的一個(gè)拷貝,但是當(dāng)文件系統(tǒng)很大時(shí),這樣浪費(fèi)了很多塊(尤其是GDT占用的塊多),后來采用了一種稀疏的方式來存儲(chǔ)這些拷貝,只有塊組號是3, 5 ,7的冪的塊組(譬如說1,3,5,7,9,25,49…)才備份這個(gè)拷貝。通常情況下,只有主拷貝(第0塊塊組)的超級塊信息被文件系統(tǒng)使用,其它拷貝只有在主拷貝被破壞的情況下才使用。
GDT用于存儲(chǔ)塊組描述符,其占用一個(gè)或者多個(gè)數(shù)據(jù)塊,具體取決于文件系統(tǒng)的大小。它主要包含塊位圖,inode位圖和inode表位置,當(dāng)前空閑塊數(shù),inode數(shù)以及使用的目錄數(shù)(用于平衡各個(gè)塊組目錄數(shù)),具體定義可以參見ext3_fs.h文件中struct ext3_group_desc。每個(gè)塊組都對應(yīng)這樣一個(gè)描述符,目前該結(jié)構(gòu)占用32個(gè)字節(jié),因此對于塊大小為4k的文件系統(tǒng)來說,每個(gè)塊可以存儲(chǔ)128個(gè)塊組描述符。由于GDT對于定位文件系統(tǒng)的元數(shù)據(jù)非常重要,因此和超級塊一樣,也對其進(jìn)行了備份。GDT在每個(gè)塊組(如果有備份)中內(nèi)容都是一樣的,其所占塊數(shù)也是相同的。從上面的介紹可以看出塊組中的元數(shù)據(jù)譬如塊位圖,inode位圖,inode表其位置不是固定的,當(dāng)然默認(rèn)情況下,文件系統(tǒng)在創(chuàng)建時(shí)其位置在每個(gè)塊組中都是一樣的,如圖2所示(假設(shè)按照稀疏方式存儲(chǔ),且n不是3,5,7的冪):
從圖我們可以看出,每個(gè)塊組大小相同,除了最后一個(gè)塊組可能包含的塊少一些(用虛線和陰影表達(dá))。
由上,文件系統(tǒng)所管理的塊最終都是分派到塊組中進(jìn)行管理的。如果我們希望擴(kuò)大文件系統(tǒng)的大小或者管理更多的物理塊,那么需要將這些待添加的物理塊分配到適當(dāng)?shù)膲K組中進(jìn)行管理。很容易就能夠想到,按照如下三個(gè)步驟一步步添加直到達(dá)到希望的文件系統(tǒng)大小為止:
當(dāng)文件系統(tǒng)在創(chuàng)建時(shí)考慮到將來在線調(diào)整文件系統(tǒng)大小的需要,預(yù)留了一些塊,并且使用一個(gè)inode(其對應(yīng)的inode號為7)來管理這些預(yù)留塊,以免這些塊被分配給其它文件使用了。因此對于步驟3,當(dāng)我們需要新塊來存儲(chǔ)塊組描述符時(shí),我們將從預(yù)留的組描述符塊中分配一個(gè)塊給GDT,由于GDT和預(yù)留的組描述符塊在物理上是相鄰的,因此很容易和原先的GDT塊合并起來。
當(dāng)我們在創(chuàng)建新的塊組時(shí),需要考慮該塊組是否需要存儲(chǔ)超級塊和GDT的備份,如果需要備份,那么拷貝備份,同時(shí)將預(yù)留塊添加到預(yù)留的組描述符inode中,然后增加超級塊的塊組數(shù),空閑塊數(shù)以及空閑inode數(shù),為了保證文件系統(tǒng)的一致性,需要這些操作要么都完成,要么都不完成,它由JBD的事務(wù)機(jī)制來保證。
由于預(yù)留的組描述符有限,當(dāng)我們需要文件系統(tǒng)增加到很大時(shí),預(yù)留塊可能已經(jīng)耗盡,此時(shí)文件系統(tǒng)不能夠增加,除非卸載文件系統(tǒng),采用ext2prepare或者類似工具來預(yù)留塊,但是文件系統(tǒng)在這段時(shí)間內(nèi)將不能夠使用,對于生產(chǎn)系統(tǒng)來說是不可接受的。因此我提交了使用meta block group來進(jìn)行在線增長文件系統(tǒng)的補(bǔ)丁,使得文件系統(tǒng)的增長不再受限于預(yù)留塊的大小和塊組大小。
元塊組的概念其實(shí)很早就出現(xiàn)在內(nèi)核中了,但是直到linux 2.6.21內(nèi)核Ext3和Ext4文件系統(tǒng)online resizing功能并未支持這種新的布局,在Ext4的實(shí)現(xiàn)計(jì)劃中將進(jìn)行支持。元塊組實(shí)際上是可以用一個(gè)組描述符塊來進(jìn)行描述的塊組集,簡單的說,它由一系列塊組組成,同時(shí)這些塊組對應(yīng)的組描述符存儲(chǔ)在一個(gè)塊中。它的出現(xiàn)使得Ext3和Ext4的磁盤布局有了一定的變化,以往超級塊后緊跟的是變長的GDT塊,現(xiàn)在超級塊(決定于是否是3,5,7的冪)和一個(gè)組描述符塊存儲(chǔ)在元塊組的第一個(gè),第二個(gè)和最后一個(gè)塊組的開始處(見圖4)。
在兩種情況下我們可能會(huì)用到這種新布局:
該方法非常高效同時(shí)保留了足夠的冗余以防止異常情況。這種布局中GDT僅占用一個(gè)塊,由于組描述符占用32個(gè)字節(jié),對于塊大小為4k的文件系統(tǒng)來說,每個(gè)元塊組包含128個(gè)塊組,可以管理16GB的空間,而且每個(gè)元塊組中對于組描述符表都有3個(gè)備份。
對比圖4與圖3我們就能夠發(fā)現(xiàn),當(dāng)增加新塊組時(shí),我們不需要給組描述符表預(yù)留空間,而是在當(dāng)前文件系統(tǒng)后面直接添加新的元塊組就可以了。
由于我們在創(chuàng)建文件系統(tǒng)時(shí)無法很好的預(yù)測將來可能的容量,因此文件系統(tǒng)的在線增長功能是非常有必要的。特別是LVM的出現(xiàn)更大的刺激了該需求,請注意本文所談到的文件系統(tǒng)的在線增長并未涉及到如何擴(kuò)大分區(qū)或者磁盤的大小,讀者可以自己先采用lvm或者類似的工具擴(kuò)大分區(qū)或者卷的大小,然后再采用ext2resize或者類似工具來完成ext3或者ext4文件系統(tǒng)的在線增長,其在內(nèi)核中的工作機(jī)制本文已經(jīng)闡述,希望對讀者能夠有所幫助。