Контрольная точка данных пользователя

В Android 10 появилась функция контрольных точек пользовательских данных (UDC), которая позволяет Android откатиться к предыдущему состоянию в случае сбоя обновления Android по беспроводной сети (OTA). Благодаря UDC, если обновление Android OTA не удается, устройство может безопасно откатиться к предыдущему состоянию. Хотя обновления A/B решают эту проблему для ранней загрузки, откат не поддерживается, если изменяется раздел пользовательских данных (смонтированный в /data ).

Функция UDC позволяет устройству восстанавливать раздел пользовательских данных даже после его модификации. Это достигается за счет возможности создания контрольных точек в файловой системе, альтернативной реализации в случае, если файловая система не поддерживает контрольные точки, интеграции с механизмом A/B загрузчика, а также поддержки обновлений без использования A/B, и поддержки привязки версий ключей и предотвращения отката ключей.

Влияние на пользователей

Функция UDC улучшает процесс обновления по воздуху (OTA), поскольку при сбое обновления теряется меньше данных. Это может уменьшить количество обращений в службу поддержки от пользователей, столкнувшихся с проблемами в процессе обновления. Однако при сбое обновления по воздуху пользователи могут заметить многократную перезагрузку устройства.

Как это работает

Функциональность контрольных точек в различных файловых системах

Для файловой системы F2FS компания UDC добавляет функцию контрольных точек в ядро ​​Linux версии 4.20 и переносит её во все распространённые ядра, поддерживаемые устройствами под управлением Android 10.

Для других файловых систем UDC использует виртуальное устройство сопоставления устройств под названием dm_bow для обеспечения работы контрольных точек. dm_bow находится между устройством и файловой системой. При монтировании раздела отправляется команда trim, в результате чего файловая система отправляет команды trim для всех свободных блоков. dm_bow перехватывает эти команды trim и использует их для создания списка свободных блоков. Затем операции чтения и записи отправляются на устройство без изменений, но прежде чем будет разрешена запись, данные, необходимые для восстановления, резервно копируются в свободный блок.

Процесс контрольной точки

Когда монтируется раздел с флагом checkpoint=fs/block , Android вызывает restoreCheckpoint на диске, чтобы позволить устройству восстановить любую текущую контрольную точку. Затем init вызывает функцию needsCheckpoint , чтобы определить, находится ли устройство в состоянии загрузчика A/B или установлено ли количество попыток обновления. Если выполняется хотя бы одно из этих условий, Android вызывает createCheckpoint , чтобы либо добавить флаги монтирования, либо создать устройство dm_bow .

После монтирования раздела вызывается код контрольной точки для выполнения операций TRIM. Затем процесс загрузки продолжается в обычном режиме. В состоянии LOCKED_BOOT_COMPLETE Android вызывает commitCheckpoint для фиксации текущей контрольной точки, и обновление продолжается в обычном режиме.

Управление ключами KeyMint (ранее Keymaster).

Ключи KeyMint используются для шифрования устройства или в других целях. Для управления этими ключами Android задерживает вызовы удаления ключа до тех пор, пока не будет зафиксирована контрольная точка.

Следите за состоянием здоровья

Демон проверки работоспособности проверяет наличие достаточного дискового пространства для создания контрольной точки. Демон проверки работоспособности находится в папке cp_healthDaemon в Checkpoint.cpp .

Демон мониторинга состояния здоровья имеет следующие параметры поведения, которые можно настроить:

  • ro.sys.cp_msleeptime : Определяет, как часто устройство проверяет использование дискового пространства.
  • ro.sys.cp_min_free_bytes : Управляет минимальным значением, которое ищет демон мониторинга состояния.
  • ro.sys.cp_commit_on_full : Управляет тем, будет ли демон проверки работоспособности перезагружать устройство или фиксировать контрольную точку и продолжать работу, когда диск заполнен.

API контрольных точек

Функция UDC использует API контрольных точек. Информацию о других API, используемых UDC, см. в IVold.aidl .

void startCheckpoint(int retry)

Создает контрольную точку.

Этот метод вызывается фреймворком, когда он готов начать обновление. Контрольная точка создается до того, как файловые системы, созданные на основе контрольных точек, такие как userdata, будут смонтированы с правами чтения/записи после перезагрузки. Если количество попыток положительное, API обрабатывает отслеживание повторных попыток, и средство обновления вызывает needsRollback чтобы проверить, требуется ли откат обновления. Если количество попыток равно -1 , API полагается на решение загрузчика A/B.

Этот метод не вызывается при обычном A/B-обновлении.

void commitChanges()

Подтверждает изменения.

Этот метод вызывается фреймворком после перезагрузки, когда изменения готовы к фиксации. Он вызывается перед записью данных (таких как изображения, видео, SMS, подтверждение получения от сервера) в пользовательские данные и перед 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 убедитесь, что /data помечен как latemount .

/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 убедитесь, что /metadata помечен как earlymount или first_stage_mount .

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

Инициализируйте раздел нулями.

Добавьте следующие строки в BoardConfig.mk :

BOARD_USES_METADATA_PARTITION := true
BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata

Обновление систем

F2FS-системы

Для систем, использующих файловую систему F2FS для форматирования данных, убедитесь, что ваша версия F2FS поддерживает контрольные точки. Дополнительную информацию см. в разделе «Функциональность контрольных точек в различных файловых системах» .

Добавьте флаг checkpoint=fs в раздел <fs_mgr_flags> файла fstab для устройства, смонтированного в /data .

Системы, не относящиеся к F2FS

Для систем, не использующих файловую систему F2FS, необходимо включить dm-bow в конфигурации ядра.

Добавьте флаг checkpoint=block в раздел <fs_mgr_flags> файла fstab для устройства, смонтированного в /data .

Проверить журналы

Записи в журнале генерируются при вызове API Checkpoint.

Валидация

Для проверки вашей реализации UDC запустите набор тестов VTS VtsKernelCheckpointTest .