HDD: GPT на большом HDD (3TB+, 4Kb сектора, aligned): порча файлов -- поиск причин и исправление

Aug 13, 2013 01:16

*** Продолжение истории тут

*** (Кратко) важно: BIOS на системе, где это будет проявляться, должен быть UEFI (сам по себе, при этом использоваться может как legacy).
Правильная формула для расчета смещения мусора.

I. Проблема

У кого-нибудь была такая штука: огромные HDD (3TB+, 4Kb сектора, aligned), информация лежит. Архивы. Точно протестированы, все в порядке. Допустим, через полгода хотите посмотреть, берете архив - CRC error. Дальше смотрю, что именно побилось. В середине архива поверх данных записаны левые 16'476 байт: GPT-таблица, со всеми этими "Microsoft Reserved Partition", "Basic Data Partition" (трижды) и окончанием "EFI PART". Все, больше ничего. Т.е. вся битость заключается в записи таблицы. (Кстати, корректно говорить о мусоре в таком размере: надо учесть кратность секторам, то есть должно быть 16'896 = 4200h = 33 сектора по 512 байт; однако, на практике данные почему-то записаны без окончания сектора, т.е. там вторая половина самого последнего сектора остается нетронутой - странно).

Какая сука так делает или может делать?

Если бы один раз произошло - списал бы на "неизвестный глюк".

Но за последние полгода произошло уже минимум дважды (возможно, на разных HDD - просто не помню, на каком из HDD, у меня их много, в прошлый раз аналогично, побился архив). В прошлый раз было абсолютно так же.

Важно! Побилось в очень короткий промежуток времени. Т.е. вначале архивы лежали на одном диске. Дальше они были протестированы. После этого они были скопированы, как бэкап копия на другой диск. На момент тестирования до копирования архивы были в порядке. После копирования тестирование ни на одном из дисков не проводилось. Т.е. побился архив в момент после тестирования, но до копирования. Т.к. битым (одинаково) архив оказался на двух дисках (т.е. на бэкапном тоже).

В данном случае архив был 16 Gb.

II. Система

ОС/драйвера:
Windows 2003 Enterprise Edition SP2 (фактически используемое ядро, кстати, дико старое было: 5.2.3790.3959, февраль 2007 года; вместо 5.2.3790.5157, май 2013 года)
Intel RST Enterprise v3.6.0.1086 (есть .1093 уже)

