Windows retrasa la escritura de la tabla FAT en una unidad USB pequeña a pesar de la "Eliminación rápida"

10

Veo escrituras retrasadas en el FAT en una unidad flash USB con formato FAT de pequeña capacidad (FAT12) a pesar de que la política para el disco está establecida en "Extracción rápida". (Creo que esto significa que la SurpriseRemovalOKbandera está configurada). Capturé los comandos SCSI enviados a la unidad a través de USB: las escrituras de truncamiento de archivos ocurren inmediatamente, todo el archivo (2 sectores de 512 bytes de largo) se escribe inmediatamente después de eso, pero luego hay un retraso de 20-90 segundos antes de la FAT se actualiza para reflejar la escritura del archivo.

El tamaño del disco es significativo. He probado y veo problemas en sistemas de archivos FAT de tamaño 15 MB y menores. En 16 MB en adelante, las escrituras no se retrasan. 16 MB es el punto de interrupción que veo entre el uso de FAT12 y FAT16 cuando formateo una unidad en Windows. (Nota añadida más tarde: pero el punto de interrupción FAT12 / FAT16 depende del número de clústeres, no del tamaño absoluto del sistema de archivos).

En 16 MB o más, Windows envía Prevent/Allow Medium Removalcomandos SCSI antes de escribir, solicitando que no se elimine el dispositivo. La memoria USB en realidad devuelve un error en estas solicitudes (porque no puede garantizar que no se elimine), pero Windows lo intenta de todos modos. Las trazas de 15 MB y más pequeñas no muestran Prevent/Allow Medium Removalcomandos.

(Descubrí este problema al usar una placa de microcontrolador que admite un pequeño sistema de archivos FAT que contiene código Python. Cuando el microcontrolador detecta una escritura en el sistema de archivos, espera un poco a que se complete la escritura y luego se reinicia automáticamente y ejecuta el código Python recién escrito Pero el microcontrolador estaba viendo código dañado o un sistema de archivos dañado debido a la escritura retrasada).

¿Por qué se retrasa tanto la escritura en el FAT, a pesar de que se haya configurado "Eliminación rápida"? Puedo forzar las escrituras haciendo un "Expulsar" en el disco, pero eso frustra la promesa de "Eliminación rápida". Si saqué el disco temprano, tendría una tabla FAT incorrecta. Esto contradice la declaración en la captura de pantalla a continuación sobre no tener que usar "Quitar hardware con seguridad". ¿Es esto un error o me falta algo? ¿Hay alguna forma de forzar que todas las escrituras sucedan de inmediato sin un "Expulsar" manual?

Unidad USB configurada para extracción rápida

Aquí hay un extracto podado de un rastro de Wireshark / USBPcap que muestra el problema. Trunco ​​un archivo existente y luego escribo una nueva copia del mismo. He agregado comentarios con ###. La mayoría de las escrituras en la unidad USB tienen lugar alrededor de 5 segundos en la traza, pero la escritura final de FAT no es hasta 26 segundos.

No.    Time  Source       Destination  Protocol  Length  Info
    ### write directory entry to truncate file
13 5.225586    host         1.2.2        USBMS    58     SCSI: Write(10) LUN: 0x00 (LBA: 0x00000041, Len: 8)
14 5.225838    host         1.2.2        USB      4123   URB_BULK out
    ### write FAT entries to truncate file
16 5.230488    host         1.2.2        USBMS    58     SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003b, Len: 1)
17 5.230707    host         1.2.2        USB      539    URB_BULK out
19 5.235110    host         1.2.2        USBMS    58     SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003e, Len: 1)
20 5.235329    host         1.2.2        USB      539    URB_BULK out
    ### write directory entry for 
22 5.252672    host         1.2.2        USBMS    58     SCSI: Write(10) LUN: 0x00 (LBA: 0x00000041, Len: 8)
23 5.252825    host         1.2.2        USB      4123   URB_BULK out
    ### write out file data (2 sectors of 512 bytes)
25 5.257416    host         1.2.2        USBMS    58     SCSI: Write(10) LUN: 0x00 (LBA: 0x000000c1, Len: 2)
26 5.257572    host         1.2.2        USB      1051   URB_BULK out
    ### 20 second delay
    ### finally, write FAT entries to indicate used sectors
79 26.559964      host      1.2.2        USBMS    58     SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003b, Len: 1)
80 26.560191      host      1.2.2        USB      539    URB_BULK out
82 26.560834      host      1.2.2        USBMS    58     SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003e, Len: 1)
83 26.560936      host      1.2.2        USB      539    URB_BULK out

He generado rastros como este usando una unidad flash normal y también con una placa de microcontrolador que emula una pequeña unidad USB MSC, tanto en Windows 7 como en Windows 10.

Para que quede claro, esta es una unidad con formato FAT12, llamada simplemente "FAT" en la herramienta de formateo de Windows.

Dan Halbert
fuente
1
¿Tienes curiosidad? ¿O se enfrenta a un escenario en el que debe usar un sistema de archivos FAT16?
Digo reinstalar a Mónica el
2
Estoy ayudando a probar una placa de microcontrolador (Adafruit Feather M0 y relacionados) que ejecuta una variante de MicroPython (CircuitPython). Tiene un pequeño sistema de archivos FAT que contiene código Python. Para su comodidad, la placa está configurada para reiniciarse automáticamente y ejecutar main.pyarchivos similares cuando detecta que el archivo se ha escrito. Se demora un poco para que se complete la escritura, pero no decenas de segundos. Podemos desactivar este reinicio automático, pero aún es necesario "Expulsar" la unidad para asegurarnos de que la escritura se complete de manera oportuna. Requerir que el usuario haga una expulsión es una molestia; Nos gustaría evitar eso.
Dan Halbert
Considere editar al comienzo de su pregunta una breve explicación de esto. Es un buen contexto de fondo tener.
Digo reinstalar a Mónica el
Buena sugerencia. Hecho.
Dan Halbert el

Respuestas:

4

Es posible que haya encontrado el código de controlador de Windows real que está causando el problema.

MS incluye el controlador del sistema de archivos FAT en un paquete de código de controlador de muestra. Hay varios lugares en ese controlador donde, si el sistema de archivos es FAT12, el controlador no se molestará en hacer algo como establecer el bit sucio (tal vez no haya ninguno para FAT12) o vaciar los datos FAT.

https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/fastfat/verfysup.c#L774 https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys /fastfat/cachesup.c#L1212 y quizás lo más crítico: https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/fastfat/cleanup.c#L1101

En el último enlace, en cleanup.c, el FAT no se vacía si el sistema de archivos es FAT12. Creo que esto puede estar causando exactamente el comportamiento que veo:

    //
    //  If that worked ok,  then see if we should flush the FAT as well.
    //

    if (NT_SUCCESS(Status) && Fcb && !FatIsFat12( Vcb) && 
        FlagOn( Fcb->FcbState, FCB_STATE_FLUSH_FAT)) {

        Status = FatFlushFat( IrpContext, Vcb);

Reportado a Microsoft en Windows Feedback Hub en https://aka.ms/btvdog (URL especial que se abre en Feedback Hub).

Dan Halbert
fuente