RFC-0226:Zircon Pager 寫回

RFC-0226:Zircon Pager 寫回
狀態已接受
領域
  • 核心
說明

提供核心支援,用於追蹤及寫回由頁面伺服器支援的 VMO

問題
毛皮變化
作者
審查人員
提交日期 (年-月-日)2023-04-13
審查日期 (年-月-日)2023-09-19

摘要

本文件說明 Zircon 核心支援哪些採用分頁式記憶體, 修改內容,然後將檔案寫回 (同步) 至網頁工具來源,例如儲存空間 磁碟。

提振精神

Zircon 支援建立由 VM 支援的 VMO (虛擬記憶體物件) Userspace 呼叫器服務,通常由檔案系統代管。個別檔案 以 VMO 的形式在記憶體中表示存取 VMO 的頁面時 使用者頁面判讀頁面顯示的錯誤內容來源 磁碟。

Zircon Pager API 最初僅支援唯讀檔案;沒有任何 將記憶體中遭隔離的 VMO 頁面 磁碟。此設計足以代管不可變的檔案系統,例如 blobfs 會在 Fuchsia 上提供所有執行檔和其他唯讀檔案。不過 基於檔案的一般用途檔案系統 內容可由用戶端修改,且需同步回磁碟。

如果沒有寫回支援,可變動的檔案系統 (例如 minfsfxfs) 將無法 也能運用需求分頁解決方法是可變動檔案系統 使用匿名 (非呼叫式) VMO 快取記憶體中的檔案 發布這些 VMO 本身的內容他們可能需要安排 整體記憶體容量 允許或拒絕要求將這些匿名 VMO 切換為支援呼叫的 VM, 即可視需要移除錯誤及撤銷,讓可變動的檔案系統更妥善地運用 記憶體用量寫回支援也讓可變動檔案系統的用戶端直接 執行讀取和寫入作業,而非依賴管道來查詢資料 受管道限制限制,速度可能非常慢。

在其餘部分,系統會交替使用「使用者呼叫器」和「檔案系統」 提供的文件。

相關人員

講師:

  • cpu@google.com

審查者:

  • adanis@google.com、csuter@google.com

諮詢:

  • brettw@google.com、cdrllrd@google.com、godtamit@google.com、 maniscalco@google.com、travisg@google.com

社交功能:

這個 RFC 經過了本機儲存空間團隊的設計審查。

需求條件

建議的設計旨在達成以下目標:

  1. 強化 Zircon 以支援寫回頁面式 VMO 的寫入作業 高效能的可變動檔案系統 (使用 Zircon 串流)。
  2. 支援透過 VM 對應 (也就是 mmap 的檔案) 讀取及寫入檔案。
  3. 提供使用者呼叫器,盡力清除骯髒的網頁,以減少 意外關機造成資料遺失的風險
  4. 在日後的疊代作業中,允許核心 (透過使用者呼叫器) 移除骯髒核心 回應系統記憶體壓力

以及一些非目標:

  1. 在使用者呼叫器啟動清除之外,核心不會 保證會清理骯髒頁面。儘管如此 未來發展可能會使無法控制未付帳款的數量 並據此啟動寫回要求
  2. 為防止因違反核心/網頁器通訊協定而造成的資料遺失, 而不是目標如果使用者呼叫器無法查詢骯髒網頁並把網頁寫回 停止對 VMO 的控制代碼 (或終止) 前,資料遺失可能會遺失 。

設計

總覽

建議的設計主要有以下兩種用途:

  • 檔案系統用戶端可透過核心物件的串流存取檔案 以納入檔案 VMO這大約是類似於 zx_vmo_read()zx_vmo_write(),因為在內部進行串流系統呼叫 包裝 VMO 讀取/寫入核心處理常式。
  • 檔案系統用戶端也可以mmap 檔案,後者大致會轉譯為 (使用 zx_vmar_map) 將檔案 VMO 對應至用戶端程序」地址 空白鍵。

為簡單起見,本文件的其餘部分將討論直接互動 透過 syscalls (zx_vmo_read/write) 或透過 VM 與檔案 VMO 搭配使用 對應 (zx_vmar_map)。

以下列舉幾個與寫回相關的互動範例

