重用page->mapping

翻譯自LWN.NET

因爲要在struct page這一小段內存中填入最大量的信息,linux kernel中的結構體page是最複雜的結構體之一。struct page中每一個區域都重度過載,開發者們都傾向於:若能避免,絕不對struct page做修改。不過,這並沒有阻止JérômeGlisse在2018年Linux存儲,文件系統和內存管理峯會的兩次全體會議上提出重大更改的建議。建議提供了一些有趣的增益,但是要實現這一目標並不是一件容易的事。

mapping段在struct page中用於描述這個頁的來路;對於緩存頁面,mapping指向struct address_space來指示這個頁面的歸屬,匿名頁面使用mapping來反向映射到struct anon_vma。對於kernel自己用的頁面,mapping段可以被slab分配器使用。就像struct page中其他的數據段一樣,mapping是一個複雜的區域,可以根據頁面在當前的用途提供不同的含義。

Glisse對於這一區域有着自己的設計,但是首先他必須找到清除mapping當前使用方式的辦法。大多數時候,與struct page相關的代碼都是通過VMA或是struct file找到struct page,在這兩種情況下,mapping的信息可以從這兩個結構體中獲得。在可獲得該信息的上下文中,無需將其存儲在頁面結構本身中;可以通過更改接口來代替它,以將映射信息向下傳遞到調用鏈。這樣做就允許他清除大多數使用mapping的情況,然後就將mapping段移做他用。

特別是,他正在考慮使用該字段爲頁面上正在等待的線程接上一個結構體。當前,在線程等待特定頁面是通過一組256個共享等待隊列完成的,替換掉這些隊列,將會加快隊列變長的情況下線程的喚醒速度。在一般情況下,沒有人在等這個頁面時,mapping段將會指向一個結構體:

struct page_mapping{

struct address_space* mapping;

unsigned long flags;

}

本質上,此機制是添加用於訪問映射信息的間接層,並添加一些標誌以達到良好的效果。但是,當有人需要在該頁面上等待時,此結構將被替換爲:

struct page_wait {

struct wait_queue_head wq[PAGE_WRITABLE_BITS];

struct wait_queue_entry entry;

struct page_mapping base;

spinlock_t lock;

bool own;

};

完成此替換後,指向page_wait結構的指針的最低有效位設置爲標記更改。任何需要舊映射字段的代碼都需要注意該更改,並通過另一個間接級別跟隨指針以獲取該信息。這種情況將一直持續到刪除最後一個等待者爲止。到那時,將恢復指向page_mapping結構的指針。

休·迪金斯(Hugh Dickins)問格利瑟(Glisse),他正試圖用這種改變解決什麼問題。 Glisse回答說,重點是要解決共享等待隊列的長度,該隊列隨着時間的推移一直在增長。迪金斯說,只需增加隊列,就可以更簡單地解決問題。肯特·奧弗斯特里特(Kent Overstreet)表示,也許可以將rhashtables用於此目的。他說,他完全贊成消除mapping字段,但是用其他內容替換該字段將是可恥的。但是,格里斯(Glisse)表示,他的目標不是完全撤離該領域。他真的只是想簡化將結構體聯繫到struct page的過程

馬修·威爾科克斯(Matthew Wilcox)建議,也許可以將私有字段用於這種結構附件,但是似乎該字段已經有太多其他用途。克里斯·梅森有力地(幽默地)斷言“私人是我的!”。

Dickins說,歸納mapping字段可能會有一些價值,但是使用它來在頁面上等待就比較“奇特”了。Glisse回答說,此功能“幾乎免費”,幾乎不需要代碼。但是Dickins堅持認爲,mapping說明了任何給定頁面的身份。如果將其替換爲其他內容,則該頁面會丟失該身份信息。他將這種機制描述爲添加一些瞬態信息的“奇怪的濫用”。

Rik van Riel詢問了該方案如何處理頁面查找和truncate操作之間的同步。truction需要mapping,Glisse說,但這是內核中僅有的少數幾個地方之一。使事情運轉起來只是在那些地方增加對新方案的認識的問題。Dave Chinner說XFS檢查一個空mapping值來處理trunction,這將打破新方案。Glisse建議增加一個新的助手,但是Overstreet表示,現在是時候找到一種更好的方法來處理trunction操作的鎖定了。

丹·威廉姆斯(Dan Williams)重複了一個問題,爲什麼確實需要該指針?這次Glisse表示他需要它來進行頁面寫保護,該主題計劃在第二天討論。他需要在struct page內設置一個指針,而mapping恰好是最容易抓住的指針。Glisse在會議結束時承認大多數開發人員似乎都認爲此更改“看起來很醜”。無論如何,他將在不久的將來發布補丁,並查看當時的反應。

通用寫保護

不過該小組尚未完成mapping相關的工作,第二天,Glisse在全體會議上主持了關於該主題的另一次會議,他在其中深入研究了這項工作的動機。在許多情況下,名義上可寫的內存必須在一段時間內被全局寫保護。一種可能的用例是“內核重複內存”,其中內存頁在整個系統中都是重複的,以提高性能。在具有多個GPU的系統中,值得在多個頁面中複製輸入數據的副本,以便每個GPU都可以使用其全部可用帶寬訪問該數據。另一個是PCIe原子事務-256字節的事務必須等待控制器的確認,這可能是一個緩慢的過程。但是,如果在主機上對存儲器進行寫保護,則可以使其速度更快。然後,GPU(或其他遠程處理器)可以在不使用慢速原子操作的情況下完成其工作。

而且,通常,他希望最大程度地減少對mapping字段的依賴,並在頁面結構中開放一些空間以用於其他用途。

