![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
NtReadFile NtFsControlFile. Разница возвращаемых данных.
Riply © (2008-04-04 21:34:00)Здравствуйте !
Давным давно я поднимала этот вопрос. Тогда ответа не нашли.
Может сейчас у кого-нибудь будут идеи, как объяснить(понять) следующий факт:
Читаем файловую запись двумя способами: NtReadFile и NtFsControlFile(..., FSCTL_GET_NTFS_FILE_RECORD, ...).
В первом случае получаем мусор, во втором корректные данные.
(какой именно FileRecord прочитала NtFsControlFile - проверяется).
Эффект довольно трудно, но воиспроизводим (я приводила диск в "непотребное" состояние :)
Когда я столкнулась с разницой между прямым чтением и чтении через API, подумла
что вот она - причина и списала этот вопрос на всевозможные "кеширования" и "буферизации".
Но сейчас, похоже, это объяснение не проходит.
Во всяком случае, эффект наблюдается (на тех одних и тех же файловых объектах)
как после длительной работы, так и сразу после холодного рестарта.
Очень бы хотелось понять происходящее. Кто что думает: какие могут быть причины ?
Riply (2008-04-05 21:41:00) [21]> [22] guav © (05.04.08 21:20)
> 1. 221120 судя по R.P. $Mft не принадлежит MFT.
Не принадлежит, учитывая фрагментированность. Если бы ее не было, то принадлежал бы.
Конечно это мало что значит, но всеже.
> Ошибка уже совершена когда это значение получено.
Это один из большого списка Lcn-ов, который так себя ведет.
К тому же этот список я получала как "законным" способом, так и "своим".
Они (списки) совпадают.
> 2. Формула, позволяющая получить из него номер в MFT - ошибочна.
Это не формула (как формула, она конечно ошибочна) а только
описание того что я с ним, кроме всего прочего, пыталась делать.
> 3. Для нумерации файлов и файлрекордов LCN не используется, используется MFT_SEGMENT_REFERENCE.
Это я знаю, но какого черта, если на него посмотреть
как на MFT_SEGMENT_REFERENCE, то получим то что нужно ?
Попробую еще раз описать, что происходит:
Сканируется "подпорченый" диск.
На директории, описание которой выше, при переборе Lcn-ов
на Lcn равным 221120 спотыкаемся (считываемая структура не валидна).
Начинаем изучать этот чертов 221120-ый. Почему именно на нем и чем он отличается от других ?
В ходе этого дела, выясняется, что если предпринять попытки из [18]
то мы получаем именно то, что и должны были получить, если бы этот LCN
"считывался" так же как и все остальные его собратья :)
guav (2008-04-05 21:36:00) [22]Если я не ошибся в анализе твоих заблуждений, то то что ты хочешь найти в 221120 находится в 306221 :)
guav (2008-04-05 21:20:00) [23]Ещё раз, на всякий случай:
1. 221120 судя по R.P. $Mft не принадлежит MFT. Ошибка уже совершена когда это значение получено.
2. Формула, позволяющая получить из него номер в MFT - ошибочна.
3. Для нумерации файлов и файлрекордов LCN не используется, используется MFT_SEGMENT_REFERENCE.
guav (2008-04-05 21:09:00) [24]> [20] Riply © (05.04.08 20:49)
Каким образом получено значение 221120 ?
Тебе приснилось что этот LCN соотвествует каким-то файлрекордам ?
"Подтверждение" вроде
> FileRefNumber := ((221120 - MftStartLcn) * BytesPerCluster)
> div BytesPerFileRecordSegment;
читается - не годится, т.к. формула предполагает то чего нету - непрерывность MFT.
Riply (2008-04-05 20:49:00) [25]> [19] guav © (05.04.08 20:08)
> И более интересный вопрос - откуда взялось 221120 ?
Как откуда ? Мы об этом "сбойном" Lcn`е толко и говорим. :)
Просто, пока я не добралась до Delphi,
пыталась "на пальцах" показать, что я делала в программе для проверки.
guav (2008-04-05 20:08:00) [26]> В программе я поступаю так: высчитываю
> FileRefNumber := ((221120 - MftStartLcn) * BytesPerCluster)
> div BytesPerFileRecordSegment;
Это что ? Где ты это взяла ?
И более интересный вопрос - откуда взялось 221120 ?
> Кстати 221120 попадает в диапазон
> [MftStartLcn < 221120 < MftStartLcn + MftValidDataLength
> div BytesPerCluster]
И что ?
> Получается, что FileRefNumber...
Нет, не получается.
Не знаю как тебе ещё объяснить...
Что по-твоему значат поля File Reference ?
Riply (2008-04-05 19:47:00) [27][17] guav © (05.04.08 18:11)
> > Значание TotalAllocated, при _CompressionUnit = 0 неопределено.
> Я бы не так сказал, не неопределено, а его просто нет, структура на него меньше.
> Разница между "не определно" и "нет" может быть важна.
Спасибо, учту. То что "не определено" я стырила у линуксоидов.
Скорее всего, не сумела правильно перевести.
> Т.е. это действиетльно LCN принадлежащий $Mft по твоему ?
Я уже не знаю что и думать :(
В программе я поступаю так: высчитываю
FileRefNumber := ((221120 - MftStartLcn) * BytesPerCluster) div BytesPerFileRecordSegment;
Кстати 221120 попадает в диапазон
[MftStartLcn < 221120 < MftStartLcn + MftValidDataLength div BytesPerCluster]
Т.е. если забыть про фрагментацию MFT, то он ей принадлежит.
Далее, по FileRef успешно считываю валидный FSCTL_GET_NTFS_FILE_RECORD
из которого получаю список, примерно из 80 файлов,
причем именно тех, которые и были "потеряны" .
Ни одним больше, ни одним меньше.
> Какой же тогда MFT номер у 221120 ?
Получается, что FileRefNumber...
Возможно нерезидентные данные, которые она вынуждена в себе
хранить учитываются каким-то особым образом ?
guav (2008-04-05 18:11:00) [28]> Значание TotalAllocated, при _CompressionUnit = 0 неопределено.
Я бы не так сказал, не неопределено, а его просто нет, структура на него меньше. Разница между "не определно" и "нет" может быть важна.
> [15] Riply © (05.04.08 16:13)
> Для получения "абсолютного смещения на диске" его надо умножить
> на BytesPerCluster
Т.е. это действиетльно LCN принадлежащий $Mft по твоему ?
Ок.
Берём R.P. $Mft из [8] и пытаемся найти его номер. Даже Dephi под рукой не надо, используем Calc:
lastLcn = fisrtLcn + count – 1
_221120_in = (fisrtLcn<=221120) AND (221120<=lastLcn)
firstLcn count lastLcn _221120_in
175371 45504 220874 ЛОЖЬ
220883 8 220890 ЛОЖЬ
305974 8697 314670 ЛОЖЬ
453599 8696 462294 ЛОЖЬ
403347 2639 405985 ЛОЖЬ
406065 8 406072 ЛОЖЬ
406123 440 406562 ЛОЖЬ
406577 8 406584 ЛОЖЬ
Какой же тогда MFT номер у 221120 ?
У кого в программе ошибка ?
Riply (2008-04-05 17:44:00) [29]Выскажу я одно предположение, только чур не смеяться.
Бывает несу чушь. Это от недосыпа :)
Трактовка Lcn`ов, возвращаемых FSCTL_GET_RETRIEVAL_POINTERS,
и, соответственно, алгоритм их чтения могут зависеть от состояния MFT.
Например, если пользователь так загнал MFT, что та аж вся форматированная
да еще и вынужденная хранить в себе данные, которые должны быть не резидентными. :)
Riply (2008-04-05 16:13:00) [30]> [13] guav © (05.04.08 16:04)
> В любом случае, 221120 на File Reference не похож, где тут последовательный номер ?
Для получения "абсолютного смещения на диске" его надо умножить на BytesPerCluster
Riply (2008-04-05 16:10:00) [31]> [13] guav © (05.04.08 16:04)
> Кстати ни разу это ни TotalAllocated
Совершенно верно.
Значание TotalAllocated, при _CompressionUnit = 0 неопределено.
Руки не доходят подправить функцию парсинга,
чтобы она не выводила TotalAllocated при нулевом CompressionUnit
guav (2008-04-05 16:04:00) [32]> Может быть что в одном файлрекорде несколько кластеров :)
Может. Но я про конкретный случай.
В любом случае, 221120 на File Reference не похож, где тут последовательный номер ?
> TypeCode AT_DATA
> TotalAllocated 3531575320579784755
Кстати ни разу это ни TotalAllocated
переводим в 0x это 3102AD0B00B1C033
00B1C0 = 45504
02AD0B = 175371
, т.е.
> Index 0 Lcn 175371 Count 45504
Riply (2008-04-05 15:58:00) [33]> [11] guav © (05.04.08 15:36)
> Файлы нумеруются не через LCN
> Ссылка на файл - это то, что в MSDN называется MTF_SEGMENT_REFERENCE,
> или File Reference в документации линукса.
Sorry. Просто оговорилась.
> т.к. в одном кластере находятся несколько файлрекордов.
Это не всегда так.
Может быть что в одном файлрекорде несколько кластеров :)
Я сейчас за компьютером, у которого есть диск (NTFS)
с такими характеристиками :
BytesPerSector 512
BytesPerCluster 512
BytesPerFileRecordSegment 1024
ClustersPerFileRecordSegment 2
> Приведи значение этого File Reference
Хорошо. Только доберусь до компьютера, где Delphi установлена.
guav (2008-04-05 15:36:00) [34]Файлы нумеруются не через LCN, т.к. в одном кластере находятся несколько файлрекордов. Ссылка на файл - это то, что в MSDN называется MTF_SEGMENT_REFERENCE, или File Reference в документации линукса.
Вот есть у тебя File Reference, передаваемый в FSCTL_GET_NTFS_FILE_RECORD. Из него же ты получаешь смещение в MFT и соответственно смещение на диске. Приведи значение этого File Reference, значение смещения, по которому читаешь и результат что прочитывается в обоих случаях.
Riply (2008-04-05 15:10:00) [35]> [9] Riply © (05.04.08 15:06)
Смайлик не тот. Должен быть :(
Riply (2008-04-05 15:06:00) [36]> [8] Riply © (05.04.08 15:02)
Опять форматирование "съехало" :)
Кодом надо было выделять, наверное.
Riply (2008-04-05 15:02:00) [37]> [7] guav © (05.04.08 11:31)
> То есть, ты смотришь содержимое :$I30:$INDEX_ALLOCATION этой директории,
> и потом проходишь по всем файлреференсам оттуда ?
Именно так.
> Или это R.P. для её ::$Data ?
Нет.
> Давай не так.
Давай :)
(Сканируется та же директория, только я ошиблась указывая "сбойный" LCN
На самом деле он - 221120 )
Вот первые данные:
Сам диск:
FSCTL_GET_NTFS_VOLUME_DATA
VolumeSerialNumber 7 967 016 108 593 429 977
NumberSectors 2 104 451
TotalClusters 526 112
FreeClusters 104
TotalReserved 0
BytesPerSector 512
BytesPerCluster 2048
BytesPerFileRecordSegment 1024
ClustersPerFileRecordSegment 0
MftValidDataLength 135 168 000
MftStartLcn 175 371
Mft2StartLcn 263 056
MftZoneStart 438 432
MftZoneEnd 438 560
ExtendedData 3.1
Часть атрибутов его MFT:
\??\D:\$MFT
MultiSectorHeader
NTFS_RECORD_HEADER
cbType FILE
UpdateSequenceArrayOffset 48
UpdateSequenceArraySize 3
_Usn64 100853279
SequenceNumber 1
LinkCount 1
AttributesOffset 56
Flags File
BytesInUse 472
BytesAllocated 1024
BaseFileRecordSegment
SegmentNumberLowPart 0
SegmentNumberHighPart 0
SequenceNumber 0
NextAttributeNumber 6
SelfRecord 0
TypeCode AT_STANDARD_INFORMATION
RecordLength 96
FormCode RESIDENT
Name
Flags STANDART
Instance 0
ValueLength 72
ValueOffset 24
_Flags Not Indexed: 0
CreationTime 2008.04.03 20.34.01
ChangeTime 2008.04.03 20.34.01
LastWriteTime 2008.04.03 20.34.01
LastAccessTime 2008.04.03 20.34.01
FileAttributes HS
MaxVersionsNum 0
VersionNum 0
ClassId 0
OwnerId 0
SecurityId 256
QuotaCharge 0
Usn64 0
TypeCode AT_FILE_NAME
RecordLength 104
FormCode RESIDENT
Name
Flags STANDART
Instance 3
ValueLength 74
ValueOffset 24
_Flags Indexed: 1
ParentDirectory
SegmentNumberLowPart 5
SegmentNumberHighPart 0
SequenceNumber 5
CreationTime 2008.04.03 20.34.01
ChangeTime 2008.04.03 20.34.01
LastWriteTime 2008.04.03 20.34.01
LastAccessTime 2008.04.03 20.34.01
AllocatedSize 16 384
DataSize 16 384
FileAttributes HS
AlignmentOrReserved 0
FILE_NAME_WIN32_AND_DOS = $MFT
TypeCode AT_DATA
RecordLength 112
FormCode NONRESIDENT
Name
Flags STANDART
Instance 1
LowestVcn 0
HighestVcn 65999
MappingPairsOffset 64
_CompressionUnit 0
AllocatedLength 135168000
FileSize 135168000
ValidDataLength 135168000
TotalAllocated 3531575320579784755
TypeCode AT_BITMAP
RecordLength 96
FormCode NONRESIDENT
Name
Flags STANDART
Instance 5
LowestVcn 0
HighestVcn 9
MappingPairsOffset 64
_CompressionUnit 0
AllocatedLength 20480
FileSize 16504
ValidDataLength 16504
TotalAllocated 8575189053052944689
RETRIEVAL_POINTERS_BUFFER
ExtentCount 8
Index 0 Lcn 175371 Count 45504
Index 1 Lcn 220883 Count 8
Index 2 Lcn 305974 Count 8697
Index 3 Lcn 453599 Count 8696
Index 4 Lcn 403347 Count 2639
Index 5 Lcn 406065 Count 8
Index 6 Lcn 406123 Count 440
Index 7 Lcn 406577 Count 8
Насчет самого объекта не поняла:
тебя интересуют данные того на кого указывает "сбойный" LCN
или данные того объекта, который выдает "сбойный" LCN ?
guav (2008-04-05 11:31:00) [38]> Пробегаюсь по ее Lcn-ам.
То есть, ты смотришь содержимое :$I30:$INDEX_ALLOCATION этой директории, и потом проходишь по всем файлреференсам оттуда ?
Или это R.P. для её ::$Data ?
Давай не так. Приведи пример с одним файлом, у которого известен:
1. Результат чтения через FSCTL_GET_NTFS_FILE_RECORD
2. Результат прямого чтения (с указанием читаемого смещения)
3. Результат FSCTL_GET_RETRIEVAL_POINTERS для $Mft, именно результат FSCTL_GET_RETRIEVAL_POINTERS а не своей работы (открывать можно с правами 0, тогда откроется)
4. Параметры ФС: размер кластера, размер сектора, размер файлрекорда
После этого можно внимательно сопоставить RETRIEVAL_POINTERS для $Mft с читаемым кластером, думаю тут и будет ошибка.
Riply (2008-04-05 09:48:00) [39]> [5] Германн © (05.04.08 02:16)
> Это что? Такая "шутка юмора"?
Нет. Это просто ачепятка :)
Германн (2008-04-05 02:16:00) [40]
> Riply © (05.04.08 00:24) [3]
> Ты учитывай, что у меня Dual-up :)
>
Это что? Такая "шутка юмора"?