Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Ikhtisar A/B Virtual

Android memiliki dua mekanisme pembaruan: pembaruan A/B (mulus) dan pembaruan non-A/B. Untuk mengurangi kerumitan kode dan menyempurnakan proses pembaruan, di Android 11 kedua mekanisme tersebut disatukan melalui A/B virtual untuk menghadirkan pembaruan tanpa hambatan ke semua perangkat dengan biaya penyimpanan yang diminimalkan. Android 12 menawarkan opsi kompresi A/B Virtual untuk mengompresi partisi yang di-snapshot. Di Android 11 dan Android 12, hal berikut ini berlaku:

  • Pembaruan A/B virtual mulus seperti pembaruan A/B. Pembaruan A/B virtual meminimalkan waktu perangkat offline dan tidak dapat digunakan.
  • Pembaruan A/B virtual dapat dibatalkan . Jika OS baru gagal untuk boot, perangkat secara otomatis memutar kembali ke versi sebelumnya.
  • Pembaruan A/B virtual menggunakan ruang ekstra minimum dengan hanya menduplikasi partisi yang digunakan oleh bootloader. Partisi yang dapat diperbarui lainnya di- snapshot .

Latar belakang dan terminologi

Bagian ini mendefinisikan terminologi dan menjelaskan teknologi yang mendukung A/B virtual.

Pemeta perangkat

Device-mapper adalah lapisan blok virtual Linux yang sering digunakan di Android. Dengan partisi dinamis , partisi seperti /system adalah tumpukan perangkat berlapis:

  • Di bagian bawah tumpukan adalah partisi super fisik (misalnya, /dev/block/by-name/super ).
  • Di tengah adalah perangkat dm-linear , menentukan blok mana dalam partisi super yang membentuk partisi yang diberikan. Ini muncul sebagai /dev/block/mapper/system_[a|b] pada perangkat A/B, atau /dev/block/mapper/system pada perangkat non-A/B.
  • Di bagian atas terdapat perangkat dm-verity , dibuat untuk partisi yang diverifikasi. Perangkat ini memverifikasi bahwa blok pada perangkat dm-linear ditandatangani dengan benar. Itu muncul sebagai /dev/block/mapper/system-verity dan merupakan sumber dari /system mount point.

Gambar 1 menunjukkan seperti apa tumpukan di bawah /system mount point.

Partition stacking underneath system

Gambar 1. Tumpuk di bawah /system mount point

dm-snapshot

Virtual A/B bergantung pada dm-snapshot , modul device-mapper untuk memotret status perangkat penyimpanan. Saat menggunakan dm-snapshot , ada empat perangkat yang dimainkan:

  • Perangkat dasar adalah perangkat yang di-snapshot. Pada halaman ini, perangkat dasar selalu merupakan partisi dinamis, seperti sistem atau vendor.
  • Perangkat copy-on-write (COW), untuk mencatat perubahan ke perangkat dasar. Ukurannya bisa berapa saja, tetapi harus cukup besar untuk mengakomodasi semua perubahan pada perangkat dasar.
  • Perangkat snapshot dibuat menggunakan target snapshot . Menulis ke perangkat snapshot ditulis ke perangkat COW. Membaca dari perangkat snapshot membaca baik dari perangkat dasar atau perangkat COW, tergantung pada apakah data yang diakses telah diubah oleh snapshot.
  • Perangkat asal dibuat menggunakan target snapshot-origin . Membaca ke perangkat asal membaca langsung dari perangkat dasar. Menulis ke perangkat asal menulis langsung ke perangkat dasar, tetapi data asli dicadangkan dengan menulis ke perangkat COW.

Device mapping for dm-snapshot

Gambar 2. Pemetaan perangkat untuk dm-snapshot

Snapshot terkompresi

Di Android 12, karena persyaratan ruang pada partisi /data bisa tinggi, Anda dapat mengaktifkan snapshot terkompresi di build Anda untuk mengatasi persyaratan ruang yang lebih tinggi dari partisi /data .

