實施虛擬 A/B - 補丁

Cherry-pick 以下補丁可解決以下已知問題。

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

在具有小於 *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來晚時可能出現的野指針錯誤)

修復 VAB 不正確的插槽切換,發布 OTA 更新

在 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 (可選 - 為unittest添加CleanupPreviousUpdateAction

防止因跳過元數據而導致數據丟失或損壞

在 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 錯誤,請使用以下命令:

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 。此設置與虛擬 A/B 不兼容,並且已知當兩者同時啟用時會導致罕見的頁面損壞問題。

對於內核 4.19 及更早版本,通過在內核配置中設置CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=n來禁用它。

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