Passthrough FUSE

Android 12 mendukung passthrough FUSE, yang meminimalkan overhead FUSE untuk mencapai performa yang sebanding dengan akses langsung ke sistem file yang lebih rendah. FUSE passthrough didukung di kernel android12-5.4, android12-5.10, dan android-mainline (khusus pengujian), yang berarti bahwa dukungan untuk fitur ini bergantung pada kernel yang digunakan oleh perangkat dan versi Android yang dijalankan perangkat:

  • Perangkat yang diupgrade dari Android 11 ke Android 12 tidak dapat mendukung penerusan FUSE karena kernel untuk perangkat ini dibekukan dan tidak dapat berpindah ke kernel yang telah diupgrade secara resmi dengan perubahan penerusan FUSE.

  • Perangkat yang diluncurkan dengan Android 12 dapat mendukung penerusan FUSE saat menggunakan kernel resmi. Untuk perangkat tersebut, kode framework Android yang mengimplementasikan penerusan FUSE disematkan dalam modul utama MediaProvider, yang diupgrade secara otomatis. Perangkat yang tidak menerapkan MediaProvider sebagai modul utama (misalnya, perangkat Android Go), juga dapat mengakses perubahan MediaProvider saat dibagikan secara publik.

FUSE versus SDCardFS

File system in Userspace (FUSE) adalah mekanisme yang memungkinkan operasi yang dilakukan pada sistem file FUSE dialihdayakan oleh kernel (driver FUSE) ke program userspace (daemon FUSE), yang menerapkan operasi. Android 11 menghentikan penggunaan SDCardFS dan menjadikan FUSE sebagai solusi default untuk emulasi penyimpanan. Sebagai bagian dari perubahan ini, Android menerapkan daemon FUSE-nya sendiri untuk mencegat akses file, menerapkan fitur keamanan dan privasi tambahan, serta memanipulasi file saat runtime.

Meskipun FUSE berperforma baik saat menangani informasi yang dapat di-cache seperti halaman atau atribut, FUSE menimbulkan regresi performa saat mengakses penyimpanan eksternal yang terutama terlihat pada perangkat kelas menengah dan bawah. Regresi ini disebabkan oleh serangkaian komponen yang beroperasi dalam penerapan sistem file FUSE, serta beberapa peralihan dari ruang kernel ke ruang pengguna dalam komunikasi antara driver FUSE dan daemon FUSE (dibandingkan dengan akses langsung ke sistem file yang lebih rendah yang lebih ramping dan sepenuhnya diterapkan di kernel).

Untuk mengurangi regresi ini, aplikasi dapat menggunakan penyambungan untuk mengurangi penyalinan data dan menggunakan ContentProvider API untuk mendapatkan akses langsung ke file sistem file yang lebih rendah. Meskipun dengan pengoptimalan lainnya, operasi baca dan tulis mungkin mengalami penurunan bandwidth saat menggunakan FUSE dibandingkan dengan akses langsung ke sistem file yang lebih rendah — terutama dengan operasi baca acak, yang tidak dapat dibantu oleh caching atau baca-depan. Selain itu, aplikasi yang mengakses penyimpanan secara langsung melalui jalur /sdcard/ lama akan terus mengalami penurunan performa yang terlihat jelas, terutama saat melakukan operasi yang intensif IO.

Permintaan ruang pengguna SDcardFS

Menggunakan SDcardFS dapat mempercepat emulasi penyimpanan dan pemeriksaan izin FUSE dengan menghapus panggilan ruang pengguna dari kernel. Permintaan ruang pengguna mengikuti jalur: Ruang pengguna → VFS → sdcardfs → VFS → ext4 → Cache halaman/Penyimpanan.

FUSE Passthrough SDcardFS

Gambar 1. Permintaan ruang pengguna SDcardFS

Permintaan ruang pengguna FUSE

FUSE awalnya digunakan untuk mengaktifkan emulasi penyimpanan dan mengizinkan aplikasi menggunakan penyimpanan internal atau kartu SD eksternal secara transparan. Penggunaan FUSE menimbulkan beberapa overhead karena setiap permintaan ruang pengguna mengikuti jalur: Ruang pengguna → VFS → Driver FUSE → Daemon FUSE → VFS → ext4 → Cache halaman/Penyimpanan.

FUSE Passthrough FUSE

Gambar 2. Permintaan ruang pengguna FUSE

Permintaan teruskan FUSE

Sebagian besar izin akses file diperiksa saat file dibuka, dengan pemeriksaan izin tambahan yang terjadi saat membaca dan menulis ke file tersebut. Dalam beberapa kasus, saat file dibuka, dapat diketahui bahwa aplikasi yang meminta memiliki akses penuh ke file yang diminta, sehingga sistem tidak perlu terus meneruskan permintaan baca dan tulis dari driver FUSE ke daemon FUSE (karena hal itu hanya akan memindahkan data dari satu tempat ke tempat lain).