要達到這一目的,需要對現在使用mapping的位置以及可能存在的替代方法進行全面的瞭解。例如,與文件相關的系統調用使用了mapping,但是它們還提供了文件(以及mapping)作爲參數,因此它們不需要從struct page中獲取mapping。同樣,與內存相關的系統調用可以訪問正在操作的虛擬內存區域(VMA);可以在此處找到mapping。從用於塊I / O的BIO結構獲取映射信息可能會有些棘手。Glisse說,他希望BIO與mapping之間的關係不會改變,但是BIO實際上有時可以包含來自多個文件的頁面。這個問題可以解決,但是可能需要將mapping信息直接存儲在BIO結構中。

移走了大多數mapping的用戶後,可以使用指向新結構的指針替換該字段,從而添加一個間接級別。事實證明,內核同頁合併(KSM)機制已經做到了。因此,第一步可能是使mapping指向page_attachment結構(不同於前一天顯示的page_mapping結構),它將替換KSM機制並使之更加通用。

Boaz Harrosh提出了前一天已經提過的問題,即爲什麼是mapping而不是private。Glisse回答說,private以“有趣的方式”被使用。知道發生了什麼並不總是容易的。刪除mapping用戶要容易得多。

Dickins同意將mapping作爲目標是正確的。但是他建議,如果在很少的地方使用它,爲什麼不將替換struct放在某個固定位置,而是將它鏈接到頁面結構呢?答案似乎是,永遠不清楚一個特定的struct連接到mapping字段結束的時間。但是Dickins堅持認爲,將mapping指向始終有用的結構應該是有意義的。他(再次)說,mapping跟蹤頁面的標識,因此應將其替換爲仍能處理該功能的結構。

他繼續說道,當初添加anon_vma機制(以允許將匿名頁面映射回引用它們的任務)時,對mapping字段的使用被“捏造”以適應它。然後,KSM做了進一步的“捏造”。開發人員一直想避免更改內核中的每個文件系統,因此他們選擇了簡單的方法。但是,他說,如果Glisse願意爲徹底改變這一領域而做的工作,那麼他應該擺脫周圍的“特殊性”。

David Howells詢問是否可以完全消除address_space結構,而將必需的信息放回inode結構中。Glisse說,他希望看到這種情況發生,但是這樣做的前景令人望而生畏。他的計劃是先創建自己想要的功能,然後再考慮類似的大型任務。

前路

Glisse制定了他的工作推進計劃。它旨在最大限度地提高對更改的信心,然後再依賴它們。第一步是用調用輔助函數替換掉對mapping的所有引用,然後將修改使用mapping的低級函數以將該函數作爲參數。此更改將使用Coccinelle之類的工具完成,並且該參數的值一開始將爲NULL;該代碼將繼續使用mapping字段,並且將忽略新參數。

在隨後的開發週期中,將更改文件系統以將mapping信息向下傳遞到需要的位置。內存管理系統調用將看到類似的更改。在此過程中的某個時候,KSM機制將轉換爲更通用的方法。

這項工作完成後,應該有可能避免在幾乎所有情況下使用mapping。但是,對於之後的幾個發行版,代碼將繼續使用mapping,同時檢查以確保它與調用堆棧中傳遞的值匹配。這應該會使我們確信轉換已正確完成或者會指出轉換尚未完成的地方。一旦可信度達到足夠高的水平,就可以採取最後一步,並且不再使用mapping字段。

Harrosh說,很可能在某些地方兩個mapping值不匹配。這可能導致bug,或者是由於某種原因而導致實際mapping不是存儲在頁面結構中的mapping的地方。但是,Glisse計劃在實際使用mapping字段的地方進行測試,因此有望有效。

Dickins擔心這項工作聽起來像是大量的擾動。他說,他將需要更多地瞭解將帶來的好處。他說,這將需要文件系統開發人員“響亮的肯定”。梅森說,使文件之間的頁面共享更加容易是“很大的事情”,因此這對他來說是一項重要功能。就像這一連串討論的一樣,要在文件間共享page還需要克服很多挑戰,這個主題最終放到了一邊,因爲文件系統的開發者需要有時間在此做足夠的工作。

Dickins還建議,如果真正的目標是對頁面進行全局寫保護,則新的頁面標誌可能是解決該問題的更好方法。威廉姆斯則表示,真正的問題是用戶空間需要寫入頁面,而這個頁面正由諸如GPU之類的設備獨佔;正確的做法是後退然後說“不要那樣做”,該解決方案可能被認爲是向用戶空間不良行爲屈服。Glisse回答說,無法更改用戶空間的程序,它可能是使用了十年的程序,使用的庫已經過更新,可以加速GPU的操作。Williams說,解決該問題的方法是,如果應用程序需要更新的性能選項,則要求它們遷移到更新的庫。

Josef Bacik說,上述提議的機制解決了他遇到的與mapping有關的問題,因此,他很高興看到它的應用。Overstreet同意該更改將使許多用例受益。戴夫·漢森(Dave Hansen)表示,其好處可能不僅限於GPU,還包括擁有自己內存的其他設備。Dickins說,他對目標沒有其他意見,但他仍然不確定改變映射是否是實現目標的正確方法。但是他感到文件系統人員很高興有一個願意做這項工作的傻瓜,並且他們希望內存管理人員不要阻塞它。

威爾科克斯指出,其中一些問題以前已經解決過。 SGI在幾年前進行二進制文本複製。這促使約翰內斯·韋納(Johannes Weiner)觀察到,如果該小組已開始交流SGI軼事,那麼現在就該總結討論了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章