RFC-0236:VMO 快照-修改的本機副本

RFC-0236:VMO 快照-修改的本機副本
狀態已接受
區域
  • 核心
說明

目標是導入新的 VMO 子項類型,可拍攝快照,擷取在呼叫器支援的 VMO 中任何修改後的頁面。

問題
變更
  • 883471
作者
審查人員
提交日期 (年/月)2023-07-20
審查日期 (年/月)2023-12-12

摘要

目標是導入新的 VMO 子項類型,可讓在受呼叫 VM 支援的 VMO 子項中,拍攝任何修改過的頁面快照。

提振精神

目前的核心支援兩種 VMO 本機副本 (也稱為子項 VMO):是的快照,因為複製作業完成後,VMO 不會看見彼此的變更,以及快照時寫入的本機副本。作業完成後,子項可以查看父項 VMO 上的變更,已寫入子項的頁面除外。

複製作業可在 VMO 副本本身重複執行,建立子項 VMO 的階層。為方便實作 Zircon 核心,不允許混合階層,您可以建立真實快照的階層或寫入時 VMO 的階層。

隨著 Starnix 的問世,Fuchsia 也必須有效支援 fork()。 分支需要將父項程序的完整位址空間複製到子項程序,包括匿名記憶體,以及呼叫器支援的資料和 VMO。

發生問題是因為核心僅支援匿名記憶體的真實快照,而對分頁式 VMO 支援的 VMO 僅支援寫入快照的本機副本。因此,複製功能無法滿足 Fork() 合約,所以強制 Starnix 實作 Eager 副本和/或其他 CPU 和記憶體密集型解決方法。

相關人員

誰擔心是否接受這個 RFC?(本節為選填,但建議填寫)。

csuter@google.com、jamesr@google.com

講師:

davemoore@google.com

審查者:

rashaeqbal@google.com、jamesr@google.com

顧問:

列出應審查 RFC,但不需要經過核准的人員。

csuter@google.com、adanis@google.com、cpu@google.com、mvanotti@google.com、lindkvist@google.com

社群媒體化:

一位 Zircon 團隊和部分 Starnix 成員聯手設計了一份設計文件,並與相關人員分享正在進行基準測試的計畫。

相關規定

  • 對於同時包含分頁式 VMO 和匿名 VMO 的複製位址空間支援。
  • 無論父項 VMO 或子項 VMO 有程序 (最後處理是關閉) 無法存取 VMO,您不應浪費記憶體。也就是說,以下兩種情況:
vmo = create_vmo();
   loop {
      child = create_snapshot_modified(vmo)
      child.write(...)
      vmo = child  // old vmo is dropped
   }
vmo = create_vmo();
   loop {
      vmo.write(...)
      child = create_snapshot_modified(vmo)
      // child is dropped
   }

設計

ZX_VMO_CHILD_SNAPSHOT_MODIFIED 是新的 VMO 本機副本類型,可建立經過快照修改的子項類型。

此標記會建立一個子項,用於保留由支援 Pager 的 VMO 的子項修改的任何頁面快照。就概念上來說,就像簡易副本會在父項中未由 Pager 支援的任何頁面上執行。如果父項中由 Pager 支援的頁面,則至少要在複製時執行複製語意。這與原始快照語意不同,後者的運作方式就像在 VMO 的所有頁面上建立快速副本一樣。

在由 Pager 支援的 VMO 上首次使用時,語意行為與使用 SNAPSHOT_AT_LEAST_ON_WRITE 一樣。系統會建立本機副本的控制代碼,這個控點一開始與父項相同,但可以對本機副本進行修改,導致差異變得不一致。

與任何匿名 VMO 搭配使用時,SNAPSHOT_MODIFIED 副本會升級以具有快照語意,類似於 SNAPSHOT_AT_LEAST_ON_WRITE 使用的現有複製類型升級語意。

如果 VMO 具有固定區域、配量或 VMO,使其以 zx_vmo_create_physical()zx_vmo_create_contiguous() 結尾,則無法複製此標記。

保護殼

已在支援分頁功能的 VMO 上修改快照

建立以分頁系統為基礎的 VMO 單一 SNAPSHOT_MODIFIED 副本時,其行為會如同已建立單一 SNAPSHOT_AT_LEAST_ON_WRITE 副本。執行本機複製時,新的 VMO 會與父項相同。

在此之前,您仍可以修改此副本,直到對本機副本執行另一個 SNAPSHOT_MODIFIED 為止。本機副本中所有未經修改的頁面都至少有複製時複製的語意。

經過至少 - 寫入或經過修改的快照後修改快照

的 VMO 數量

由於 SNAPSHOT_MODIFIEDSNAPSHOT_AT_LEAST_ON_WRITE 在支援 Pager 的 VMO 上的行為相同,因此兩次在受 Pager 支援的本機副本上呼叫 SNAPSHOT_MODIFIED 時,都會產生相同的語意。凡是不再透過分頁器支援的頁面,都會有快照,而使用 Pager 支援的頁面則會有備用的複製時複製語意。

已在建立快照後修改快照

在此情況下,語意會升級為快照,與 snapshot-at-least-on-write 類似。

不支援的案件

目前不支援以下情況,如果嘗試複製 SNAPSHOT_MODIFIED,會傳回 ZX_ERR_NOT_SUPPORTED

已修改快照位置 (至少處理時) 的快照結束

經過修改的快照可能可以擴充,以在 snapshot-at-least-on-write 鏈結的結尾使用。這可能會造成混淆,但來自複製的 VMO 的未分支頁面可以透過單向 VMO 鏈結全部看到修改,最接近讀取的相對關係。這會造成與原始承諾不一致,指出使用者可以建立任何已修改的頁面快照。