示例 1

  1. 檔案系統用戶端會對指定範圍的檔案 VMO 執行 zx_vmo_read()
  2. 由於 VMO 受到分頁式支援,因此核心會針對 取得關聯的使用者呼叫器
  3. 檔案系統代管的使用者頁面程式會執行這項要求。其供應 其中內容是從磁碟讀取的
  4. 檔案系統用戶端在 VMO 上執行 zx_vmo_write(),以達到相同的目的 範圍。先前在步驟 3 中填入 VMO 的頁面, 以寫入的方式修改的內容只會顯示在記憶體中 系統需要將資料反映於磁碟
  5. 使用者呼叫器向核心查詢 VMO 中的範圍 內容髒污 / 修改。這項作業可在定期背景清除時執行 或回應檔案系統要求的清除 用戶端。
  6. 使用者呼叫器將查詢的骯髒範圍寫入磁碟。在此 指出修改的檔案內容已成功保存到磁碟中。

示例 2

  1. 檔案系統用戶端使用 zx_vmar_map() 對應檔案 VMO。對應關係開始 地址:addr。用戶端讀取從 addr 開始的範圍。
  2. 與範例 1 相同。
  3. 與範例 1 相同。
  4. 檔案系統用戶端現在會從 addr 開始寫入相同的範圍。 因為已經填入了基準網頁,所以內容 會在記憶體中修改您必須將修改內容反映到以下位置的磁碟: 在某種程度上
  5. 與範例 1 相同。
  6. 與範例 1 相同。

此處的範例從執行寫入前的 VMO 讀取開始。請注意, 這個方法只會將使用者呼叫器區分成 以便清楚明確。用戶端可以直接寫入檔案偏移範圍, 記憶體;除非使用者呼叫器提供頁面,否則寫入作業只會遭到封鎖 首先。

以上兩個範例都假設檔案系統遵循覆寫模型 適合寫入;填入 (修訂) 頁面可直接寫入,無需 要求取得額外空間修改後的內容會寫回相同的 所以不需分配額外空間進行修改。 不過,fxfsminfs 等檔案系統使用複製/寫入 (CoW) 模型。 每個修改都需要新空間分配到磁碟。我們也要 需要有機制保留空間以寫入既有的頁面 承諾;步驟 4 已修改為等待該預留項目,然後才能寫入 繼續。

如要執行寫回作業,Zircon Pager API 擴充了支援下列項目:

  • 核心會封鎖使用者呼叫器指定 VMO 的寫入作業 遵循「寫入」架構,然後在使用者呼叫器 才能確認寫入
  • 核心會追蹤 VMO 中的骯髒頁面,並設有機制 將相關資訊提供給使用者呼叫器
  • 使用者呼叫器會向核心表示同步處理內部的骯髒範圍 VMO 和作業完成後,讓核心可以更新骯髒追蹤 狀態。
  • 核心也會向使用者顯示 VMO 大小調整作業的相關資訊。
  • 使用者呼叫器可讓使用者查詢核心追蹤的相關資訊 上次修改 VMO 的時間

建立呼叫器和 VMO

呼叫器建立 syscall 會保持不變,也就是使用 zx_pager_create() 建立呼叫器,並將 options 設為 0。

透過 zx_pager_create_vmo() 建立並相關聯的 VMO 這組金鑰會在網頁要求封包中使用 VMO。zx_pager_create_vmo() syscall 也支援新的 options 標記 ZX_VMO_TRAP_DIRTY。這表示核心應將任何寫入作業 並要求使用者確認寫入作業。 這個標記適用於在寫入模式下運作的檔案。更多內容 稍後會提供此標記的詳細資料。

// Create a VMO (returned via |out|) backed by |pager|. Pager requests will be
// queued on |port| and will contain the provided |key| as an identifier.
// |size| will be rounded up to the page boundary.
//
// |options| must be 0 or a combination of the following flags:
// ZX_VMO_RESIZABLE - if the VMO can be resized.
// ZX_VMO_TRAP_DIRTY - if writes to clean pages in the VMO should be trapped by the
// kernel and forwarded to the pager service for acknowledgement before proceeding
// with the write.
zx_status_t zx_pager_create_vmo(zx_handle_t pager,
                                uint32_t options,
                                zx_handle_t port,
                                uint64_t key,
                                uint64_t size,
                                zx_handle_t* out);

根據預設,所有受呼叫器支援的 VMO 都會視為可變動。這也適用於 實作唯讀檔案系統,無需額外付費。程式碼路徑 我們預計不會針對唯讀 VMO 執行修改頁面。如果 VMO 經修改 (或許是誤用),但使用者呼叫器從未 查詢中有問題的網頁,並嘗試寫回網頁, 只會保留在記憶體中。日後核心產生 寫入要求,使用者呼叫器可以處理這類要求的回傳要求 VMO 可當做錯誤或直接忽略。

提供 VMO 頁面

使用呼叫器 VMO 的頁面會隨需填入使用者呼叫器 zx_pager_supply_pages()。這段 Syscall 可與唯讀 VMO 搭配使用

回傳的頁面狀態

