사용자 데이터 체크포인트(UDC)

Android 10에는 Android OTA(over-the-air) 실패 시 Android가 이전 상태로 롤백할 수 있게 해주는 사용자 데이터 체크포인트(UDC)가 도입되었습니다. UDC를 사용하면 Android OTA 업데이트 실패 시 기기를 이전 상태로 안전하게 롤백할 수 있습니다. A/B 업데이트는 부팅 초반의 경우 이 문제를 해결하지만 /data에 마운트된 사용자 데이터 파티션이 수정된 경우에는 롤백이 지원되지 않습니다.

UDC는 수정된 후에도 기기가 사용자 데이터 파티션을 되돌릴 수 있게 해줍니다. 이는 파일 시스템에 대한 체크포인트 기능을 제공하기 때문에 가능한 것으로, 파일 시스템이 체크포인트 기능, 부트로더 A/B 메커니즘과의 통합을 지원하지 않지만 비 A/B 업데이트는 지원하고 키 버전 바인딩 및 키 롤백 차단을 지원하는 경우에 대체로 구현할 수 있는 방법입니다.

사용자 영향

UDC 기능은 사용자의 OTA 업데이트 환경을 개선합니다. 이렇게 하면 OTA 업데이트 실패 시 데이터를 손실하는 사용자의 수가 감소하기 때문입니다. 이렇게 하면 업데이트 프로세스 도중 문제를 경험하는 사용자의 지원 통화 건수를 줄일 수 있습니다. 하지만 OTA 업데이트에 실패하면 사용자는 기기가 여러 차례 재부팅되는 모습을 보게 될 수 있습니다.

사용 방법

다른 파일 시스템의 체크포인트 기능

F2FS 파일 시스템의 경우 UDC는 업스트림 4.20 Linux 커널에 체크포인트 기능을 추가하고 Android 10을 실행하는 기기에서 지원하는 모든 일반 커널에 이를 백포트합니다.

다른 파일 시스템의 경우 UDC는 체크포인트 기능에 dm_bow라 불리는 기기 매퍼 가상 기기를 사용합니다. dm_bow는 기기와 파일 시스템 사이에 위치합니다. 파티션이 마운트되면 trim이 실행되어 파일 시스템이 모든 여유 블록에서 trim 명령어를 실행하도록 합니다. dm_bow는 이러한 trim을 가로챈 후 여유 블록 목록을 설정하는 데 사용합니다. 그러면 읽기 및 쓰기가 수정되지 않은 상태에서 기기로 전송되지만, 쓰기가 허용되기 전에 복원에 필요한 데이터가 여유 블록에 백업됩니다.

Checkpointing 프로세스

checkpoint=fs/block 플래그가 포함된 파티션이 마운트되면 Android는 드라이브에서 restoreCheckpoint를 호출하여 기기가 현재의 모든 체크포인트를 복원할 수 있도록 허용합니다. 그러면 initneedsCheckpoint 함수를 호출하여 기기가 부트로더 A/B 상태인지, 아니면 업데이트 재시도 횟수를 설정했는지 확인합니다. 둘 다 아닌 경우 Android는 createCheckpoint를 호출하여 플래그를 마운트하거나 dm_bow 기기를 빌드합니다.

파티션이 마운트되면 체크포인트 코드가 호출되어 trim을 실행합니다. 그러면 부팅 프로세스가 정상적으로 계속됩니다. LOCKED_BOOT_COMPLETE에서 Android는 commitCheckpoint를 호출하여 현재의 체크포인트를 커밋하며, 업데이트는 정상적으로 계속됩니다.

keymaster 키 관리

Keymaster 키는 기기 암호화 또는 기타 용도로 사용됩니다. 이 키를 관리하기 위해 Android는 체크포인트가 커밋될 때까지 키 삭제 호출을 지연시킵니다.

상태 모니터링

상태 데몬은 체크포인트 생성을 위한 디스크 공간이 충분한지 확인합니다. 상태 데몬은 Checkpoint.cppcp_healthDaemon에 위치합니다.

상태 데몬에는 다음과 같은 구성 가능한 동작이 있습니다.

  • ro.sys.cp_msleeptime: 기기가 디스크 사용량을 검사하는 빈도를 제어합니다.
  • ro.sys.cp_min_free_bytes: 상태 데몬이 찾는 최솟값을 제어합니다.
  • ro.sys.cp_commit_on_full: 상태 데몬이 기기를 재부팅하거나 체크포인트를 커밋하고 디스크가 가득 찼을 때 계속 작동하도록 할지 제어합니다.