已修改快照位置 (至少處理時) 鏈結的中間部分

含有子項的 VMO 一律無法使用經過修改的快照,這類 VM 可能在含有子項的 VMO 中 (例如在寫入時位於快照的鏈結中),因為這樣可能會導致階層結構不一致。

命名法

zx_vmo_create_child() 中現有的副本類型標記命名慣例是要透過描述所提供語意的方式命名標記。此標記目前的名稱是 SNAPSHOT_MODIFIED,因為該標記總結了在本機副本中修改的頁面是如何建立快照的行為。類似的選項為 SNAPSHOT_MODIFICATIONS。其他考慮到的標記是 SNAPSHOT_MIXED,用於說明語意,但 SNAPSHOT_PAGER_MODIFICATIONS 較不明顯,但並不適合將 VMO 與呼叫器搭配使用。

實作

修改快照會影響 Zircon 中的多個檔案,但您可以細分為 CL,以便在核心內部新增對新快照類型的支援,再將選項標記新增至系統呼叫。

我們會在第一階段新增一些核心測試,以驗證新結構的正確行為。此外,我們也會加入選項旗標,納入更複雜的核心測試。

效能

在大多數情況下,只有在新建已修改快照的本機副本時,系統才會呼叫新增的程式碼,因此現有程式碼的效能不會改變。有一個例外狀況是,在建立 SNAPSHOT_AT_LEAST_ON_WRITE 子項時,一般方法會加入額外的 VMO 鎖定,但如果這會對效能造成負面影響,可能會再重構複製選取程式碼來避免這種情況。

安全性考量

透過現有的 Zircon 基元進行建構,且未導入新功能,修改快照功能不太可能導入任何安全漏洞。

測試

相關 CL 將包含核心單元測試和核心測試。

說明文件

我們即將推出針對 Zircon 開發人員的詳細設計文件。該指南將概述新的資料結構、支援和不支援的案例,以及程式碼的變更、挑戰和替代方案。

系統隨即會在 zx_vmo_create_child() 中新增標記,並提供說明:

ZX_VMO_CHILD_SNAPSHOT_MODIFIED - 建立子項,如同在父項中非由 Pager 支援的任何頁面上執行,亦即已由受 Pager 支援的 VMO 子項修改的網頁。透過 Pager 支援的頁面至少會有寫入時複製的語意。這個標記可能無法用於透過 zx_vmo_create_physical()、zx_vmo_create_continueiguous()、包含固定頁面的 VMO,或是這類 VMO 的子系建立的 VMO。使用 SNAPSHOT_AT_LEAST_ON_WRITE 建立且具有非配量子項,或並非受呼叫器支援的 VMO 子項的任何 VMO 也不支援此旗標。

缺點、替代方案和未知

為受呼叫器支援的 VMO 建立快照語意並不容易,只要使用現有的 Zircon VMO 原始項目即可。使用者呼叫器運作的方式為提供對單一 VMO 的頁面要求,而呈現其子項則會形成具有寫入時複製語意的單一單向鏈結。

可在匿名 VMO 上使用的快照旗標會建立隱藏的 VmCowPages,這是目標 VMO 及其新的快照的共同祖系。由於沒有指向隱藏 VmCowPages 的隱藏 VmCowPages,所以無法改變其頁面。這個隱藏的 VmCowPages 會保留目標 VMO 中的頁面,而子項修改具有寫入時的語意。因此,在這個階層中搜尋頁面時,會向上探索樹狀結構中最後的樹狀結構。

由於根 VMO 一律將隱藏,而原始 VMO 會變成左側子項,因此很難將現有的快照資料結構用於 Pager 使用。如果 Pager 仍指向原始 VMO (現在具有隱藏的父項),則分頁作業必須傳播至隱藏的根層級,以便在子項要求時提供頁面。這會在將頁面新增至非運作中的節點時,造成不一致。

最簡單的解決方法是建立混合階層,在根層級可見,並有一個隱藏的子項做為快照樹狀結構的隱藏根。

向使用者說明所提供的語意有很多種。RFC 中的說明概述提供了與 Pager 相關的已知行為,但另一個頁框頁框僅可用於修改及複製頁面。範例如下:

「這個旗標會建立一個子項,用於保留父項中所有已修改頁面的快照。如果根 vmo 會在快照發生後寫入未經修改的頁面,則經過修改的子項就會看到變更。這與原始快照語意不同,後者的行為就像建立快速副本一樣。

儘管此說明正確無誤,但需要特別說明此行為需要使用 Pager 的注意事項,因為在匿名 VMO 上使用標記時,標記會升級至快照語意。

可以 SNAPSHOT_MODIFIED 取代 SNAPSHOT_AT_LEAST_ON_WRITE 嗎?

如果是在寫入時逐步淘汰快照,並將其替換為經過修改的快照,因為這兩個副本類型的語意不同,這可能會導致意外行為。雖然這兩種副本類型都提供「至少複製時複製」的語意,但建立快照時,在同一個 VMO 中可混合使用快照和寫入最少的頁面。此外,這項變更需要效能測試。當 VMO 支援分頁作業時,由於沒有隱藏的通用祖系,因此快照建立時,系統會在每個本機副本建立較少的記憶體,因此,遷移所有使用快照時 (即至少寫入一次) 的行為,可能會在部分使用情境中造成效能迴歸。

不過,您可能值得研究替換 SNAPSHOT_AT_LEAST_ON_WRITE,因為這會簡化 zx_vmo_create_child() 的 API,做為大多數 Fdio 的輔助程式承諾與 SNAPSHOT_MODIFIED 相容的語意。

先前的圖片和參考資料

zx_vmo_create_child()