網頁工具支援的 VMO 可具有三種狀態頁面:DirtyCleanAwaitingClean。這些狀態已在 vm_page_t 中編碼。

如要在三種狀態之間轉換,請按照下列步驟操作:

  1. 新提供 zx_pager_supply_pages() 的頁面一開始 使用 Clean
  2. 頁面寫入後會轉換為 Dirty。如果 VMO 已 使用 ZX_VMO_TRAP_DIRTY 建立,則核心區塊會用於確認 DIRTY 要求從使用者呼叫器發出。更多相關資訊 稍後可取得互動項目。
  3. 使用者呼叫器透過 稍後執行 Sycall 作業
  4. 針對核心傳回的每個骯髒頁面,使用者呼叫器會叫用 Syscall 會向核心發出信號,表示正在開始寫入頁面。 將其狀態變更為 AwaitingClean
  5. 如果網頁寫入這個時間點之後,頁面狀態會變回 Dirty
  6. 使用者呼叫器完成寫入網頁後,再次發出 syscall。 如果此時頁面狀態是 AwaitingClean,會轉換為 Clean
  7. 如果使用者呼叫器在回覆訊息時遇到錯誤,網頁會留在 AwaitingClean。日後查詢骯髒網頁時,系統會同時傳回 AwaitingCleanDirty 網頁,方便使用者呼叫回條 可以選取「重新建立」,再次生成新的提示

下列狀態圖表顯示這些狀態之間的轉換。

骯髒狀態轉換圖表

