Wirtualny przegląd A/B

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ądzeniu dm-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 .

Partition stacking underneath 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.

Device mapping for dm-snapshot

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:

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

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.

Sequence diagram, IO path for metadata construction

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.

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 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:

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

Proces wirtualnej kompresji A/B

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:

  1. init pierwszego etapu uruchamia snapuserd z ramdysku i zapisuje do niego otwarty deskryptor pliku w zmiennej środowiskowej.
  2. init pierwszego etapu przełącza główny system plików na partycję systemową, a następnie wykonuje kopię systemową init .
  3. Kopia systemowa init wczytuje połączoną sepolicy do łańcucha.
  4. Init wywołuje mlock() na wszystkich stronach wspieranych przez ext4. Następnie dezaktywuje wszystkie tabele mapowania urządzeń dla urządzeń migawkowych i zatrzymuje snapuserd . Po tym zabrania się czytania z partycji, ponieważ powoduje to zakleszczenie.
  5. 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.
  6. 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