Snapshot terkompresi A/B virtual dibuat di atas dua komponen baru yang tersedia di Android 12:

  • dm-user , modul kernel yang mirip dengan FUSE yang memungkinkan ruang pengguna untuk mengimplementasikan perangkat blok.
  • snapuserd , daemon userspace untuk mengimplementasikan format snapshot baru.

Komponen-komponen ini memungkinkan kompresi. Perubahan lain yang diperlukan untuk menerapkan kemampuan snapshot terkompresi diberikan di bagian berikutnya: format COW untuk snapshot terkompresi , dm-user , dan Snapuserd .

Format COW untuk snapshot terkompresi

Di Android 12, snapshot terkompresi menggunakan format COW baru. Mirip dengan format bawaan kernel yang digunakan untuk snapshot yang tidak terkompresi, format COW untuk snapshot terkompresi memiliki bagian metadata dan data yang bergantian. Metadata format asli hanya diperbolehkan untuk operasi "ganti": Ganti blok X di gambar dasar dengan konten blok Y di snapshot. Format COW snapshot terkompresi lebih ekspresif dan mendukung tiga operasi:

  • Salin - Blok X di perangkat dasar harus diganti dengan blok Y di perangkat dasar.
  • Ganti - Blok X di perangkat dasar harus diganti dengan konten blok Y di snapshot. Masing-masing blok ini dikompresi gz.
  • Nol - Blok X di perangkat dasar harus diganti dengan semua nol.

Pembaruan OTA lengkap hanya terdiri dari penggantian dan operasi nol . Pembaruan OTA tambahan dapat memiliki operasi penyalinan .

pengguna dm di Android 12

Modul kernel dm-user memungkinkan userspace untuk mengimplementasikan perangkat blok device-mapper. Entri tabel dm-user membuat perangkat lain-lain di bawah /dev/dm-user/<control-name> . Proses userspace dapat melakukan polling perangkat untuk menerima permintaan baca dan tulis dari kernel. Setiap permintaan memiliki buffer terkait untuk ruang pengguna untuk diisi (untuk dibaca) atau disebarkan (untuk ditulis).

Modul kernel dm-user menyediakan antarmuka baru yang dapat dilihat pengguna ke kernel yang bukan bagian dari basis kode kernel.org upstream. Sampai saat ini, Google berhak untuk memodifikasi antarmuka dm-user di Android.

pengguna snap

Komponen snapuserd userspace ke dm-user mengimplementasikan Virtual A/B Compression.

Dalam versi Virtual A/B yang tidak terkompresi, (baik di Android 11 dan yang lebih rendah, atau di Android 12 tanpa opsi snapshot terkompresi), perangkat COW adalah file mentah. Saat kompresi diaktifkan, COW berfungsi sebagai perangkat dm-user , yang terhubung ke instance daemon snapuserd .

Kernel tidak menggunakan format COW baru. Jadi komponen snapuserd menerjemahkan permintaan antara format Android COW dan format bawaan kernel:

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

Gambar 3. Diagram alir snapuserd sebagai penerjemah antara format Android dan Kernel COW

Terjemahan dan dekompresi ini tidak pernah terjadi pada disk. Komponen snapuserd mencegat pembacaan dan penulisan COW yang terjadi di kernel, dan mengimplementasikannya menggunakan format Android COW.

Proses kompresi A/B virtual

Bagian ini memberikan detail mengenai proses yang digunakan dalam kompresi A/B Virtual: membaca metadata, menggabungkan, dan melakukan transisi init.

Membaca metadata

Metadata dibangun oleh daemon snapuserd . Metadata utamanya adalah pemetaan 2 ID, masing-masing 8 byte, yang mewakili sektor yang akan digabungkan. Dalam dm-snapshot itu disebut sebagai disk_exception .

struct disk_exception {
    uint64_t old_chunk;
    uint64_t new_chunk;
};

Pengecualian disk digunakan ketika sepotong data lama diganti dengan yang baru.

