Btrfs 簡(jiǎn)介
文件系統(tǒng)似乎是內(nèi)核中比較穩(wěn)定的部分,多年來(lái),人們一直使用 ext2/3,ext 文件系統(tǒng)以其卓越的穩(wěn)定性成為了事實(shí)上的 Linux 標(biāo)準(zhǔn)文件系統(tǒng)。近年來(lái) ext2/3 暴露出了一些擴(kuò)展性問題,于是便催生了 ext4 。在 2008 年發(fā)布的 Linux2.6.19 內(nèi)核中集成了 ext4 的 dev 版本。 2.6.28 內(nèi)核發(fā)布時(shí),ext4 結(jié)束了開發(fā)版,開始接受用戶的使用。似乎 ext 就將成為 Linux 文件系統(tǒng)的代名詞。然而當(dāng)您閱讀很多有關(guān) ext4 的文章時(shí),會(huì)發(fā)現(xiàn)都不約而同地提到了 btrfs,并認(rèn)為 ext4 將是一個(gè)過(guò)渡的文件系統(tǒng)。 ext4 的作者 Theodore Tso 也盛贊 btrfs 并認(rèn)為 btrfs 將成為下一代 Linux 標(biāo)準(zhǔn)文件系統(tǒng)。 Oracle,IBM, Intel 等廠商也對(duì) btrfs 表現(xiàn)出了極大的關(guān)注,投入了資金和人力。為什么 btrfs 如此受人矚目呢。這便是本文首先想探討的問題。
Kevin Bowling[1] 有一篇介紹各種文件系統(tǒng)的文章,在他看來(lái),ext2/3 等文件系統(tǒng)屬于“古典時(shí)期”。文件系統(tǒng)的新時(shí)代是 2005 年由 Sun 公司的 ZFS 開創(chuàng)的。 ZFS 代表” last word in file system ”,意思是此后再也不需要開發(fā)其他的文件系統(tǒng)了。 ZFS 的確帶來(lái)了很多嶄新的觀念,對(duì)文件系統(tǒng)來(lái)講是一個(gè)劃時(shí)代的作品。
如果您比較 btrfs 的特性,將會(huì)發(fā)現(xiàn) btrfs 和 ZFS 非常類似。也許我們可以認(rèn)為 btrfs 就是 Linux 社區(qū)對(duì) ZFS 所作出的回應(yīng)。從此往后在 Linux 中也終于有了一個(gè)可以和 ZFS 相媲美的文件系統(tǒng)。
btrfs 的特性
您可以在 btrfs 的主頁(yè)上 [2] 看到 btrfs 的特性列表。我自作主張,將那張列表分成了四大部分。
首先是擴(kuò)展性 (scalability) 相關(guān)的特性,btrfs 最重要的設(shè)計(jì)目標(biāo)是應(yīng)對(duì)大型機(jī)器對(duì)文件系統(tǒng)的擴(kuò)展性要求。 Extent,B-Tree 和動(dòng)態(tài) inode 創(chuàng)建等特性保證了 btrfs 在大型機(jī)器上仍有卓越的表現(xiàn),其整體性能而不會(huì)隨著系統(tǒng)容量的增加而降低。
其次是數(shù)據(jù)一致性 (data integrity) 相關(guān)的特性。系統(tǒng)面臨不可預(yù)料的硬件故障,Btrfs 采用 COW 事務(wù)技術(shù)來(lái)保證文件系統(tǒng)的一致性。 btrfs 還支持 checksum,避免了 silent corrupt 的出現(xiàn)。而傳統(tǒng)文件系統(tǒng)則無(wú)法做到這一點(diǎn)。
第三是和多設(shè)備管理相關(guān)的特性。 Btrfs 支持創(chuàng)建快照 (snapshot),和克隆 (clone) 。 btrfs 還能夠方便的管理多個(gè)物理設(shè)備,使得傳統(tǒng)的卷管理軟件變得多余。
最后是其他難以歸類的特性。這些特性都是比較先進(jìn)的技術(shù),能夠顯著提高文件系統(tǒng)的時(shí)間 / 空間性能,包括延遲分配,小文件的存儲(chǔ)優(yōu)化,目錄索引等。
擴(kuò)展性相關(guān)的特性
B-Tree
btrfs 文件系統(tǒng)中所有的 metadata 都由 BTree 管理。使用 BTree 的主要好處在于查找,插入和刪除操作都很高效。可以說(shuō) BTree 是 btrfs 的核心。
一味地夸耀 BTree 很好很高效也許并不能讓人信服,但假如稍微花費(fèi)一點(diǎn)兒時(shí)間看看 ext2/3 中元數(shù)據(jù)管理的實(shí)現(xiàn)方式,便可以反襯出 BTree 的優(yōu)點(diǎn)。
妨礙 ext2/3 擴(kuò)展性的一個(gè)問題來(lái)自其目錄的組織方式。目錄是一種特殊的文件,在 ext2/3 中其內(nèi)容是一張線性表格。如圖 1-1 所示 [6]:
圖 1. ext2 directory [6]
圖 1 展示了一個(gè) ext2 目錄文件的內(nèi)容,該目錄中包含四個(gè)文件。分別是 "home1","usr","oldfile" 和 "sbin" 。如果需要在該目錄中查找目錄 sbin,ext2 將遍歷前三項(xiàng),直至找到 sbin 這個(gè)字符串為止。
這種結(jié)構(gòu)在文件個(gè)數(shù)有限的情況下是比較直觀的設(shè)計(jì),但隨著目錄下文件數(shù)的增加,查找文件的時(shí)間將線性增長(zhǎng)。 2003 年,ext3 設(shè)計(jì)者開發(fā)了目錄索引技術(shù),解決了這個(gè)問題。目錄索引使用的數(shù)據(jù)結(jié)構(gòu)就是 BTree 。如果同一目錄下的文件數(shù)超過(guò) 2K,inode 中的 i_data 域指向一個(gè)特殊的 block 。在該 block 中存儲(chǔ)著目錄索引 BTree 。 BTree 的查找效率高于線性表,
但為同一個(gè)元數(shù)據(jù)設(shè)計(jì)兩種數(shù)據(jù)結(jié)構(gòu)總是不太優(yōu)雅。在文件系統(tǒng)中還有很多其他的元數(shù)據(jù),用統(tǒng)一的 BTree 管理是非常簡(jiǎn)單而優(yōu)美的設(shè)計(jì)。
Btrfs 內(nèi)部所有的元數(shù)據(jù)都采用 BTree 管理,擁有良好的可擴(kuò)展性。 btrfs 內(nèi)部不同的元數(shù)據(jù)由不同的 Tree 管理。在 superblock 中,有指針指向這些 BTree 的根。如圖 2 所示:
圖 2. btrfs btree
FS Tree 管理文件相關(guān)的元數(shù)據(jù),如 inode,dir 等; Chunk tree 管理設(shè)備,每一個(gè)磁盤設(shè)備都在 Chunk Tree 中有一個(gè) item ; Extent Tree 管理磁盤空間分配,btrfs 每分配一段磁盤空間,便將該磁盤空間的信息插入到 Extent tree 。查詢 Extent Tree 將得到空閑的磁盤空間信息; Tree of tree root 保存很多 BTree 的根節(jié)點(diǎn)。比如用戶每建立一個(gè)快照,btrfs 便會(huì)創(chuàng)建一個(gè) FS Tree 。為了管理所有的樹,btrfs 采用 Tree of tree root 來(lái)保存所有樹的根節(jié)點(diǎn); checksum Tree 保存數(shù)據(jù)塊的校驗(yàn)和。
基于 Extent 的文件存儲(chǔ)
現(xiàn)代很多文件系統(tǒng)都采用了 extent 替代 block 來(lái)管理磁盤。 Extent 就是一些連續(xù)的 block,一個(gè) extent 由起始的 block 加上長(zhǎng)度進(jìn)行定義。
Extent 能有效地減少元數(shù)據(jù)開銷。為了進(jìn)一步理解這個(gè)問題,我們還是看看 ext2 中的反面例子。
ext2/3 以 block 為基本單位,將磁盤劃分為多個(gè) block 。為了管理磁盤空間,文件系統(tǒng)需要知道哪些 block 是空閑的。 Ext 使用 bitmap 來(lái)達(dá)到這個(gè)目的。 Bitmap 中的每一個(gè) bit 對(duì)應(yīng)磁盤上的一個(gè) block,當(dāng)相應(yīng) block 被分配后,bitmap 中的相應(yīng) bit 被設(shè)置為 1 。這是很經(jīng)典也很清晰的一個(gè)設(shè)計(jì),但不幸的是當(dāng)磁盤容量變大時(shí),bitmap 自身所占用的空間也將變大。這就導(dǎo)致了擴(kuò)展性問題,隨著存儲(chǔ)設(shè)備容量的增加,bitmap 這個(gè)元數(shù)據(jù)所占用的空間也隨之增加。而人們希望無(wú)論磁盤容量如何增加,元數(shù)據(jù)不應(yīng)該隨之線形增加,這樣的設(shè)計(jì)才具有可擴(kuò)展性。
下圖比較了 block 和 extent 的區(qū)別:
圖 3. 采用 extent 的 btrfs 和采用 bitmap 的 ext2/3
在 ext2/3 中,10 個(gè) block 需要 10 個(gè) bit 來(lái)表示;在 btrfs 中則只需要一個(gè)元數(shù)據(jù)。對(duì)于大文件,extent 表現(xiàn)出了更加優(yōu)異的管理性能。
Extent 是 btrfs 管理磁盤空間的最小單位,由 extent tree 管理。 Btrfs 分配 data 或 metadata 都需要查詢 extent tree 以便獲得空閑空間的信息。
動(dòng)態(tài) inode 分配
為了理解動(dòng)態(tài) inode 分配,還是需要借助 ext2/3 。下表列舉了 ext2 文件系統(tǒng)的限制:
表 1. ext2 限制
圖 4 顯示了 ext2 的磁盤布局:
圖 4. ext2 layout
在 ext2 中 inode 區(qū)是被預(yù)先固定分配的,且大小固定,比如一個(gè) 100G 的分區(qū)中,inode table 區(qū)中只能存放 131072 個(gè) inode,這就意味著不可能創(chuàng)建超過(guò) 131072 個(gè)文件,因?yàn)槊恳粋€(gè)文件都必須有一個(gè)唯一的 inode 。
為了解決這個(gè)問題,必須動(dòng)態(tài)分配 inode 。每一個(gè) inode 只是 BTree 中的一個(gè)節(jié)點(diǎn),用戶可以無(wú)限制地任意插入新的 inode,其物理存儲(chǔ)位置是動(dòng)態(tài)分配的。所以 btrfs 沒有對(duì)文件個(gè)數(shù)的限制。
針對(duì) SSD 的優(yōu)化支持
SSD 是固態(tài)存儲(chǔ) Solid State Disk 的簡(jiǎn)稱。在過(guò)去的幾十年中,CPU/RAM 等器件的發(fā)展始終遵循著摩爾定律,但硬盤 HDD 的讀寫速率卻始終沒有飛躍式的發(fā)展。磁盤 IO 始終是系統(tǒng)性能的瓶頸。
SSD 采用 flash memory 技術(shù),內(nèi)部沒有磁盤磁頭等機(jī)械裝置,讀寫速率大幅度提升。 flash memory 有一些不同于 HDD 的特性。 flash 在寫數(shù)據(jù)之前必須先執(zhí)行擦除操作;其次,flash 對(duì)擦除操作的次數(shù)有一定的限制,在目前的技術(shù)水平下,對(duì)同一個(gè)數(shù)據(jù)單元最多能進(jìn)行約 100 萬(wàn)次擦除操作,因此,為了延長(zhǎng) flash 的壽命,應(yīng)該將寫操作平均到整個(gè) flash 上。
SSD 在硬件內(nèi)部的微代碼中實(shí)現(xiàn)了 wear leveling 等分布寫操作的技術(shù),因此系統(tǒng)無(wú)須再使用特殊的 MTD 驅(qū)動(dòng)和 FTL 層。雖然 SSD 在硬件層面做了很多努力,但畢竟還是有限。文件系統(tǒng)針對(duì) SSD 的特性做優(yōu)化不僅能提高 SSD 的使用壽命,而且能提高讀寫性能。 Btrfs 是少數(shù)專門對(duì) SSD 進(jìn)行優(yōu)化的文件系統(tǒng)。 btrfs 用戶可以使用 mount 參數(shù)打開對(duì) SSD 的特殊優(yōu)化處理。
Btrfs 的 COW 技術(shù)從根本上避免了對(duì)同一個(gè)物理單元的反復(fù)寫操作。如果用戶打開了 SSD 優(yōu)化選項(xiàng),btrfs 將在底層的塊空間分配策略上進(jìn)行優(yōu)化:將多次磁盤空間分配請(qǐng)求聚合成一個(gè)大小為 2M 的連續(xù)的塊。大塊連續(xù)地址的 IO 能夠讓固化在 SSD 內(nèi)部的微代碼更好的進(jìn)行讀寫優(yōu)化,從而提高 IO 性能。
數(shù)據(jù)一致性相關(guān)的特性
COW 事務(wù)
理解 COW 事務(wù),必須首先理解 COW 和事務(wù)這兩個(gè)術(shù)語(yǔ)。
什么是 COW?
所謂 COW,即每次寫磁盤數(shù)據(jù)時(shí),先將更新數(shù)據(jù)寫入一個(gè)新的 block,當(dāng)新數(shù)據(jù)寫入成功之后,再更新相關(guān)的數(shù)據(jù)結(jié)構(gòu)指向新 block 。
什么是事務(wù)?
COW 只能保證單一數(shù)據(jù)更新的原子性。但文件系統(tǒng)中很多操作需要更新多個(gè)不同的元數(shù)據(jù),比如創(chuàng)建文件需要修改以下這些元數(shù)據(jù):
修改 extent tree,分配一段磁盤空間
創(chuàng)建一個(gè)新的 inode,并插入 FS Tree 中
增加一個(gè)目錄項(xiàng),插入到 FS Tree 中
任何一個(gè)步驟出錯(cuò),文件便不能創(chuàng)建成功,因此可以定義為一個(gè)事務(wù)。
下面將演示一個(gè) COW 事務(wù)。
A 是 FS Tree 的根節(jié)點(diǎn),新的 inode 的信息將被插入節(jié)點(diǎn) C 。首先,btrfs 將 inode 插入一個(gè)新分配的 block C ’中,并修改上層節(jié)點(diǎn) B,使其指向新的 block C ’;修改 B 也將引發(fā) COW,以此類推,引發(fā)一個(gè)連鎖反應(yīng),直到最頂層的 Root A 。當(dāng)整個(gè)過(guò)程結(jié)束后,新節(jié)點(diǎn) A ’變成了 FS Tree 的根。但此時(shí)事務(wù)并未結(jié)束,superblock 依然指向 A 。
圖 5. COW transaction 1
接下來(lái),修改目錄項(xiàng)(E 節(jié)點(diǎn)),同樣引發(fā)這一過(guò)程,從而生成新的根節(jié)點(diǎn) A ’’。
圖 6. COW transaction 2
此時(shí),inode 和目錄項(xiàng)都已經(jīng)寫入磁盤,可以認(rèn)為事務(wù)已經(jīng)結(jié)束。 btrfs 修改 superblock,使其指向 A ’’,如下圖所示:
圖 7. COW transaction 3
COW 事務(wù)能夠保證文件系統(tǒng)的一致性,并且系統(tǒng) Reboot 之后不需要執(zhí)行 fsck 。因?yàn)?superblock 要么指向新的 A ’’,要么指向 A,無(wú)論哪個(gè)都是一致的數(shù)據(jù)。
Checksum
Checksum 技術(shù)保證了數(shù)據(jù)的可靠性,避免 silent corruption 現(xiàn)象。由于硬件原因,從磁盤上讀出的數(shù)據(jù)會(huì)出錯(cuò)。比如 block A 中存放的數(shù)據(jù)為 0x55,但讀取出來(lái)的數(shù)據(jù)變是 0x54,因?yàn)樽x取操作并未報(bào)錯(cuò),所以這種錯(cuò)誤不能被上層軟件所察覺。
解決這個(gè)問題的方法是保存數(shù)據(jù)的校驗(yàn)和,在讀取數(shù)據(jù)后檢查校驗(yàn)和。如果不符合,便知道數(shù)據(jù)出現(xiàn)了錯(cuò)誤。
ext2/3 沒有校驗(yàn)和,對(duì)磁盤完全信任。而不幸的是,磁盤的錯(cuò)誤始終存在,不僅發(fā)生在廉價(jià)的 IDE 硬盤上,昂貴的 RAID 也存在 silent corruption 問題。而且隨著存儲(chǔ)網(wǎng)絡(luò)的發(fā)展,即使數(shù)據(jù)從磁盤讀出正確,也很難確保能夠安全地穿越網(wǎng)絡(luò)設(shè)備。
btrfs 在讀取數(shù)據(jù)的同時(shí)會(huì)讀取其相應(yīng)的 checksum 。如果最終從磁盤讀取出來(lái)的數(shù)據(jù)和 checksum 不相同,btrfs 會(huì)首先嘗試讀取數(shù)據(jù)的鏡像備份,如果數(shù)據(jù)沒有鏡像備份,btrfs 將返回錯(cuò)誤。寫入磁盤數(shù)據(jù)之前,btrfs 計(jì)算數(shù)據(jù)的 checksum 。然后將 checksum 和數(shù)據(jù)同時(shí)寫入磁盤。
Btrfs 采用單獨(dú)的 checksum Tree 來(lái)管理數(shù)據(jù)塊的校驗(yàn)和,把 checksum 和 checksum 所保護(hù)的數(shù)據(jù)塊分離開,從而提供了更嚴(yán)格的保護(hù)。假如在每個(gè)數(shù)據(jù) block 的 header 中加入一個(gè)域保存 checksum,那么這個(gè)數(shù)據(jù) block 就成為一個(gè)自己保護(hù)自己的結(jié)構(gòu)。這種結(jié)構(gòu)下有一種錯(cuò)誤無(wú)法檢測(cè)出來(lái),比如本來(lái)文件系統(tǒng)打算從磁盤上讀 block A,但返回了 block B,由于 checksum 在 block 內(nèi)部,因此 checksum 依舊是正確的。 btrfs 采用 checksum tree 來(lái)保存數(shù)據(jù)塊的 checksum,避免了上述問題。
Btrfs 采用 crc32 算法計(jì)算 checksum,在將來(lái)的開發(fā)中會(huì)支持其他類型的校驗(yàn)算法。為了提高效率,btrfs 將寫數(shù)據(jù)和 checksum 的工作分別用不同的內(nèi)核線程并行執(zhí)行。
多設(shè)備管理相關(guān)的特性
每個(gè) Unix 管理員都曾面臨為用戶和各種應(yīng)用分配磁盤空間的任務(wù)。多數(shù)情況下,人們無(wú)法事先準(zhǔn)確地估計(jì)一個(gè)用戶或者應(yīng)用在未來(lái)究竟需要多少磁盤空間。磁盤空間被用盡的情況經(jīng)常發(fā)生,此時(shí)人們不得不試圖增加文件系統(tǒng)空間。傳統(tǒng)的 ext2/3 無(wú)法應(yīng)付這種需求。
很多卷管理軟件被設(shè)計(jì)出來(lái)滿足用戶對(duì)多設(shè)備管理的需求,比如 LVM 。 Btrfs 集成了卷管理軟件的功能,一方面簡(jiǎn)化了用戶命令;另一方面提高了效率。
多設(shè)備管理
Btrfs 支持動(dòng)態(tài)添加設(shè)備。用戶在系統(tǒng)中增加新的磁盤之后,可以使用 btrfs 的命令將該設(shè)備添加到文件系統(tǒng)中。
為了靈活利用設(shè)備空間,Btrfs 將磁盤空間劃分為多個(gè) chunk 。每個(gè) chunk 可以使用不同的磁盤空間分配策略。比如某些 chunk 只存放 metadata,某些 chunk 只存放數(shù)據(jù)。一些 chunk 可以配置為 mirror,而另一些 chunk 則可以配置為 stripe 。這為用戶提供了非常靈活的配置可能性。
Subvolume
Subvolume 是很優(yōu)雅的一個(gè)概念。即把文件系統(tǒng)的一部分配置為一個(gè)完整的子文件系統(tǒng),稱之為 subvolume 。
采用 subvolume,一個(gè)大的文件系統(tǒng)可以被劃分為多個(gè)子文件系統(tǒng),這些子文件系統(tǒng)共享底層的設(shè)備空間,在需要磁盤空間時(shí)便從底層設(shè)備中分配,類似應(yīng)用程序調(diào)用 malloc() 分配內(nèi)存一樣??梢苑Q之為存儲(chǔ)池。這種模型有很多優(yōu)點(diǎn),比如可以充分利用 disk 的帶寬,可以簡(jiǎn)化磁盤空間的管理等。
所謂充分利用 disk 的帶寬,指文件系統(tǒng)可以并行讀寫底層的多個(gè) disk,這是因?yàn)槊總€(gè)文件系統(tǒng)都可以訪問所有的 disk 。傳統(tǒng)的文件系統(tǒng)不能共享底層的 disk 設(shè)備,無(wú)論是物理的還是邏輯的,因此無(wú)法做到并行讀寫。
所謂簡(jiǎn)化管理,是相對(duì)于 LVM 等卷管理軟件而言。采用存儲(chǔ)池模型,每個(gè)文件系統(tǒng)的大小都可以自動(dòng)調(diào)節(jié)。而使用 LVM,如果一個(gè)文件系統(tǒng)的空間不夠了,該文件系統(tǒng)并不能自動(dòng)使用其他磁盤設(shè)備上的空閑空間,而必須使用 LVM 的管理命令手動(dòng)調(diào)節(jié)。
Subvolume 可以作為根目錄掛載到任意 mount 點(diǎn)。 subvolume 是非常有趣的一個(gè)特性,有很多應(yīng)用。
假如管理員只希望某些用戶訪問文件系統(tǒng)的一部分,比如希望用戶只能訪問 /var/test/ 下面的所有內(nèi)容,而不能訪問 /var/ 下面其他的內(nèi)容。那么便可以將 /var/test 做成一個(gè) subvolume 。 /var/test 這個(gè) subvolume 便是一個(gè)完整的文件系統(tǒng),可以用 mount 命令掛載。比如掛載到 /test 目錄下,給用戶訪問 /test 的權(quán)限,那么用戶便只能訪問 /var/test 下面的內(nèi)容了。
快照和克隆
快照是對(duì)文件系統(tǒng)某一時(shí)刻的完全備份。建立快照之后,對(duì)文件系統(tǒng)的修改不會(huì)影響快照中的內(nèi)容。這是非常有用的一種技術(shù)。
比如數(shù)據(jù)庫(kù)備份。假如在時(shí)間點(diǎn) T1,管理員決定對(duì)數(shù)據(jù)庫(kù)進(jìn)行備份,那么他必須先停止數(shù)據(jù)庫(kù)。備份文件是非常耗時(shí)的操作,假如在備份過(guò)程中某個(gè)應(yīng)用程序修改了數(shù)據(jù)庫(kù)的內(nèi)容,那么將無(wú)法得到一個(gè)一致性的備份。因此在備份過(guò)程中數(shù)據(jù)庫(kù)服務(wù)必須停止,對(duì)于某些關(guān)鍵應(yīng)用這是不能允許的。
利用快照,管理員可以在時(shí)間點(diǎn) T1 將數(shù)據(jù)庫(kù)停止,對(duì)系統(tǒng)建立一個(gè)快照。這個(gè)過(guò)程一般只需要幾秒鐘,然后就可以立即重新恢復(fù)數(shù)據(jù)庫(kù)服務(wù)。此后在任何時(shí)候,管理員都可以對(duì)快照的內(nèi)容進(jìn)行備份操作,而此時(shí)用戶對(duì)數(shù)據(jù)庫(kù)的修改不會(huì)影響快照中的內(nèi)容。當(dāng)備份完成,管理員便可以刪除快照,釋放磁盤空間。
快照一般是只讀的,當(dāng)系統(tǒng)支持可寫快照,那么這種可寫快照便被稱為克隆??寺〖夹g(shù)也有很多應(yīng)用。比如在一個(gè)系統(tǒng)中安裝好基本的軟件,然后為不同的用戶做不同的克隆,每個(gè)用戶使用自己的克隆而不會(huì)影響其他用戶的磁盤空間。非常類似于虛擬機(jī)。
Btrfs 支持 snapshot 和 clone 。這個(gè)特性極大地增加了 btrfs 的使用范圍,用戶不需要購(gòu)買和安裝昂貴并且使用復(fù)雜的卷管理軟件。下面簡(jiǎn)要介紹一下 btrfs 實(shí)現(xiàn)快照的基本原理。
如前所述 Btrfs 采用 COW 事務(wù)技術(shù),從圖 1-10 可以看到,COW 事務(wù)結(jié)束后,如果不刪除原來(lái)的節(jié)點(diǎn) A,C,E,那么 A,C,E,D,F 依然完整的表示著事務(wù)開始之前的文件系統(tǒng)。這就是 snapshot 實(shí)現(xiàn)的基本原理。
Btrfs 采用引用計(jì)數(shù)決定是否在事務(wù) commit 之后刪除原有節(jié)點(diǎn)。對(duì)每一個(gè)節(jié)點(diǎn),btrfs 維護(hù)一個(gè)引用計(jì)數(shù)。當(dāng)該節(jié)點(diǎn)被別的節(jié)點(diǎn)引用時(shí),該計(jì)數(shù)加一,當(dāng)該節(jié)點(diǎn)不再被別的節(jié)點(diǎn)引用時(shí),該計(jì)數(shù)減一。當(dāng)引用計(jì)數(shù)歸零時(shí),該節(jié)點(diǎn)被刪除。對(duì)于普通的 Tree Root, 引用計(jì)數(shù)在創(chuàng)建時(shí)被加一,因?yàn)?Superblock 會(huì)引用這個(gè) Root block 。很明顯,初始情況下這棵樹中的所有其他節(jié)點(diǎn)的引用計(jì)數(shù)都為一。當(dāng) COW 事務(wù) commit 時(shí),superblock 被修改指向新的 Root A ’’,原來(lái) Root block A 的引用計(jì)數(shù)被減一,變?yōu)榱?,因?A 節(jié)點(diǎn)被刪除。 A 節(jié)點(diǎn)的刪除會(huì)引發(fā)其子孫節(jié)點(diǎn)的引用計(jì)數(shù)也減一,圖 1-10 中的 B,C 節(jié)點(diǎn)的引用計(jì)數(shù)因此也變成了 0,從而被刪除。 D,E 節(jié)點(diǎn)在 COW 時(shí),因?yàn)楸?A ’’所引用,計(jì)數(shù)器加一,因此計(jì)數(shù)器這時(shí)并未歸零,從而沒有被刪除。
創(chuàng)建 Snapshot 時(shí),btrfs 將的 Root A 節(jié)點(diǎn)復(fù)制到 sA,并將 sA 的引用計(jì)數(shù)設(shè)置為 2 。在事務(wù) commit 的時(shí)候,sA 節(jié)點(diǎn)的引用計(jì)數(shù)不會(huì)歸零,從而不會(huì)被刪除,因此用戶可以繼續(xù)通過(guò) Root sA 訪問 snapshot 中的文件。
圖 8. Snapshot
軟件 RAID
RAID 技術(shù)有很多非常吸引人的特性,比如用戶可以將多個(gè)廉價(jià)的 IDE 磁盤組合為 RAID0 陣列,從而變成了一個(gè)大容量的磁盤; RAID1 和更高級(jí)的 RAID 配置還提供了數(shù)據(jù)冗余保護(hù),從而使得存儲(chǔ)在磁盤中的數(shù)據(jù)更加安全。
Btrfs 很好的支持了軟件 RAID,RAID 種類包括 RAID0,RAID1 和 RAID10.
Btrfs 缺省情況下對(duì) metadata 進(jìn)行 RAID1 保護(hù)。前面已經(jīng)提及 btrfs 將設(shè)備空間劃分為 chunk,一些 chunk 被配置為 metadata,即只存儲(chǔ) metadata 。對(duì)于這類 chunk,btrfs 將 chunk 分成兩個(gè)條帶,寫 metadata 的時(shí)候,會(huì)同時(shí)寫入兩個(gè)條帶內(nèi),從而實(shí)現(xiàn)對(duì) metadata 的保護(hù)。
其他特性
Btrfs 主頁(yè)上羅列的其他特性不容易分類,這些特性都是現(xiàn)代文件系統(tǒng)中比較先進(jìn)的技術(shù),能夠提高文件系統(tǒng)的時(shí)間或空間效率。
Delay allocation
延遲分配技術(shù)能夠減少磁盤碎片。在 Linux 內(nèi)核中,為了提高效率,很多操作都會(huì)延遲。
在文件系統(tǒng)中,小塊空間頻繁的分配和釋放會(huì)造成碎片。延遲分配是這樣一種技術(shù),當(dāng)用戶需要磁盤空間時(shí),先將數(shù)據(jù)保存在內(nèi)存中。并將磁盤分配需求發(fā)送給磁盤空間分配器,磁盤空間分配器并不立即分配真正的磁盤空間。只是記錄下這個(gè)請(qǐng)求便返回。
磁盤空間分配請(qǐng)求可能很頻繁,所以在延遲分配的一段時(shí)間內(nèi),磁盤分配器可以收到很多的分配請(qǐng)求,一些請(qǐng)求也許可以合并,一些請(qǐng)求在這段延遲期間甚至可能被取消。通過(guò)這樣的“等待”,往往能夠減少不必要的分配,也有可能將多個(gè)小的分配請(qǐng)求合并為一個(gè)大的請(qǐng)求,從而提高 IO 效率。
Inline file
系統(tǒng)中往往存在大量的小文件,比如幾百個(gè)字節(jié)或者更小。如果為其分配單獨(dú)的數(shù)據(jù) block,便會(huì)引起內(nèi)部碎片,浪費(fèi)磁盤空間。 btrfs 將小文件的內(nèi)容保存在元數(shù)據(jù)中,不再額外分配存放文件數(shù)據(jù)的磁盤塊。改善了內(nèi)部碎片問題,也增加了文件的訪問效率。
圖 9. inline file
上圖顯示了一個(gè) BTree 的葉子節(jié)點(diǎn)。葉子中有兩個(gè) extent data item 元數(shù)據(jù),分別用來(lái)表示文件 file1 和 file2 所使用的磁盤空間。
假設(shè) file1 的大小僅為 15 個(gè)字節(jié); file2 的大小為 1M 。如圖所示,file2 采用普通的 extent 表示方法:extent2 元數(shù)據(jù)指向一段 extent,大小為 1M,其內(nèi)容便是 file2 文件的內(nèi)容。
而對(duì)于 file1, btrfs 會(huì)把其文件內(nèi)容內(nèi)嵌到元數(shù)據(jù) extent1 中。如果不采用 inline file 技術(shù)。如虛線所示,extent1 指向一個(gè)最小的 extent,即一個(gè) block,但 file1 有 15 個(gè)字節(jié),其余的空間便成為了碎片空間。
采用 inline 技術(shù),讀取 file1 時(shí)只需要讀取元數(shù)據(jù) block,而無(wú)需先讀取 extent1 這個(gè)元數(shù)據(jù),再讀取真正存放文件內(nèi)容的 block,從而減少了磁盤 IO 。
得益于 inline file 技術(shù),btrfs 處理小文件的效率非常高,也避免了磁盤碎片問題。
目錄索引 Directory index
當(dāng)一個(gè)目錄下的文件數(shù)目巨大時(shí),目錄索引可以顯著提高文件搜索時(shí)間。 Btrfs 本身采用 BTree 存儲(chǔ)目錄項(xiàng),所以在給定目錄下搜索文件的效率是非常高的。
然而,btrfs 使用 BTree 管理目錄項(xiàng)的方式無(wú)法同時(shí)滿足 readdir 的需求。 readdir 是 POSIX 標(biāo)準(zhǔn) API,它要求返回指定目錄下的所有文件,并且特別的,這些文件要按照 inode number 排序。而 btrfs 目錄項(xiàng)插入 BTree 時(shí)的 Key 并不是 Inode number,而是根據(jù)文件名計(jì)算的一個(gè) hash 值。這種方式在查找一個(gè)特定文件時(shí)非常高效,但卻不適于 readdir 。為此,btrfs 在每次創(chuàng)建新的文件時(shí),除了插入以 hash 值為 Key 的目錄項(xiàng)外,還同時(shí)插入另外一種目錄項(xiàng)索引,該目錄項(xiàng)索引的 KEY 以 sequence number 作為 BTree 的鍵值。這個(gè) sequence number 在每次創(chuàng)建新文件時(shí)線性增加。因?yàn)?Inode number 也是每次創(chuàng)建新文件時(shí)增加的,所以 sequence number 和 inode number 的順序相同。以這種 sequence number 作為 KEY 在 BTree 中查找便可以方便的得到一個(gè)以 inode number 排序的文件列表。
另外以 sequence number 排序的文件往往在磁盤上的位置也是相鄰的,所以以 sequence number 為序訪問大量文件會(huì)獲得更好的 IO 效率。
壓縮
大家都曾使用過(guò) zip,winrar 等壓縮軟件,將一個(gè)大文件進(jìn)行壓縮可以有效節(jié)約磁盤空間。 Btrfs 內(nèi)置了壓縮功能。
通常人們認(rèn)為將數(shù)據(jù)寫入磁盤之前進(jìn)行壓縮會(huì)占用很多的 CPU 計(jì)算時(shí)間,必然降低文件系統(tǒng)的讀寫效率。但隨著硬件技術(shù)的發(fā)展,CPU 處理時(shí)間和磁盤 IO 時(shí)間的差距不斷加大。在某些情況下,花費(fèi)一定的 CPU 時(shí)間和一些內(nèi)存,但卻能大大節(jié)約磁盤 IO 的數(shù)量,這反而能夠增加整體的效率。
比如一個(gè)文件不經(jīng)過(guò)壓縮的情況下需要 100 次磁盤 IO 。但花費(fèi)少量 CPU 時(shí)間進(jìn)行壓縮后,只需要 10 次磁盤 IO 就可以將壓縮后的文件寫入磁盤。在這種情況下,IO 效率反而提高了。當(dāng)然,這取決于壓縮率。目前 btrfs 采用 zlib 提供的 DEFALTE/INFLATE 算法進(jìn)行壓縮和解壓。在將來(lái),btrfs 應(yīng)該可以支持更多的壓縮算法,滿足不同用戶的不同需求。
目前 btrfs 的壓縮特性還存在一些不足,當(dāng)壓縮使能后,整個(gè)文件系統(tǒng)下的所有文件都將被壓縮,但用戶可能需要更細(xì)粒度的控制,比如針對(duì)不同的目錄采用不同的壓縮算法,或者禁止壓縮。我相信,btrfs 開發(fā)團(tuán)隊(duì)將在今后的版本中解決這個(gè)問題。
對(duì)于某些類型的文件,比如 jpeg 文件,已經(jīng)無(wú)法再進(jìn)行壓縮。嘗試對(duì)其壓縮將純粹浪費(fèi) CPU 。為此,當(dāng)對(duì)某文件的若干個(gè) block 壓縮后發(fā)現(xiàn)壓縮率不佳,btrfs 將不會(huì)再對(duì)文件的其余部分進(jìn)行壓縮操作。這個(gè)特性在某種程度上提高了文件系統(tǒng)的 IO 效率。
預(yù)分配
很多應(yīng)用程序有預(yù)先分配磁盤空間的需要。他們可以通過(guò) posix_fallocate 接口告訴文件系統(tǒng)在磁盤上預(yù)留一部分空間,但暫時(shí)并不寫入數(shù)據(jù)。如果底層文件系統(tǒng)不支持 fallocate,那么應(yīng)用程序只有使用 write 預(yù)先寫一些無(wú)用信息以便為自己預(yù)留足夠的磁盤空間。
由文件系統(tǒng)來(lái)支持預(yù)留空間更加有效,而且能夠減少磁盤碎片,因?yàn)樗械目臻g都是一次分配,因而更有可能使用連續(xù)的空間。 Btrfs 支持 posix_fallocate 。
總結(jié)
至此,我們對(duì) btrfs 的很多特性進(jìn)行了較為詳細(xì)的探討,但 btrfs 能提供的特性卻并不止這些。 btrfs 正處于試驗(yàn)開發(fā)階段,還將有更多的特性。
Btrfs 也有一個(gè)重要的缺點(diǎn),當(dāng) BTree 中某個(gè)節(jié)點(diǎn)出現(xiàn)錯(cuò)誤時(shí),文件系統(tǒng)將失去該節(jié)點(diǎn)之下的所有的文件信息。而 ext2/3 卻避免了這種被稱為”錯(cuò)誤擴(kuò)散”的問題。
但無(wú)論怎樣,希望您和我一樣,開始認(rèn)同 btrfs 將是 Linux 未來(lái)最有希望的文件系統(tǒng)。
BTRFS 使用簡(jiǎn)介
了解了 btrfs 的特性,想必您一定想親身體驗(yàn)一下 btrfs 的使用。本章將簡(jiǎn)要介紹如何使用 btrfs 。
創(chuàng)建文件系統(tǒng)
mkfs.btrfs 命令建立一個(gè) btrfs 格式的文件系統(tǒng)??梢杂萌缦旅钤谠O(shè)備 sda5 上建立一個(gè) btrfs 文件系統(tǒng),并將其掛載到 /btrfsdisk 目錄下:
這樣一個(gè) Btrfs 就在設(shè)備 sda5 上建立好了。值得一提的是在這種缺省情況下,即使只有一個(gè)設(shè)備,Btrfs 也會(huì)對(duì) metadata 進(jìn)行冗余保護(hù)。如果有多個(gè)設(shè)備,那么您可以在創(chuàng)建文件系統(tǒng)的時(shí)候進(jìn)行 RAID 設(shè)置。詳細(xì)信息請(qǐng)參見后續(xù)的介紹。
這里介紹其他幾個(gè) mkfs.btrfs 的參數(shù)。
Nodesize 和 leafsize 用來(lái)設(shè)定 btrfs 內(nèi)部 BTree 節(jié)點(diǎn)的大小,缺省為一個(gè) page 大小。但用戶也可以使用更大的節(jié)點(diǎn),以便增加 fanout,減小樹的高度,當(dāng)然這只適合非常大的文件系統(tǒng)。
Alloc-start 參數(shù)用來(lái)指定文件系統(tǒng)在磁盤設(shè)備上的起始地址。這使得用戶可以方便的預(yù)留磁盤前面的一些特殊空間。
Byte-count 參數(shù)設(shè)定文件系統(tǒng)的大小,用戶可以只使用設(shè)備的一部分空間,當(dāng)空間不足時(shí)再增加文件系統(tǒng)大小。
修改文件系統(tǒng)的大小
當(dāng)文件系統(tǒng)建立好之后,您可以修改文件系統(tǒng)的大小。 /dev/sda5 掛載到了 /btrfsdisk 下,大小為 800M 。假如您希望只使用其中的 500M,則需要減小當(dāng)前文件系統(tǒng)的大小,這可以通過(guò)如下命令實(shí)現(xiàn):
同樣的,您可以使用 btrfsctl 命令增加文件系統(tǒng)的大小。
創(chuàng)建 Snapshot
下面的例子中,創(chuàng)建快照 snap1 時(shí)系統(tǒng)存在 2 個(gè)文件。創(chuàng)建快照之后,對(duì) test1 的內(nèi)容進(jìn)行修改。再回到 snap1,打開 test1 文件,可以看到 test1 的內(nèi)容依舊是之前的內(nèi)容。
可以從上面的例子看到,快照 snap1 保存的內(nèi)容不會(huì)被后續(xù)的寫操作所改變。
創(chuàng)建 subvolume
使用 btrfs 命令,用戶可以方便的建立 subvolume 。假設(shè) /btrfsdisk 已經(jīng)掛載到了 btrfs 文件系統(tǒng),則用戶可以在這個(gè)文件系統(tǒng)內(nèi)創(chuàng)建新的 subvolume 。比如建立一個(gè) /sub1 的 subvolume,并將 sub1 掛載到 /mnt/test 下:
Subvolme 可以方便管理員在文件系統(tǒng)上創(chuàng)建不同用途的子文件系統(tǒng),并對(duì)其進(jìn)行一些特殊的配置,比如有些目錄下的文件關(guān)注節(jié)約磁盤空間,因此需要打開壓縮,或者配置不同的 RAID 策略等。目前 btrfs 尚處于開發(fā)階段,創(chuàng)建的 subvolme 和 snapshot 還無(wú)法刪除。此外針對(duì) subvolume 的磁盤 quota 功能也未能實(shí)現(xiàn)。但隨著 btrfs 的不斷成熟,這些功能必然將會(huì)進(jìn)一步完善。
創(chuàng)建 RAID
mkfs 的時(shí)候,可以指定多個(gè)設(shè)備,并配置 RAID 。下面的命令演示了如何使用 mkfs.btrfs 配置 RAID1 。 Sda6 和 sda7 可以配置為 RAID1,即 mirror 。用戶可以選擇將數(shù)據(jù)配置為 RAID1,也可以選擇將元數(shù)據(jù)配置為 RAID1 。
將數(shù)據(jù)配置為 RAID1,可以使用 mkfs.btrfs 的 -d 參數(shù)。如下所示:
添加新設(shè)備
當(dāng)設(shè)備的空間快被使用完的時(shí)候,用戶可以使用 btrfs-vol 命令為文件系統(tǒng)添加新的磁盤設(shè)備,從而增加存儲(chǔ)空間。下面的命令向 /btrfsdisk 文件系統(tǒng)增加一個(gè)設(shè)備 /sda
-
Linux
+關(guān)注
關(guān)注
87文章
11292瀏覽量
209318
原文標(biāo)題:新一代 Linux 文件系統(tǒng) btrfs 簡(jiǎn)介-btrfs 的特性和使用
文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論