Предполагаемые причины:
Ядро ОС / драйвер / какой-то софт / внешний box: его контроллер / контроллер на плате / BIOS / Acronis WD Aligner (при align'е новых дисков) / LDM/VDS (при импорте/создании новых дисков) / нет идей

III. Поверхностный анализ

Начало битого:
Физический сектор (номер сектора, НЕ смещение): 3061759343 (B67E'BD6Fh)
Логический сектор (номер сектора, НЕ смещение): 914013551 (367A'BD6Fh)
Смещение внутри partition: 006C`F57A'DE00h

Первый сектор partition: 2147745792
Смещение partition: 0100`0800'0000h
Т.е. это второй partition, > чем 1TB и, тем более, 746.52Gb

IV. Общая теоретическая информация

https://en.wikipedia.org/wiki/GUID_Partition_Table
https://en.wikipedia.org/wiki/Microsoft_Reserved_Partition
https://en.wikipedia.org/wiki/Basic_data_partition
https://en.wikipedia.org/wiki/EFI_System_Partition

http://www.hdsentinel.com/forum/viewtopic.php?p=3651#p3651

V. Сторонние практические случаи

Обновлено: О! Тут люди подогнали интересный линк по теме. Изучаю. Цитата четко о моем случае: "I've done a bit more digging, comparing the binary data of the two files. This corrupted copy has a 16KB chunk of mostly all zeros. Towards the end of this zero'd chunk is the string "EFI PART" and some more characters of garbage, which leads me to believe that this is the backup copy of the GPT, written smack bang in the middle of my data."

Возможно файл был побит, когда был перенесен на 3-ий partition (1 TB + 1 TB + 0.7 TB) (не знаю когда), а потом уже просто битым был позже перенесен назад на второй partition (это на днях сделал). Так что его текущее смещение, вероятно, смотреть нет никакого смысла. Сейчас по всем дискам буду искать "EFI PART" и смотреть на какие сектора и файлы попадает.

VI. Полноценный анализ ситуации и исправление

Обновлено 2: Что удалось найти.
Обновлено 4 (обновлены данные в списках)
  • HardDisk1 [8x8x5x5] {с этим диском при сканировании еще и ошибки контроллера [mv91xx/12 шт|disk/24 шт], ~2 минуты}:
    • Partition 2, Relative Sector No: 1565301679, Offset: 00BA`A147'5E00h (это как раз граница 746.52Gb), 27% от диска.
      Просмотр внутри Partition 2 (не физически, логически): Offset: 00BA`9937'5E00h - сектор с "EFI PART" (реальное начало мусора, таблицы GPT: 00BA`9937'1E00h), выпадает на существующий файл(!) - архив. Физический offset по диску (не логический) - это четко граница ~746.52Gb, это стандартная проблема.
      Т.е. какая-то сука поверх файла в какой-то момент записала эту убогую таблицу, неправильно распознав размер диска. Восстановил этот файл (это был архив с Recovery Record, очень повезло), этот архив (битый) переименовал в специальное имя с пометкой не удалять (файл 1.8gb, битое посередине файла) и оставлю на диске, чтобы он занимал нужные сектора (по сути как bad block). Defrag я не запускаю. Блок размером в 4200h байт заполнил данными "DAMAGED-SECTORS-746.52GB-RANGE  ", чтобы не мешало поиску "EFI PART" по всему диску для поиска битых файлов.
    • Partition >4 (в реальности - конец диска), Relative Sector No: n/a ( :)) ), Offset: 02BA`A147'5E00h, 100% от диска. В общем, это метка там, где нужно - последний сектор диска.
  • HardDisk5 [0x1x2x3]:
    • Partition 2, Relative Sector No: 1565303693, Offset: 00BA`A147'5E00h (это как раз граница 746.52Gb) (то же смещение; не очень понял, почему Relative Sector другой), 27% от диска.
      Просмотр внутри Partition 2 (не физически, логически): Offset: 00BA`9937'5E00h - сектор с "EFI PART" (реальное начало мусора, таблицы GPT: 00BA`9937'1E00h) [Physical Sector No: 1565565871 / Logical Sector No: 1565301679], выпадает на удаленный файл - архив; сейчас буду искать этот файл по другим дискам, т.к. возможно, перенес туда (после того, как он был испорчен на этом диске). Физический offset по диску (не логический) - это четко граница ~746.52Gb, это стандартная проблема.
      Чтобы на этом диске решить проблему, видимо, сейчас сгенерирую 10mb-ый файл и буду его записывать сотнями и тысячами копий на диск, пока не забью его полностью. Дальше посмотрю на какую из копий выпадает смещение, переименую его в damaged_sectors и оставлю "на всю жизнь". Остальные удалю. (Писать утилиту, как я предложил ниже, используя defrag API, сейчас не буду - так гораздо быстрее будет и тестировать ничего не надо).
    • Partition >5, Relative Sector No: n/a, Offset: 02BA`A147'5E00h, 100% от диска. В общем, это метка там, где нужно - последний сектор диска.
  • HardDisk0 [0x4x4x0]:
    • Partition 2, Relative Sector No: 1565301679, Offset: 00BA`A147'5E00h (это как раз граница 746.52Gb), в общем - все как выше.
      Просмотр внутри Partition 2 (не физически, логически): Offset: 00BA`9937'5E00h - сектор с "EFI PART" (реальное начало мусора, таблицы GPT: 00BA`9937'1E00h) [Physical Sector No: 1565565839 / Logical Sector No: 1565301647], выпало на файл из того же массива - бэкап тех данных, но чуть на другой файл (тоже повезло: из-за смещения данных на диске, потому что на этот volume были записаны еще другие данные, произошло логическое отличие дисков - была бы возможность перекрестно восстановить файлы, архив#1 взять с этого диска [побитый на другом диске], а архив#2 взять того диска [и заменить тот, что был побит на этом диске]). Физический offset по диску (не логический) - это четко граница ~746.52Gb, это стандартная проблема.
      Переименовал этот файл в специальное имя с пометкой не удалять (файл 8gb, битое ближе к концу файла). Блок размером в 4200h байт заполнил данными "DAMAGED-SECTORS-746.52GB-RANGE  ", чтобы не мешало поиску "EFI PART" по всему диску для поиска битых файлов.
    • Partition 3, Relative Sector No: 13822504 (от начала Partition: 2147745792; т.е. физический сектор: 2161568296), Offset: 0101`ADD4'5000. Это, похоже, остатки от сдампленных в файл 16kb мусора (badblock.bin) [почему так решил: рядом текстовый файл с compare двух архивов; + сейчас проверил раскладку по MFT, четко указывает, что здесь был файл _badblock.bin, сейчас удален]. Надо эти сектора затереть, чтобы не путаться в будущем, т.к. файл уже удален с этого диска. Занулил.
    • Partition 3, Relative Sector No: 914013583 (от начала Partition), Offset: 016C`FD7B'1E00h (что это за место - не понятно пока совершенно; 1459.96Gb - странно), 52% от диска, не выпал ни на какой файл - вроде бы, по MFT пусто (хотя какой-то мусор вокруг есть). Посмотрел по MFT четко: Free space, даже не "удалено ранее" (либо слишком давно). Возможно, в этом месте ранее лежала одна из копий испорченного файла (до переноса, например). Но, видимо, очень давно. Занулил данные, чтобы не мешало.
  • HardDisk2 [2x3x4x1]:
    • Patition >4 (в реальности - конец диска), Relative Sector No: n/a ( :)) ), Offset: 02BA`A147'5E00h, 100% от диска. В общем, это метка там, где нужно - последний сектор диска.
      Странно, но на этом диске нет мусора. Может контроллер другой? Надо посмотреть в чем отличие. Т.е. этот диск "идеальный", как и должен быть. Очень странно.
      А, знаю. Этот диск зашифрован еще поверх. Через доступ к physical disk. Так что тут все еще усложняется сильнее... Хотя сейчас я считываю сектора, естественно, в дешефрованном виде. Тут есть тонкость. Возможно, дешифруется "незашифрованная" GPT-таблица и в итоге получается шифро-мусор при чтении, якобы, расшифрованного.
      Точно! Проверил файл (это архив) - файл битый! При этом по смещению, где должна (уже смешно) была идти plain-text'ом GPT-таблица - мусор. Теперь уверен, что какая-то сука не просто пишет сектора, а пишет это четко на physical disk, да причем так, что обходит фильтры. Т.е. нечто записало поверх зашифрованных секторов незашифрованную GPT-таблицу. И сейчас фильтр диска "расшифровывает" эту plain-text GPT-таблицу в "мусор", тем самым "бьет" архив.
      Сделал по аналогии с HardDisk0 (смещения и сектора в Partition 2 такие же, как у него; файл 4gb, мусор на 87% файла).
      Искать на этом диске "битые" области (для проверки) придется как при "расшифрованном" варианте (найдется только в конце, правильная таблица), так и в "зашифрованном" варианте - если будет, то будет plain-text сектор с таблицей, записанный поверх зашифрованных секторов.
На будущее:
  • Чтобы найти "EFI PART", нужно перейти на физичеком диске (не логическом разделе) по физическому смещению: BAA1475E00h (Relative to: begininng; bytes (hexadec.)).
  • Реальное начало 16kb мусора находится выше, а "EFI PART" - это его последний сектор. Чтобы перейти на начало, нужно на физическом диске (не логическом разделе) по физическому смещению: BAA1471E00h. С этого смещения 4200h байт - мусор (GPT таблица).
  • Смещение внутри Partition вычисляется просто: начальный сектор Partition + Relative Sector, полученный при посмотре диска. Дальше все перевести в hex и переход: Relative to: beginning; sectors (hexadec.).
  • На первом Partition (Partition 2), если он больше 746.52Gb (это важно, т.к. иначе нужен не первый), нужные сектора (начало неверной копии GPT) находится по смещению: BA99371E00h (Physical Sector No: 1565565839 / Logical Sector No: 1565301647)
Правильная формула для расчета смещения мусора

Инструменты: WinHEX, HIEW, FAR, WinRAR, Windows Calculator :)

VII. Теоретизация по ситуации и гипотезы

(Устаревшая мысль) Вот теперь думаю: для проверки занулить, может, эти сектора и вокруг +/- штук 100 (или даже не занулить, а заполнить специальными сигнатурами). И посмотреть что будет. Не появится ли опять GPT-таблица там через некоторое время или еще вдруг перезаписано будет какими другими данными.

В целом, если это так (и я не найду кто гадит), уже придумал формальное решение: сделать файл на 16'896 байт (4200h), дальше с помощью Defrag API передвинуть его кластеры по нужным смещениям на диске. А после этого заблокировать возможность переноса этих кластеров. Можно и не блокировать (т.к. это еще тоже вопрос, смотря кто и как туда пишет - может оказаться не так просто это сделать), потому что я defrag и так не использую на этих дисках, т.е. файл будет всегда находится по нужным секторам. Т.е. даже если кто и будет писать - то гадить будут в специальный мусорный файл. По сути, это как пометить bad sectors.

Произошло на всех 4-х дисках, имеющихся на руках. Подключенных разным способом к разным контроллерам (два внешних, два внутренних, причем внутри тоже два разных контроллера). Т.е. из этого можно сделать с 95% вероятностью вывод, что проблема именно в софте (драйвер, ядро и т.д., см. по списку выше). +5% до 100%, что это программная проблема, т.к. проблема обнаружена и на зашифрованном диске (см. описание выше про HardDisk2).

Пока же подозрение на гажение идет на... старое ядро ОС (см. выше - февраль 2007 года). Потому что не удалось легко найти кто же еще пишет "EFI PART" сигнатуру (думал в *vds* .dll/.exe где-то будет - нету) [пишет отдельными dword'ами, "EFI " и "PART"]. А в ядре не мало функций нашлось, связанных с записыванием и чтением таких секторов. Надо внимательно посмотреть как там вычисляются смещения, правильно ли.

VIII. Решение

Обновлено 3: Обновил ядро ОС. Дизасмить старое ядро и проверять код по записи секторов пока ну очень лениво.

Обновлено 5: В общем, на всех дисках, где были на границе в 746.52Gb найдены битые сектора и они выпадали на файлы - сохранил эти файлы, переименовав их в специальное имя. + Сделал truncate на файл сразу же после 16kb блока "плохих секторов" (чтобы файл меньше занимал, отрезал весь конец: где много, где чуть-чуть, в зависимости от того, куда "выпадали" эти 16kb). Эти файлы я никогда не буду удалять и ничего с ними делать не буду. По сути, они будут работать (выполнять роль) как bad blocks на диске. Дефрагментацию я не запускаю на этих дисках никогда, поэтому они будут находится в тех же кластерах (на тех же секторах). Т.е. даже если какая-то сволочь будет туда всячески/периодически писать бэкап GPT-таблицы - пожалуйста. Хоть обпишитесь, файлы эти никому не нужен.

Если позже будет не лень, напишу все-таки утилиту, с помощью которой можно будет занимать на диске не столько места, сколько был битый файл, а всего 16кб. Т.е. будет создаваться файл, проверяться не заняты ли сектора на границе 746.52Gb, и если не заняты, то этот файл с помощью defrag API будет переносится именно на эти сектора. Дальше же с этим файлом схема, как описана выше (используется сейчас) -- файл будет специальным образом назван и никогда не будет сдвигаться.

Пока еще занят "забитием" диска, на котором битая область находится на месте удаленных файлов. (Делаю, чтобы битая область выпала на один из этих файлов). Сделал. Нужный файл нашел и пометил. Остальные удалил.

При подключении новых дисков, буду сразу же после форматирования и align нужный партишн (на который будет выпадать граница 746.52Gb) заполнять файлами, чтобы создать специальный файл для "битых" секторов. Все, оставить его и забыть о проблеме глючного софта, написанного гадами безрукими.

Правильная формула для расчета смещения мусора

IX. Проверка

После проведенных мероприятий, делаю повторную проверку:

  • HardDisk1 - найдено только в конце физического диска, где и должно быть
  • HardDisk5 - найдено только в конце физического диска, где и должно быть
  • HardDisk0 - найдено только в конце физического диска, где и должно быть
  • HardDisk2 - найдено только в конце физического диска, где и должно быть [в зашифрованном состоянии - зашифрованные данные; в расшифрованном - расшифрованные; все нормально]
X. Выводы

В целом, я советую всем, у кого есть HDD > 2.2TB сделать себе такие псевдо "bad block" файлы по нужному смещению (формулу для расчета в зависимости от объема диска см. во второй статье), чтобы в случае, если какой-то софт, драйвера или железо, попытается туда писать - не испортило ваши данные. Кроме того, чтобы не вышло, как у человека по этой ссылке, когда он подключил свой HDD к старому контроллеру, который не поддерживал 3TB HDD, и тот записал поверх его данных 16kb мусора. Очень странно, что производители HDD или OS не сделали специальные "зарезервированные" сектора на диске размером всего в 16kb. Это уберегло бы огромное количество пользователей от потери данных в абсолютно разных непредвиденных ситуациях. Т.е. это примерно как зарезервировать указатели 0 и блок у FFFF'FFFF, для специальных нужд. Тогда такой проблемы просто не было бы вообще! (Ну, кроме одного дикого случая: цикличная запись секторов с выходом за границы по модулю).

ВНИМАНИЕ! Для дисков другого объема смещение может быть другим. Корректная формула расчета смещения описана во втором посте. Здесь исправлять-обновлять все не буду. Просто укажу на этот момент.

Правильная формула для расчета смещения мусора

*** Продолжение истории тут

marvell, bugs, hardware, efi, gpt, uefi, hdd

Previous post Next post
Up