實施虛擬 A/B - 補丁

精選以下補丁來解決以下已知問題。

側載時正確檢查可分配空間

在超級分割區大小小於 *2 * sum(更新群組大小)* 的虛擬 A/B 裝置上旁載入完整 OTA 套件可能會失敗,並在復原日誌/tmp/recovery.log中顯示以下內容:

The maximum size of all groups with suffix _b (...) has exceeded half of allocatable space for dynamic partitions ...

這是日誌的範例:

[INFO:dynamic_partition_control_android.cc(1020)] Will overwrite existing partitions. Slot A may be unbootable until update finishes!
[...]
[ERROR:dynamic_partition_control_android.cc(803)] The maximum size of all groups with suffix _b (2147483648) has exceeded half of allocatable space for dynamic partitions 1073741824.

如果您遇到此問題,請選擇CL 1399393 ,重建並刷新啟動分割區或復原分割區(如果裝置不使用復原作為啟動)。

修復合併期間的分段錯誤

套用 OTA 更新後,在 VAB 合併過程中,呼叫update_engine_client --cancel會導致CleanupPreviousUpdateAction崩潰。當markSlotSuccessful遲到時,也存在潛在的野指針錯誤。

透過加入StopActionInternal函數解決了這個問題。 CleanupPreviousUpdateAction取消銷毀時的待處理任務。它維護一個變量,用於追蹤訊息循環中待處理任務的任務 ID。銷毀時,掛起的任務將取消以避免段錯誤。

確保 Android 11 原始碼樹中存在以下更改,以修復合併期間update_engine中的SIGSEGV當機:

  • CL 1439792 (CL 1439372 的先決條件)
  • CL 1439372CleanupPreviousUpdateAction :取消銷毀時的待處理任務)
  • CL 1663460 (修正markSlotSuccessful遲到時潛在的野指標錯誤)

修正 OTA 更新後 VAB 插槽切換不正確的問題

在 Android 11 及更高版本中,OTA 更新後無法同步裝置中的插槽開關可能會使裝置進入不可用狀態。如果IBootControl HAL 的槽切換實作執行寫入,則必須立即刷新這些寫入。如果寫入未刷新,且裝置在合併開始後重新啟動,但在硬體刷新插槽開關寫入之前,裝置可能會恢復到先前的插槽並無法啟動。

有關範例程式碼解決方案,請查看此 CL: CL 1535570

防止 update_engine 過早合併

當裝置啟動(Android 11 及更高版本)且啟動完成時, update_engine會呼叫ScheduleWaitMarkBootSuccessful()WaitForMergeOrSchedule() 。這將啟動合併過程。但是,設備會重新啟動到舊插槽。由於合併已經開始,設備無法啟動且無法操作。

將以下變更新增至您的原始程式碼樹。請注意,CL 1664859 是可選的。

  • CL 1439792 (CL 1439372 的先決條件)
  • CL 1439372CleanupPreviousUpdateAction :取消銷毀時的待處理任務)
  • CL 1663460 (修正markSlotSuccessful遲到時潛在的野指標錯誤)
  • CL 1664859 (可選 - 為CleanupPreviousUpdateAction新增unittest

防止因跳過元資料而導致資料遺失或損壞

在 Android 11 及更高版本中,如果儲存裝置具有揮發性回寫緩存,在某些情況下,已完成合併的元資料將被跳過,從而導致資料遺失或損壞。

狀況:

  1. 完成一組異常的合併操作後,呼叫merge_callback()
  2. 追蹤合併完成的 COW 裝置中的元資料已更新。 (COW 裝置的此更新已徹底刷新。)

結果:由於最近合併的儲存設備快取未刷新,系統崩潰。

請參閱以下內容來實施決議:

確保 dm-verity 配置正確

在 Android 11 及更高版本中,裝置可能會無意中配置以下 dm-verity 選項:

  • 核心中的CONFIG_DM_VERITY_AVB=y
  • 引導程式配置為使用任何驗證模式(例如AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE ),而不使用AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO

使用此設備配置,任何驗證錯誤都會導致 vbmeta 分區損壞,並導致非 A/B 設備無法操作。同樣,如果合併已經開始,A/B 設備也可能變得無法操作。僅使用AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO驗證模式。

  1. 在核心中設定CONFIG_DM_VERITY_AVB=n
  2. 將設備配置為使用AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO模式。

有關更多信息,並作為實踐問題,請參考 verity 文件:處理 dm-verity 錯誤

在緊急系統關閉期間跳過驗證工作以回應 I/O 錯誤

在 Android 11 及更高版本中,如果呼叫緊急系統關閉(如熱關閉的情況),則 dm 裝置可以處於作用中狀態,而區塊裝置無法再處理 I/O 請求。在這種狀態下,新的 dm I/O 請求或已經在處理的 I/O 請求處理的 I/O 錯誤可能會導致真實性損壞狀態,這是一種誤判。

若要在系統關閉時跳過驗證工作以回應 I/O 錯誤,請使用下列命令:

CL 1847875 (在關閉期間跳過驗證工作以回應 I/O 錯誤)

確保 DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED 已關閉

運行 4.19 核心或更早版本的 Android Go 裝置的核心配置中可能有DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=y 。此設定與 Virtual A/B 不相容,並且已知在同時啟用兩者時會導致罕見的頁面損壞問題。

對於核心 4.19 及更早版本,透過在核心配置中設定CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=n來停用它。

對於內核 5.4 及更高版本,程式碼已被刪除,且配置選項不可用。

確認合併文件配置正確

如果您分別建立系統映像和供應商映像,然後使用merge_target_files合併它們,則虛擬 A/B 配置可能會在合併過程中被錯誤刪除。若要驗證合併的目標檔案中的虛擬 A/B 配置是否正確,請套用下列修補程式: CL 2084183 (合併動態分割區資訊中的相同鍵/值對)

更新必要的元件

從 Android 13 開始, snapuserd已從供應商 ramdisk 遷移到通用 ramdisk。如果您的裝置要升級到 Android 13,則供應商 ramdisk 和通用 ramdisk 可能都包含snapuserd的副本。在這種情況下,虛擬 A/B 需要snapuserd的系統副本。若要確保snapuserd的正確副本已就位,請套用CL 2031243 (將snapuserd複製到first_stage_ramdisk)。