AwaitingClean 必須視為個別狀態來追蹤,有幾種不同情況 原因:

  • 即使 CleanAwaitingClean 狀態的網頁轉換為 Dirty 時,使用者呼叫工具所處理的頁面 回覆方式與 Clean 網頁不同。Clean 頁 符合在記憶體壓力之下重組的資格 以免回收。

  • 核心需要知道哪個版本已寫回,以便順利寫入 可以在使用者呼叫器完成時正確轉換為 Clean。這是 重要的是區分 清除快取前的網頁寫入動作 (也就是 才能安全順利地將連接元件傳送至磁碟 傳回的問題

  • 我們可以避免在寫入開始時,使用者呼叫器發出 sys 呼叫 核心可在系統傳回AwaitingClean 網頁的一部分。不過 網頁提示所呈現的 而這樣就留有較長的時間,它就會再次清除。透過 讓寫法與包圍的視窗包圍曝光,這樣就提高了使用者 Pager 就可以順利將網頁移至 Clean 狀態。

為了更新骯髒狀態,核心會追蹤頁面寫入 透過 VMO 和串流寫入系統呼叫 以及透過 VM 對應請注意, 這適用於透過 VM 對應執行的任何寫入作業 使用者或核心所執行的作業,同樣適用於由核心完成的寫入作業 帶有 user_copy 作為系統呼叫 (例如 zx_channel_read()) 的一部分

在發出系統呼叫 (例如 zx_vmo_write()) 時推斷含有骯髒頁面的程序相當簡單明瞭。 因為範圍是您指定的範圍VMO 的另一個存取方式是 對應程序中的對應項目位址空間。如要追蹤 由頁面伺服器支援的 VMO,在移除寫入權限後,會開始執行可寫入的對應關係 對應的網頁表格項目中。因此,寫入內容會產生防護 復原寫入權限並標示頁面即可解決 狀態:Dirty

這裡提到的 Dirty 狀態是由 vm_page_t,即軟體追蹤的骯髒狀態。骯髒的位元追蹤為 ,但我們不建議使用該功能 衍生出網頁的骯髒狀態。我們需要追蹤 即使是不支援骯髒的舊版 arm64 平台,都難免有髒汙 個位元中的位元數。為了確保實作的一致性和簡單性 剛開始的時候,就沒有使用硬體的骯髒位元來推斷網頁的 骯髒 / 乾淨狀態依賴硬體頁面的表格位元 因此需要考慮頁面表格重組的小工具 在未來仰賴硬體位元

值得注意的是,只有直接由頁面工具背書的 VMO 才符合骯髒資格 追蹤。換句話說,未針對受呼叫器支援的 VMO 複製 CoW 副本 追蹤骯髒追蹤,您就不會看到任何寫回要求。屬於 複製的內容會取自上層頁面和頁面副本的分支 而是以獨立頁面的形式直接發布這些資源

為待處理的寫入保留空間

撰寫給 VMO,並加上標記以捕捉骯髒轉換的標記 ZX_VMO_TRAP_DIRTY 建立選項旗標,須經過 檔案系統這項解決方案分為兩個部分,以簡單的 v1 開頭 並更專注於正確性,而在第 1 版上 建構第 2 版 才需進行v1 提案主要為同步模型, 檔案系統會為新的寫入保留空間。第二版則是在 在核心中明確提供骯髒的預留配額,以及 VMO 如何套用配額,因此 讓核心自行追蹤預留項目如此一來,您就能根據 減少核心間的往返溝通 以及檔案系統

ZX_VMO_TRAP_DIRTY v1

ZX_VMO_TRAP_DIRTY VMO 建立旗標表示核心應順利傳輸 任何 Clean->Dirty 頁面轉場效果 (或 AwaitingClean->Dirty 轉換) VMO。如果寫入的頁面上尚未呈現骯髒的頁面,核心會 ZX_PAGER_VMO_DIRTY 呼叫器要求。如果是透過 VM 對應進行寫入,則要求 橫跨包含錯誤地址的單一網頁。針對串流/VMO 寫入 核心會針對 第一個需要寫入的範圍

[start, end) 範圍的骯髒要求如下所示。

zx_packet_page_request_t request {
    .command = ZX_PAGER_VMO_DIRTY,
    .flags = 0,
    // |offset| and |length| will be page-aligned.
    .offset = start,
    .length = end - start,
};

ZX_VMO_TRAP_DIRTY 建立旗標適用於以 CoW 編寫的檔案 模式以及「覆寫」模式的稀疏檔案未指定旗標時 網頁會標示為 Dirty,且在使用者不需呼叫的情況下繼續寫入;本 適用於以覆寫模式編寫的非稀疏檔案。

使用者呼叫器確認了以下 ZX_PAGER_VMO_DIRTY 要求: zx_pager_op_range():

  • ZX_PAGER_OP_DIRTY 會將非 Dirty 網頁的狀態設為 Dirty。 而核心會繼續執行遭封鎖的寫入作業。
  • ZX_PAGER_OP_FAIL 不會變更網頁目前的狀態,因此會導致 zx_vmo_write() 呼叫來源的寫入作業,會產生嚴重的頁面錯誤 VM 對應的例外狀況,以及傳回 zx_stream_write() 時 接受部分寫入作業成功
// |pager| is the pager handle.
// |pager_vmo| is the VMO handle.
// |offset| and |length| specify the range, i.e. [|offset|, |offset| + |length|).
//
// |op| can be:
//
// ZX_PAGER_OP_DIRTY - The userspace pager wants to transition pages in the range
// [offset, offset + length) from clean to dirty. This will unblock any writes that
// were waiting on ZX_PAGER_VMO_DIRTY page requests for the specified range.
// |data| must be 0.
//
// ZX_PAGER_OP_FAIL - The userspace pager failed to fulfill page requests for
// |pager_vmo| in the range [offset, offset + length) with command
// ZX_PAGER_VMO_READ or ZX_PAGER_VMO_DIRTY.
//
// |data| contains the error encountered, a zx_status_t error code sign-extended
// to a |uint64_t| value - permitted values are ZX_ERR_IO, ZX_ERR_IO_DATA_INTEGRITY,
// ZX_ERR_BAD_STATE and ZX_ERR_NO_SPACE.
zx_status_t zx_pager_op_range(zx_handle_t pager,
                              uint32_t op,
                              zx_handle_t pager_vmo,
                              uint64_t offset,
                              uint64_t length,
                              uint64_t data);

取決於檔案系統清除骯髒資料及標記頁面的頻率 Clean,如果網頁 都是由用戶端撰寫的如要避免這項成本,檔案系統可能會考慮延遲清除 而且時間越久,這並不是件好事 無法去除骯髒頁面,這類頁面會導致記憶體壓力 此外,資料清除間隔也可能提高資料遺失的可能性。 v2 提案嘗試降低用戶端的部分效能成本 寫入。

ZX_VMO_TRAP_DIRTY v2

將會新增 syscall zx_pager_set_dirty_pages_limit(),以指定 核心允許累積一定數量的骯髒頁面。 因此檔案系統為這些大量檔案預留空間 移除的骯髒頁面即為單頁簡介的限制,並預設為零。 您可以使用 zx_pager_set_dirty_pages_limit()。而 v1 設計基本上是以 上限設為零

zx_status_t zx_pager_set_dirty_pages_limit(zx_handle_t pager_handle,
                                           uint64_t num_dirty_pages);

這個核心會追蹤每個呼叫器的骯髒頁數 (如需進一步瞭解 符合追蹤資格的網頁), 會轉換至 Dirty,並在轉換至 Clean 時減少。核心 仍會像 v1 一樣規避每一個骯髒轉換 分配的 Dirty 上限。如果新的計數未超過限制,核心 會在不涉及使用者呼叫器的情況下繼續寫入。這是可預期的情況 是一般作業模式,因此能節省往返時間 也就是使用者呼叫器。

透過這個方法,使用者呼叫器必須傳達兩件事 核心:

  1. 網頁程式的骯髒上限
  2. 頁面清理後會計入該限制的網頁

2) 我們再次依賴 ZX_VMO_TRAP_DIRTY VMO 建立旗標。這個 旗標現在會觸發系統產生新型呼叫器要求的內容: ZX_VMO_DIRTY_MODE。當核心陷阱寫入時,它會查詢 檔案系統,藉此決定該系統是否應將這些網頁納入計算。 違反髒汙限制使用者呼叫器以 zx_pager_op_range 回應 兩種新的作業類型之一

  • ZX_PAGER_OP_DIRTY_MODE_POOLED 會告知核心,該範圍內的頁面 會計入每頁簡介數量限制。主要用於檔案 在 CoW 模式中運作,且適用於檔案在覆寫模式下的稀疏區域。

  • ZX_PAGER_OP_DIRTY_MODE_UNPOOLED 會告知核心特定範圍中的頁面。 也不會計入髒汙限制。非稀疏性 在「覆寫」模式下運作的稀疏檔案區域。

