Android tiene dos mecanismos de actualización: actualizaciones A/B (ininterrumpidas) y actualizaciones no A/B. Para reducir la complejidad del código y mejorar el proceso de actualización, en Android 11 los dos mecanismos se unifican a través de A/B virtual para brindar actualizaciones sin inconvenientes a todos los dispositivos con un costo de almacenamiento mínimo. Android 12 ofrece la opción de compresión A/B virtual para comprimir particiones instantáneas. Tanto en Android 11 como en Android 12, se aplica lo siguiente:
- Las actualizaciones virtuales A/B son perfectas como las actualizaciones A/B. Las actualizaciones virtuales A/B minimizan el tiempo que un dispositivo está fuera de línea e inutilizable.
- Las actualizaciones virtuales A/B se pueden revertir . Si el nuevo sistema operativo no se inicia, los dispositivos retroceden automáticamente a la versión anterior.
- Las actualizaciones virtuales A/B usan un mínimo de espacio adicional al duplicar solo las particiones que usa el gestor de arranque. Se capturan instantáneas de otras particiones actualizables.
Antecedentes y terminología
Esta sección define la terminología y describe la tecnología que admite A/B virtual.
mapeador de dispositivos
Device-mapper es una capa de bloque virtual de Linux que se usa a menudo en Android. Con particiones dinámicas , las particiones como /system
son una pila de dispositivos en capas:
- En la parte inferior de la pila se encuentra la superpartición física (por ejemplo,
/dev/block/by-name/super
). - En el medio hay un dispositivo
dm-linear
, que especifica qué bloques en la súper partición forman la partición dada. Aparece como/dev/block/mapper/system_[a|b]
en un dispositivo A/B o/dev/block/mapper/system
en un dispositivo que no es A/B. - En la parte superior reside un dispositivo
dm-verity
, creado para particiones verificadas. Este dispositivo verifica que los bloques en el dispositivodm-linear
estén firmados correctamente. Aparece como/dev/block/mapper/system-verity
y es la fuente del punto de montaje/system
.
La Figura 1 muestra cómo se ve la pila debajo del punto de montaje /system
.
Figura 1. Pila debajo del punto de montaje /system
dm-instantánea
Virtual A/B se basa en dm-snapshot
, un módulo mapeador de dispositivos para tomar instantáneas del estado de un dispositivo de almacenamiento. Al usar dm-snapshot
, hay cuatro dispositivos en juego:
- El dispositivo base es el dispositivo del que se toma una instantánea. En esta página, el dispositivo base siempre es una partición dinámica, como un sistema o un proveedor.
- El dispositivo de copia en escritura (COW), para registrar cambios en el dispositivo base. Puede ser de cualquier tamaño, pero debe ser lo suficientemente grande para acomodar todos los cambios en el dispositivo base.
- El dispositivo de instantánea se crea utilizando el destino de la
snapshot
. Las escrituras en el dispositivo de instantáneas se escriben en el dispositivo COW. Las lecturas del dispositivo de instantánea se leen desde el dispositivo base o desde el dispositivo COW, dependiendo de si la instantánea ha cambiado los datos a los que se accede. - El dispositivo de origen se crea utilizando el destino
snapshot-origin
. Las lecturas en el dispositivo de origen se leen directamente desde el dispositivo base. Escribe en el dispositivo de origen escribe directamente en el dispositivo base, pero los datos originales se respaldan escribiendo en el dispositivo COW.
Figura 2. Asignación de dispositivos para dm-snapshot
Instantáneas comprimidas
En Android 12, debido a que los requisitos de espacio en la partición /data
pueden ser altos, puede habilitar instantáneas comprimidas en su compilación para abordar los requisitos de espacio más altos de la partición /data
.
Las instantáneas comprimidas virtuales A/B se basan en dos nuevos componentes que están disponibles en Android 12:
-
dm-user
, un módulo del núcleo similar a FUSE que permite que el espacio de usuario implemente dispositivos de bloque. -
snapuserd
, un demonio de espacio de usuario para implementar un nuevo formato de instantánea.
Estos componentes permiten la compresión. Los otros cambios necesarios realizados para implementar las capacidades de instantáneas comprimidas se proporcionan en las siguientes secciones: formato COW para instantáneas comprimidas , dm-user y Snapuserd .
Formato COW para instantáneas comprimidas
En Android 12, las instantáneas comprimidas usan un nuevo formato COW. De manera similar al formato integrado del kernel que se usa para las instantáneas sin comprimir, el formato COW para las instantáneas comprimidas tiene secciones alternas de metadatos y datos. Los metadatos del formato original solo permitían operaciones de "reemplazo": Reemplace el bloque X en la imagen base con el contenido del bloque Y en la instantánea. El formato COW de instantáneas comprimidas es más expresivo y admite tres operaciones:
- Copiar : el bloque X en el dispositivo base debe reemplazarse con el bloque Y en el dispositivo base.
- Reemplazar : el bloque X en el dispositivo base debe reemplazarse con el contenido del bloque Y en la instantánea. Cada uno de estos bloques está comprimido en gz.
- Cero : el bloque X en el dispositivo base debe reemplazarse con ceros.
Las actualizaciones OTA completas consisten únicamente en operaciones de reemplazo y puesta a cero . Las actualizaciones incrementales de OTA también pueden tener operaciones de copia .
dm-usuario en Android 12
El módulo de kernel dm-user permite que el userspace
de usuario implemente dispositivos de bloque mapeador de dispositivos. Una entrada de la tabla dm-user crea un dispositivo misceláneo en /dev/dm-user/<control-name>
. Un proceso de userspace
de usuario puede sondear el dispositivo para recibir solicitudes de lectura y escritura del kernel. Cada solicitud tiene un búfer asociado para que el espacio de usuario se complete (para una lectura) o se propague (para una escritura).
El módulo de kernel dm-user
proporciona una nueva interfaz visible para el usuario para el kernel que no forma parte de la base de código upstream kernel.org. Hasta que lo sea, Google se reserva el derecho de modificar la interfaz dm-user
en Android.
Snapusuario
El componente de espacio de usuario snapuserd
para dm-user
implementa la compresión A/B virtual.
En la versión sin comprimir de Virtual A/B (ya sea en Android 11 y versiones anteriores, o en Android 12 sin la opción de instantánea comprimida), el dispositivo COW es un archivo sin formato. Cuando la compresión está habilitada, COW funciona como un dispositivo dm-user
, que está conectado a una instancia del daemon snapuserd
.
El kernel no usa el nuevo formato COW. Entonces, el componente snapuserd
traduce las solicitudes entre el formato COW de Android y el formato integrado del kernel:
Figura 3. Diagrama de flujo de snapuserd como traductor entre los formatos Android y Kernel COW
Esta traducción y descompresión nunca ocurre en el disco. El componente snapuserd
intercepta las lecturas y escrituras COW que ocurren en el kernel y las implementa usando el formato COW de Android.
Procesos de compresión A/B virtual
Estas secciones brindan detalles sobre los procesos utilizados en la compresión Virtual A/B: lectura de metadatos, fusión y realización de transiciones de inicio.
Lectura de metadatos
Los metadatos son construidos por un daemon snapuserd
. Los metadatos son principalmente un mapeo de 2 ID, de 8 bytes cada uno, que representan los sectores que se fusionarán. En dm-snapshot
se llama disk_exception
.
struct disk_exception {
uint64_t old_chunk;
uint64_t new_chunk;
};
Se utiliza una excepción de disco cuando una parte antigua de datos se reemplaza por una nueva.
Un demonio Snapuserd
lee el archivo COW interno a través de la biblioteca COW y construye los metadatos para cada una de las operaciones COW presentes en el archivo COW.
Las lecturas de metadatos se inician desde dm-snapshot
en el kernel cuando se crea el dispositivo dm- dm- snapshot
.
La siguiente figura proporciona un diagrama de secuencia para la ruta de E/S para la construcción de metadatos.
Figura 4. Flujo de secuencia para la ruta de E/S en la construcción de metadatos
fusión
Una vez que se completa el proceso de inicio, el motor de actualización marca la ranura como un inicio exitoso e inicia la combinación cambiando el destino dm-snapshot
al destino dm-snapshot-merge
.
dm-snapshot
recorre los metadatos e inicia una E/S de combinación para cada excepción de disco. A continuación se muestra una descripción general de alto nivel de la ruta de E/S de combinación.
Figura 5. Descripción general de la ruta Merge IO
Si el dispositivo se reinicia durante el proceso de combinación, la combinación se reanuda en el próximo reinicio y la combinación se completa.
transiciones de inicio
Al arrancar con instantáneas comprimidas, el init de primera etapa debe iniciar snapuserd
para montar particiones. Esto plantea un problema: cuando se carga y aplica sepolicy
, snapuserd
se coloca en el contexto incorrecto y sus solicitudes de lectura fallan, con denegaciones de selinux.
Para abordar esto, las transiciones de snapuserd
con init
, de la siguiente manera:
- El
snapuserd
init
el ramdisk y guarda un descriptor de archivo abierto en una variable de entorno. - El
init
de primera etapa cambia el sistema de archivos raíz a la partición del sistema y luego ejecuta la copia del sistema deinit
. - La copia del sistema de
init
lee la política combinada en una cadena. -
Init
invocamlock()
en todas las páginas respaldadas por ext4. A continuación, desactiva todas las tablas del mapeador de dispositivos para dispositivos de instantáneas y detienesnapuserd
. Después de esto, está prohibido leer de las particiones, ya que al hacerlo se produce un interbloqueo. - Usando el descriptor abierto de la copia ramdisk de
snapuserd
,init
relanza el daemon con el contexto selinux correcto. Se reactivan las tablas del mapeador de dispositivos para dispositivos de instantáneas. - Init invoca
munlockall()
- es seguro realizar IO nuevamente.
uso del espacio
La siguiente tabla proporciona una comparación del uso del espacio para diferentes mecanismos de OTA que usan el sistema operativo de Pixel y los tamaños de OTA.
Impacto de tamaño | no-A/B | A/B | A/B virtuales | A/B virtual (comprimido) |
---|---|---|---|---|
Imagen original de fábrica | Super de 4,5 GB (imagen de 3,8 G + 700 M reservados) 1 | Super de 9GB (3.8G + 700M reservados, para dos ranuras) | Super de 4,5 GB (imagen de 3,8 G + 700 M reservados) | Super de 4,5 GB (imagen de 3,8 G + 700 M reservados) |
Otras particiones estáticas | /cache | Ninguna | Ninguna | Ninguna |
Almacenamiento adicional durante OTA (espacio devuelto después de aplicar OTA) | 1,4 GB en/datos | 0 | 3.8GB 2 en /datos | 2.1GB 2 en /datos |
Almacenamiento total requerido para aplicar OTA | 5.9GB 3 (súper y datos) | 9 GB (súper) | 8.3GB 3 (súper y datos) | 6.6GB 3 (súper y datos) |
1 Indica el diseño asumido basado en el mapeo de píxeles.
2 Supone que la nueva imagen del sistema tiene el mismo tamaño que la original.
3 El requisito de espacio es transitorio hasta que se reinicia.
Para implementar Virtual A/B, o para usar capacidades de instantáneas comprimidas, consulte Implementación de Virtual A/B