web-dev-qa-db-ja.com

「クイックリムーバル」にもかかわらず、Windowsが小型USBドライブへのFATテーブルの書き込みを遅らせる

ドライブのポリシーが「クイックリムーバル」に設定されているにもかかわらず、小容量の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テーブルが正しくなくなります。これは、「ハードウェアを安全に取り外す」を使用する必要がないことについての以下のスクリーンショットのステートメントに反します。これはバグですか、それとも何かが足りませんか?手動の「イジェクト」なしですべての書き込みをすぐに実行する方法はありますか?

USB drive set to Quick Removal

これは、問題を示す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」と呼ばれています。

10
Dan Halbert

問題の原因となっている実際の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)。

4
Dan Halbert