Dengan penerusan FUSE, daemon FUSE yang menangani permintaan buka dapat memberi tahu driver FUSE bahwa operasi diizinkan dan semua permintaan baca dan tulis berikutnya dapat diteruskan langsung ke sistem file yang lebih rendah. Hal ini menghindari overhead tambahan karena menunggu daemon FUSE ruang pengguna membalas permintaan driver FUSE.

Perbandingan permintaan FUSE dan FUSE passthrough ditampilkan di bawah.

Perbandingan Passthrough FUSE

Gambar 3. Permintaan FUSE versus permintaan teruskan FUSE

Saat aplikasi melakukan akses sistem file FUSE, operasi berikut akan terjadi:

  1. Driver FUSE menangani dan mengantrekan permintaan, lalu menyajikannya ke daemon FUSE yang menangani sistem file FUSE tersebut melalui instance koneksi tertentu pada file /dev/fuse, yang tidak dapat dibaca oleh daemon FUSE.

  2. Saat menerima permintaan untuk membuka file, daemon FUSE akan memutuskan apakah FUSE passthrough harus tersedia untuk file tertentu tersebut. Jika tersedia, daemon:

    1. Memberi tahu driver FUSE tentang permintaan ini.

    2. Mengaktifkan penerusan FUSE untuk file menggunakan ioctl FUSE_DEV_IOC_PASSTHROUGH_OPEN, yang harus dilakukan pada deskriptor file /dev/fuse yang dibuka.

  3. ioctl menerima (sebagai parameter) struktur data yang berisi berikut:

    • Deskriptor file dari file sistem file yang lebih rendah yang menjadi target untuk fitur penerusan.

    • ID unik permintaan FUSE yang sedang ditangani (harus berupa open atau create-and-open).

    • Kolom tambahan yang dapat dibiarkan kosong dan ditujukan untuk implementasi mendatang.

  4. Jika ioctl berhasil, daemon FUSE akan menyelesaikan permintaan buka, driver FUSE akan menangani balasan daemon FUSE, dan referensi ke file sistem file yang lebih rendah akan ditambahkan ke file FUSE dalam kernel. Saat aplikasi meminta operasi baca/tulis pada file FUSE, driver FUSE akan memeriksa apakah referensi ke file sistem file yang lebih rendah tersedia.

    • Jika referensi tersedia, driver akan membuat permintaan Virtual File System (VFS) baru dengan parameter yang sama yang menargetkan file sistem file yang lebih rendah.

    • Jika referensi tidak tersedia, driver akan meneruskan permintaan ke daemon FUSE.

Operasi di atas terjadi untuk baca/tulis dan baca-iter/tulis-iter pada file generik dan operasi baca/tulis pada file yang dipetakan ke memori. FUSE passthrough untuk file tertentu ada hingga file tersebut ditutup.

Menerapkan passthrough FUSE

Untuk mengaktifkan penerusan FUSE di perangkat yang menjalankan Android 12, tambahkan baris berikut ke file $ANDROID_BUILD_TOP/device/…/device.mk perangkat target.

# Use FUSE passthrough
PRODUCT_PRODUCT_PROPERTIES += \
    persist.sys.fuse.passthrough.enable=true

Untuk menonaktifkan penerusan FUSE, hapus perubahan konfigurasi di atas atau tetapkan persist.sys.fuse.passthrough.enable ke false. Jika Anda sebelumnya telah mengaktifkan FUSE passthrough, menonaktifkannya akan mencegah perangkat menggunakan FUSE passthrough tetapi perangkat tetap berfungsi.

Untuk mengaktifkan/menonaktifkan penerusan FUSE tanpa mem-flash perangkat, ubah properti sistem menggunakan perintah ADB. Contohnya ditampilkan di bawah ini.

adb root
adb shell setprop persist.sys.fuse.passthrough.enable {true,false}
adb reboot

Untuk bantuan tambahan, lihat implementasi referensi.

Memvalidasi penerusan FUSE

Untuk memvalidasi bahwa MediaProvider menggunakan penerusan FUSE, periksa logcat untuk pesan debug. Contoh:

adb logcat FuseDaemon:V \*:S
--------- beginning of main
03-02 12:09:57.833  3499  3773 I FuseDaemon: Using FUSE passthrough
03-02 12:09:57.833  3499  3773 I FuseDaemon: Starting fuse...

Entri FuseDaemon: Using FUSE passthrough dalam log memastikan bahwa penerusan FUSE sedang digunakan.

CTS Android 12 menyertakan CtsStorageTest, yang mencakup pengujian yang memicu penerusan FUSE. Untuk menjalankan pengujian secara manual, gunakan atest seperti yang ditunjukkan di bawah:

atest CtsStorageTest