表示「ZX_PAGER_OP_DIRTY_MODE_POOLED」的網頁已轉換至 Dirty 在未超過 或呼叫器資料庫數量限制如果維護網頁會超出頁面錯誤上限 但核心會開始產生 ZX_PAGER_VMO_DIRTY 封包,即 預設模式,如第 1 版中所述還可以提供選用旗標來設定 未正常運作 (轉換至 Clean) 的骯髒模式 可節省日後寫入成本,以便產生 ZX_VMO_DIRTY_MODE 呼叫器要求。

這項設計可提供靈活彈性的模型,供檔案系統混合使用 處理 VMO 上幾種寫入模式以 CoW 模式編寫的檔案 透過 ZX_VMO_TRAP_DIRTY 建立的 VMO,網頁就能使用 Pooled 模式。同樣地,您可以在覆寫模式下使用 ZX_VMO_TRAP_DIRTY 旗標,並使用集區和未集區模式進行稀疏與 三個不稀疏區域。一律使用覆寫模式的檔案 ZX_VMO_TRAP_DIRTY 標記,而且他們也不需要支付 寫入頁面器要求成本的費用。

一旦使用者呼叫器開始收到ZX_PAGER_VMO_DIRTY 如果配額不清,則應開始清理網頁,以騰出空間 新的骯髒網頁使用完畢後,裝置就會發出訊號 zx_pager_set_dirty_pages_limit(),使用與之前或新配額相同的限制。 此呼叫之後,核心將繼續檢查累積的骯髒次數 以因應日後寫入的骯髒限制,並會產生 ZX_PAGER_VMO_DIRTY 要求系統傳送

ZX_VMO_TRAP_DIRTY v1 和 v2 之間的差異

第 1 版和第 2 版的主要差異在於 來追蹤預訂數量在第 1 版中,檔案系統會負責 會讓核心告知你 增加預留項目數量由於負責攔截 預留項目的潛在變更 (核心) 與實體不同 實際進行簿記 (檔案系統) 時,需要配合 兩者之間在第 2 版中,我們試著使用核心測試群組來放鬆這一點 也就是預留項目數量因此需要與檔案系統通訊 只有 - 1) VMO 範圍需設為啟用 (或停用) 核心 預訂追蹤和 2) 核心用盡預訂配額, 檔案系統必須介入

我們預期 2) 屬於極端案例,因為檔案系統會定期 將骯髒頁面排進磁碟中大多數通訊皆是 導致問題發生率為 1)。核心可以多次要求相同範圍的資訊 (例如:適用於橫跨重疊範圍的寫入作業),而類似的檔案系統則可 向核心多次提供相同範圍的備援資訊。 在網頁上設定骯髒模式,並不會真的 骯髒限制,因為只有在實際瀏覽網頁時, 。因此,檔案系統也可以在網頁上設定骯髒模式 盡可能減少日後呼叫器要求的效能成本 (多點考量,因為網頁移除程序可能會發生問題)。

正在發現骯髒範圍

使用者呼叫器需要某種機制來找出 VMO 中的骯髒網頁, 只能寫回這裡有兩種不同的模型:提取 這個模型會在使用者呼叫器查詢核心中的骯髒網頁資訊時建立這個模型, 推送模型,其中核心會傳送使用者呼叫器,指出含有骯髒頁面 寫入要求。初始設計是從更簡單的提取模型開始 並產生用來查詢 Syscall 的骯髒範圍範圍,如下所示:

