Virtual AB系统
概览
Virtual AB系统
(1)无缝升级:virtual AB和AB系统一样,支持无缝升级
(2)回滚:Virtual AB支持系统回滚。当系统升级失败的时候,设备会自动回滚到旧的系统版本。
(3)省空间:在Virtual AB中,super分区采用dm-snapshot技术来进行升级,不需要分AB系统,所以virtual AB系统比AB系统节省了很多空间。
背景
Device-mapper技术

System分区的dm设备挂载栈如图上所示:
(1)最底层是物理分区:super分区
(2)第二层是用dm-linear技术实现的动态逻辑分区:为/dev/block/mapper/system_a分区
(3)第三层是用dm-verity技术实现的校验分区:为/dev/block/mapper/system-verity分区
(4)最后system分区挂载在/dev/block/mapper/system-verity分区上面
Dm-snapshot技术概览

Dm-snapshot分区由四个设备组成:
(1)通常system分区被作为base设备
(2)COW设备用来保存base设备所改动的文件。
(3)Dm-snapshot设备由snapshot目标创建。往dm-snapshot设备写文件,会写到COW设备中。从dm-snapshot设备读文件,则会从base设备和COW设备中读文件,如果文件通过dm-snapshot改变过,则从COW设备中读;否则从base设备中读。
(4)dm-snapshot-origin设备由snapshot-origin目标创建。读写文件都是从base设备中进行读写。
BootControl服务
Misc分区中相关的数据结构。
(1)bootloader_message_ab数据结构
struct bootloader_message_ab {
struct bootloader_message message;
char slot_suffix[32]; // 为bootloader_control数据结构,相关的信息都存放于此
char update_channel[128];
char reserved[1888];
};
(2)bootloader_control 数据结构
struct bootloader_control {
// NUL terminated active slot suffix.
char slot_suffix[4]; // 存放_a或者_b
// Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
uint32_t magic; // 为0x42414342
// Version of struct being used (see BOOT_CTRL_VERSION).
uint8_t version; // 为1
// Number of slots being managed.
uint8_t nb_slot : 3; // slot的数目,一般为2(AB)
// Number of times left attempting to boot recovery.
uint8_t recovery_tries_remaining : 3;
// Status of any pending snapshot merge of dynamic partitions.
uint8_t merge_status : 3;
// Ensure 4-bytes alignment for slot_info field.
uint8_t reserved0[1];
// Per-slot information. Up to 4 slots.
struct slot_metadata slot_info[4]; // 最大支持4个slot
// Reserved for further use.
uint8_t reserved1[8];
// CRC32 of all 28 bytes preceding this field (little endian
// format).
uint32_t crc32_le;
} __attribute__((packed));
(3)slot_metadata数据结构
struct slot_metadata {
// Slot priority with 15 meaning highest priority, 1 lowest
// priority and 0 the slot is unbootable.
uint8_t priority : 4; // slot的优先级,优先级高的先启动,最高为15,最低为1。为0时不给启动
// Number of times left attempting to boot this slot.
uint8_t tries_remaining : 3; // 该slot能重启的次数
// 1 if this slot has booted successfully, 0 otherwise.
uint8_t successful_boot : 1; // 当该slot成功启动的时候,该位置1
// 1 if this slot is corrupted from a dm-verity corruption, 0
// otherwise.
uint8_t verity_corrupted : 1; // 目前无人设此值1
// Reserved for further use.
uint8_t reserved : 7;
} __attribute__((packed));
Virtual AB的分区概览图

除了super分区,其他分区如果需要升级,都需要分为AB分区。因为super分区不用分AB,而其他分区又比较小,所以virtual AB比AB系统要节省很多空间。
Snapshot和合并流程
升级前的分区概览

OTA升级过程中

