標籤:des class code c tar ext
Btrfs 被稱為是下一代 Linux 檔案系統。近年來 ext2/3 遇到越來越多的擴充性問題,在期待 ext4 的同時,人們發現了 btrfs,據說它採用了很多先進的檔案系統設計,不僅解決了 ext2/3 的擴充性問題,還讓人們看到了下一代檔案系統所具有的許多其他特性。這一切都讓人不禁心生好奇,btrfs 究竟提供了哪些特性?它是如何?的?本文便圍繞這些問題展開探討,首先研究了 btrfs 所提供的新特性,並簡要介紹了 btrfs 內部實現這些特性的原理;然後示範了 btrfs 的常用命令。
2010 年 9 月 20 日
Btrfs 簡介
檔案系統似乎是核心中比較穩定的部分,多年來,人們一直使用 ext2/3,ext 檔案系統以其卓越的穩定性成為了事實上的 Linux 標準檔案系統。近年來 ext2/3 暴露出了一些擴充性問題,於是便催生了 ext4 。在 2008 年發布的 Linux2.6.19 核心中整合了 ext4 的 dev 版本。 2.6.28 核心發布時,ext4 結束了開發版,開始接受使用者的使用。似乎 ext 就將成為 Linux 檔案系統的代名詞。然而當您閱讀很多有關 ext4 的文章時,會發現都不約而同地提到了 btrfs,並認為 ext4 將是一個過渡的檔案系統。 ext4 的作者 Theodore Tso 也盛讚 btrfs 並認為 btrfs 將成為下一代 Linux 標準檔案系統。 Oracle,IBM, Intel 等廠商也對 btrfs 表現出了極大的關注,投入了資金和人力。為什麼 btrfs 如此受人矚目呢。這便是本文首先想探討的問題。
Kevin Bowling[1] 有一篇介紹各種檔案系統的文章,在他看來,ext2/3 等檔案系統屬於“古典時期”。檔案系統的新時代是 2005 年由 Sun 公司的 ZFS 開創的。 ZFS 代表” last word in file system ”,意思是此後再也不需要開發其他的檔案系統了。 ZFS 的確帶來了很多嶄新的觀念,對檔案系統來講是一個劃時代的作品。
如果您比較 btrfs 的特性,將會發現 btrfs 和 ZFS 非常類似。也許我們可以認為 btrfs 就是 Linux 社區對 ZFS 所作出的回應。從此往後在 Linux 中也終於有了一個可以和 ZFS 相媲美的檔案系統。
回頁首
btrfs 的特性
您可以在 btrfs 的首頁上 [2] 看到 btrfs 的特性列表。我自作主張,將那張列表分成了四大部分。
首先是擴充性 (scalability) 相關的特性,btrfs 最重要的設計目標是應對大型主機器對檔案系統的擴充性要求。 Extent,B-Tree 和動態 inode 建立等特性保證了 btrfs 在大型主機器上仍有卓越的表現,其整體效能而不會隨著系統容量的增加而降低。
其次是資料一致性 (data integrity) 相關的特性。系統面臨不可預料的硬體故障,Btrfs 採用 COW 事務技術來保證檔案系統的一致性。 btrfs 還支援 checksum,避免了 silent corrupt 的出現。而傳統檔案系統則無法做到這一點。
第三是和多裝置管理相關的特性。 Btrfs 支援建立快照 (snapshot),和複製 (clone) 。 btrfs 還能夠方便的管理多個物理裝置,使得傳統的卷管理軟體變得多餘。
最後是其他難以歸類的特性。這些特性都是比較先進的技術,能夠顯著提高檔案系統的時間 / 空間效能,包括延遲分配,小檔案的儲存最佳化,目錄索引等。
擴充性相關的特性
B-Tree
btrfs 檔案系統中所有的 metadata 都由 BTree 管理。使用 BTree 的主要好處在於尋找,插入和刪除操作都很高效。可以說 BTree 是 btrfs 的核心。
一味地誇耀 BTree 很好很高效也許並不能讓人信服,但假如稍微花費一點兒時間看看 ext2/3 中中繼資料管理的實現方式,便可以反襯出 BTree 的優點。
妨礙 ext2/3 擴充性的一個問題來自其目錄的組織方式。目錄是一種特殊的檔案,在 ext2/3 中其內容是一張線性表格。 1-1 所示 [6]:
圖 1. ext2 directory [6]
圖 1 展示了一個 ext2 目錄檔案的內容,該目錄中包含四個檔案。分別是 "home1","usr","oldfile" 和 "sbin" 。如果需要在該目錄中尋找目錄 sbin,ext2 將遍曆前三項,直至找到 sbin 這個字串為止。
這種結構在檔案個數有限的情況下是比較直觀的設計,但隨著目錄下檔案數的增加,尋找檔案的時間將線性增長。 2003 年,ext3 設計者開發了目錄索引技術,解決了這個問題。目錄索引使用的資料結構就是 BTree 。如果同一目錄下的檔案數超過 2K,inode 中的 i_data 域指向一個特殊的 block 。在該 block 中儲存著目錄索引 BTree 。 BTree 的尋找效率高於線性表,
但為同一個中繼資料設計兩種資料結構總是不太優雅。在檔案系統中還有很多其他的中繼資料,用統一的 BTree 管理是非常簡單而優美的設計。
Btrfs 內部所有的中繼資料都採用 BTree 管理,擁有良好的可擴充性。 btrfs 內部不同的中繼資料由不同的 Tree 管理。在 superblock 中,有指標指向這些 BTree 的根。 2 所示:
圖 2. btrfs btree
FS Tree 管理檔案相關的中繼資料,如 inode,dir 等; Chunk tree 管理裝置,每一個磁碟裝置都在 Chunk Tree 中有一個 item ; Extent Tree 管理磁碟空間分配,btrfs 每分配一段磁碟空間,便將該磁碟空間的資訊插入到 Extent tree 。查詢 Extent Tree 將得到閒置磁碟空間資訊; Tree of tree root 儲存很多 BTree 的根節點。比如使用者每建立一個快照,btrfs 便會建立一個 FS Tree 。為了管理所有的樹,btrfs 採用 Tree of tree root 來儲存所有樹的根節點; checksum Tree 儲存資料區塊的校正和。
基於 Extent 的檔案儲存體
現代很多檔案系統都採用了 extent 替代 block 來管理磁碟。 Extent 就是一些連續的 block,一個 extent 由起始的 block 加上長度進行定義。
Extent 能有效地減少中繼資料開銷。為了進一步理解這個問題,我們還是看看 ext2 中的反面例子。
ext2/3 以 block 為基本單位,將磁碟劃分為多個 block 。為了管理磁碟空間,檔案系統需要知道哪些 block 是閒置。 Ext 使用 bitmap 來達到這個目的。 Bitmap 中的每一個 bit 對應磁碟上的一個 block,當相應 block 被分配後,bitmap 中的相應 bit 被設定為 1 。這是很經典也很清晰的一個設計,但不幸的是當磁碟容量變大時,bitmap 自身所佔用的空間也將變大。這就導致了擴充性問題,隨著存放裝置容量的增加,bitmap 這個中繼資料所佔用的空間也隨之增加。而人們希望無論磁碟容量如何增加,中繼資料不應該隨之線形增加,這樣的設計才具有可擴充性。
比較了 block 和 extent 的區別:
圖 3. 採用 extent 的 btrfs 和採用 bitmap 的 ext2/3
在 ext2/3 中,10 個 block 需要 10 個 bit 來表示;在 btrfs 中則只需要一個中繼資料。對於大檔案,extent 表現出了更加優異的管理效能。
Extent 是 btrfs 管理磁碟空間的最小單位,由 extent tree 管理。 Btrfs 分配 data 或 metadata 都需要查詢 extent tree 以便獲得空閑空間的資訊。
動態 inode 分配
為了理解動態 inode 分配,還是需要藉助 ext2/3 。下表列舉了 ext2 檔案系統的限制:
表 1. ext2 限制
| |
限制 |
| 最大檔案數量 |
檔案系統空間大小 V / 8192 比如 100G 大小的檔案系統中,能建立的檔案個數最大為 131072 |
圖 4 顯示了 ext2 的磁碟布局:
圖 4. ext2 layout
在 ext2 中 inode 區是被預先固定分配的,且大小固定,比如一個 100G 的分區中,inode table 區中只能存放 131072 個 inode,這就意味著不可能建立超過 131072 個檔案,因為每一個檔案都必須有一個唯一的 inode 。
為瞭解決這個問題,必須動態分配 inode 。每一個 inode 只是 BTree 中的一個節點,使用者可以無限制地任意插入新的 inode,其實體儲存體位置是動態分配的。所以 btrfs 沒有對檔案個數的限制。
針對 SSD 的最佳化支援
SSD 是固態儲存 Solid State Disk 的簡稱。在過去的幾十年中,CPU/RAM 等器件的發展始終遵循著摩爾定律,但硬碟 HDD 的讀寫速率卻始終沒有飛躍式的發展。磁碟 IO 始終是系統效能的瓶頸。
SSD 採用 flash memory 技術,內部沒有磁碟磁頭等機械裝置,讀寫速率大幅度提升。 flash memory 有一些不同於 HDD 的特性。 flash 在寫資料之前必須先執行擦除操作;其次,flash 對擦除操作的次數有一定的限制,在目前的技術水平下,對同一個資料單元最多能進行約 100 萬次擦除操作,因此,為了延長 flash 的壽命,應該將寫操作平均到整個 flash 上。
SSD 在硬體內部的微代碼中實現了 wear leveling 等分布寫操作的技術,因此系統無須再使用特殊的 MTD 驅動和 FTL 層。雖然 SSD 在硬體層面做了很多努力,但畢竟還是有限。檔案系統針對 SSD 的特性做最佳化不僅能提高 SSD 的使用壽命,而且能提高讀寫效能。 Btrfs 是少數專門對 SSD 進行最佳化的檔案系統。 btrfs 使用者可以使用 mount 參數開啟對 SSD 的特殊最佳化處理。
Btrfs 的 COW 技術從根本上避免了對同一個物理單元的反覆寫操作。如果使用者開啟了 SSD 最佳化選項,btrfs 將在底層的塊空間分配策略上進行最佳化:將多次磁碟空間分配請求彙總成一個大小為 2M 的連續的塊。大塊連續地址的 IO 能夠讓固化在 SSD 內部的微代碼更好的進行讀寫最佳化,從而提高 IO 效能。
資料一致性相關的特性
COW 事務
理解 COW 事務,必須首先理解 COW 和事務這兩個術語。
什麼是 COW?
所謂 COW,即每次寫磁碟資料時,先將更新資料寫入一個新的 block,當新資料寫入成功之後,再更新相關的資料結構指向新 block 。
什麼是事務?
COW 只能保證單一資料更新的原子性。但檔案系統中很多操作需要更新多個不同的中繼資料,比如建立檔案需要修改以下這些中繼資料:
- 修改 extent tree,分配一段磁碟空間
- 建立一個新的 inode,並插入 FS Tree 中
- 增加一個目錄項,插入到 FS Tree 中
任何一個步驟出錯,檔案便不能建立成功,因此可以定義為一個事務。
下面將示範一個 COW 事務。
A 是 FS Tree 的根節點,新的 inode 的資訊將被插入節點 C 。首先,btrfs 將 inode 插入一個新分配的 block C ’中,並修改上層節點 B,使其指向新的 block C ’;修改 B 也將引發 COW,以此類推,引發一個連鎖反應,直到最頂層的 Root A 。當整個過程結束後,新節點 A ’變成了 FS Tree 的根。但此時事務並未結束,superblock 依然指向 A 。
圖 5. COW transaction 1
接下來,修改目錄項(E 節點),同樣引發這一過程,從而產生新的根節點 A ’’。
圖 6. COW transaction 2
此時,inode 和目錄項都已經寫入磁碟,可以認為事務已經結束。 btrfs 修改 superblock,使其指向 A ’’,如所示:
圖 7. COW transaction 3
COW 事務能夠保證檔案系統的一致性,並且系統 Reboot 之後不需要執行 fsck 。因為 superblock 要麼指向新的 A ’’,要麼指向 A,無論哪個都是一致的資料。
Checksum
Checksum 技術保證了資料的可靠性,避免 silent corruption 現象。由於硬體原因,從磁碟上讀出的資料會出錯。比如 block A 中存放的資料為 0x55,但讀取出來的資料變是 0x54,因為讀取操作並未報錯,所以這種錯誤不能被上層軟體所察覺。
解決這個問題的方法是儲存資料的校正和,在讀取資料後檢查校正和。如果不符合,便知道資料出現了錯誤。
ext2/3 沒有校正和,對磁碟完全信任。而不幸的是,磁碟的錯誤始終存在,不僅發生在廉價的 IDE 硬碟上,昂貴的 RAID 也存在 silent corruption 問題。而且隨著儲存網路的發展,即使資料從磁碟讀出正確,也很難確保能夠安全地穿越網路裝置。
btrfs 在讀取資料的同時會讀取其相應的 checksum 。如果最終從磁碟讀取出來的資料和 checksum 不相同,btrfs 會首先嘗試讀取資料的鏡像備份,如果資料沒有鏡像備份,btrfs 將返回錯誤。寫入磁碟資料之前,btrfs 計算資料的 checksum 。然後將 checksum 和資料同時寫入磁碟。
Btrfs 採用單獨的 checksum Tree 來管理資料區塊的校正和,把 checksum 和 checksum 所保護的資料區塊分離開,從而提供了更嚴格的保護。假如在每個資料 block 的 header 中加入一個域儲存 checksum,那麼這個資料 block 就成為一個自己保護自己的結構。這種結構下有一種錯誤無法檢測出來,比如本來檔案系統打算從磁碟上讀 block A,但返回了 block B,由於 checksum 在 block 內部,因此 checksum 依舊是正確的。 btrfs 採用 checksum tree 來儲存資料區塊的 checksum,避免了上述問題。
Btrfs 採用 crc32 演算法計算 checksum,在將來的開發中會支援其他類型的校正演算法。為了提高效率,btrfs 將寫資料和 checksum 的工作分別用不同的核心線程並存執行。
多裝置管理相關的特性
每個 Unix 管理員都曾面臨為使用者和各種應用程式指派磁碟空間的任務。多數情況下,人們無法事先準確地估計一個使用者或者應用在未來究竟需要多少磁碟空間。磁碟空間被用盡的情況經常發生,此時人們不得不試圖增加檔案系統空間。傳統的 ext2/3 無法應付這種需求。
很多卷管理軟體被設計出來滿足使用者對多裝置管理的需求,比如 LVM 。 Btrfs 整合了卷管理軟體的功能,一方面簡化了使用者命令;另一方面提高了效率。
多裝置管理
Btrfs 支援動態添加裝置。使用者在系統中增加新的磁碟之後,可以使用 btrfs 的命令將該裝置添加到檔案系統中。
為了靈活利用裝置空間,Btrfs 將磁碟空間劃分為多個 chunk 。每個 chunk 可以使用不同的磁碟空間分配策略。比如某些 chunk 只存放 metadata,某些 chunk 只存放資料。一些 chunk 可以配置為 mirror,而另一些 chunk 則可以配置為 stripe 。這為使用者提供了非常靈活的配置可能性。
Subvolume
Subvolume 是很優雅的一個概念。即把檔案系統的一部分配置為一個完整的子檔案系統,稱之為 subvolume 。
採用 subvolume,一個大的檔案系統可以被劃分為多個子檔案系統,這些子檔案系統共用底層的裝置空間,在需要磁碟空間時便從底層裝置中分配,類似應用程式調用 malloc() 分配記憶體一樣。可以稱之為儲存池。這種模型有很多優點,比如可以充分利用 disk 的頻寬,可以簡化磁碟空間的管理等。
所謂充分利用 disk 的頻寬,指檔案系統可以並行讀寫底層的多個 disk,這是因為每個檔案系統都可以訪問所有的 disk 。傳統的檔案系統不能共用底層的 disk 裝置,無論是物理的還是邏輯的,因此無法做到並行讀寫。
所謂簡化管理,是相對於 LVM 等卷管理軟體而言。採用儲存池模型,每個檔案系統的大小都可以自動調節。而使用 LVM,如果一個檔案系統的空間不夠了,該檔案系統並不能自動使用其他磁碟裝置上的空閑空間,而必須使用 LVM 的管理命令手動調節。
Subvolume 可以作為根目錄掛載到任意 mount 點。 subvolume 是非常有趣的一個特性,有很多應用。
假如管理員只希望某些使用者訪問檔案系統的一部分,比如希望使用者只能訪問 /var/test/ 下面的所有內容,而不能訪問 /var/ 下面其他的內容。那麼便可以將 /var/test 做成一個 subvolume 。 /var/test 這個 subvolume 便是一個完整的檔案系統,可以用 mount 命令掛載。比如掛載到 /test 目錄下,給使用者訪問 /test 的許可權,那麼使用者便只能訪問 /var/test 下面的內容了。
快照和複製
快照是對檔案系統某一時刻的完全備份。建立快照之後,對檔案系統的修改不會影響快照中的內容。這是非常有用的一種技術。
比如Database Backup。假如在時間點 T1,管理員決定對資料庫進行備份,那麼他必須先停止資料庫。備份檔案是非常耗時的操作,假如在備份過程中某個應用程式修改了資料庫的內容,那麼將無法得到一個一致性的備份。因此在備份過程中資料庫服務必須停止,對於某些關鍵應用這是不能允許的。
利用快照,管理員可以在時間點 T1 將資料庫停止,對系統建立一個快照。這個過程一般只需要幾秒鐘,然後就可以立即重新恢複資料庫服務。此後在任何時候,管理員都可以對快照的內容進行備份操作,而此時使用者對資料庫的修改不會影響快照中的內容。當備份完成,管理員便可以刪除快照,釋放磁碟空間。
快照一般是唯讀,當系統支援可寫快照,那麼這種可寫快照便被稱為複製。複製技術也有很多應用。比如在一個系統中安裝好基本的軟體,然後為不同的使用者做不同的複製,每個使用者使用自己的複製而不會影響其他使用者的磁碟空間。非常類似於虛擬機器。
Btrfs 支援 snapshot 和 clone 。這個特性極大地增加了 btrfs 的使用範圍,使用者不需要購買和安裝昂貴並且使用複雜的卷管理軟體。下面簡要介紹一下 btrfs 實現快照的基本原理。
如前所述 Btrfs 採用 COW 事務技術,從圖 1-10 可以看到,COW 事務結束後,如果不刪除原來的節點 A,C,E,那麼 A,C,E,D,F 依然完整的表示著事務開始之前的檔案系統。這就是 snapshot 實現的基本原理。
Btrfs 採用引用計數決定是否在事務 commit 之後刪除原有節點。對每一個節點,btrfs 維護一個引用計數。當該節點被別的節點引用時,該計數加一,當該節點不再被別的節點引用時,該計數減一。當引用計數歸零時,該節點被刪除。對於普通的 Tree Root, 引用計數在建立時被加一,因為 Superblock 會引用這個 Root block 。很明顯,初始情況下這棵樹中的所有其他節點的引用計數都為一。當 COW 事務 commit 時,superblock 被修改指向新的 Root A ’’,原來 Root block A 的引用計數被減一,變為零,因此 A 節點被刪除。 A 節點的刪除會引發其子孫節點的引用計數也減一,圖 1-10 中的 B,C 節點的引用計數因此也變成了 0,從而被刪除。 D,E 節點在 COW 時,因為被 A ’’所引用,計數器加一,因此計數器這時並未歸零,從而沒有被刪除。
建立 Snapshot 時,btrfs 將的 Root A 節點複製到 sA,並將 sA 的引用計數設定為 2 。在事務 commit 的時候,sA 節點的引用計數不會歸零,從而不會被刪除,因此使用者可以繼續通過 Root sA 訪問 snapshot 中的檔案。
圖 8. Snapshot
軟體 RAID
RAID 技術有很多非常迷人的特性,比如使用者可以將多個廉價的 IDE 磁碟組合為 RAID0 陣列,從而變成了一個大容量的磁碟; RAID1 和更進階的 RAID 配置還提供了資料冗餘保護,從而使得儲存在磁碟中的資料更加安全。
Btrfs 很好的支援了軟體 RAID,RAID 種類包括 RAID0,RAID1 和 RAID10.
Btrfs 預設情況下對 metadata 進行 RAID1 保護。前面已經提及 btrfs 將裝置空間劃分為 chunk,一些 chunk 被配置為 metadata,即只儲存 metadata 。對於這類 chunk,btrfs 將 chunk 分成兩個條帶,寫 metadata 的時候,會同時寫入兩個條帶內,從而實現對 metadata 的保護。
其他特性
Btrfs 首頁上羅列的其他特性不容易分類,這些特性都是現代檔案系統中比較先進的技術,能夠提高檔案系統的時間或空間效率。
Delay allocation
延遲分配技術能夠減少磁碟片段。在 Linux 核心中,為了提高效率,很多操作都會延遲。
在檔案系統中,小塊空間頻繁的分配和釋放會造成片段。延遲分配是這樣一種技術,當使用者需要磁碟空間時,先將資料儲存在記憶體中。並將磁碟分配需求發送給磁碟空間分配器,磁碟空間分配器並不立即分配真正的磁碟空間。只是記錄下這個請求便返回。
磁碟空間分配請求可能很頻繁,所以在延遲分配的一段時間內,磁碟分配器可以收到很多的分配請求,一些請求也許可以合并,一些請求在這段延遲期間甚至可能被取消。通過這樣的“等待”,往往能夠減少不必要的分配,也有可能將多個小的分配請求合并為一個大的請求,從而提高 IO 效率。
Inline file
系統中往往存在大量的小檔案,比如幾百個位元組或者更小。如果為其分配單獨的資料 block,便會引起內部片段,浪費磁碟空間。 btrfs 將小檔案的內容儲存在中繼資料中,不再額外分配存放檔案資料的磁碟塊。改善了內部片段問題,也增加了檔案的訪問效率。
圖 9. inline file
顯示了一個 BTree 的葉子節點。葉子中有兩個 extent data item 中繼資料,分別用來表示檔案 file1 和 file2 所使用的磁碟空間。
假設 file1 的大小僅為 15 個位元組; file2 的大小為 1M 。,file2 採用普通的 extent 表示方法:extent2 中繼資料指向一段 extent,大小為 1M,其內容便是 file2 檔案的內容。
而對於 file1, btrfs 會把其檔案內容內嵌到中繼資料 extent1 中。如果不採用 inline file 技術。如虛線所示,extent1 指向一個最小的 extent,即一個 block,但 file1 有 15 個位元組,其餘的空間便成為了片段空間。
採用 inline 技術,讀取 file1 時只需要讀取中繼資料 block,而無需先讀取 extent1 這個中繼資料,再讀取真正存放檔案內容的 block,從而減少了磁碟 IO 。
得益於 inline file 技術,btrfs 處理小檔案的效率非常高,也避免了磁碟片段問題。
目錄索引 Directory index
當一個目錄下的檔案數目巨大時,目錄索引可以顯著提高檔案搜尋時間。 Btrfs 本身採用 BTree 儲存目錄項,所以在給定目錄下搜尋檔案的效率是非常高的。
然而,btrfs 使用 BTree 管理目錄項的方式無法同時滿足 readdir 的需求。 readdir 是 POSIX 標準 API,它要求返回指定目錄下的所有檔案,並且特別的,這些檔案要按照 inode number 排序。而 btrfs 目錄項插入 BTree 時的 Key 並不是 Inode number,而是根據檔案名稱計算的一個 hash 值。這種方式在尋找一個特定檔案時非常高效,但卻不適於 readdir 。為此,btrfs 在每次建立新的檔案時,除了插入以 hash 值為 Key 的目錄項外,還同時插入另外一種目錄項索引,該目錄項索引的 KEY 以 sequence number 作為 BTree 的索引值。這個 sequence number 在每次建立新檔案時線性增加。因為 Inode number 也是每次建立新檔案時增加的,所以 sequence number 和 inode number 的順序相同。以這種 sequence number 作為 KEY 在 BTree 中尋找便可以方便的得到一個以 inode number 排序的檔案清單。
另外以 sequence number 排序的檔案往往在磁碟上的位置也是相鄰的,所以以 sequence number 為序訪問大量檔案會獲得更好的 IO 效率。
壓縮
大家都曾使用過 zip,winrar 等壓縮軟體,將一個大檔案進行壓縮可以有效節約磁碟空間。 Btrfs 內建了壓縮功能。
通常人們認為將資料寫入磁碟之前進行壓縮會佔用很多的 CPU 計算時間,必然降低檔案系統的讀寫效率。但隨著硬體技術的發展,CPU 處理時間和磁碟 IO 時間的差距不斷加大。在某些情況下,花費一定的 CPU 時間和一些記憶體,但卻能大大節約磁碟 IO 的數量,這反而能夠增加整體的效率。
比如一個檔案不經過壓縮的情況下需要 100 次磁碟 IO 。但花費少量 CPU 時間進行壓縮後,只需要 10 次磁碟 IO 就可以將壓縮後的檔案寫入磁碟。在這種情況下,IO 效率反而提高了。當然,這取決於壓縮率。目前 btrfs 採用 zlib 提供的 DEFALTE/INFLATE 演算法進行壓縮和解壓。在將來,btrfs 應該可以支援更多的壓縮演算法,滿足不同使用者的不同需求。
目前 btrfs 的壓縮特性還存在一些不足,當壓縮使能後,整個檔案系統下的所有檔案都將被壓縮,但使用者可能需要更細粒度的控制,比如針對不同的目錄採用不同的壓縮演算法,或者禁止壓縮。我相信,btrfs Team Dev將在今後的版本中解決這個問題。
對於某些類型的檔案,比如 jpeg 檔案,已經無法再進行壓縮。嘗試對其壓縮將純粹浪費 CPU 。為此,當對某檔案的若干個 block 壓縮後發現壓縮率不佳,btrfs 將不會再對檔案的其餘部分進行壓縮操作。這個特性在某種程度上提高了檔案系統的 IO 效率。
預分配
很多應用程式有預先分配磁碟空間的需要。他們可以通過 posix_fallocate 介面告訴檔案系統在磁碟上預留一部分空間,但暫時並不寫入資料。如果底層檔案系統不支援 fallocate,那麼應用程式只有使用 write 預先寫一些無用資訊以便為自己預留足夠的磁碟空間。
由檔案系統來支援預留空間更加有效,而且能夠減少磁碟片段,因為所有的空間都是一次分配,因而更有可能使用連續的空間。 Btrfs 支援 posix_fallocate 。
總結
至此,我們對 btrfs 的很多特性進行了較為詳細的探討,但 btrfs 能提供的特性卻並不止這些。 btrfs 正處於實驗開發階段,還將有更多的特性。
Btrfs 也有一個重要的缺點,當 BTree 中某個節點出現錯誤時,檔案系統將失去該節點之下的所有的檔案資訊。而 ext2/3 卻避免了這種被稱為”錯誤擴散”的問題。
但無論怎樣,希望您和我一樣,開始認同 btrfs 將是 Linux 未來最有希望的檔案系統。
回頁首
BTRFS 使用簡介
瞭解了 btrfs 的特性,想必您一定想親身體驗一下 btrfs 的使用。本章將簡要介紹如何使用 btrfs 。
建立檔案系統
mkfs.btrfs 命令建立一個 btrfs 格式的檔案系統。可以用如下命令在裝置 sda5 上建立一個 btrfs 檔案系統,並將其掛載到 /btrfsdisk 目錄下:
#mkfs.btrfs /dev/sda5 #mkdir /btrfsdisk #mount – t btrfs /dev/sda5 /btrfsdisk
這樣一個 Btrfs 就在裝置 sda5 上建立好了。值得一提的是在這種預設情況下,即使只有一個裝置,Btrfs 也會對 metadata 進行冗餘保護。如果有多個裝置,那麼您可以在建立檔案系統的時候進行 RAID 設定。詳細資料請參見後續的介紹。
這裡介紹其他幾個 mkfs.btrfs 的參數。
Nodesize 和 leafsize 用來設定 btrfs 內部 BTree 節點的大小,預設為一個 page 大小。但使用者也可以使用更大的節點,以便增加 fanout,減小樹的高度,當然這隻適合非常大的檔案系統。
Alloc-start 參數用來指定檔案系統在磁碟裝置上的起始地址。這使得使用者可以方便的預留磁碟前面的一些特殊空間。
Byte-count 參數設定檔案系統的大小,使用者可以只使用裝置的一部分空間,當空間不足時再增加檔案系統大小。
修改檔案系統的大小
當檔案系統建立好之後,您可以修改檔案系統的大小。 /dev/sda5 掛載到了 /btrfsdisk 下,大小為 800M 。假如您希望只使用其中的 500M,則需要減小當前檔案系統的大小,這可以通過如下命令實現:
#df Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda1 101086 19000 76867 20% /boot /dev/sda5 811248 32 811216 1% /btrfsdisk #btrfsctl – r -300M /btrfsdisk #df Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda1 101086 19000 76867 20% /boot /dev/sda5 504148 32 504106 1% /btrfsdisk
同樣的,您可以使用 btrfsctl 命令增加檔案系統的大小。
建立 Snapshot
下面的例子中,建立快照 snap1 時系統存在 2 個檔案。建立快照之後,對 test1 的內容進行修改。再回到 snap1,開啟 test1 檔案,可以看到 test1 的內容依舊是之前的內容。
#ls /btrfsdisk test1 test2 #vi test1 This is a test #btrfsctl – s snap1 /btrfsdisk #vi test1 Test1 is modified #cd /btrfsdisk/snap1 #cat test1 This is a test
可以從上面的例子看到,快照 snap1 儲存的內容不會被後續的寫操作所改變。
建立 subvolume
使用 btrfs 命令,使用者可以方便的建立 subvolume 。假設 /btrfsdisk 已經掛載到了 btrfs 檔案系統,則使用者可以在這個檔案系統內建立新的 subvolume 。比如建立一個 /sub1 的 subvolume,並將 sub1 掛載到 /mnt/test 下:
#mkdir /mnt/test #btrfsctl – S sub1 /btrfsdisk #mount – t btrfs – o subvol=sub1 /dev/sda5 /mnt/test
Subvolme 可以方便管理員在檔案系統上建立不同用途的子檔案系統,並對其進行一些特殊的配置,比如有些目錄下的檔案關注節約磁碟空間,因此需要開啟壓縮,或者配置不同的 RAID 策略等。目前 btrfs 尚處於開發階段,建立的 subvolme 和 snapshot 還無法刪除。此外針對 subvolume 的磁碟 quota 功能也未能實現。但隨著 btrfs 的不斷成熟,這些功能必然將會進一步完善。
建立 RAID
mkfs 的時候,可以指定多個裝置,並配置 RAID 。下面的命令示範了如何使用 mkfs.btrfs 配置 RAID1 。 Sda6 和 sda7 可以配置為 RAID1,即 mirror 。使用者可以選擇將資料配置為 RAID1,也可以選擇將中繼資料配置為 RAID1 。
將資料配置為 RAID1,可以使用 mkfs.btrfs 的 -d 參數。如下所示:
#mkfs.btrfs – d raid1 /dev/sda6 /dev/sda7 #mount – t btrfs /dev/sda6 /btrfsdisk
添加新裝置
當裝置的空間快被使用完的時候,使用者可以使用 btrfs-vol 命令為檔案系統添加新的磁碟裝置,從而增加儲存空間。下面的命令向 /btrfsdisk 檔案系統增加一個裝置 /sda8
#btrfs-vol – a /dev/sda8 /btrfsdisk
SSD 支援
使用者可以使用 mount 參數開啟 btrfs 針對 SSD 的最佳化。命令如下:
#mount – t btrfs – o SSD /dev/sda5 /btrfsdisk
開啟壓縮功能
使用者可以使用 mount 參數開啟壓縮功能。命令如下:
#mount – t btrfs – o compress /dev/sda5 /btrfsdisk
同步檔案系統
為了提高效率,btrfs 的 IO 操作由一些核心線程非同步處理。這使得使用者對檔案的操作並不會立即反應到磁碟上。您可以做一個實驗,在 btrfs 上建立一個檔案後,稍等 5 到 10 秒將系統電源切斷,再次重啟後,建立的檔案並沒有出現。
對於多數應用這並不是問題,但有些時候使用者希望 IO 操作立即執行,此時就需要對檔案系統進行同步。下面的 btrfs 命令用來同步檔案系統:
#btrfsctl – c /btrfsdisk
Debug 功能
Btrfs 提供了一定的 debug 功能,對於想瞭解 Btrfs 內部實現原理的讀者,debug 將是您最喜歡的工具。這裡簡單介紹一下 debug 功能的命令使用。
下面的命令將裝置 sda5 上的 btrfs 檔案系統中的中繼資料列印到螢幕上。
#btrfs-debug-tree /dev/sda5
通過對列印資訊的分析,您將能瞭解 btrfs 內部各個 BTree 的變化情況,從而進一步理解每一個檔案系統功能的內部實現細節。
比如您可以在建立一個檔案之前將 BTree 的內容列印出來,建立檔案後再次列印。通過比較兩次的不同來瞭解 btrfs 建立一個檔案需要修改哪些中繼資料。進而理解 btrfs 內部的工作原理。