// |pager| is the pager handle.
// |pager_vmo| is the vmo handle.
// |offset| and |length| specify the VMO range to query dirty pages within.
// Must be page-aligned.
//
// |buffer| points to an array of type |zx_vmo_dirty_range_t| defined as follows.
// typedef struct zx_vmo_dirty_range {
//   // Represents the range [offset, offset + length).
//   uint64_t offset;
//   uint64_t length;
//   // Any options applicable to the range.
//   // ZX_VMO_DIRTY_RANGE_IS_ZERO indicates that the range contains all zeros.
//   uint64_t options;
// } zx_vmo_dirty_range_t;
//
// |buffer_size| is the size of |buffer|.
//
// |actual| is an optional pointer to return the number of dirty ranges that were
// written to |buffer|.
//
// |avail| is an optional pointer to return the number of dirty ranges that are
// available to read. If |buffer| is insufficiently large, |avail| will be larger
// than |actual|.
//
// Upon success, |actual| will contain the number of dirty ranges that were copied
// out to |buffer|. The number of dirty ranges that are copied out to |buffer| is
// constrained by |buffer_size|, i.e. it is possible for there to exist more dirty
// ranges in [offset, offset + length) that could not be accommodated in |buffer|.
// The caller can assume than any range that had been made dirty prior to
// making the call will either be contained in |buffer|, or will have a start
// offset strictly greater than the last range in |buffer|. Therefore, the caller
// can advance |offset| and make another query to discover further dirty ranges,
// until |avail| is zero.
//
zx_status_t zx_pager_query_dirty_ranges(zx_handle_t pager,
                                        zx_handle_t pager_vmo,
                                        uint64_t offset,
                                        uint64_t length,
                                        void* buffer,
                                        size_t buffer_size,
                                        size_t* actual,
                                        size_t* avail);

使用者呼叫器應多次叫用這項查詢, 直到處理完所有骯髒頁面為止。

在提取模型中,清理頁面的比率完全取決於 檔案系統選擇查詢骯髒範圍並嘗試查詢的速率 寫入回應在某些情況下,核心本身需要 發出寫入頁面的要求,例如在記憶體壓力之下 可以清理並移除有問題的網頁核心可能會 在這個案例中,以 LRU 順序來針對骯髒網頁的寫回要求。目的在於 做為提示使用者呼叫器的提示,提高網頁使用率 因此網頁處理要求是否有延遲

VMO 中 [start, end) 骯髒範圍的寫入要求可能會如下所示: 後面。

zx_packet_page_request_t request {
    .command = ZX_PAGER_VMO_WRITEBACK,
    .flags = ZX_PAGER_MEMORY_PRESSURE,
    // |offset| and |length| will be page-aligned.
    .offset = start,
    .length = end - start,
};

寫出髒亂範圍

zx_pager_op_range() 系統呼叫已擴充,可支援兩個額外的作業。 ZX_PAGER_OP_WRITEBACK_BEGINZX_PAGER_OP_WRITEBACK_END,讓系統發送通知 使用者呼叫器開始時,會分別開始清除網頁和內容。

  • ZX_PAGER_OP_WRITEBACK_BEGIN 會變更 Google Analytics 中任何 Dirty 頁面的狀態 指定範圍是 AwaitingClean。如果 AwaitingCleanClean 狀態,然後保持這些狀態。
  • ZX_PAGER_OP_WRITEBACK_END 會變更以下項目中任何 AwaitingClean 網頁的狀態: 將指定範圍設為 Clean。系統會忽略所有既有的頁面 CleanDirty 的網頁,但其狀態維持不變。

如果在執行清除作業時發生任何錯誤,例如 ZX_PAGER_OP_WRITEBACK_BEGIN,但在 ZX_PAGER_OP_WRITEBACK_END之前,使用者 呼叫呼叫器無須執行其他操作。這些網頁仍保留在「AwaitingClean」中 並假設其他寫入作業未成功執行。當 再次對骯髒頁面進行查詢,就會包含 AwaitingClean 個網頁 與 Dirty 網頁一樣,使用者呼叫器可以嘗試寫回這些網頁 失敗的網頁。

// Supported |op| values are:
// ZX_PAGER_OP_WRITEBACK_BEGIN indicates that the user pager is about to
// begin writing back the specified range and the pages are marked |AwaitingClean|.
// ZX_PAGER_OP_WRITEBACK_END indicates that that user pager is done writing
// back the specified range and the pages are marked |Clean|.
//
// |pager| is the pager handle.
// |pager_vmo| is the VMO handle.
// |offset| and |length| specify the range to apply the |op| to, i.e. [|offset|,
// |offset| + |length|).
// For ZX_PAGER_OP_WRITEBACK_*, |data| is unused and should be 0.
zx_status_t zx_pager_op_range(zx_handle_t pager,
                              uint32_t op,
                              zx_handle_t pager_vmo,
                              uint64_t offset,
                              uint64_t length,
                              uint64_t data);

