精選以下補丁來解決以下已知問題。
側載時正確檢查可分配空間
在超級分割區大小小於 *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 1439372 (
CleanupPreviousUpdateAction
:取消銷毀時的待處理任務) - 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 1439372 (
CleanupPreviousUpdateAction
:取消銷毀時的待處理任務) - CL 1663460 (修正
markSlotSuccessful
遲到時潛在的野指標錯誤) - CL 1664859 (可選 - 為
CleanupPreviousUpdateAction
新增unittest
)
防止因跳過元資料而導致資料遺失或損壞
在 Android 11 及更高版本中,如果儲存裝置具有揮發性回寫緩存,在某些情況下,已完成合併的元資料將被跳過,從而導致資料遺失或損壞。
狀況:
- 完成一組異常的合併操作後,呼叫
merge_callback()
。 - 追蹤合併完成的 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
驗證模式。
- 在核心中設定
CONFIG_DM_VERITY_AVB=n
- 將設備配置為使用
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)。