Windows затримує запис таблиці FAT на невеликому USB-накопичувачі, незважаючи на "Швидке видалення"


10

Я бачу затримку запису в FAT на невеликій ємності FAT (FAT12) -форматоване флеш-накопичувач USB, хоча політика для диска встановлена ​​на "Швидке видалення". (Я вважаю, це означає, що SurpriseRemovalOKпрапор встановлений). Я захопив команди SCSI, що надсилаються на накопичувач через USB: запис усікання файлів відбувається негайно, весь файл (2 512-байтних секторів) записується одразу після цього, але тоді перед затримкою FAT затримка 20-90 секунд оновлюється для відображення запису файлу.

Розмір накопичувача є значним. Я протестував і бачу проблеми у файлових системах FAT розміром 15 Мб і менше. З 16 Мб і вище, записи не затримуються. 16 Мб - це точка розриву, яку я бачу між використанням FAT12 та FAT16, коли я форматую диск у Windows. (Примітка додана пізніше: Але точка розриву FAT12 / FAT16 залежить від кількості кластерів, а не від абсолютного розміру файлової системи).

У розмірі 16 Мб і більше Windows надсилає Prevent/Allow Medium Removalкоманди SCSI перед записом із проханням не знімати пристрій. USB-накопичувач насправді повертає збій у цих запитах (оскільки він не може гарантувати видалення), але Windows все одно намагається. На 15 Мб і менших слідах не відображаються Prevent/Allow Medium Removalкоманди.

(Я виявив цю проблему під час використання плати мікроконтролера, яка підтримує крихітну файлову систему FAT, що містить код Python. Коли мікроконтролер виявить запис у файловій системі, він трохи чекає завершення запису, а потім автоматично перезавантажує і запускає щойно написаний код Python . Але мікроконтролер бачив пошкоджений код або пошкоджену файлову систему через затримку запису.)

Чому запис у FAT затримується так довго, незважаючи на встановлення "Швидкого видалення"? Я можу змусити записати, виконавши "Витягнення" на диску, але це перешкоджає обіцянню "Швидке видалення". Якщо я витягнув диск, він мав би неправильну таблицю FAT. Це заперечує твердження на знімку екрана нижче про те, що не потрібно використовувати "Безпечне видалення обладнання". Це помилка чи я щось пропускаю? Чи є якийсь спосіб змусити всі записи статися негайно без посібника "Витягнення"?

USB-накопичувач встановлений на швидке видалення

Ось підрізаний витяг із сліду 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
Вам просто цікаво? Або ви стикаєтесь зі сценарієм, коли вам потрібно використовувати файлову систему FAT16?
Я кажу, відновіть Моніку

2
Я допомагаю протестувати плату мікроконтролера (Adafruit Feather M0 та пов'язані з нею), що виконує варіант MicroPython (CircuitPython). У нього крихітна файлова система FAT, що містить код Python. Як зручність, плата встановлюється для автоматичного скидання та запуску main.pyабо подібних файлів, коли виявляє, що файл був записаний. Це затримує трохи на завершення запису, але не десятки секунд. Ми можемо відключити цей автоматичний перезапуск, але все-таки потрібно "вийняти" накопичувач, щоб переконатися, що запис завершено своєчасно. Вимагати від користувача виконувати Eject - це неприємність; ми хотіли б цього уникнути.
Ден Халберт

Розгляньте редагування на початку запитання коротке пояснення цього. Це хороший фоновий контекст.
Я кажу, відновіть Моніку

Гарна пропозиція. Зроблено.
Ден Халберт

Відповіді:


4

Можливо, я знайшов фактичний код драйвера 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.cFAT не розмивається, якщо файлова система 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 за адресою https://aka.ms/btvdog (спеціальна URL-адреса, яка відкриється у Центрі зворотного зв’язку).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.