Estou vendo gravações atrasadas no FAT em uma unidade flash USB formatada por FAT (FAT12) de pequena capacidade, mesmo que a política da unidade esteja definida como "Remoção rápida". (Eu acredito que isso significa que a SurpriseRemovalOK
bandeira está definida). Capturei os comandos SCSI enviados para a unidade via USB: a gravação do truncamento de arquivos acontece imediatamente, o arquivo inteiro (2 setores de 512 bytes) é gravado imediatamente depois disso, mas há um atraso de 20 a 90 segundos antes do FAT é atualizado para refletir a gravação do arquivo.
O tamanho da unidade é significativo. Eu testei e vejo problemas em sistemas de arquivos FAT de tamanho 15 MB e menor. Nos 16 MB e acima, as gravações não são atrasadas. 16 MB é o ponto de interrupção que vejo entre o uso do FAT12 e do FAT16 ao formatar uma unidade no Windows. (Observação adicionada posteriormente: mas o ponto de interrupção do FAT12 / FAT16 depende do número de clusters, não do tamanho absoluto do sistema de arquivos).
Em 16 MB ou mais, o Windows envia Prevent/Allow Medium Removal
comandos SCSI antes da gravação, solicitando que o dispositivo não seja removido. O pendrive USB realmente retorna a falha nessas solicitações (porque não pode garantir nenhuma remoção), mas o Windows tenta assim mesmo. Os rastreamentos de 15 MB e menores não mostram Prevent/Allow Medium Removal
comandos.
(Descobri esse problema ao usar uma placa de microcontrolador que suporta um pequeno sistema de arquivos FAT contendo código Python. Quando o microcontrolador detecta uma gravação no sistema de arquivos, ele espera um pouco para que a gravação seja concluída e, em seguida, reinicia automaticamente e executa o código Python recém-gravado. Mas o microcontrolador estava vendo código corrompido ou um sistema de arquivos corrompido devido à gravação atrasada.)
Por que a gravação no FAT está atrasada há tanto tempo, apesar de a "Remoção rápida" estar definida? Eu posso forçar as gravações fazendo um "Ejetar" na unidade, mas isso anula a promessa de "Remoção rápida". Se eu puxasse a unidade mais cedo, haveria uma tabela FAT incorreta. Isso esconde a declaração na captura de tela abaixo sobre não ter que usar "Remover hardware com segurança". Isso é um bug ou estou faltando alguma coisa? Existe alguma maneira de forçar todas as gravações a ocorrer imediatamente sem um "Ejetar" manual?
Aqui está uma extração removida de um rastreamento do Wireshark / USBPcap mostrando o problema. Trunco um arquivo existente e, em seguida, escrevo uma nova cópia dele. Adicionei comentários com ###
. A maioria das gravações na unidade USB ocorre em torno de 5 segundos no rastreamento, mas a gravação final em FAT não ocorre até 26 segundos.
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
Criei traços como esse usando uma unidade flash comum e também com uma placa de microcontrolador que emula uma pequena unidade USB MSC, no Windows 7 e no Windows 10.
Só para esclarecer, esta é uma unidade formatada em FAT12, chamada apenas "FAT" na ferramenta de formatação do Windows.
fonte
main.py
arquivos semelhantes quando detectar que o arquivo foi gravado. Atrasa um pouco a conclusão da gravação, mas não dezenas de segundos. Podemos desativar essa reinicialização automática, mas ainda é necessário "Ejetar" a unidade para garantir que a gravação seja concluída em tempo hábil. Exigir que o usuário faça uma Ejeção é um incômodo; nós gostaríamos de evitar isso.Respostas:
Talvez eu tenha encontrado o código do driver real do Windows que está causando o problema.
A Microsoft inclui o driver do sistema de arquivos FAT em um pacote de código de driver de amostra. Existem vários locais nesse driver em que, se o sistema de arquivos for FAT12, o driver não se preocupará em fazer algo como definir o bit sujo (talvez não exista nenhum para o FAT12) ou liberar os dados do 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 e talvez o mais crítico: https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/fastfat/cleanup.c#L1101
No último link, em
cleanup.c
, o FAT não será liberado se o sistema de arquivos for FAT12. Eu acho que isso pode estar causando exatamente o comportamento que vejo:Relatado à Microsoft no Windows Feedback Hub em https://aka.ms/btvdog (URL especial que é aberta no Feedback Hub).
fonte