Checkpoint API

Checkpoint API는 UDC 기능에 사용됩니다. UDC에 사용되는 다른 API는 IVold.aidl을 참고하세요.

void startCheckpoint(int retry)

체크포인트를 생성합니다.

프레임워크는 업데이트를 시작할 준비가 되면 이 메서드를 호출합니다. 체크포인트는 사용자 데이터와 같은 체크포인트가 적용된 파일 시스템이 재부팅 후에 마운트(읽기/쓰기)되면 생성됩니다. 재시도 횟수가 양수이면 API는 추적 재시도를 처리하며 업데이터는 needsRollback을 호출하여 업데이트 롤백이 필요한지 확인합니다. 재시도 횟수가 -1이면 API는 A/B 부트로더의 판단을 따릅니다.

이 메서드는 일반 A/B 업데이트를 실행할 때 호출됩니다.

void commitChanges()

변경사항을 커밋합니다.

프레임워크는 변경사항을 커밋할 준비가 되면 재부팅 후에 이 메서드를 호출합니다. 이는 데이터가 사용자 데이터에 쓰이기 전, 그리고 BootComplete 전에 호출됩니다.

체크포인트가 적용된 활성 업데이트가 존재하지 않으면 이 메서드는 효과가 없습니다.

abortChanges()

강제로 재부팅하여 체크포인트로 되돌립니다. 최초 재부팅 이후의 모든 사용자 데이터 수정사항을 취소합니다.

프레임워크는 재부팅 후, commitChanges 전에 이 메서드를 호출합니다. 이 메서드가 호출되면 retry_counter가 줄어들고 로그 항목이 생성됩니다.

bool needsRollback()

롤백이 필요한지 파악합니다.

체크포인트가 없는 기기에서는 false를 반환합니다. 체크포인트 기기에서는 체크포인트 없이 진행된 부팅 도중 true를 반환합니다.

UDC 구현

참조 구현

UDC 구현 방법의 예는 dm-bow.c를 참고하세요. 이 기능에 관한 추가 정보는 dm-bow.txt를 참고하세요.

설정

init.hardware.rc 파일의 on fs에서 다음이 있는지 확인합니다.

mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early

init.hardware.rc 파일의 on late-fs에서 다음이 있는지 확인합니다.

mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late

fstab.hardware 파일에서 /datalatemount로 태깅되었는지 확인합니다.

/dev/block/bootdevice/by-name/userdata              /data              f2fs
noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier
latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M,checkpoint=fs

메타데이터 파티션 추가

UDC는 메타데이터 파티션에서 비 부트로더 재시도 횟수 및 키를 저장하도록 요구합니다. 메타데이터 파티션을 설정하고 /metadata에서 미리 마운트합니다.

fstab.hardware 파일에서 /metadataearlymount 또는 first_stage_mount로 태깅되었는지 확인합니다.

/dev/block/by-name/metadata           /metadata           ext4
noatime,nosuid,nodev,discard,sync
wait,formattable,first_stage_mount

파티션을 전부 0으로 초기화합니다.

BoardConfig.mk에 다음 줄을 추가합니다.

BOARD_USES_METADATA_PARTITION := true
BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata

시스템 업데이트

F2FS 시스템

F2FS를 사용하여 데이터를 포맷하는 시스템의 경우 F2FS 버전이 체크포인트를 지원해야 합니다. 자세한 내용은 여러 파일 시스템의 체크포인트 기능을 참고하세요.

/data에 마운트된 기기의 fstab의 <fs_mgr_flags> 섹션에 checkpoint=fs 플래그를 추가합니다.

비 F2FS 시스템

비 F2FS 시스템의 경우 커널 config에 dm-bow를 사용 설정해야 합니다.

/data에 마운트된 기기의 fstab의 <fs_mgr_flags> 섹션에 checkpoint=block 플래그를 추가합니다.

로그 확인

로그 항목은 Checkpoint API가 호출되면 생성됩니다.

유효성 검사

UDC 구현을 테스트하려면 VTS 테스트의 VtsKernelCheckpointTest 모음을 실행합니다.