Конференция "WinAPI" » NtReadFile NtFsControlFile. Разница возвращаемых данных.
 
  • Riply © (04.04.08 21:34) [0]
    Здравствуйте !
    Давным давно я поднимала этот вопрос. Тогда ответа не нашли.
    Может сейчас у кого-нибудь будут идеи, как объяснить(понять) следующий факт:

    Читаем файловую запись двумя способами: NtReadFile и NtFsControlFile(..., FSCTL_GET_NTFS_FILE_RECORD, ...).
    В первом случае получаем мусор, во втором корректные данные.
    (какой именно FileRecord прочитала NtFsControlFile - проверяется).
    Эффект довольно трудно, но воиспроизводим (я приводила диск в "непотребное" состояние :)

    Когда я столкнулась с разницой между прямым чтением и чтении через API, подумла
    что вот она - причина и списала этот вопрос на всевозможные "кеширования" и "буферизации".

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

    Очень бы хотелось понять происходящее. Кто что думает: какие могут быть причины ?
  • Riply © (04.04.08 21:36) [1]
    > [0] Riply ©   (04.04.08 21:34)
    > Читаем файловую запись двумя способами: NtReadFile и NtFsControlFile

    NtReadFile - имеется ввиду "прямое" чтение.
  • guav © (05.04.08 00:11) [2]
    > Кто что думает: какие могут быть причины ?

    Я думаю что причина в том что в программе ошибка :)
    Пришли образ где явление наблюдается.
  • Riply © (05.04.08 00:24) [3]
    > [2] guav ©   (05.04.08 00:11)
    > Я думаю что причина в том что в программе ошибка :)

    Я понимаю, что ошибка может быть везде, но перепроверила сто раз.
    Вынесла все в отдельную процедуру.
    Передаю в нее номер рекода, читаю так и так и сравниваю результат.
    Что может быть проще ?

    > Пришли образ где явление наблюдается.
    Образ чего прислать ?

    Ты учитывай, что у меня Dual-up :)
  • Riply © (05.04.08 00:42) [4]
    Может это поможет ?
    Здесь выдержка атрибутов сканируемой директории (сожержит только файлы).
    Пробегаюсь по ее Lcn-ам.
    И при чтении Lcn`а 221544 вылетаю из цикла с ошибкой несовпадения MagicType у рекорда.
    Передаю этот Lcn в вынесенную процедуру и убеждаюсь, что читается по-разному.
    Если в основном блоке заменить ReadFile на ControlFile, то все работает.

    \??\D:\DestDir_46\0
    MultiSectorHeader
    NTFS_RECORD_HEADER
    cbType  FILE
    UpdateSequenceArrayOffset 48
    UpdateSequenceArraySize 3
    _Usn64 108368966
    SequenceNumber 1
    LinkCount  1
    AttributesOffset 56
    Flags  Dir
    BytesInUse 808
    BytesAllocated 1024
    BaseFileRecordSegment
    SegmentNumberLowPart 0
    SegmentNumberHighPart 0
    SequenceNumber 0
    NextAttributeNumber 8
    SelfRecord 88986

    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 22.05.50
    ChangeTime 2008.04.03 22.06.29
    LastWriteTime 2008.04.03 22.06.29
    LastAccessTime 2008.04.05 00.28.20
    FileAttributes $0
    MaxVersionsNum 0
    VersionNum 0
    ClassId 0
    OwnerId  0
    SecurityId 260
    QuotaCharge 0
    Usn64  0

    TypeCode AT_FILE_NAME
    RecordLength 96
    FormCode RESIDENT
    Name  
    Flags  STANDART
    Instance 2
    ValueLength 68
    ValueOffset 24
    _Flags Indexed: 1
    ParentDirectory
    SegmentNumberLowPart 57290
    SegmentNumberHighPart 0
    SequenceNumber 1
    CreationTime 2008.04.03 22.05.50
    ChangeTime 2008.04.03 22.05.50
    LastWriteTime 2008.04.03 22.05.50
    LastAccessTime 2008.04.03 22.05.50
    AllocatedSize 0
    DataSize  0
    FileAttributes $10000000I30
    AlignmentOrReserved 0
    FILE_NAME_WIN32_AND_DOS = 0

    TypeCode AT_INDEX_ROOT
    RecordLength 88
    FormCode RESIDENT
    Name  $I30
    Flags  STANDART
    Instance 7
    ValueLength 56
    ValueOffset 32
    _Flags Not Indexed: 0
    cbType AT_FILE_NAME
    CollationRule 1
    BytesPerIndexBlock 4096
    ClustersPerIndexBlock 2
    DirectoryIndex
    EntriesOffset 16
    IndexBlockLength 40
    AllocatedSize 40
    Flags  Large
    Enum Dir Entries

    TypeCode AT_INDEX_ALLOCATION
    RecordLength 416
    FormCode NONRESIDENT
    Name  $I30
    Flags  STANDART
    Instance 3
    LowestVcn 0
    HighestVcn 231
    MappingPairsOffset 72
    _CompressionUnit 0
    AllocatedLength  475136
    FileSize  475136
    ValidDataLength 475136
    TotalAllocated 13511017930227748

    TypeCode AT_BITMAP
    RecordLength 48
    FormCode RESIDENT
    Name  $I30
    Flags  STANDART
    Instance 4
    ValueLength 16
    ValueOffset 32
    _Flags Not Indexed: 0

    RETRIEVAL_POINTERS_BUFFER
    ExtentCount 111
    Index 0 Lcn 228215 Count 2
    Index 1 Lcn 228291 Count 2
    Index 2 Lcn 228348 Count 2
    Index 3 Lcn 228393 Count 2
    Index 4 Lcn 228444 Count 2
    Index 5 Lcn 228468 Count 4
    Index 6 Lcn 228522 Count 2
    Index 7 Lcn 228565 Count 2
    Index 8 Lcn 228639 Count 2
    Index 9 Lcn 228673 Count 2
    Index 10 Lcn 228720 Count 2
    Index 11 Lcn 228743 Count 2
    Index 12 Lcn 228787 Count 2
    Index 13 Lcn 228835 Count 2
    Index 14 Lcn 228901 Count 2
    Index 15 Lcn 228975 Count 2
    Index 16 Lcn 229023 Count 2
    Index 17 Lcn 229085 Count 2
    Index 18 Lcn 229129 Count 2
    Index 19 Lcn 229173 Count 2
    Index 20 Lcn 229235 Count 2
    Index 21 Lcn 229269 Count 2
    Index 22 Lcn 229334 Count 2
    Index 23 Lcn 229372 Count 2
    Index 24 Lcn 229403 Count 2
    Index 25 Lcn 229447 Count 2
    Index 26 Lcn 229490 Count 2
    Index 27 Lcn 229561 Count 2
    Index 28 Lcn 229623 Count 2
    Index 29 Lcn 222468 Count 2
    Index 30 Lcn 222518 Count 2
    Index 31 Lcn 222581 Count 2
    Index 32 Lcn 222631 Count 2
    Index 33 Lcn 222676 Count 2
    Index 34 Lcn 222729 Count 4
    Index 35 Lcn 222795 Count 2
    Index 36 Lcn 222852 Count 2
    Index 37 Lcn 222908 Count 2
    Index 38 Lcn 222949 Count 2
    Index 39 Lcn 222999 Count 2
    Index 40 Lcn 223050 Count 2
    Index 41 Lcn 223115 Count 2
    Index 42 Lcn 223187 Count 2
    Index 43 Lcn 223262 Count 2
    Index 44 Lcn 223309 Count 2
    Index 45 Lcn 223363 Count 2
    Index 46 Lcn 223412 Count 2
    Index 47 Lcn 223464 Count 2
    Index 48 Lcn 223559 Count 2
    Index 49 Lcn 223615 Count 2
    Index 50 Lcn 223649 Count 2
    Index 51 Lcn 223700 Count 4
    Index 52 Lcn 223741 Count 2
    Index 53 Lcn 223792 Count 2
    Index 54 Lcn 223876 Count 2
    Index 55 Lcn 223931 Count 2
    Index 56 Lcn 223993 Count 2
    Index 57 Lcn 224068 Count 2
    Index 58 Lcn 224108 Count 2
    Index 59 Lcn 224148 Count 2
    Index 60 Lcn 224233 Count 2
    Index 61 Lcn 224290 Count 2
    Index 62 Lcn 224327 Count 2
    Index 63 Lcn 224387 Count 2
    Index 64 Lcn 224429 Count 2
    Index 65 Lcn 224473 Count 2
    Index 66 Lcn 224532 Count 2
    Index 67 Lcn 224577 Count 2
    Index 68 Lcn 224619 Count 6
    Index 69 Lcn 224641 Count 2
    Index 70 Lcn 224661 Count 2
    Index 71 Lcn 221544 Count 2
    Index 72 Lcn 221588 Count 2
    Index 73 Lcn 221657 Count 2
    Index 74 Lcn 221709 Count 2
    Index 75 Lcn 221758 Count 2
    Index 76 Lcn 221808 Count 2
    Index 77 Lcn 221845 Count 2
    Index 78 Lcn 221878 Count 2
    Index 79 Lcn 221925 Count 2
    Index 80 Lcn 221952 Count 2
    Index 81 Lcn 222022 Count 2
    Index 82 Lcn 222059 Count 2
    Index 83 Lcn 222094 Count 2
    Index 84 Lcn 222114 Count 2
    Index 85 Lcn 222151 Count 4
    Index 86 Lcn 222200 Count 2
    Index 87 Lcn 222245 Count 2
    Index 88 Lcn 222273 Count 2
    Index 89 Lcn 222304 Count 2
    Index 90 Lcn 222340 Count 2
    Index 91 Lcn 222394 Count 2
    Index 92 Lcn 222431 Count 1
    Index 93 Lcn 221120 Count 1
    Index 94 Lcn 221155 Count 2
    Index 95 Lcn 221193 Count 2
    Index 96 Lcn 221236 Count 2
    Index 97 Lcn 221267 Count 2
    Index 98 Lcn 221311 Count 2
    Index 99 Lcn 221335 Count 2
    Index 100 Lcn 221380 Count 2
    Index 101 Lcn 221419 Count 2
    Index 102 Lcn 221446 Count 2
    Index 103 Lcn 221502 Count 2
    Index 104 Lcn 220992 Count 2
    Index 105 Lcn 221030 Count 2
    Index 106 Lcn 221051 Count 2
    Index 107 Lcn 221085 Count 2
    Index 108 Lcn 221115 Count 2
    Index 109 Lcn 220962 Count 2
    Index 110 Lcn 220914 Count 2
  • Германн © (05.04.08 02:16) [5]

    > Riply ©   (05.04.08 00:24) [3]


    > Ты учитывай, что у меня Dual-up :)
    >

    Это что? Такая "шутка юмора"?
  • Riply © (05.04.08 09:48) [6]
    > [5] Германн ©   (05.04.08 02:16)
    > Это что? Такая "шутка юмора"?

    Нет. Это просто ачепятка :)
  • guav © (05.04.08 11:31) [7]
    > Пробегаюсь по ее 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 © (05.04.08 15:02) [8]
    > [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 ?
  • Riply © (05.04.08 15:06) [9]
    > [8] Riply ©   (05.04.08 15:02)

    Опять форматирование "съехало" :)
    Кодом надо было выделять, наверное.
  • Riply © (05.04.08 15:10) [10]
    >  [9] Riply ©   (05.04.08 15:06)

    Смайлик не тот. Должен быть :(
  • guav © (05.04.08 15:36) [11]
    Файлы нумеруются не через LCN, т.к. в одном кластере находятся несколько файлрекордов. Ссылка на файл - это то, что в MSDN называется MTF_SEGMENT_REFERENCE, или File Reference в документации линукса.

    Вот есть у тебя File Reference, передаваемый в FSCTL_GET_NTFS_FILE_RECORD. Из него же ты получаешь смещение в MFT и соответственно смещение на диске. Приведи значение этого File Reference, значение смещения, по которому читаешь и результат что прочитывается в обоих случаях.
  • Riply © (05.04.08 15:58) [12]
    > [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 © (05.04.08 16:04) [13]
    > Может быть что в одном файлрекорде несколько кластеров :)

    Может. Но я про конкретный случай.
    В любом случае, 221120 на File Reference не похож, где тут последовательный номер ?

    > TypeCode AT_DATA


    > TotalAllocated 3531575320579784755

    Кстати ни разу это ни TotalAllocated
    переводим в 0x это 3102AD0B00B1C033
    00B1C0 = 45504
    02AD0B = 175371
    , т.е.

    > Index 0 Lcn 175371 Count 45504
  • Riply © (05.04.08 16:10) [14]
    > [13] guav ©   (05.04.08 16:04)
    > Кстати ни разу это ни TotalAllocated

    Совершенно верно.
    Значание TotalAllocated, при _CompressionUnit = 0 неопределено.
    Руки не доходят подправить функцию парсинга,
    чтобы она не выводила TotalAllocated при нулевом CompressionUnit
  • Riply © (05.04.08 16:13) [15]
    > [13] guav ©   (05.04.08 16:04)
    > В любом случае, 221120 на File Reference не похож, где тут последовательный номер ?
    Для получения "абсолютного смещения на диске" его надо умножить на BytesPerCluster
  • Riply © (05.04.08 17:44) [16]
    Выскажу я одно предположение, только чур не смеяться.
    Бывает несу чушь. Это от недосыпа :)

    Трактовка Lcn`ов, возвращаемых FSCTL_GET_RETRIEVAL_POINTERS,
    и, соответственно, алгоритм их чтения могут зависеть от состояния MFT.

    Например, если пользователь так загнал MFT, что та аж вся форматированная
    да еще и вынужденная хранить в себе данные, которые должны быть не резидентными. :)
  • guav © (05.04.08 18:11) [17]
    > Значание 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 © (05.04.08 19:47) [18]
    [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 © (05.04.08 20:08) [19]
    > В программе я поступаю так: высчитываю
    > FileRefNumber := ((221120 - MftStartLcn) * BytesPerCluster)
    > div BytesPerFileRecordSegment;

    Это что ? Где ты это взяла ?
    И более интересный вопрос - откуда взялось 221120 ?


    > Кстати 221120 попадает в диапазон
    > [MftStartLcn < 221120 < MftStartLcn + MftValidDataLength
    > div BytesPerCluster]

    И что ?


    > Получается, что FileRefNumber...

    Нет, не получается.

    Не знаю как тебе ещё объяснить...
    Что по-твоему значат поля File Reference ?
 
Конференция "WinAPI" » NtReadFile NtFsControlFile. Разница возвращаемых данных.
Есть новые Нет новых   [134432   +20][b:0][p:0.001]