Wirtualny przegląd A/B

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Android ma dwa mechanizmy aktualizacji: aktualizacje A/B (bezproblemowe) i aktualizacje inne niż A/B. Aby zmniejszyć złożoność kodu i usprawnić proces aktualizacji, w systemie Android 11 oba mechanizmy są zunifikowane za pomocą wirtualnego A/B, aby zapewnić płynne aktualizacje na wszystkich urządzeniach przy zminimalizowanych kosztach przechowywania. Android 12 oferuje opcję kompresji Virtual A/B do kompresji zrzutów partycji. Zarówno w systemie Android 11, jak i Android 12 obowiązują następujące zasady:

  • Wirtualne aktualizacje A/B są płynne jak aktualizacje A/B. Wirtualne aktualizacje A/B minimalizują czas, w którym urządzenie jest w trybie offline i nie nadaje się do użytku.
  • Aktualizacje wirtualnych A/B można wycofać . Jeśli nowy system operacyjny nie uruchomi się, urządzenia automatycznie przywrócą poprzednią wersję.
  • Aktualizacje wirtualne A/B zajmują minimalną ilość dodatkowego miejsca , duplikując tylko partycje używane przez program ładujący. Inne partycje, które można aktualizować, są zapisywane w migawkach .

Tło i terminologia

W tej sekcji zdefiniowano terminologię i opisano technologię obsługującą wirtualne A/B.

Urządzenie do mapowania

Device-mapper to wirtualna warstwa bloków Linuksa, często używana w Androidzie. W przypadku partycji dynamicznych partycje takie jak /system są stosem urządzeń warstwowych:

  • Na dole stosu znajduje się fizyczna superpartycja (na przykład /dev/block/by-name/super ) .
  • W ś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ądzeniu dm-linear są poprawnie podpisane. Pojawia się jako /dev/block/mapper/system-verity i jest źródłem punktu montowania /system .

Rysunek 1 pokazuje, jak wygląda stos pod punktem montowania /system .

Partition stacking underneath system

Rysunek 1. Stos pod /punktem montowania systemu

dm-migawka

Wirtualne A/B opiera się na dm-snapshot , module mapowania urządzenia do tworzenia migawek stanu urządzenia pamięci masowej. Podczas korzystania z dm-snapshot w grze dostępne są cztery urządzenia:

  • Urządzeniem podstawowym jest urządzenie, na którym wykonano migawkę. Na tej stronie urządzenie podstawowe jest zawsze partycją dynamiczną, taką jak system lub dostawca.
  • Urządzenie typu copy-on-write (COW) służące do rejestrowania zmian w urządzeniu podstawowym. Może mieć dowolny rozmiar, ale musi być wystarczająco duży, aby pomieścić wszystkie zmiany w urządzeniu podstawowym.
  • Urządzenie do zrzutu obrazu jest tworzone przy użyciu celu snapshot . Zapisy do urządzenia migawkowego są zapisywane na urządzeniu COW. Odczyty z urządzenia migawkowego odczytane z urządzenia podstawowego lub urządzenia COW, w zależności od tego, czy dane, do których uzyskuje się dostęp, zostały zmienione przez migawkę.
  • Urządzenie źródłowe jest tworzone przy użyciu docelowego miejsca pochodzenia snapshot-origin . Odczytuje do urządzenia źródłowego odczytywane bezpośrednio z urządzenia podstawowego. Zapisuje w urządzeniu źródłowym, zapisuje bezpośrednio w urządzeniu podstawowym, ale kopia zapasowa oryginalnych danych jest tworzona przez zapis na urządzeniu COW.

Device mapping for dm-snapshot

Rysunek 2. Mapowanie urządzeń dla dm-snapshot

Skompresowane migawki

W systemie Android 12 i nowszych, ponieważ wymagania dotyczące miejsca na partycji /data mogą być wysokie, możesz włączyć skompresowane migawki w swojej kompilacji, aby sprostać wyższym wymaganiom dotyczącym miejsca na partycji /data .

Wirtualne skompresowane migawki A/B są oparte na następujących składnikach dostępnych w systemie Android 12 i nowszych:

  • dm-user , moduł jądra podobny do FUSE, który pozwala przestrzeni użytkownika na implementację urządzeń blokowych.
  • snapuserd , demon przestrzeni użytkownika do implementacji nowego formatu migawki.

