Android ma dwa mechanizmy aktualizacji: aktualizacje A/B (płynne) i aktualizacje inne niż A/B. Aby zmniejszyć złożoność kodu i usprawnić proces aktualizacji, w systemie Android 11 oba mechanizmy zostały ujednolicone poprzez wirtualne A/B, aby zapewnić płynne aktualizacje na wszystkich urządzeniach przy minimalnych kosztach przechowywania. Android 12 oferuje opcję wirtualnej kompresji A/B w celu kompresji migawek partycji. Zarówno w systemie Android 11, jak i Android 12 obowiązują następujące zasady:
- Wirtualne aktualizacje A/B przebiegają tak samo płynnie , jak aktualizacje A/B. Wirtualne aktualizacje A/B minimalizują czas, w którym urządzenie jest offline i nie nadaje się do użytku.
- Wirtualne aktualizacje A/B można wycofać . Jeśli nowy system operacyjny nie uruchomi się, urządzenia automatycznie przywrócą poprzednią wersję.
- Wirtualne aktualizacje A/B zajmują minimum dodatkowej przestrzeni , duplikując tylko partycje używane przez program ładujący. Wykonywane są migawki innych partycji, które można aktualizować.
Tło i terminologia
W tej sekcji zdefiniowano terminologię i opisano technologię obsługującą wirtualne A/B.
Mapowanie urządzeń
Device-mapper to wirtualna warstwa blokowa systemu Linux często używana w systemie Android. W przypadku partycji dynamicznych partycje takie jak /system
są stosem urządzeń warstwowych:
- Na dole stosu znajduje się fizyczna super partycja (na przykład
/dev/block/by-name/super
). - Pośrodku znajduje się urządzenie
dm-linear
, określające, które bloki w super partycji tworzą daną partycję. Pojawia się jako/dev/block/mapper/system_[a|b]
na urządzeniu A/B lub/dev/block/mapper/system
na urządzeniu innym niż A/B. - Na górze znajduje się urządzenie
dm-verity
, stworzone dla zweryfikowanych partycji. To urządzenie sprawdza, czy bloki na urządzeniudm-linear
są poprawnie podpisane. Pojawia się jako/dev/block/mapper/system-verity
i jest źródłem punktu podłączenia/system
.
Rysunek 1 pokazuje, jak wygląda stos pod punktem podłączenia /system
.
Rysunek 1. Stos pod punktem montowania /system
migawka dm
Virtual A/B opiera się na dm-snapshot
, module mapowania urządzeń służącym do tworzenia migawek stanu urządzenia pamięci masowej. Podczas korzystania z dm-snapshot
w grze biorą udział cztery urządzenia:
- Urządzenie podstawowe to urządzenie, na którym wykonywana jest migawka. Na tej stronie urządzeniem podstawowym jest zawsze partycja dynamiczna, taka jak systemowa lub dostawcy.
- Urządzenie kopiujące przy zapisie (COW) służące do rejestrowania zmian w urządzeniu podstawowym. Może mieć dowolny rozmiar, ale musi być na tyle duży, aby pomieścić wszystkie zmiany w urządzeniu podstawowym.
- Urządzenie migawkowe jest tworzone przy użyciu obiektu
snapshot
. Zapisy na urządzeniu migawkowym są zapisywane na urządzeniu COW. Odczytuje z urządzenia migawkowego odczytanego z urządzenia podstawowego lub urządzenia COW, w zależności od tego, czy dane, do których uzyskiwany jest dostęp, zostały zmienione przez migawkę. - Urządzenie źródłowe jest tworzone przy użyciu obiektu
snapshot-origin
. Odczytuje do urządzenia źródłowego bezpośrednio z urządzenia podstawowego. Zapisuje na urządzeniu źródłowym, zapisuje bezpośrednio na urządzeniu bazowym, ale kopia zapasowa oryginalnych danych jest tworzona poprzez zapis na urządzeniu COW.
Rysunek 2. Mapowanie urządzeń dla migawki dm
Skompresowane migawki
W systemie Android 12 i nowszych wersjach, ponieważ wymagania dotyczące miejsca na partycji /data
mogą być wysokie, możesz włączyć w kompilacji skompresowane migawki, aby sprostać większym wymaganiom dotyczącym miejsca na partycji /data
.
Wirtualne migawki skompresowane A/B są zbudowane w oparciu o następujące komponenty dostępne w systemie Android 12 i nowszych wersjach:
-
dm-user
, moduł jądra podobny do FUSE, który umożliwia przestrzeni użytkownika implementację urządzeń blokowych. -
snapuserd
, demon przestrzeni użytkownika do implementacji nowego formatu migawki.
Elementy te umożliwiają kompresję. Inne niezbędne zmiany wprowadzone w celu wdrożenia możliwości skompresowanych migawek są podane w następnych sekcjach: Format COW dla skompresowanych migawek , dm-user i Snapuserd .
Format COW dla skompresowanych migawek
W systemie Android 12 i nowszych skompresowanych migawkach używa się formatu COW. Podobnie do wbudowanego formatu jądra używanego do nieskompresowanych migawek, format COW dla skompresowanych migawek zawiera naprzemienne sekcje metadanych i danych. Metadane oryginalnego formatu umożliwiały jedynie operacje zastępowania : Zamień blok X w obrazie podstawowym zawartością bloku Y w migawce. Skompresowany format migawek COW jest bardziej wyrazisty i obsługuje następujące operacje:
- Kopiuj : Blok X w urządzeniu podstawowym należy zastąpić blokiem Y w urządzeniu podstawowym.
- Zamień : Blok X w urządzeniu podstawowym powinien zostać zastąpiony zawartością bloku Y w migawce. Każdy z tych bloków jest skompresowany gz.
- Zero : Blok X w urządzeniu bazowym należy zastąpić samymi zerami.
- XOR : Urządzenie COW przechowuje skompresowane bajty XOR pomiędzy blokami X i blokami Y. (Dostępne w Androidzie 13 i nowszych.)
Pełne aktualizacje OTA składają się wyłącznie z operacji zamiany i zera . Przyrostowe aktualizacje OTA mogą dodatkowo obejmować operacje kopiowania .
dm-user w Androidzie 12
Moduł jądra dm-user umożliwia userspace
implementację urządzeń blokowych mapujących urządzenia. Wpis w tabeli dm-user tworzy różne urządzenie w katalogu /dev/dm-user/<control-name>
. Proces userspace
może odpytywać urządzenie w celu otrzymania żądań odczytu i zapisu z jądra. Każde żądanie ma powiązany bufor przestrzeni użytkownika, który może zostać zapełniony (w przypadku odczytu) lub propagowany (w przypadku zapisu).
Moduł jądra dm-user
zapewnia nowy, widoczny dla użytkownika interfejs jądra, który nie jest częścią wcześniejszej bazy kodu kernel.org. Do tego czasu Google zastrzega sobie prawo do modyfikacji interfejsu dm-user
w systemie Android.
snapuserd
Komponent przestrzeni użytkownika snapuserd
dla dm-user
implementuje wirtualną kompresję A/B.
W nieskompresowanej wersji Virtual A/B (w systemie Android 11 i starszych wersjach lub w systemie Android 12 bez opcji skompresowanej migawki) urządzenie COW jest plikiem surowym. Gdy kompresja jest włączona, COW działa zamiast tego jako urządzenie dm-user
, które jest podłączone do instancji demona snapuserd
.
Jądro nie używa nowego formatu COW. Zatem komponent snapuserd
tłumaczy żądania między formatem COW systemu Android a formatem wbudowanym w jądro:
Rysunek 3. Schemat działania snapuserd jako tłumacza między formatami Androida i Kernel COW
To tłumaczenie i dekompresja nigdy nie występują na dysku. Komponent snapuserd
przechwytuje odczyty i zapisy COW występujące w jądrze i implementuje je przy użyciu formatu COW systemu Android.
Kompresja XOR
W przypadku urządzeń z systemem Android 13 i nowszym funkcja kompresji XOR, która jest domyślnie włączona, umożliwia migawkom przestrzeni użytkownika przechowywanie skompresowanych bajtów XOR między starymi i nowymi blokami. Gdy podczas wirtualnej aktualizacji A/B zmienia się tylko kilka bajtów w bloku, schemat przechowywania z kompresją XOR zużywa mniej miejsca niż domyślny schemat przechowywania, ponieważ migawki nie przechowują pełnych 4 KB bajtów. To zmniejszenie rozmiaru migawki jest możliwe, ponieważ dane XOR zawierają wiele zer i są łatwiejsze do kompresji niż surowe dane blokowe. Na urządzeniach Pixel kompresja XOR zmniejsza rozmiar migawki o 25–40%.
W przypadku urządzeń aktualizowanych do wersji Android 13 lub nowszej należy włączyć kompresję XOR. Aby uzyskać szczegółowe informacje, zobacz Kompresja XOR .
Wirtualne procesy kompresji A/B
W tej sekcji znajdują się szczegółowe informacje na temat procesu wirtualnej kompresji A/B stosowanego w systemach Android 13 i Android 12.
Odczytywanie metadanych (Android 12)
Metadane są konstruowane przez demona snapuserd
. Metadane to przede wszystkim mapowanie dwóch identyfikatorów, każdy po 8 bajtów, które reprezentują sektory, które mają zostać scalone. W dm-snapshot
nazywa się to disk_exception
.
struct disk_exception {
uint64_t old_chunk;
uint64_t new_chunk;
};
Wyjątek dysku jest używany, gdy stary fragment danych zostaje zastąpiony nowym.
Demon snapuserd
odczytuje wewnętrzny plik COW poprzez bibliotekę COW i konstruuje metadane dla każdej operacji COW zawartej w pliku COW.
Odczyty metadanych są inicjowane z dm-snapshot
w jądrze podczas tworzenia urządzenia dm- snapshot
.
Poniższy rysunek przedstawia diagram sekwencji ścieżki we/wy do konstruowania metadanych.
Rysunek 4. Przebieg sekwencji dla ścieżki IO w konstrukcji metadanych
Łączenie (Android 12)
Po zakończeniu procesu rozruchu silnik aktualizacji oznacza gniazdo jako pomyślne i inicjuje scalanie, przełączając cel dm-snapshot
na cel dm-snapshot-merge
.
dm-snapshot
przegląda metadane i inicjuje scalanie operacji we/wy dla każdego wyjątku dysku. Poniżej przedstawiono ogólny przegląd ścieżki we/wy scalania.
Rysunek 5. Przegląd ścieżki scalania we/wy
Jeśli urządzenie zostanie ponownie uruchomione podczas procesu scalania, scalanie zostanie wznowione przy następnym uruchomieniu i scalanie zostanie zakończone.
Warstwy mapowania urządzeń
W przypadku urządzeń z systemem Android 13 i nowszym procesy tworzenia migawek i łączenia migawek w ramach wirtualnej kompresji A/B są wykonywane przez komponent przestrzeni użytkownika snapuserd
. W przypadku urządzeń z systemem Android 13 lub nowszym ta funkcja musi być włączona. Aby uzyskać szczegółowe informacje, zobacz Łączenie przestrzeni użytkownika .
Poniżej opisano proces wirtualnej kompresji A/B:
- Struktura montuje partycję
/system
z urządzeniadm-verity
, które jest ułożone na urządzeniudm-user
. Oznacza to, że każde wejście/wyjście z głównego systemu plików jest kierowane dodm-user
. -
dm-user
kieruje operacje we/wy do demonasnapuserd
w przestrzeni użytkownika, który obsługuje żądania we/wy. - Po zakończeniu operacji scalania struktura zwija
dm-verity
nadm-linear
(system_base
) i usuwadm-user
.
Rysunek 6. Proces wirtualnej kompresji A/B
Proces scalania migawek może zostać przerwany. Jeśli urządzenie zostanie ponownie uruchomione podczas procesu scalania, proces scalania zostanie wznowiony po ponownym uruchomieniu.
Rozpocznij przejścia
Podczas uruchamiania ze skompresowanymi migawkami, init pierwszego etapu musi uruchomić snapuserd
, aby zamontować partycje. Stanowi to problem: gdy ładowana i wymuszana jest sepolicy
, snapuserd
zostaje umieszczony w niewłaściwym kontekście, a jego żądania odczytu kończą się niepowodzeniem, co powoduje odmowy Selinux.
Aby rozwiązać ten problem, snapuserd
przechodzi w kroku blokady za pomocą init
w następujący sposób:
-
init
pierwszego etapu uruchamiasnapuserd
z ramdysku i zapisuje do niego otwarty deskryptor pliku w zmiennej środowiskowej. -
init
pierwszego etapu przełącza główny system plików na partycję systemową, a następnie wykonuje kopię systemowąinit
. - Kopia systemowa
init
wczytuje połączoną sepolicy do łańcucha. -
Init
wywołujemlock()
na wszystkich stronach wspieranych przez ext4. Następnie dezaktywuje wszystkie tabele mapowania urządzeń dla urządzeń migawkowych i zatrzymujesnapuserd
. Po tym zabrania się czytania z partycji, ponieważ powoduje to zakleszczenie. - Używając otwartego deskryptora kopii
snapuserd
na dysku RAM,init
ponownie uruchamia demona z poprawnym kontekstem selinux. Tabele mapowania urządzeń dla urządzeń migawkowych zostały ponownie aktywowane. - Init wywołuje
munlockall()
- można bezpiecznie ponownie wykonać IO.
Wykorzystanie przestrzeni
Poniższa tabela przedstawia porównanie wykorzystania miejsca dla różnych mechanizmów OTA przy użyciu rozmiarów systemów operacyjnych i OTA Pixela.
Wpływ rozmiaru | nie-A/B | A/B | Wirtualny A/B | Wirtualny A/B (skompresowany) |
---|---|---|---|---|
Oryginalny obraz fabryczny | Super 4,5 GB (obraz 3,8 G + zarezerwowane 700 MB) 1 | 9 GB super (3,8 G + 700 M zarezerwowane na dwa gniazda) | Super 4,5 GB (obraz 3,8 GB + zarezerwowane 700 MB) | Super 4,5 GB (obraz 3,8 GB + zarezerwowane 700 MB) |
Inne partycje statyczne | /Pamięć podręczna | Nic | Nic | Nic |
Dodatkowa pamięć podczas OTA (przestrzeń zwrócona po zastosowaniu OTA) | 1,4 GB na /dane | 0 | 3,8 GB 2 na /dane | 2,1 GB 2 na /dane |
Łączna ilość miejsca wymagana do zastosowania OTA | 5,9 GB 3 (super i dane) | 9 GB (super) | 8,3 GB 3 (super i dane) | 6,6 GB 3 (super i dane) |
1 Wskazuje założony układ oparty na mapowaniu pikseli.
2 Zakłada się, że nowy obraz systemu ma ten sam rozmiar co oryginał.
3 Zapotrzebowanie na miejsce jest przejściowe do momentu ponownego uruchomienia.
Aby zaimplementować Virtual A/B lub skorzystać z możliwości skompresowanej migawki, zobacz Implementowanie Virtual A/B