Fusible de paso

Android 12 es compatible con FUSE passthrough, lo que minimiza la sobrecarga de FUSE para lograr un rendimiento comparable al acceso directo al sistema de archivos inferior. FUSE passthrough es compatible con los android12-5.4 , android12-5.10 y android-mainline (solo para pruebas), lo que significa que la compatibilidad con esta función depende del núcleo que utilice el dispositivo y la versión de Android que esté ejecutando el dispositivo:

  • Los dispositivos que se actualizan de Android 11 a Android 12 no pueden admitir la transferencia de FUSE, ya que los núcleos de estos dispositivos están congelados y no pueden pasar a un kernel que se haya actualizado oficialmente con los cambios de transferencia de FUSE.

  • Los dispositivos que se inician con Android 12 pueden admitir el paso de FUSE cuando se usa un kernel oficial. Para tales dispositivos, el código del marco de trabajo de Android que implementa el paso de FUSE está integrado en el módulo principal de MediaProvider , que se actualiza automáticamente. Los dispositivos que no implementan MediaProvider como módulo principal (por ejemplo, dispositivos Android Go), también pueden acceder a los cambios de MediaProvider a medida que se comparten públicamente.

FUSIBLE contra SDCardFS

El sistema de archivos en el espacio de usuario (FUSE) es un mecanismo que permite que el kernel (controlador FUSE) subcontrate las operaciones realizadas en un sistema de archivos FUSE a un programa de espacio de usuario (demonio FUSE), que implementa las operaciones. Android 11 dejó de usar SDCardFS y convirtió a FUSE en la solución predeterminada para la emulación de almacenamiento. Como parte de este cambio, Android implementó su propio demonio FUSE para interceptar accesos a archivos, aplicar funciones adicionales de seguridad y privacidad y manipular archivos en tiempo de ejecución.

Si bien FUSE funciona bien cuando se trata de información almacenable en caché, como páginas o atributos, presenta regresiones de rendimiento al acceder al almacenamiento externo que son especialmente visibles en dispositivos de gama media y baja. Estas regresiones son causadas por una cadena de componentes que cooperan en la implementación del sistema de archivos FUSE, así como múltiples cambios del espacio del kernel al espacio del usuario en las comunicaciones entre el controlador FUSE y el demonio FUSE (en comparación con el acceso directo al archivo inferior). sistema más ligero y completamente implementado en el núcleo).

Para mitigar estas regresiones, las aplicaciones pueden usar el empalme para reducir la copia de datos y usar la API de ContentProvider para obtener acceso directo a los archivos del sistema de archivos inferiores. Incluso con estas y otras optimizaciones , las operaciones de lectura y escritura pueden ver un ancho de banda reducido cuando se usa FUSE en comparación con el acceso directo al sistema de archivos inferior, especialmente con operaciones de lectura aleatorias, donde el almacenamiento en caché o la lectura anticipada pueden ayudar. Y las aplicaciones que acceden directamente al almacenamiento a través de la ruta heredada /sdcard/ continúan experimentando caídas de rendimiento notables, especialmente cuando se realizan operaciones intensivas de IO.

Solicitudes de espacio de usuario SDcardFS

El uso de SDcardFS puede acelerar la emulación de almacenamiento y las verificaciones de permisos de FUSE al eliminar la llamada de espacio de usuario del kernel. Las solicitudes de espacio de usuario siguen la ruta: Espacio de usuario → VFS → sdcardfs → VFS → ext4 → Caché de página/Almacenamiento.

Tarjeta SD FUSE Passthrough FS

Figura 1. Solicitudes de espacio de usuario SDcardFS

Solicitudes de espacio de usuario FUSE

FUSE se usó inicialmente para habilitar la emulación de almacenamiento y permitir que las aplicaciones usaran de forma transparente el almacenamiento interno o una tarjeta SD externa. El uso de FUSE presenta algunos gastos generales porque cada solicitud de espacio de usuario sigue la ruta: Espacio de usuario → VFS → Controlador FUSE → Demonio FUSE → VFS → ext4 → Caché/almacenamiento de página.

FUSIBLE Pasante FUSIBLE

Figura 2. Solicitudes de espacio de usuario de FUSE