Daemon Snapuserd membaca file KK internal melalui perpustakaan KK dan menyusun metadata untuk setiap operasi KK yang ada dalam file KK.

Pembacaan metadata dimulai dari dm-snapshot di kernel saat perangkat dm- dm- snapshot dibuat.

Gambar di bawah memberikan diagram urutan untuk jalur IO untuk konstruksi metadata.

Sequence diagram, IO path for metadata construction

Gambar 4. Alur urutan untuk jalur IO dalam konstruksi metadata

Penggabungan

Setelah proses boot selesai, mesin pembaruan menandai slot sebagai boot berhasil dan memulai penggabungan dengan mengalihkan target dm-snapshot ke target dm-snapshot-merge .

dm-snapshot menelusuri metadata dan memulai penggabungan IO untuk setiap pengecualian disk. Ikhtisar tingkat tinggi dari jalur gabungan IO ditunjukkan di bawah ini.

Merge IO path

Gambar 5. Menggabungkan ikhtisar jalur IO

Jika perangkat di-boot ulang selama proses penggabungan, penggabungan dilanjutkan pada reboot berikutnya, dan penggabungan selesai.

Init transisi

Saat mem-boot dengan snapshot terkompresi, init tahap pertama harus memulai snapuserd untuk memasang partisi. Ini menimbulkan masalah: Ketika sepolicy dimuat dan ditegakkan, snapuserd dimasukkan ke dalam konteks yang salah, dan permintaan bacanya gagal, dengan penolakan selinux.

Untuk mengatasinya, snapuserd transisi dalam lock-step dengan init , sebagai berikut:

  1. init tahap pertama meluncurkan snapuserd dari ramdisk, dan menyimpan deskriptor file yang terbuka ke dalamnya dalam variabel lingkungan.
  2. init tahap pertama mengalihkan sistem file root ke partisi sistem, lalu mengeksekusi salinan sistem init .
  3. Salinan sistem init membaca kebijakan gabungan menjadi string.
  4. Init memanggil mlock() pada semua halaman yang didukung ext4. Ini kemudian menonaktifkan semua tabel device-mapper untuk perangkat snapshot, dan menghentikan snapuserd . Setelah ini dilarang membaca dari partisi, karena hal itu menyebabkan kebuntuan.
  5. Menggunakan deskriptor terbuka ke salinan ramdisk dari snapuserd , init meluncurkan kembali daemon dengan konteks selinux yang benar. Tabel device-mapper untuk perangkat snapshot diaktifkan kembali.
  6. Init memanggil munlockall() - aman untuk melakukan IO lagi.

Penggunaan ruang

Tabel berikut memberikan perbandingan penggunaan ruang untuk mekanisme OTA yang berbeda menggunakan OS Pixel dan ukuran OTA.

Dampak Ukuran non-A/B A/B Virtual A/B Virtual A/B (terkompresi)
Gambar Pabrik Asli 4.5GB super (gambar 3.8G + 700 juta dicadangkan) 1 9GB super (3.8G + 700M dicadangkan, untuk dua slot) 4.5GB super (gambar 3.8G + 700 juta dicadangkan) 4.5GB super (gambar 3.8G + 700 juta dicadangkan)
Partisi statis lainnya /cache Tidak ada Tidak ada Tidak ada
Penyimpanan tambahan Selama OTA (ruang dikembalikan setelah menerapkan OTA) 1.4GB di /data 0 3,8 GB 2 pada / data 2.1GB 2 di /data
Total penyimpanan yang diperlukan untuk menerapkan OTA 5.9GB 3 (super dan data) 9GB (super) 8.3GB 3 (super dan data) 6.6GB 3 (super dan data)

1 Menunjukkan tata letak yang diasumsikan berdasarkan pemetaan Piksel.

2 Diasumsikan citra sistem baru berukuran sama dengan aslinya.

3 Kebutuhan ruang bersifat sementara hingga reboot.

Untuk menerapkan A/B Virtual, atau untuk menggunakan kemampuan snapshot terkompresi, lihat Menerapkan A/B Virtual