Te składniki umożliwiają kompresję. Inne niezbędne zmiany wprowadzone w celu zaimplementowania 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 skompresowane migawki używają 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 zezwalały tylko na operacje zastępowania : Zastąp blok X w obrazie podstawowym zawartością bloku Y w migawce. Skompresowany format COW migawek 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 w gz.
  • Zero : Blok X w urządzeniu podstawowym należy zastąpić wszystkimi zerami.
  • XOR : Urządzenie COW przechowuje skompresowane bajty XOR między blokiem X a blokiem Y. (Dostępne w systemie Android 13 i nowszych.)

Pełne aktualizacje OTA składają się tylko z operacji wymiany i zerowania . Przyrostowe aktualizacje OTA mogą dodatkowo zawierać operacje kopiowania .

dm-user w Androidzie 12

Moduł jądra dm-user umożliwia userspace implementację urządzeń blokowych mapowania urządzeń. Wpis tabeli dm-user tworzy różne urządzenia w /dev/dm-user/<control-name> . Proces userspace może odpytywać urządzenie, aby otrzymać żądania odczytu i zapisu z jądra. Każde żądanie ma skojarzony bufor dla przestrzeni użytkownika do wypełnienia (dla odczytu) lub propagacji (dla zapisu).

Moduł jądra dm-user zapewnia nowy, widoczny dla użytkownika interfejs do jądra, który nie jest częścią podstawowego kodu kernel.org. Do tego czasu Google zastrzega sobie prawo do modyfikacji interfejsu dm-user w systemie Android.

snapuserd

Komponent przestrzeni użytkownika snapuserd do dm-user implementuje kompresję Virtual A/B.

