New tricks for XFS
LWN原文連結:https://lwn.net/Articles/747633/
簡介
XFS檔案系統進入核心已有15個年頭,並且在那之前它就已經被用在執行IRIX的生產系統上5年之久。但是,就像Dave
Chinner在他linux.conf.au
2018的演講上一開始說的那樣,現在也許是時候教這條檔案系統界的“老狗”一些新的花招了。與一些更加現代的檔案系統相比,XFS還缺少不少新特性,比如快照(snapshots)和子捲(subvolumes);但是Dave正在思考如何給XFS增加這些特性並著手編碼。
作者
關爾昱,Linux系統工程師,來自阿裡雲系統組。
本文中若有任何疏漏錯誤,有任何建議和意見,請回覆核心月談微信公眾號,或透過eguan at linux.alibaba.com或者 tao.ma at linux.alibaba.com反饋。
阿裡雲系統團隊,是由原淘寶核心組擴建而成,2013年淘寶核心組響應阿裡巴巴集團的號召,整建制轉入阿裡雲,開始為雲端計算底層系統構建完善的系統支援。
阿裡雲系統團隊是由一群具有高度使命感和自我追求的核心開發人員組成,團隊中的大多數人,都是活躍的社群核心開發人員。目前的工作領域主要涉及(但不限於)
Linux內核的記憶體管理、檔案系統、網路和核心維護構建,以及和核心相關聯的使用者態庫和工具。如果你對我們的工作很感興趣,歡迎加入我們,請將簡歷傳送至
tao.ma at linux.alibaba.com或者 boyu.mt at alibaba-inc.com。
一些背景資訊
XFS是“初始的B樹檔案系統”,因為檔案系統儲存的所有內容都是以B樹形式組織的。然而它們並不是傳統意義上的B樹,它們是B+樹的一種。其中的區別在於B+樹的每個節點都有一個指向其兄弟節點的指標,這個指標讓樹的橫向遍歷成為可能。而這種橫向遍歷對於像寫時複製(CoW)等特性至關重要。
XFS檔案系統在內部被分成“像迷你係統一樣”的分配組(allocation
groups);每個分配組都有自己的空閑空間索引B樹,索引節點B樹,反向對映(reverse-mapping)B樹等等。檔案資料也是用基於B樹的extent來索引的。“檔案夾和擴充套件屬性就是更多的B樹”,其中檔案夾B樹是最複雜的,因為為了可擴充套件性,它被設計為“虛擬對映的,具有各種雜湊的多索引B樹”。
XFS使用預寫日誌機制(writeahead journaling)來抵禦系統崩潰導致的不一致。它的基於檢查點的日誌記錄是為了減輕因修改日誌中已有的塊而導致的寫放大。
他隨後簡要介紹了CoW檔案系統。當CoW檔案系統寫入一個資料或元資料塊時,它首先做一份複製併在複製上做修改;
然後它需要更新索引樹條目以指向新塊。這導致需要修改儲存這些索引條目的塊,這又需要一次塊複製,因此需要修改父索引條目,以此類推,一直要修改到檔案系統的根節點。所有這些更新可以在檔案系統的任何位置一起被寫入,這樣可以進行大量最佳化。它還保證了on-disk磁碟結構的一致性,因為可以在對根級索引進行原子更改之前寫入整個更新。
所有這些都對系統崩潰的恢復很有用,但缺點是這需要為這些磁碟更新預先分配空間。這個空間分配過程需要更新元資料,這意味著元資料樹的更新,因此需要為此分配更多空間。這導致一個問題,那就是檔案系統無法確切知道給定CoW操作所需的確切空間。“這會在未來導致其他的問題。”
正是這些對索引樹的更新操作使得許多與CoW檔案系統相關的特性成為可能,Chinner說,“共享,快照,子捲等等”。它們都是在具有取用計數物件的索引樹結構基礎上的自然擴充套件;這種擴充套件允許多個索引透過增加取用計數來指向相同的物件。快照只是繼續保留一顆已被取代的索引樹;
這可以透過增加對那棵樹的取用來完成。複製(replication)是透過建立一顆樹及其所有物件的副本來完成的,這是一個複雜的過程,但是“確實為我們提供了使用者熟悉的傳送-接收式複製(send-receive-style
replication)”。
XFS中的CoW是不同的。由於使用的是B+樹,XFS不能只完成一般CoW檔案系統所做的從葉到根的更新,它還需要做橫向更新;這在最壞的情況下意味著更新整個檔案系統。因此XFS中僅對資料做CoW。
純資料CoW限制了XFS可以提供的功能;像資料去重和檔案級克隆這種特性是可能實現的,但其他的則不然了。Chinner表示,XFS能夠提供的那些特性對overlayfs和NFS等專案是非常有用。純資料CoW的優點是不會影響非共享資料或元資料。另外,XFS總是可以確切計算出CoW操作需要多少空間,因為只有資料被複製,元資料則在原地更新。
但是,由於元資料更新沒有使用CoW,要做到安全的從系統崩潰中恢復要更困難一些
– 這不是像建立一個樹的新分支然後以原子方式切換到它那麼簡單。Chinner說,XFS實現了一種“延遲操作”(deferred
operations),這是一種“意圖記錄機制”(intent logging
mechanism)。延遲操作過去被用於釋放extent,但現在已被擴充套件到對取用計數和反向B樹對映進行更新。這允許把CoW更新作為恢復的一部分一起做日誌回放。
什麼是子捲
關於CoW的這一切讓Chinner開始思考使用純資料CoW能夠做什麼。每個人似乎都希望能夠對子捲做快照,但這似乎需要對元資料做CoW操作。我們是否可以換個角度來思考該問題以便實現相同的功能呢?當然,這是我們最終的標的。首先要瞭解檔案系統為了實現子捲到底需要什麼。而且還有其他的實現可以供我們參考學習,他說,“我們應該避免什麼?他們做對了什麼?”好的想法是可以被借用的
– “因為這是最簡單的方法”。
讓我們回到最初的概念上來看問題,他問道:“什麼是子捲?它提供了什麼?”
據他所知,有三個屬性定義了一個子捲。子捲具有靈活的容量,因此它可以在沒有任何影響的情況下增長或縮小。子捲也是一個功能完備的檔案系統,支援像在檔案中打洞(punch
hole)或者克隆檔案這樣的操作。但是,作為快照的粒度單元是一個子捲最主要的屬性。其他一切都建立在這三個屬性之上。
他隨後問:是否可以用在檔案系統之上構造名稱空間的形式來實現子捲?系結掛載和掛載名稱空間(bind
mounts and mount
namespaces)已經存在於VFS中,他想知道是否可以使用這些來建立“一個看起來像子捲”的東西。如果你在系結掛載之上新增針對目錄層次結構配額功能,就會得到一種靈活的空間管理方式。如果你“從另外一種足夠大的角度來看”,他說道,這就是一個像子捲的東西。
同樣的,使用–reflink=always的遞迴複製操作可以實現一種快照。它仍然複製元資料,但絕大多數結構已被克隆,而不複製資料。可以使用rsync和tar完成複製;
“當然,這很慢”,但有些工具確實是這麼做的。Chinner說,這種子捲跟Btrfs子捲很不一樣,但它仍然可以提供相同的功能。此外,overlayfs複製資料並複製元資料,這表示你確實可以用“純資料CoW的方式”來實現“一些看起來像子捲的東西”。
另一個可能的想法是透過在檔案系統下層的裝置來實現子捲。事實上,這種方法已經存在了。檔案系統映象可以儲存在一個稀疏檔案中,然後透過loopback方式掛載。該映象檔案可以使用純資料CoW進行克隆,從而實現快速快照。這種方法的空間管理是“相對靈活的”,但還是受限於塊層提供的功能和檔案系統的實現。複製就是一個簡單的檔案複製。
這表明“我們所想的這種子捲其實我們已經在使用了”,Chinner說,構建子捲所需的基礎設施已經在那裡了,人們只是以其他方式在使用它們而不會讓人想到它們是子捲。
但是,loopback檔案系統方案還會遇到經典的ENOSPC問題。如果儲存映象檔案的底層檔案系統空間不足,它將傳回ENOSPC來指示這種情況,但映象內的檔案系統並不會針對此情況做任何準備並處理該故障,它只會遭到嚴重的損毀:“blammo!”。精簡配置裝置(thin
provisioning)也有相同的問題。它比CoW檔案系統ENOSPC問題更糟糕,因為你無法預測問題何時會發生,並且當問題發生後你也無法恢復。
然後Chinner把話題轉回了從別人那裡學習。他說到,Overlayfs和Btrfs(在較小程度上)教會我們,透過掛載選項指定子捲是“非常非常笨重”的方法。Btrfs子捲共享相同的超級塊,這可能導致查詢或備份等各種工具產生一些微妙的問題。一個子捲需要作為一個獨立的VFS物體來實現,而不僅僅是行為表現像一個VFS物體。“透過欺騙只能隱藏一時。”
解決ENOSPC問題很重要。問題的根源在於上下層級之間(無論如何定義)對空閑空間可用性有不同的看法,而且這兩層之間不會就此進行通訊。我們已經就此問題在LSFMM上討論過多次(例如,2017年和2016年),但沒有取得任何實質性進展。但是一段時間之前,Christoph
Hellwig提出了一個在XFS上執行的並行NFS(pNFS)伺服器的檔案介面;
它允許pNFS客戶端從伺服器遠端對映檔案並從伺服器分配塊。實際的資料儲存在其他地方,並且客戶端會從這些位置執行實際的讀寫操作;也就是客戶端在伺服器上進行檔案系統塊分配,然後在其他地方執行I/O。這為空間統計和管理的跨層溝通提供了一個“非常具有啟發性”的模型。
一種新的子捲
Chinner在構思一種新型子捲的時候把將這一切都加入到考慮範圍內;這種新型子捲在行為上跟傳統CoW子捲一致,但實現方式完全不同。我們可以修改內核以便可以直接掛載映象檔案(而不透過loopback裝置),並且可以新增一種裝置空間管理API。如果一個檔案系統實現了該API的兩端(主機端和客戶端),則可以將相同檔案系統型別的映象檔案當作子捲來使用。API可用於獲取對映資訊,這將允許子捲直接對宿主檔案系統的塊裝置執行其I/O操作。這打破了長期以來檔案系統必須使用塊裝置的要求;
有了這個變化,檔案系統現在可以直接使用檔案。
但是這種機制仍然可以用於塊裝置,這對精簡配置情況也很有用。精簡配置塊裝置(如dm-thin)可以實現空間管理API的主機端;
檔案系統可以使用客戶端API進行空間統計和I
/O對映。這樣,底層塊裝置將在檔案系統修改其結構和發出I/O之前報告ENOSPC。這是一種額外獎勵,他說,但如果他的想法真的同時解決了兩個問題,那麼這讓他有理由認為他正走在正確的軌道上。
快照“在這個模型中非常容易”。凍結子捲然後克隆映象檔案。它即快速又高效。實際上,即使其檔案系統沒有實現針對元資料的CoW操作,該子捲的元資料也是寫時複製的;因為下層檔案系統(映象檔案所在的地方)的純資料CoW提供了子捲元資料的CoW。
複製可以透過複製映象檔案來完成,但還有更好的方法。可以比較兩個映象檔案以確定哪些塊在兩個快照之間發生了變化。這很簡單,並且不需要知道正在被覆制的檔案中的內容。他用200行shell指令碼和xfs_io工具實現了一個針對loopback裝置上的XFS的工具原型。
“它基本上是一個增量複製”,並且與檔案系統映像中的內容是無關的;如果你有兩個ext4檔案系統的快照,那麼相同的程式碼也可以工作。
有人想要一些已有的CoW檔案系統(例如Btrfs,ZFS)無法提供的功能,但是這種新的方案可以。當前,許多資料在磁碟上是可以在檔案間被共享的,但資料一旦被載入到頁面快取就不能繼續被共享了。比如500個基於同一個映象的容器,你可以建立多個快照,但每個容器在快取中都有同一個檔案的一份複製。“所以你在記憶體中擁有500份/bin/bash”,他說。Overlayfs把這件事情做對了,因為它可以把一份未被修改的Bash映象快取在記憶體中並被所有容器共享。
他的標的是讓這個新子捲模型擁有同樣的行為。這需要在頁面快取中共享shared
extents中的資料。Chinner說,這是一個複雜而困難的問題,因為頁面快取是按檔案和偏移索引的,而shared
extent中唯一可用資訊是它們在檔案系統中的物理位置(即塊號)。為了檢視一個shared
extent是否已經被快取而在頁面快取中進行徹底搜尋不是可取的方法,相反,他建議新增一個按塊號索引的buffer
cache。XFS已經有一個buffer cache,但它沒有辦法在多個檔案之間共享頁面。Chinner表示,Matthew
Wilcox正在努力解決這個問題;解決方案“也許會在下週發出來”,他笑著說。
很長一段時間以來,人們一直在說不需要為子捲加密,因為容器是相互隔離的,但是隨後出現了Meltdown和Specter,這打破了所有的隔離。他認為這可能會導致一些人想要更多的防禦層,以便在隔離失效時更難以竊取他們的資料。在XFS中使用VFS檔案加密API將允許XFS對映象檔案和/或子捲內的單個檔案進行加密。將金鑰管理新增到空間管理API中也可能會有其他收穫。
Chinner說,看起來XFS是可以提供“加密的,可快照的,克隆的子捲”的。當然,這其中還有很多工作要做,它仍處於早期階段。
使用者的管理介面尚未確定;他當前更專註於讓這些技術變得可行,而在此之前他不會去關心策略管理的問題。子捲要如何呈現,宿主捲(host
volume)對使用者來說是什麼樣子,以及是否所有東西都是子捲,以上這些都是當前需要解決的問題。此外,還需要將此工作與Anaconda和Docker等工具進行整合。
目前,程式碼尚未得到其他人的任何審閱;程式碼都還在他的膝上型電腦和伺服器上。補丁一旦被髮布,就會有大量相關討論。就此可能還會產生“一些聖戰,大聲爭吵,畢竟有衝突矛盾電視劇才好看”。他推薦邊吃爆米花邊看熱鬧。
隨後他做了一個現場展示(YouTube的影片中大約36:56開始,),他演示了迄今為止能夠工作的內容。這是一個相當典型的早期演示,但他儘量避免使用subvolume和snapshot關鍵字,在演示中它們分別是“blammo”和“kaboom”。
演示結束後,Chinner對這次演講(和這項工作)做了總結。他首先研究如何在不實現元資料的CoW的情況下獲得與子捲相同的功能。最終結論是將檔案用作子捲並將子捲視為檔案系統。這為XFS這條老狗提供了與CoW檔案系統相同的功能。
本文轉載自核心月談公眾號