User Data Checkpoint(UDC)


背景

​ 由於AB升級的回滾機制只支持到early_boot階段,如果OTA升級的過程中,data分區被修改了,並且OTA升級失敗了,則data分區是無法回滾到之前的狀態的。UDC功能是為了解決OTA升級失敗后,當data分區被修改后,不支持回滾data分區的問題。UDC同時支持綁定key版本以及防止key回滾的功能。

實現機制

​ 對於f2fs,UDC添加checkpoint功能到4.20版本的內核中,其他版本的內核也可以移植該功能過去。所以,f2fs系統是默認支持checkpoint功能的。對於在 /data 裝載的設備,請將 checkpoint=fs 標記添加到 fstab 的 <fs_mgr_flags> 部分。

​ 對於其他文件系統,UDC會使用dm-bow,必須在內核配置中啟用 dm-bow。對於在 /data 裝載的設備,請將 checkpoint=block 標記添加到 fstab 的 <fs_mgr_flags> 部分。

源碼解析

1. Checkpoint模塊

init: Calling: /system/bin/vdc checkpoint needsCheckpoint -> vold->needsCheckpoint(&enabled) -> cp_needsCheckpoint

1.1 cp_needsCheckpoint

bool cp_needsCheckpoint() {
    std::lock_guard<std::mutex> lock(isCheckpointingLock);

    // Make sure we only return true during boot. See b/138952436 for discussion
    // 已經checkpoint過了,就直接返回了
    if (needsCheckpointWasCalled) return isCheckpointing;
    needsCheckpointWasCalled = true;

    bool ret;
    std::string content;
    sp<IBootControl> module = IBootControl::getService();

    if (isCheckpointing) return isCheckpointing;
// 正常情況isSlotMarkedSuccessful返回為true,不走進去
    if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
        // OTA階段為false,走這里;返回true
        isCheckpointing = true;
        return true;
    }// const std::string kMetadataCPFile = "/metadata/vold/checkpoint";
    // 找不到文件,返回false
    ret = android::base::ReadFileToString(kMetadataCPFile, &content);
    if (ret) {
        ret = content != "0";
        isCheckpointing = ret;
        return ret;
    }
    return false;	// 正常情況返回false
}

checkpointing的流程

  1. mount_all階段掛載data分區時

    • 調用cp_needsCheckpoint函數:如果是OTA升級階段或者是第一次刷固件的時候(調用boot_ctrl判斷當前slot是否已經Marked Successful了,如果沒有,表明此時處於OTA升級階段或者是第一次刷固件的時候,需要進行checkpoint),則返回true;正常情況就是false
    • 如果上面返回true,則調用UpdateCheckpointPartition函數:mount data分區的時候加上checkpoint=disable選項。然后如果OTA升級失敗了,就可以恢復到這個點上了。
  2. ActivityManager finishBoot階段

    • 調用cp_commitChanges函數:調用boot_ctrlmarkBootSuccessful函數,以及用checkpoint=enable選項,重新掛載data分區(f2fs文件系統就會自動將對data分區的改動寫入data分區中,表明OTA升級成功)。
    ActivityManager: About to commit checkpoint
    

如果在mount_allfinishboot期間,OTA升級失敗並重啟了,則寫入到data分區的數據重啟之后全部無效。這就達到了data分區回滾的目的了。

管理 keymaster 密鑰

​ Keymaster 密鑰用於設備加密或其他目的。為管理這些密鑰,Android 特地推遲到提交檢查點之后才調用密鑰刪除命令。

監控運行狀況

​ 該線程在開機的post-fs-data:vdc checkpoint prepareCheckpoint階段運行,要在start checkpoint之后才會運行該線程。運行狀況守護進程會檢查是否有足夠的磁盤空間來創建檢查點。運行狀況守護進程位於 Checkpoint.cpp 中的 cp_healthDaemon 內。

​ 默認表現:當data分區的可用空間小於100M的時候,它就會提交檢查點(cp_commitChanges提交對data分區的修改)或者重啟設備(放棄對data分區的修改)。

運行狀況守護進程具有以下可配置的行為:

  • ro.sys.cp_msleeptime:控制設備檢查磁盤使用情況的頻率。(隔多久去檢查磁盤的可用空間,默認為1秒鍾)
  • ro.sys.cp_min_free_bytes:控制運行狀況守護進程查找的最小值。(可用空間的最小值,默認為100M)
  • ro.sys.cp_commit_on_full:控制運行狀況守護進程在磁盤已滿時,是重新啟動設備還是提交檢查點並繼續運行。

checkpoint配置

  1. device/softwinner/ceres-common/init.sun50iw10p1.rc文件的on fs中添加
mount_all /vendor/etc/fstab.sun50iw10p1 --early
  1. device/softwinner/ceres-common/init.sun50iw10p1.rc文件的on late-fs中添加
mount_all /vendor/etc/fstab.sun50iw10p1 --late
  1. device/softwinner/ceres-b3/fstab.sun50iw10p1文件的data分區中添加latemountcheckpoint=fs
/dev/block/by-name/UDISK                               /data        f2fs     noatime,nosuid,nodev,discard wait,check,formattable,quota,reservedsize=33554432,fileencryption=aes-256-xts:aes-256-cts,latemount,checkpoint=fs
  1. device/softwinner/ceres-b3/fstab.sun50iw10p1文件的metadata分區中添加first_stage_mount
/dev/block/by-name/metadata                            /metadata    ext4     nodev,noatime,nosuid,errors=panic wait,first_stage_mount,formattable,check
  1. device/softwinner/ceres-b3/BoardConfig.mk文件中添加:
BOARD_USES_METADATA_PARTITION := true

驗證

要測試您的 UDC 實現,請運行 VTS 測試的 VtsKernelCheckpointTest 測試集。

參考

1. f2fs: checkpoint disabling
https://lwn.net/Articles/763072/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM