Windows задерживает запись таблицы FAT на маленький USB-накопитель, несмотря на "быстрое удаление"
Я вижу отложенные записи в FAT на USB-флэш-накопителе с малой емкостью FAT(FAT12), даже если для политики задано "Быстрое удаление". (Я считаю, что это означает, что SurpriseRemovalOK
флаг установлен). Я перехватил команды SCSI, отправленные на диск через USB: запись усечения файла происходит немедленно, весь файл (2 512-байтовых секторов) записывается сразу после этого, но затем перед FAT происходит задержка в 20-90 секунд обновляется, чтобы отразить запись файла.
Размер диска значительный. Я проверил и вижу проблемы на файловых системах FAT размером 15 МБ и меньше. На 16 МБ и выше запись не задерживается. 16 МБ - это точка останова между использованием FAT12 и FAT16, когда я форматирую диск в Windows. (Примечание добавлено позже: Но точка останова FAT12/FAT16 зависит от количества кластеров, а не от абсолютного размера файловой системы).
На 16 МБ и больше, Windows отправляет SCSI Prevent/Allow Medium Removal
Команды перед записью с просьбой не удалять устройство. USB-накопитель фактически возвращает ошибку при этих запросах (потому что не может гарантировать удаление), но Windows все равно пытается. 15 МБ и меньшие следы показывают нет Prevent/Allow Medium Removal
команды.
(Я обнаружил эту проблему при использовании платы микроконтроллера, которая поддерживает крошечную файловую систему FAT, содержащую код Python. Когда микроконтроллер обнаруживает запись в файловую систему, он немного ждет завершения записи, а затем автоматически перезапускает и запускает вновь написанный код 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
Подобные следы я генерировал, используя обычную флешку, а также с платой микроконтроллера, которая эмулирует крошечный USB MSC-накопитель, как в Windows 7, так и в Windows 10.
Просто чтобы быть понятным, это диск в формате FAT12, просто называемый "FAT" в средстве форматирования Windows.
1 ответ
Возможно, я нашел фактический код драйвера Windows, который вызывает проблему.
MS включает драйвер файловой системы FAT в пакет примера кода драйвера. В этом драйвере есть несколько мест, где, если файловая система FAT12, драйвер не потрудится сделать что-то вроде установки грязного бита (возможно, его нет для FAT12) или сброса данных 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 и, возможно, наиболее критично: https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/fastfat/cleanup.c#L1101
В последней ссылке, в cleanup.c
, FAT не очищается, если файловая система FAT12. Я думаю, что это может быть причиной именно того поведения, которое я вижу:
//
// 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);
Об этом сообщает Microsoft в Windows Feedback Hub по адресу https://aka.ms/btvdog (специальный URL, который открывается в Feedback Hub).