如果是 ZX_PAGER_OP_WRITEBACK_BEGIN,您可以選擇將 data 設為 ZX_VMO_DIRTY_RANGE_IS_ZERO 表示呼叫端想要寫回 指定為零這個程序的用途是讓呼叫端 處理 zx_pager_query_dirty_ranges() 所傳回範圍的 options已設為 ZX_VMO_DIRTY_RANGE_IS_ZERO。它可以確保 在查詢之後、寫入之前、之後建立的內容範圍 並未遺失,而是誤以假設仍為 0 並標示為 乾淨 (可收回)。

調整 VMO 大小

強制回應的 VMO 與匿名 (非呼叫式) VMO 不同 當 VMO 中沒有內容會經過處理。匿名 VMO 具有隱含初始值 如果內容為零,則未修訂頁面表示為零。系統不會 由頁面伺服器支援的 VMO,未修訂頁面並不表示為零;只是代表 表示網頁尚未為這些網頁提供內容。調整成 不過,網頁工具無法提供新延伸 只是因為該內容不存在於支援來源中 (例如 儲存空間磁碟),因此沒有可分頁的內容。核心可以提供 使網頁中的網頁視為 0,不需參考使用者呼叫器。

調整大小是由追蹤零間隔進行處理,範圍涵蓋剛調整過的 範圍,核心默示提供零個頁面。使用者呼叫器是 還不知道這個零區間,因此在 使用者呼叫器查詢的骯髒範圍此外, 已將「zx_vmo_dirty_range_t」設為 ZX_VMO_DIRTY_RANGE_IS_ZERO。 表示其為零

如果 VMO 已使用 ZX_VMO_TRAP_DIRTY 旗標建立, 在這個新擴充的範圍內進行寫入時,核心會產生 在提交 ZX_PAGER_VMO_DIRTY 頁呼叫器要求前。這是 因為檔案系統可能需要為實際 (非零) 保留空間。 此模型假設 將檔案系統視為稀疏區域,因此只有在 最新的延伸範圍

將 VMO 從分頁器卸離

zx_pager_detach_vmo() 會將 ZX_PAGER_COMPLETE 封包排入佇列, 使用者呼叫器應該不會再看到 VMO 的後續頁面要求 這也表示使用者呼叫器應查詢並寫回任何 未成年的骯髒網頁請注意,卸離後,直到髒亂為止 網頁已寫回;只會告知使用者

卸離後,zx_vmo_read() / zx_vmo_write() 需要 產生呼叫器要求失敗,並顯示 ZX_ERR_BAD_STATE。讀取與寫入 找出類似網頁伺服器要求會產生要求的對應 嚴重例外狀況。這個核心可以隨意捨棄 VMO。不過,核心會一直保留著髒頁面,直到遭到清除 使用者呼叫器也就是說,ZX_PAGER_OP_WRITEBACK_BEGINZX_PAGER_OP_WRITEBACK_END 將繼續受到支援 (即使 VMO) 已卸離所有其他作業的 zx_pager_op_range(),以及 zx_pager_supply_pages() 在卸離的 Vmo 上執行 ZX_ERR_BAD_STATE 失敗。

如果呼叫器在關聯 VMO 中的骯髒頁面被刪除,核心就會是 您可以在移除時任意移除這些網頁,不論網頁是否 待處理的寫入要求換句話說,如果網頁未經檢索 才會保留在記憶體中,前提是呼叫器可清除這些物件。

查詢呼叫器 VMO 統計資料

核心也會追蹤 VMO 是否已修改,如要查詢 VMO 是否修改 使用者呼叫器這個號碼可供使用者呼叫器用來追蹤「mtime」。

// |pager| is the pager handle.
// |pager_vmo| is the VMO handle.
// |options| can be ZX_PAGER_RESET_VMO_STATS to reset the queried stats.
// |buffer| points to a struct of type |zx_pager_vmo_stats_t|.
// |buffer_size| is the size of the buffer and should be large enough to
// accommodate |zx_pager_vmo_stats_t|.
//
// typedef struct zx_pager_vmo_stats {
//   uint32_t modified;
// } zx_pager_vmo_stats_t;
zx_status_t zx_pager_query_vmo_stats(zx_handle_t pager,
                                     zx_handle_t pager_vmo,
                                     uint32_t options,
                                     void* buffer,
                                     size_t buffer_size);