W nieskompresowanej wersji Virtual A/B (w systemie Android 11 i niższych 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 połączone z instancją demona snapuserd .

Jądro nie używa nowego formatu COW. Tak więc komponent snapuserd tłumaczy żądania między formatem Android COW a wbudowanym formatem jądra:

Snapuserd component translating requests between Android COW format and kernel built-in format

Rysunek 3. Schemat działania snapuserda jako tłumacza między formatami Android i Kernel COW

Ta translacja i dekompresja nigdy nie występują na dysku. Komponent snapuserd przechwytuje odczyty i zapisy COW, które występują w jądrze i implementuje je przy użyciu formatu Android COW.

Kompresja XOR

W przypadku urządzeń uruchamianych z systemem Android 13 i nowszym funkcja kompresji XOR, która jest domyślnie włączona, umożliwia przechowywanie migawek przestrzeni użytkownika skompresowanych bajtów XOR między starymi blokami a nowymi blokami. Gdy podczas aktualizacji Virtual A/B zmienia się tylko kilka bajtów w bloku, schemat pamięci masowej kompresji XOR zużywa mniej miejsca niż domyślny schemat pamięci masowej, 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ż nieprzetworzone dane blokowe. Na urządzeniach Pixel kompresja XOR zmniejsza rozmiar migawki o 25% do 40%.

W przypadku urządzeń uaktualniających do systemu Android 13 lub nowszego kompresja XOR musi być włączona. Aby uzyskać szczegółowe informacje, zobacz Kompresja XOR .

Wirtualne procesy kompresji A/B

Ta sekcja zawiera szczegółowe informacje na temat procesu kompresji Virtual A/B używanego 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ć połączone. 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 jest zastępowany przez nowy.

Demon snapuserd odczytuje wewnętrzny plik COW przez bibliotekę COW i konstruuje metadane dla każdej z operacji COW obecnych w pliku COW.

Odczyty metadanych są inicjowane z dm-snapshot w jądrze podczas tworzenia urządzenia dm- dm- snapshot .

Poniższy rysunek przedstawia diagram sekwencji dla ścieżki we/wy do budowy metadanych.

Sequence diagram, IO path for metadata construction

Rysunek 4. Przebieg sekwencji dla ścieżki IO w konstrukcji metadanych

Scalanie (Android 12)

Po zakończeniu procesu uruchamiania mechanizm aktualizacji oznacza gniazdo jako pomyślne uruchomienie i inicjuje scalenie, przełączając cel dm-snapshot na cel dm-snapshot-merge .

dm-snapshot przechodzi przez metadane i inicjuje scalanie we/wy dla każdego wyjątku dysku. Ogólny przegląd ścieżki scalania we/wy pokazano poniżej.

Merge IO path

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 ponownym uruchomieniu, a scalanie zostanie zakończone.

Warstwy urządzenie-mapper

W przypadku urządzeń uruchamianych z systemem Android 13 i nowszym procesy scalania migawek i migawek w kompresji Virtual A/B są wykonywane przez składnik przestrzeni użytkownika snapuserd . W przypadku urządzeń uaktualniających do systemu Android 13 lub nowszego ta funkcja musi być włączona. Aby uzyskać szczegółowe informacje, zobacz Scalanie przestrzeni użytkownika .

Poniżej opisano proces kompresji Virtual A/B:

  1. Struktura montuje partycję /system z urządzenia dm-verity , które jest ułożone w stos na urządzeniu dm-user . Oznacza to, że każde I/O z głównego systemu plików jest kierowane do dm-user .
  2. dm-user kieruje I/O do demona snapuserd w przestrzeni użytkownika, który obsługuje żądania I/O.
  3. Po zakończeniu operacji scalania framework zwija dm-verity na dm-linear ( system_base ) i usuwa dm-user .

Wirtualny proces kompresji A/B

Rysunek 6. Wirtualny proces kompresji A/B

Proces scalania migawek można przerwać. Jeśli urządzenie zostanie ponownie uruchomione podczas procesu scalania, proces scalania zostanie wznowiony po ponownym uruchomieniu.

Przejścia początkowe

Podczas uruchamiania ze skompresowanymi migawkami, init pierwszego etapu musi uruchomić snapuserd , aby zamontować partycje. Stwarza to problem: gdy sepolicy są ładowane i egzekwowane, snapuserd jest umieszczany w niewłaściwym kontekście, a jego żądania odczytu kończą się niepowodzeniem, z odmowami selinuksa.

Aby rozwiązać ten problem, snapuserd przechodzi w lock-step z init , w następujący sposób:

  1. snapuserd init ramdysku i zapisuje w nim otwarty deskryptor pliku w zmiennej środowiskowej.
  2. W pierwszym etapie init przełącza główny system plików na partycję systemową, a następnie wykonuje kopię systemową init .
  3. Systemowa kopia init odczytuje połączoną sepolitykę w łańcuch.
  4. Init wywołuje mlock() na wszystkich stronach obsługiwanych przez ext4. Następnie dezaktywuje wszystkie tabele mapowania urządzeń dla urządzeń migawkowych i zatrzymuje snapuserd . Po tym nie wolno czytać z partycji, ponieważ powoduje to zakleszczenie.
  5. Używając otwartego deskryptora do kopii snapuserd na ramdysku, init ponownie uruchamia demona z poprawnym kontekstem selinux. Tabele mapowania urządzeń dla urządzeń migawek są ponownie aktywowane.
  6. Init wywołuje munlockall() - można ponownie wykonać IO.

Wykorzystanie przestrzeni

Poniższa tabela zawiera porównanie wykorzystania miejsca przez różne mechanizmy OTA przy użyciu systemów operacyjnych Pixel i rozmiarów OTA.

Wpływ rozmiaru nie-A/B A/B Wirtualne A/B Wirtualne A/B (skompresowane)
Oryginalny obraz fabryczny 4,5 GB super (obraz 3,8 GB + zarezerwowane 700 MB) 1 Super 9 GB (zarezerwowane 3,8 G + 700 M, na dwa gniazda) 4,5 GB super (obraz 3,8 GB + zarezerwowane 700 MB) 4,5 GB super (obraz 3,8 GB + zarezerwowane 700 MB)
Inne partycje statyczne /Pamięć podręczna Nic Nic Nic
Dodatkowa pamięć podczas OTA (przestrzeń zwracana po zastosowaniu OTA) 1,4 GB na /dane 0 3,8 GB 2 na /dane 2,1 GB 2 na /dane
Całkowita pamięć 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 zakładany układ na podstawie mapowania pikseli.

2 Zakłada, że ​​nowy obraz systemu ma taki sam rozmiar jak oryginalny.

3 Wymagane miejsce jest przejściowe do ponownego uruchomienia.

Aby zaimplementować Virtual A/B lub skorzystać z funkcji skompresowanych migawek, zobacz Implementacja Virtual A/B