Solicitudes de transferencia FUSE {#fuse-passthrough-requests}

La mayoría de los permisos de acceso a archivos se verifican en el momento de abrir el archivo, y se realizan verificaciones de permisos adicionales al leer y escribir en ese archivo. En algunos casos, es posible saber en el momento de abrir el archivo que la aplicación solicitante tiene acceso total al archivo solicitado, por lo que el sistema no necesita continuar reenviando las solicitudes de lectura y escritura del controlador FUSE al demonio FUSE (ya que eso solo movería datos de un lugar a otro).

Con FUSE passthrough, el demonio FUSE que maneja una solicitud abierta puede notificar al controlador FUSE que la operación está permitida y que todas las solicitudes posteriores de lectura y escritura se pueden reenviar directamente al sistema de archivos inferior. Esto evita la sobrecarga adicional de esperar a que el demonio FUSE del espacio del usuario responda a las solicitudes del controlador FUSE.

A continuación se muestra una comparación de las solicitudes de transferencia de FUSE y FUSE.

Comparación de transferencia de FUSE

Figura 3. Solicitud de FUSE frente a solicitud de transferencia de FUSE

Cuando una aplicación realiza un acceso al sistema de archivos FUSE, ocurren las siguientes operaciones:

  1. El controlador FUSE maneja y pone en cola la solicitud, luego la presenta al demonio FUSE que maneja ese sistema de archivos FUSE a través de una instancia de conexión específica en el archivo /dev/fuse , que el demonio FUSE no puede leer.

  2. Cuando el demonio FUSE recibe una solicitud para abrir un archivo, decide si FUSE passthrough debe estar disponible para ese archivo en particular. Si está disponible, el daemon:

    1. Notifica al controlador FUSE sobre esta solicitud.

    2. Habilita el paso de FUSE para el archivo mediante el ioctl FUSE_DEV_IOC_PASSTHROUGH_OPEN , que debe realizarse en el descriptor de archivo del /dev/fuse abierto.

  3. El ioctl recibe (como parámetro) una estructura de datos que contiene lo siguiente:

    • Descriptor de archivo del archivo del sistema de archivos inferior que es el destino de la función de acceso directo.

    • Identificador único de la solicitud FUSE que se está manejando actualmente (debe ser abierta o crear y abrir).

    • Campos adicionales que se pueden dejar vacíos y están destinados a implementaciones futuras.

  4. Si ioctl tiene éxito, el demonio FUSE completa la solicitud abierta, el controlador FUSE maneja la respuesta del demonio FUSE y se agrega una referencia al archivo del sistema de archivos inferior al archivo FUSE dentro del kernel. Cuando una aplicación solicita una operación de lectura/escritura en un archivo FUSE, el controlador FUSE verifica si la referencia a un archivo del sistema de archivos inferior está disponible.

    • Si hay una referencia disponible, el controlador crea una nueva solicitud del sistema de archivos virtual (VFS) con los mismos parámetros que apuntan al archivo del sistema de archivos inferior.

    • Si no hay una referencia disponible, el controlador reenvía la solicitud al demonio FUSE.

Las operaciones anteriores ocurren para lectura/escritura y lectura-iteración/escritura-iteración en archivos genéricos y operaciones de lectura/escritura en archivos mapeados en memoria. El paso FUSE para un archivo determinado existe hasta que se cierra ese archivo.

Implementando el paso de FUSE

Para habilitar el paso de FUSE en dispositivos con Android 12, agregue las siguientes líneas al $ANDROID_BUILD_TOP/device/…/device.mk del dispositivo de destino.

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

Para deshabilitar FUSE passthrough, omita el cambio de configuración anterior o establezca persist.sys.fuse.passthrough.enable en false . Si anteriormente habilitó el paso de FUSE, deshabilitarlo evita que el dispositivo use el paso de FUSE, pero el dispositivo sigue funcionando.

Para habilitar/deshabilitar el paso de FUSE sin flashear el dispositivo, cambie la propiedad del sistema usando los comandos ADB. A continuación se muestra un ejemplo.

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

Para obtener ayuda adicional, consulte la implementación de referencia .

Validando el paso de FUSE

Para validar que MediaProvider está utilizando FUSE passthrough, verifique logcat para ver los mensajes de depuración. Por ejemplo:

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

El FuseDaemon: Using FUSE passthrough en el registro garantiza que FUSE passthrough esté en uso.

El CTS de Android 12 incluye CtsStorageTest , que incluye pruebas que activan el paso de FUSE. Para ejecutar la prueba manualmente, use atest como se muestra a continuación:

atest CtsStorageTest