ドライブのポリシーが「クイックリムーバル」に設定されているにもかかわらず、小容量のFAT(FAT12)フォーマットのUSBフラッシュドライブでFATへの書き込みが遅れるのが見られます。 (これは、SurpriseRemovalOK
フラグが設定されていることを意味すると思います)。 USB経由でドライブに送信されたSCSIコマンドをキャプチャしました。ファイルの切り捨て書き込みはすぐに発生し、ファイル全体(2 512バイトセクター長)はその直後に書き込まれますが、FATの前に20〜90秒の遅延がありますファイルの書き込みを反映するように更新されます。
ドライブのサイズは重要です。サイズ15MB以下のFATファイルシステムでテストし、問題を確認しました。 16MB以上では、書き込みは遅延しません。 16MBは、WindowsでドライブをフォーマットするときにFAT12とFAT16を使用する間に表示されるブレークポイントです。 (後で追加される注:ただし、FAT12/FAT16ブレークポイントは、ファイルシステムの絶対サイズではなく、クラスターの数に依存します)。
16MB以上では、Windowsは書き込みの前にSCSI Prevent/Allow Medium Removal
コマンドを送信し、デバイスを取り外さないように要求します。 USBスティックは実際にはこれらの要求で失敗を返します(削除が保証されないため)が、Windowsはとにかく試行します。 15MB以下のトレースは、noPrevent/Allow Medium Removal
コマンドを示しています。
(Pythonコードを含む小さなFATファイルシステムをサポートするマイクロコントローラーボードを使用しているときにこの問題を発見しました。マイクロコントローラーがファイルシステムへの書き込みを検出すると、書き込みが完了するまで少し待ってから、新しく書き込まれたPythonコードを自動的に再起動して実行します。ただし、書き込みの遅延により、マイクロコントローラーは破損したコードまたは破損したファイルシステムを認識していました。)
「クイック削除」が設定されているのに、FATへの書き込みが非常に長く遅れるのはなぜですか?ドライブしますが、それは「クイックリムーバル」の約束を破ります。ドライブを早く引っ張ると、FATテーブルが正しくなくなります。これは、「ハードウェアを安全に取り外す」を使用する必要がないことについての以下のスクリーンショットのステートメントに反します。これはバグですか、それとも何かが足りませんか?手動の「イジェクト」なしですべての書き込みをすぐに実行する方法はありますか?
これは、問題を示すWireshark/USBPcapトレースからのプルーニングされた抽出です。既存のファイルを切り捨ててから、その新しいコピーを書き込みます。 ###
でコメントを追加しました。 USBドライブへの書き込みのほとんどはトレースの約5秒で行われますが、最終的なFAT書き込みは26秒まで行われません。
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
私は、通常のフラッシュドライブと、Windows7とWindows10の両方で小さなUSB MSCドライブをエミュレートするマイクロコントローラーボードを使用して、このようなトレースを生成しました。
明確にするために、これはFAT12でフォーマットされたドライブであり、Windowsフォーマットツールでは「FAT」と呼ばれています。
問題の原因となっている実際のWindowsドライバーコードを見つけた可能性があります。
MSは、サンプルドライバコードのパッケージにFATファイルシステムドライバを含めています。そのドライバーには、ファイルシステムがFAT12の場合、ドライバーがダーティビットの設定(FAT12にはない可能性があります)やFATデータのフラッシュなどをわざわざ行わない場所がいくつかあります。
https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/fastfat/verfysup.c#L774https://github.com/Microsoft/ Windows-driver-samples/blob/master/filesys/fastfat/cachesup.c#L1212 そしておそらく最も重要なのは: https://github.com/Microsoft/Windows-driver-samples/blob/master /filesys/fastfat/cleanup.c#L1101
最後のリンクでは、cleanup.c
、ファイルシステムがFAT12の場合、FATはフラッシュされません。これがまさに私が見ている振る舞いを引き起こしているのではないかと思います。
//
// 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);
WindowsフィードバックハブでMicrosoftに報告 https://aka.ms/btvdog (フィードバックハブで開く特別なURL)。