微網(wǎng)站 微信app關(guān)鍵詞優(yōu)化
(翻譯 《ZFS On-Disk Specification》, 由于是2006年給出的文檔,與當(dāng)前ZFS系統(tǒng)肯定有很多的不同,但是也是一份相當(dāng)有幫助的ZFS學(xué)習(xí)文檔)
?
1.1 虛擬設(shè)備
?
ZFS存儲池是由一個虛擬設(shè)備集合構(gòu)成的。這里面一共有兩種虛擬設(shè)備:物理虛擬設(shè)備(physical virtual devices,也稱為葉虛擬設(shè)備,leaf vdevs),以及邏輯虛擬設(shè)備(logical virtual devices,也稱為內(nèi)部虛擬設(shè)備,interior vdevs)。物理設(shè)備是一個可寫的塊設(shè)備(比如一個磁盤);邏輯設(shè)備在概念上的一組物理設(shè)備。
?
Vdev是通過一個以物理設(shè)備為葉子節(jié)點(diǎn)的樹來管理的。每一個pool都有一個被稱為“root vdev”的設(shè)備作為這棵樹的根。root節(jié)點(diǎn)的所有直接子節(jié)點(diǎn)(無論是邏輯的還是物理的)都被稱為top-level vdevs。下圖顯示了一個由兩個Mirror構(gòu)成的pool的虛擬設(shè)備樹。第一個Mirror(標(biāo)簽為M1)有兩個磁盤,分別通過“vdev A”和“vdev B”來表示;同樣的,第二個Mirror(標(biāo)簽為M2)也有兩個磁盤,分別通過“vdev C”和“vdev D”來表示。虛擬設(shè)備A,B,C,D都是物理虛擬設(shè)備。“M1”和“M2”都是邏輯虛擬設(shè)備,由于M1和M2都是root的直接子節(jié)點(diǎn),所以都是“top-level vdevs”。
1.2 虛擬設(shè)備標(biāo)簽(Vdev Label)
?
Pool中的每一個物理虛擬設(shè)備都包含一個256K的結(jié)構(gòu)體——vdev_label。這個Label描述了這個設(shè)備以及同一top-level vdev下的其他所有虛擬設(shè)備的信息。例如:對于虛擬設(shè)備C,它的vdev label中包含虛擬設(shè)備C,D以及M2的信息。vdev label的詳細(xì)信息在下一節(jié)中詳細(xì)描述。
?
使用vdev label有兩個目的:它提供訪問pool中信息的入口;另外它還被用于驗(yàn)證pool的完整新和可用性。為了保證vdev label總是合法可用的,我們使用冗余和特殊的更新方式。冗余:pool中的每個物理虛擬設(shè)備都有4個相同的Label,同一個設(shè)備上的4份是完全相同的,不同設(shè)備則是不同的。更新:Label的更新過程中,使用兩階段的事務(wù)來更新,這樣確保虛擬設(shè)備上至少有一個合法的Label。下面詳細(xì)介紹一下Label的冗余和更新技術(shù)。
?
1.2.1 Label<span "="">冗余
?
pool中的每個物理虛擬設(shè)備都有4份相同的Label,在更新過程中,這4份Label每一個都可以用來訪問、驗(yàn)證pool中的數(shù)據(jù)。當(dāng)一個設(shè)備被添加到pool中時,ZFS在設(shè)備的最前面放兩個Label,最后面也放兩個Label。下圖顯示四個Label的分布,N表示設(shè)備的總大小,L0、L1為前兩個Label,L2、L3為后兩個Label。
<span "="">考慮到一般情況下設(shè)備的損壞都是一個連續(xù)的段,所以要將Label放在兩個不同的地方。
?
1.2.2 <span "="">兩階段的事務(wù)性更新
?
Label<span "="">的位置是在設(shè)備加入pool時就設(shè)定好了,因此Label的更新并不能像ZFS對待其他數(shù)據(jù)那樣采用Copy-On-Write技術(shù),也就是說,對Label的更新是直接覆蓋原有的數(shù)據(jù)。但是在寫任何數(shù)據(jù)的過程中都有可能發(fā)生錯誤,為了保證ZFS任何時候總是有一個合法的Label,Label的更新過程被分為兩個階段。第一階段更新偶數(shù)的Label(L0、L2),如果在這一階段中任何時刻發(fā)生了錯誤,奇數(shù)Label(L1、L3)仍然是合法的。在L0、L2更新結(jié)束之后,第二階段則是更新L1、L3。
?
1.3 vdev技術(shù)細(xì)節(jié)
?
vdev label的信息被分成了4部分:8K的空閑空間(Blank Space),8K的boot header信息,112K的name-value鍵值對以及128長度的1K大小的uberblock結(jié)構(gòu)數(shù)組。下圖顯示了L0的擴(kuò)展視圖。
1.3.1 <span "="">空閑空間
?
ZFS支持使用VTOC(Volume Table of Content)和EFI兩種方式來描述磁盤布局。EFI標(biāo)簽并不是Slice的一部分(它有自己的保留空間),VTOC標(biāo)簽必須被寫在Slice0的前8K空間內(nèi),所以為了支持VTOC標(biāo)簽,vdev_label的前8K空間被保留下來防止重寫了VTOC標(biāo)簽。
?
1.3.2 Boot Block Header
?
保留,以后使用。
?
1.3.3 Name-Value Pair List
?
后面的112KB存儲描述這個設(shè)備以及其關(guān)聯(lián)設(shè)備的鍵值對。關(guān)聯(lián)設(shè)備即:同一個top level vdev下的設(shè)備。比如下圖中的灰色圓內(nèi)部的A,B,M1三個設(shè)備。
所有的鍵值對都使用XDR encoded nvlists存儲。關(guān)于更多的XDR encoding或是nvlists請參見 libnvpair(3LIB)和nvlist_free(3NVPAIR)man手冊。以下的鍵值對都被包含在這112K的部分內(nèi)。
vdev_tree遞歸地描述與當(dāng)前vdev相關(guān)的vdev的信息。
每個vdev_tree都包含以下信息:
?
1.3.4 uberblock
?
nvlist之后就是uberblock的數(shù)組。uberblock是訪問pool中數(shù)據(jù)的入口。任意時刻,只有一個uberblock處于激活狀態(tài),所有uberblock中事務(wù)組編號最高且通過SHA-256 checksum驗(yàn)證合法的uberblock為激活的uberblock,它類似于UFS文件系統(tǒng)中的超級塊。
?
為了能夠持續(xù)訪問激活的uberblock,激活的uberblock永遠(yuǎn)不會被覆蓋。所有對uberblock的修改都是通過寫入uberblock數(shù)組中的另外一個元素來完成的。在寫入新的uberblock時,事務(wù)組編號以及時間戳都是在同一個原子性的操作中完成。Uberblock通過循環(huán)的方式寫入。
?
下圖顯示兩個uberblock。
uberblock技術(shù)細(xì)節(jié)
?
uberblock按照機(jī)器的字節(jié)模式存儲。
?
ub_magic
?
用于表示該設(shè)備包含ZFS數(shù)據(jù)。ub_magic的值為0x00bab10c(oo-ba-bloc)
?
ub_version
?
版本號,與前文中鍵值對的版本號意義相同。
?
ub_txg
?
ZFS中所有的寫操作都是通過事務(wù)組來完成的。每個事務(wù)組都有一個對應(yīng)的事務(wù)組編號。ub_txg用來表示寫入這個uberblock的事務(wù)組編號。ub_txg必須大于等于前面鍵值對中的txg編號。
?
ub_guid_sum
?
用來檢驗(yàn)pool中所有設(shè)備的可用性。當(dāng)pool被打開后,ZFS遍歷pool中所有的葉虛擬設(shè)備計(jì)算這些GUID的和,然后與ub_guid_sum進(jìn)行比較,來驗(yàn)證pool中磁盤的可用性。
?
ub_timestamp
?
當(dāng)前uberblock寫入的時間戳(1970年1月1日至今的秒數(shù))
?
ub_rootbp
?
這是一個blkptr結(jié)構(gòu)體,包含了MOS的位置。MOS和blkptr將在后文中詳細(xì)描述。
?
1.4 Boot Block
?
L0和L1之后有一個3.5M的保留空間。