虛擬 A/B 概述

Android 有兩種更新機制:A/B(無縫)更新和非 A/B 更新。為了降低代碼複雜度並增強更新過程,在 Android 11 中,這兩種機制通過虛擬 A/B 統一起來,以最小化存儲成本為所有設備帶來無縫更新。 Android 12 提供了虛擬 A/B 壓縮選項來壓縮快照分區。在 Android 11 和 Android 12 中,以下內容均適用:

  • 虛擬 A/B 更新與 A/B 更新一樣無縫。虛擬 A/B 更新可最大限度地減少設備脫機和不可用的時間。
  • 虛擬 A/B 更新可以回滾。如果新操作系統無法啟動,設備會自動回滾到之前的版本。
  • 虛擬 A/B 更新通過僅複製引導加載程序使用的分區來使用最少的額外空間。其他可更新分區被快照

背景和術語

本節定義了術語並描述了支持虛擬 A/B 的技術。

設備映射器

Device-mapper 是 Android 中經常使用的 Linux 虛擬塊層。使用動態分區,像/system這樣的分區是一堆分層設備:

  • 堆棧的底部是物理超級分區(例如/dev/block/by-name/super )。
  • 中間是一個dm-linear設備,指定超級分區中的哪些塊形成給定的分區。這在 A/B 設備上顯示為/dev/block/mapper/system_[a|b] ,在非 A/B 設備上顯示為 /dev/ /dev/block/mapper/system
  • 頂部是一個dm-verity設備,為已驗證的分區創建。該設備驗證dm-linear設備上的塊是否已正確簽名。它顯示為/dev/block/mapper/system-verity並且是/system安裝點的來源。

圖 1 顯示了/system掛載點下的堆棧的樣子。

Partition stacking underneath system

圖 1. /system 掛載點下的堆棧

dm-快照

虛擬 A/B 依賴於dm-snapshot ,這是一個設備映射器模塊,用於對存儲設備的狀態進行快照。使用dm-snapshot時,有四個設備在運行:

  • 基本設備是快照的設備。在此頁面上,基本設備始終是動態分區,例如係統或供應商。
  • 寫時復制(COW) 設備,用於記錄對基本設備的更改。它可以是任意大小,但必須足夠大以適應對基本設備的所有更改。
  • 快照設備是使用snapshot目標創建的。對快照設備的寫入將寫入 COW 設備。從快照設備讀取從基本設備​​或 COW 設備讀取,具體取決於正在訪問的數據是否已被快照更改。
  • 設備是使用snapshot-origin目標創建的。直接從基礎設備讀取到源設備。寫入源設備直接寫入基礎設備,但通過寫入COW設備備份原始數據。

Device mapping for dm-snapshot

圖 2. dm-snapshot 的設備映射

壓縮快照

在 Android 12 中,由於/data分區的空間要求可能很高,您可以在構建中啟用壓縮快照來解決/data分區的更高空間要求。

虛擬 A/B 壓縮快照基於 Android 12 中可用的兩個新組件構建:

  • dm-user ,一個類似於 FUSE 的內核模塊,允許用戶空間實現塊設備。
  • snapuserd ,一個用戶空間守護進程,用於實現新的快照格式。

這些組件啟用壓縮。為實現壓縮快照功能所做的其他必要更改將在下一節中給出:壓縮快照的 COW 格式dm-userSnapuserd

壓縮快照的 COW 格式

在 Android 12 中,壓縮快照使用新的 COW 格式。與用於未壓縮快照的內核內置格式類似,壓縮快照的 COW 格式具有元數據和數據的交替部分。原始格式的元數據只允許“替換”操作:將基礎映像中的塊X替換為快照中塊Y的內容。壓縮快照 COW 格式更具表現力,支持三種操作:

  • 複製- 基礎設備中的塊X應替換為基礎設備中的塊Y。
  • 替換- 基礎設備中的塊X應替換為快照中塊Y的內容。這些塊中的每一個都經過 gz 壓縮。
  • - 基本設備中的塊X應替換為全零。

完整的 OTA 更新僅包括替換歸零操作。增量 OTA 更新還可以具有復制操作。

Android 12 中的 dm 用戶

dm-user 內核模塊使userspace能夠實現設備映射器塊設備。 dm-user 表條目在/dev/dm-user/<control-name>下創建了一個雜項設備。 userspace進程可以輪詢設備以接收來自內核的讀寫請求。每個請求都有一個關聯的緩衝區供用戶空間填充(用於讀取)或傳播(用於寫入)。

