Windows ritarda la scrittura della tabella FAT su una piccola unità USB nonostante “Rimozione rapida”


10

Sto vedendo le scritture ritardate sul FAT su un'unità flash USB formattata FAT (FAT12) di piccola capacità anche se il criterio per l'unità è impostato su "Rimozione rapida". (Credo che questo significhi che la SurpriseRemovalOKbandiera è impostata). Ho acquisito i comandi SCSI inviati all'unità tramite USB: le scritture di troncamento dei file avvengono immediatamente, l'intero file (2 settori da 512 byte) viene scritto immediatamente dopo, ma poi c'è un ritardo di 20-90 secondi prima del FAT viene aggiornato per riflettere la scrittura del file.

La dimensione dell'unità è significativa. Ho testato e riscontrato problemi con filesystem FAT di dimensioni pari o inferiori a 15 MB. A partire da 16 MB, le scritture non vengono ritardate. 16 MB è il punto di interruzione che vedo tra l'utilizzo di FAT12 e FAT16 quando formatto un'unità in Windows. (Nota aggiunta in seguito: Ma il punto di interruzione FAT12 / FAT16 dipende dal numero di cluster, non dalla dimensione assoluta del filesystem).

Su 16 MB e oltre, Windows invia i Prevent/Allow Medium Removalcomandi SCSI prima della scrittura, chiedendo che il dispositivo non venga rimosso. La chiavetta USB in realtà restituisce errori su queste richieste (perché non può garantire alcuna rimozione), ma Windows ci prova comunque. I 15 MB e le tracce più piccole non mostrano alcunPrevent/Allow Medium Removal comando.

(Ho scoperto questo problema durante l'utilizzo di una scheda microcontrollore che supporta un piccolo filesystem FAT contenente codice Python. Quando il microcontrollore rileva una scrittura sul filesystem, attende un po 'il completamento della scrittura, quindi si riavvia automaticamente ed esegue il codice Python appena scritto Ma il microcontrollore stava vedendo un codice danneggiato o un filesystem danneggiato a causa della scrittura ritardata.)

Perché la scrittura su FAT è stata ritardata così a lungo, nonostante sia stata impostata la "Rimozione rapida"? Posso forzare le scritture facendo un "Espulsione" sul disco ma questo sconfigge la promessa di "Rimozione rapida". Se avessi estratto l'unità in anticipo, avrebbe una tabella FAT errata. Questo smentisce l'affermazione nella schermata qui sotto sul non dover usare "Rimozione sicura dell'hardware". È un bug o mi sto perdendo qualcosa? C'è un modo per forzare che tutte le scritture avvengano immediatamente senza un "espulsione" manuale?

Unità USB impostata su Rimozione rapida

Ecco un estratto eliminato da una traccia di Wireshark / USBPcap che mostra il problema. Troncare un file esistente e quindi scriverne una nuova copia. Ho aggiunto commenti con ###. La maggior parte delle scritture sull'unità USB avvengono nella traccia circa 5 secondi, ma la scrittura FAT finale non dura fino a 26 secondi.

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

Ho generato tracce come questa utilizzando una normale unità flash e anche con una scheda microcontrollore che emula una piccola unità MSC USB, sia su Windows 7 che su Windows 10.

Per essere chiari, si tratta di un'unità formattata FAT12, chiamata semplicemente "FAT" nello strumento di formattazione di Windows.


1
Sei solo curioso? O stai affrontando uno scenario in cui ti viene richiesto di utilizzare un filesystem FAT16?
Dico Reinstate Monica il

2
Sto aiutando a testare una scheda microcontrollore (Adafruit Feather M0 e relative) che esegue una variante di MicroPython (CircuitPython). Ha un piccolo file system FAT contenente codice Python. Per comodità, la scheda è impostata per il ripristino automatico e l'esecuzione main.pyo file simili quando rileva che il file è stato scritto. Ritarda un po 'il completamento della scrittura, ma non decine di secondi. È possibile disabilitare questo riavvio automatico, ma è comunque necessario "Espellere" l'unità per assicurarsi che la scrittura venga completata in modo tempestivo. Richiedere all'utente di espellere è un fastidio; vorremmo evitarlo.
Dan Halbert,

Si prega di considerare la modifica all'inizio della domanda una breve spiegazione di ciò. È un buon contesto per avere.
Dico Reinstate Monica il

Buon consiglio Fatto.
Dan Halbert,

Risposte:


4

Potrei aver trovato il codice del driver di Windows effettivo che sta causando il problema.

MS sembra includere il driver del file system FAT in un pacchetto di codice driver di esempio. Esistono diversi punti in quel driver in cui, se il filesystem è FAT12, il driver non si preoccuperà di fare qualcosa come impostare il bit sporco (forse non ce n'è per FAT12) o svuotare i dati 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 e forse più criticamente: https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/fastfat/cleanup.c#L1101

Nell'ultimo collegamento, in cleanup.c, il FAT non viene scaricato se il filesystem è FAT12. Penso che questo possa causare esattamente il comportamento che vedo:

    //
    //  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);

Segnalato a Microsoft nell'hub di feedback di Windows all'indirizzo https://aka.ms/btvdog (URL speciale che si apre nell'hub di feedback).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.