Autor Téma: Od určitého sektoru na PhysicalDrive přestane fungovat WriteFile  (Přečteno 495 krát)

Offline Fantom007

  • Nováček
  • *
  • Příspěvků: 11
  • Karma: 0
    • Verze Delphi: Lazarus
Chtěl jsem si otestovat nový USB SSD disk. Vymazal jsem sektory na nulu (stačilo prvních pár tisíc), aby se netvářil jako zformátovaný a aby Windows neblokovaly přístup k některým oblastem. Na začátek každého sektoru potom zapíšu číslo sektoru, čas a datum. Zapisuji v blocích po 256 sektorech.
Přístup k souboru:
Kód: Delphi [Vybrat]
  1. DriveHandle:=CreateFile(PChar('\\.\PHYSICALDRIVE'+IntToStr(i)), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ ,nil, OPEN_EXISTING, 0, 0)
Nejprve nastavím file pointer na počáteční sektor pro zápis:
Kód: Delphi [Vybrat]
  1. SetFilePointer(DriveHandle,Longint(DrivePos.LowPart),@DrivePos.HighPart,FILE_BEGIN);
Potom se v cyklu volá
Kód: Delphi [Vybrat]
  1. WriteFile(DriveHandle,BufferW[0],BytesToWrite,BytesWritten,nil)
(kde BytesToWrite:=SectorsToWrite*SECTOR_SIZE).

