Windows verzögert das Schreiben der FAT-Tabelle auf einem kleinen USB-Laufwerk trotz "Schnellentfernung"

598
Dan Halbert

Ich sehe verzögerte Schreibvorgänge in das FAT auf einem FAT (FAT12) -formatierten USB-Flashlaufwerk mit geringer Kapazität, obwohl die Richtlinie für das Laufwerk auf "Schnellentfernung" festgelegt ist. (Ich glaube, das bedeutet, dass die SurpriseRemovalOKFlagge gesetzt ist). Ich habe die über USB an das Laufwerk gesendeten SCSI-Befehle erfasst: Die Schreibvorgänge für die Dateiverkürzung werden sofort ausgeführt, die gesamte Datei (2 512 Byte lange Sektoren) wird unmittelbar danach geschrieben, aber dann gibt es eine Verzögerung von 20 bis 90 Sekunden vor der FAT wird aktualisiert, um das Schreiben der Datei anzuzeigen.

Die Größe des Laufwerks ist erheblich. Ich habe mit FAT-Dateisystemen der Größe 15 MB und kleiner getestet und sehe Probleme. Bei 16 MB und mehr werden die Schreibvorgänge nicht verzögert. 16 MB ist der Haltepunkt, den ich beim Formatieren eines Laufwerks unter Windows zwischen FAT12 und FAT16 sehe. (Hinweis später hinzugefügt: Der FAT12 / FAT16-Haltepunkt hängt jedoch von der Anzahl der Cluster ab, nicht von der absoluten Größe des Dateisystems).

Bei 16 MB und mehr sendet Windows Prevent/Allow Medium Removalvor dem Schreiben SCSI- Befehle und fordert das Gerät auf, nicht entfernt zu werden. Der USB-Stick gibt tatsächlich einen Fehler für diese Anfragen zurück (da er keine Entfernung garantieren kann), aber Windows versucht es trotzdem. Die 15 MB und kleinere Spuren zeigen keine Prevent/Allow Medium Removal Befehle.

(Ich habe dieses Problem entdeckt, als ich eine Mikrocontroller-Platine verwendete, die ein kleines FAT-Dateisystem mit Python-Code unterstützt. Wenn der Mikrocontroller einen Schreibvorgang in das Dateisystem erkennt, wartet er ein wenig auf den Schreibvorgang und startet automatisch den neu geschriebenen Python-Code Der Mikrocontroller sah jedoch aufgrund des verzögerten Schreibens beschädigten Code oder ein beschädigtes Dateisystem.)

Warum ist der Schreibvorgang auf die FAT trotz "Quick Removal" so lange verzögert? Ich kann die Schreibvorgänge erzwingen, indem ich einen "Auswurf" auf dem Laufwerk durchführe, der jedoch das Versprechen des "Schnellentfernens" missachtet. Wenn ich das Laufwerk frühzeitig zog, hätte es eine falsche FAT-Tabelle. Dies widerspricht der Aussage in der Abbildung unten, dass "Safely Remove Hardware" nicht verwendet werden muss. Ist das ein Fehler oder fehlt mir etwas? Gibt es eine Möglichkeit, alle Schreibvorgänge sofort ohne manuelles "Auswerfen" zu erzwingen?

USB-Laufwerk auf Schnellentfernung eingestellt

Hier ist ein Ausschnitt aus einem Wireshark / USBPcap-Trace, der das Problem zeigt. Ich schneide eine vorhandene Datei ab und schreibe dann eine neue Kopie davon. Ich habe Kommentare mit hinzugefügt ###. Die meisten Schreibvorgänge auf das USB-Laufwerk erfolgen etwa 5 Sekunden nach Ablauf der Ablaufverfolgung, der endgültige FAT-Schreibvorgang dauert jedoch erst 26 Sekunden.

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 

Solche Spuren habe ich mit einem normalen Flash-Laufwerk und mit einer Mikrocontroller-Platine, die ein winziges USB-MSC-Laufwerk emuliert, sowohl unter Windows 7 als auch unter Windows 10, erzeugt.

Um es klar zu sagen: Dies ist ein FAT12-formatiertes Laufwerk, das im Windows-Formatierungstool "FAT" genannt wird.

8
Bist du nur neugierig? Oder stehen Sie vor einem Szenario, in dem Sie ein FAT16-Dateisystem verwenden müssen? Twisty Impersonator vor 7 Jahren 1
Ich helfe beim Testen eines Mikrocontroller-Boards (Adafruit Feather M0 und ähnliches), das eine Variante von MicroPython (CircuitPython) ausführt. Es hat ein kleines FAT-Dateisystem, das Python-Code enthält. Der Einfachheit halber ist das Board so eingerichtet, dass es automatisch zurückgesetzt wird und "main.py" oder ähnliche Dateien ausführt, wenn es erkennt, dass die Datei geschrieben wurde. Es dauert ein wenig, bis der Schreibvorgang abgeschlossen ist, jedoch nicht mehrere zehn Sekunden. Wir können diesen automatischen Neustart deaktivieren, aber es ist immer noch erforderlich, das Laufwerk "auszuwerfen", um sicherzustellen, dass der Schreibvorgang rechtzeitig abgeschlossen wird. Das Auffordern des Benutzers, einen Auswurf durchzuführen, ist ein Ärgernis; das möchten wir gerne vermeiden. Dan Halbert vor 7 Jahren 2
Bitte betrachten Sie am Anfang Ihrer Frage eine kurze Erläuterung dazu. Es ist ein guter Hintergrund, um zu haben. Twisty Impersonator vor 7 Jahren 0
Guter Vorschlag. Erledigt. Dan Halbert vor 7 Jahren 0

1 Antwort auf die Frage

2
Dan Halbert

Ich habe möglicherweise den tatsächlichen Windows-Treibercode gefunden, der das Problem verursacht.

MS fügt den FAT-Dateisystemtreiber zufällig in ein Paket mit Beispieltreibercode ein. Es gibt mehrere Stellen in diesem Treiber, an denen der Treiber, wenn das Dateisystem FAT12 ist, nicht etwas unternimmt, wie das Setzen des Dirty-Bits (möglicherweise gibt es kein für FAT12) oder das Löschen der FAT-Daten.

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 und möglicherweise am kritischsten: https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/fastfat/cleanup.c#L1101

In der letzten Verknüpfung in cleanup.cwird die FAT nicht geleert, wenn das Dateisystem FAT12 ist. Ich denke, dass dies genau das Verhalten verursacht, das ich sehe:

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

An Microsoft in Windows Feedback Hub unter https://aka.ms/btvdog (spezielle URL, die in Feedback Hub geöffnet wird) gemeldet .