傳回 zx_pager_vmo_stats_tmodified 欄位已設為 ZX_PAGER_VMO_STATS_MODIFIED 表示 VMO 已修改,否則為 0。 日後可以擴充包含更多欄位的 zx_pager_vmo_stats_t 結構體 方便使用者查詢

modified 狀態已在系統修改 VMO 的系統呼叫上更新,例如 zx_vmo_write()zx_vmo_set_size(),以及第一次寫入頁面 錯誤流傳網頁上第一個寫入錯誤 已正確追蹤 Clean 轉換為 Dirty 的轉換作業,因此 隨後會更新 modified 狀態。日後透過對應作業進來的寫入作業 系統不會追蹤骯髒網頁;這會大幅拖慢執行速度 寫入對應的 VMO。因此 modified 狀態不一定完全準確 對應的 VMO

如果使用者呼叫器也想執行以下動作,options 可以是 ZX_PAGER_RESET_VMO_STATS 重設查詢的統計資料。options 的值為 0 不會重設任何狀態, 執行純查詢請注意,這個呼叫可能在未來 zx_pager_query_vmo_stats() 呼叫方法,方法是使用可查詢的狀態, 已指定 ZX_PAGER_RESET_VMO_STATS 選項。舉例來說 zx_vmo_write()後面加上兩個連續的 zx_pager_query_vmo_stats() 呼叫 ZX_PAGER_RESET_VMO_STATS 選項,則只有第一個選項 請參閱已設定的modified。因為在第一次嘗試 zx_pager_query_vmo_stats(),第二個zx_pager_query_vmo_stats()會 傳回 modified 為 0。

實作

翻頁寫入功能已有一段時間,所有新的 API 部分已開發完成 可在 @next vDSO 中使用。fxfs 已採用寫回 API 來提供支援 以及串流讀取/寫入和 mmap

成效

透過翻頁寫入功能,fxfs 可以從執行 I/O 切換作業開始 新增串流管理頻道 許多基準都進行改善

安全性考量

無。

隱私權注意事項

無。

測試

我們編寫了核心核心測試和壓力測試,用於練習呼叫器 syscalls另外還有儲存空間測試和效能基準。

說明文件

核心 syscall 說明文件已更新。

缺點、替代方案和未知

頻率限制寫回要求的頻率

在核心日後的疊代作業產生寫入要求時, 也就是記憶體壓力或背景穩定時,我們需要 政策,控管在頁面器通訊埠排入佇列的寫入要求數量。 其中一個選項是讓核心追蹤 記得不要超過特定限制

另一個選項是由使用者呼叫器設定可微調的項目 也就是直接或間接產生寫回要求的頻率。例如: 使用者呼叫器可以指定建議的離開網頁時間長度 送出佇列前的緩衝時間,或是使用者一般資料傳輸速率 Pager 可支援寫入功能。某些檔案系統可能需要背景 比全域系統預設值高出許多其他可能 也很適合使用者呼叫器指定精細程度 (系統頁面的多個頁面) 才能夠處理要求接著,核心可以把這點 ,並能產生較少要求 。

追蹤及查詢網頁年齡資訊

在初始實作中,核心會追蹤頁面佇列中的骯髒頁面。 而是根據網頁首次遭到隔離時的順序來排列。這個佇列可用於 系統可以在清除網頁後產生寫入要求 且可以從中途排出,移至 (清理) 呼叫佇列的 (清理) 頁面佇列。 。您可能需要 追蹤骯髒網頁的年齡;建議你拆分髒汙和乾淨 將網頁整合到通用集區中,以便使用老式和存取的位元追蹤功能 w.r.t.形成全球工作組我們也可能會想 透過新的 API 傳送至使用者呼叫器,以便在處理時將其納入考量 寫入要求。

在寫回期間封鎖進一步寫入

此處提議的設計並不會封鎖同時傳入的新寫入 寫回作業正在進行中,亦即在 ZX_PAGER_OP_WRITEBACK_BEGINZX_PAGER_OP_WRITEBACK_END。取而代之的是 再次標示為骯髒也許某些檔案系統會想要封鎖 網頁處於 AwaitingClean 狀態時。建議加上 未來的 ZX_PAGER_OP_WRITEBACK_BEING_SYNC 會封鎖寫入作業期間的寫入作業 寫入回應請注意,ZX_VMO_TRAP_DIRTY v1 確實可以解決這個問題 並傳回 ZX_PAGER_VMO_DIRTY 呼叫器要求,而檔案系統可保留此要求 需要特別注意

既有藝術品和參考資料