Program krásně běží a zapisuje bez chyb, ale po následné kontrole jsem zjistil, že poslední zapsaný sektor na disku je 31 877 663 (dekadicky).
Pokud spustím znovu program, aby zapisoval od následujícího nezapsaného sektoru, program pomocí SetFilePointer správně nastaví file pointer a na správně místo správně zapíše celý blok dat (256 sektorů). Ačkoliv zápisový cyklus dále pokračuje (podle kontrolních výpisů bez chyb), na další sektory už zapsáno není. Při dalších pokusech se vždy jednou zapíše (popíše se dalších 256 sektorů) a konec. Pokud by WriteFile vrátila False, vypisuji chybu pomocí GetLastError, ale do chyby tento program vůbec nechodí. Vypadá to, jako by se od určitého sektoru špatně aktualizoval file pointer (ze začátku se správně automaticky posouvá o BytesToWrite (=BytesWritten). Nevím, jak zjistit aktuální pozici file pointeru (abych ji zkontroloval), umím ji pouze nastavit. Rozuměl bych tomu, kdyby byl disk fyzicky vadný, jenže při každém spuštění zápisu postoupí zapsaná oblast o dalších 256 sektorů (1 blok) a dále se zápisy neprovádějí.

Nevíte někdo, jestli má funkce WriteFile nějaký limit pro zápis do velikých souborů/disků? A jak tento limit  obejít? Nebo se jedná o jiný problém? Díky za odpovědi.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3279
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Od určitého sektoru na PhysicalDrive přestane fungovat WriteFile
« Odpověď #1 kdy: 21-07-2021, 16:26:38 »
Excellent
Rated 1 time
(kde BytesToWrite:=SectorsToWrite*SECTOR_SIZE).
jakeho typu mas ty promenne?

Citace
Nevím, jak zjistit aktuální pozici file pointeru (abych ji zkontroloval)
Zase volanim SetFilePointer s offsetem=0 a typem posunu FILE_CURRENT viz return value v https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilepointer

Offline Fantom007

  • Nováček
  • *
  • Příspěvků: 11
  • Karma: 0
    • Verze Delphi: Lazarus
Re:Od určitého sektoru na PhysicalDrive přestane fungovat WriteFile
« Odpověď #2 kdy: 21-07-2021, 19:50:57 »
Musím  uznat, že u SetFilePointer zadat nulový posun od aktuální pozice je mazaná náhrada neexistující GetFilePointer  :D.
Hned jsem to vrznul do zápisového cyklu s WriteFile, a zjistil jsem, že před prvním úspěšným zápisem i před dalšími neúspěšnými je hodnota file pointeru nastavena správně. Tak moje podezření se nepotvrdilo.

SectorsToWrite, BytesToWrite i BytesWritten jsou typu Cardinal (tj. DWord). SECTOR_SIZE je konstanta = 512 (bytu v sectoru). Když jsem si vypisoval BytesToWrite a BytesWritten, obě hodnoty byly vždy totožné, a to 256 sectors * 512 = 131072.

Ještě důležité zpřesnění. Pokud zapisuji v jednom bloku >= 128 sektorů (třeba 256), zapíše se jich při prvním zápisu vždy jen 128. Pokud zapisuji méně (např.64, nebo i jediný), zapíše se jen tento zadaný počet.

Zkoušel jsem program přeložit v překladači Lazarus, ale výsledek je stejný.

To jsem tedy blázen ...

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3279
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Od určitého sektoru na PhysicalDrive přestane fungovat WriteFile
« Odpověď #3 kdy: 22-07-2021, 10:40:51 »
Good
Rated 1 time
Pokud zapisuji v jednom bloku >= 128 sektorů (třeba 256), zapíše se jich při prvním zápisu vždy jen 128.
Jak mam rozumet tomu "pri prvnim zapisu" - co to udela pri dalsich zapisech?

Citace
Pokud zapisuji méně (např.64, nebo i jediný), zapíše se jen tento zadaný počet.
A temi kratsimi bloky popises cely disk?

Tech 128 x 256 = 32 K => zkousel jsi FILE_FLAG_NO_BUFFERING a/nebo FILE_FLAG_WRITE_THROUGH (u CreateFile)? Kdyz si prectes na MSDN popis u fyzickych disku: jak to mas s partition, kdyz jsi rikal, ze jsi prvnich par sektoru prepsal nulami? Podle vseho driver nejak velikost partition hlida, pokud to nevypnes FSCTL_ALLOW_EXTENDED_DASD_IO IOCTL. Poradne bych si to vsechno precetl. Jeste ta hodnota posledniho sektoru z prvniho emajlu pripomina hodnotu 31M9 z named pipes...

Offline Fantom007

  • Nováček
  • *
  • Příspěvků: 11
  • Karma: 0
    • Verze Delphi: Lazarus
Re:Od určitého sektoru na PhysicalDrive přestane fungovat WriteFile
« Odpověď #4 kdy: 22-07-2021, 22:36:21 »
Zatím jsem vyzkoušel tři klasické harddisky - PATA 160GB, SATA 160GB a SATA 120GB, a můj program vždy popsal a následně zkontroloval celý disk bez problémů. Začínám mít podezření, že u 2TB externího (USB) SSD disku je nakopnutý řadič (ale dost zvláštně, protože se všechno tváří OK). Nebo že by u SSD disků fungovalo číslování sektorů jinak? Zkusím někde sehnat jiný SSD disk a otestovat ho. Kamarádi mi svoje disky moc půjčovat nechtějí, i když jim slíbím, že ho "jen" celý přemažu :D. Doporučené rady samozřejmě ještě vyzkouším.

Offline František

  • Guru
  • *****
  • Příspěvků: 690
  • Karma: 7
    • Verze Delphi: primárne v XE5, občas 10.2.3 comunity
Re:Od určitého sektoru na PhysicalDrive přestane fungovat WriteFile
« Odpověď #5 kdy: 23-07-2021, 13:19:42 »
Ok
Rated 1 time
a robil si TRIM?

Offline Fantom007

  • Nováček
  • *
  • Příspěvků: 11
  • Karma: 0
    • Verze Delphi: Lazarus
Re:Od určitého sektoru na PhysicalDrive přestane fungovat WriteFile
« Odpověď #6 kdy: 25-07-2021, 11:10:04 »
Mám Windows 10 a zkontroloval jsem si, že funkce TRIM je zapnutá.
Zkusil jsem jiný USB flash 128GB, a opět zápis i kontrola bez problémů. Nepomohlo ani FILE_FLAG_NO_BUFFERING a/nebo FILE_FLAG_WRITE_THROUGH u CreateFile.

Zkusil jsem low level software Victoria (který mě nikdy nezklamal, a kterým jsem se inspiroval). Funkce Test&Repair, volba Write LBA num - opět stejný výsledek. Ale je zajímavé, že přesně na stejné oblasti se skokově mění délka operace z intervalu do 60ms na interval do 240ms. Při volbě DDD (Data Distortion Detect system - po zápisu se ihned kontrolují zapsaná data) se přesně od začátku této oblasti objevují samé distortion bloky. Vypadá to, že chyba nebude u mne, když i profesionální software se chová stejně. Zřejmě chyba v hardwaru (možná řadič).

Je zajímavé, že první zápis bloku 128 sektorů se povede, ostatní nikoliv (ale všechny kontroly procházejí bez chyb). I když cyklus pokusně osekám na
Kód: Delphi [Vybrat]
  1. while true do WriteFile(DriveHandle,BufferW[0],BytesToWrite,BytesWritten,nil);
,
chová se pořád stejně. Nepomáhá ani vkládání Sleep (zkoušel jsem 100,1000 a 10000), ani nastavování pozice na harddisku od začátku v cyklu (stejně jako před cyklem), ani opakování všech akcí po stisku tlačítka před cyklem také pokaždé v cyklu (kromě inicializace aktuálního sektoru).

Tímto prohlašuji externí 2TB USB SSD disk za pokažený. Sebral mi spoustu hodin života, hajzlík jeden. Děkuji všem, kteří se mi snažili pomoci.

Offline František

  • Guru
  • *****
  • Příspěvků: 690
  • Karma: 7
    • Verze Delphi: primárne v XE5, občas 10.2.3 comunity
Re:Od určitého sektoru na PhysicalDrive přestane fungovat WriteFile
« Odpověď #7 kdy: 25-07-2021, 19:51:19 »
no a ta zmena chovania nie je sposobena zaplnenim cache?

btw. ci si na nom farmarcil?