当update_engine开始写一个新的system分区的时候,它会创建以下设备:
(1)基于system_a设备创建system_b_base设备(dm-5设备)
(2)在/data/gsi/ota/目录下创建system_b-cow-img.img.0000文件,然后通过/dev/block/loop0设备进行挂载。然后创建dm-6设备将其映射到system_cow上
(3)创建dm-7(dm-snapshot)设备,将起映射为system_b
(4)打开dm-snapshot设备,将OTA升级包中的system.img写进去,此时写的内容,就写到了/data/gsi/ota/system_b-cow-img.img.0000文件中。
(5)升级成功之后,调用boot_ctrl中的SetActiveBootSlot函数:将_a(目前slot)的priority值设小(如果最大就减1)。然后将_b(要升级的slot) 的priority值设为15(最大),以及tries_remaining的值设为6(升级失败,最多可以重启6次)。
//在升级过程中创建设备:
[INFO:dynamic_partition_control_android.cc(319)] Loaded metadata from slot B in /dev/block/by-name/super
update_engine: Successfully unmapped snapshot system_b
vold : Disk at 253:5 changed
update_engine: [libfs_mgr]Created logical partition system_b-base on device /dev/block/dm-5
vold : Disk at 7:1 changed
gsid : Created loop device /dev/block/loop1 for file /data/gsi/ota/system_b-cow-img.img.0000
update_engine: Mapped system_b-cow-img to /dev/block/loop1
update_engine: Calling GetMappedImageDevice with local image manager; device /dev/block/loop1may not be available in first stage init!
vold : Disk at 253:6 changed
update_engine: Mapped COW device for system_b at /dev/block/dm-6
vold : Disk at 253:7 changed
update_engine: Mapped system_b as snapshot device at /dev/block/dm-7
[INFO:dynamic_partition_control_android.cc(173)] Succesfully mapped system_b to device mapper (force_writable = 1); device path at /dev/block/dm-7
//升级成功之后,调用boot_ctrl中的SetActiveBootSlot函数:
[INFO:postinstall_runner_action.cc(376)] All post-install commands succeeded
OTA升级完成后,重启,uboot端slot切换流程。
(1)遍历所有slot,如果该slot的tries_remaining为0则跳过(不从该slot启动,当_b系统无法启动,则在这里切换回_a系统)。然后选择priority最高的slot进行启动(升级后,_b最高)
(2)如果当前slot的successful_boot为0(OTA升级重启成功后,会将此值设为1),则tries_remaining的值减1
(3)将slot_suffix的值改为_b
OTA升级完成后,重启过程中

(1)创建dm-0设备,作为system_b_base设备(映射super分区中的system分区)
(2)创建dm-1设备,作为system_b-cow-img设备(映射data分区中的system_b-cow-img.img.0000文件)
(3)创建dm-2设备,映射为system_cow设备
(4)创建dm-3设备,映射为dm-snapshot设备(system_b分区)
(5)将system分区挂载在dm-3上(dm-snapshot设备)
(6)然后系统启动读system分区的时候,如果读到的文件,在system_cow中记录到有改变,则直接读system_cow中的文件。
// 在first stage init过程中创建dm设备:
init: Creating logical partitions with snapshots as needed
random: init: uninitialized urandom read (16 bytes read)
init: [libfs_mgr]Created logical partition system_b-base on device /dev/block/dm-0
random: init: uninitialized urandom read (16 bytes read)
init: [libfs_mgr]Created logical partition system_b-cow-img on device /dev/block/dm-1
init: Mapped system_b-cow-img to 253:1
init: Mapped COW device for system_b at /dev/block/dm-2
init: Mapped system_b as snapshot device at /dev/block/dm-3
重启完成后,开始snapshot-merge

(1)重启成功后,调用BootControl的MarkBootSuccessful函数,将successful_boot和tries_remaining设为1。
(2)将dm-snapshot设备设为merge状态,将cow设备和base设备的内容进行合并。
(3)umaped相关的设备
(4)合并成功之后,删除/data/gsi/ota目录下的img文件以及/metadata/ota目录下的相关文件。
// 1. 启动完成之后,调用BootControl的MarkBootSuccessful函数
[INFO:cleanup_previous_update_action.cc(137)] Boot completed, waiting on markBootSuccessful()
// 2. 进行合并,大概30秒左右
17:34:51.739365 [INFO:cleanup_previous_update_action.cc(338)] Attempting to initiate merge.
设置dm-snapshot为merge:
update_engine: Successfully switched snapshot device to a merge target: system_b
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 8%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 20%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 27%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 33%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 40%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 48%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 55%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 63%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 70%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 78%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 85%.
[INFO:cleanup_previous_update_action.cc(302)] Waiting for merge to complete: 93%.
// 3. unmap设备,然后清除data目录下的img文件
update_engine: Removing all update state.
// 4. merge完成
17:35:21.018875 [INFO:cleanup_previous_update_action.cc(262)] Merge finished with state MergeCompleted.
Snapshot-merge完成后

异常处理
Update_verifier程序
Update_verifier程序:如果没有配置checkpoint,则会调用boot_ctrl的module->markBootSuccessful,导致android如果升级失败,会无法回退。
解决办法:配置checkpoint。

浙公网安备 33010602011771号