dm-user內核模塊為內核提供了一個新的用戶可見界面,該界面不屬於上游 kernel.org 代碼庫的一部分。在此之前,Google 保留修改 Android 中的dm-user界面的權利。

快照用戶

dm-usersnapuserd用戶空間組件實現了虛擬 A/B 壓縮。

在 Virtual A/B 的未壓縮版本中(在 Android 11 及更低版本中,或在沒有壓縮快照選項的 Android 12 中),COW 設備是原始文件。啟用壓縮後,COW 將作為dm-user設備運行,該設備連接到snapuserd守護程序的實例。

內核不使用新的 COW 格式。所以snapuserd組件在 Android COW 格式和內核內置格式之間轉換請求:

Snapuserd component translating requests between Android COW format and kernel built-in format

圖 3. snapuserd 作為 Android 和 Kernel COW 格式之間的轉換器的流程圖

這種轉換和解壓縮永遠不會發生在磁盤上。 snapuserd組件攔截發生在內核中的 COW 讀取和寫入,並使用 Android COW 格式實現它們。

虛擬 A/B 壓縮過程

這些部分提供了有關虛擬 A/B 壓縮中使用的過程的詳細信息:讀取元數據、合併和執行初始化轉換。

讀取元數據

元數據由snapuserd守護進程構建。元數據主要是 2 個 ID 的映射,每個 8 字節,表示要合併的扇區。在dm-snapshot中,它被稱為disk_exception

struct disk_exception {
    uint64_t old_chunk;
    uint64_t new_chunk;
};

當舊數據塊被新數據替換時,會使用磁盤異常。

Snapuserd守護程序通過 COW 庫讀取內部 COW 文件,並為 COW 文件中存在的每個 COW 操作構造元數據。

創建 dm- dm- snapshot設備時,從內核中的dm-snapshot啟動元數據讀取。

下圖提供了元數據構建的 IO 路徑的時序圖。

Sequence diagram, IO path for metadata construction

圖 4.元數據構建中 IO 路徑的序列流

合併

引導過程完成後,更新引擎會將插槽標記為引導成功,並通過將dm-snapshot目標切換到dm-snapshot-merge目標來啟動合併。

dm-snapshot遍曆元數據並為每個磁盤異常啟動一個合併 IO。下面顯示了合併 IO 路徑的高級概述。

Merge IO path

圖 5.合併 IO 路徑概覽

如果設備在合併過程中重新啟動,則合併在下次重新啟動時恢復,合併完成。

初始化轉換

使用壓縮快照啟動時,第一階段 init 必須啟動snapuserd以掛載分區。這帶來了一個問題:當sepolicy被加載和執行時, snapuserd被置於錯誤的上下文中,並且它的讀取請求失敗,並被 selinux 拒絕。

為了解決這個問題, snapuserdinit同步轉換,如下所示:

  1. 第一階段init從 ramdisk 啟動snapuserd ,並將打開的文件描述符保存在環境變量中。
  2. 第一階段init將根文件系統切換到系統分區,然後執行init的系統副本。
  3. init的系統副本將組合的 sepolicy 讀入一個字符串。
  4. Init在所有 ext4 支持的頁面上調用mlock() 。然後,它會停用快照設備的所有設備映射表,並停止snapuserd 。在此之後,禁止從分區讀取,因為這樣做會導致死鎖。
  5. 使用snapuserd的 ramdisk 副本的打開描述符, init使用正確的 selinux 上下文重新啟動守護程序。重新激活快照設備的設備映射表。
  6. Init 調用munlockall() - 再次執行 IO 是安全的。

空間使用

下表提供了使用 Pixel 的操作系統和 OTA 大小的不同 OTA 機制的空間使用比較。

尺寸影響非 A/B甲/乙虛擬 A/B虛擬 A/B(壓縮)
原廠圖片4.5GB超級(3.8G圖片+700M預留) 1 9GB 超級(3.8G + 700M 預留,兩個插槽) 4.5GB超級(3.8G圖片+700M預留) 4.5GB超級(3.8G圖片+700M預留)
其他靜態分區/緩存沒有任何沒有任何沒有任何
OTA期間的額外存儲(應用OTA後返回的空間) /data 1.4GB 0 /data 3.8GB 2 /data 2.1GB 2
應用 OTA 所需的總存儲空間5.9GB 3 (超級和數據) 9GB(超級) 8.3GB 3 (超級和數據) 6.6GB 3 (超級和數據)

1表示基於像素映射的假定佈局。

2假設新系統映像與原始系統映像大小相同。

3空間需求是暫時的,直到重新啟動。

要實施虛擬 A/B,或使用壓縮快照功能,請參閱實施虛擬 A/B