Вы когда-нибудь работали с виртуальными машинами, создавали виртуальные диски? Если да, то наверняка вы обратили внимание на такие удобные возможности, как динамическое увеличение размера диска (возможность хранить только то, что было записано) и возможность создания snapshot'ов — моментальных снимков состояния диска. Если вам интересно узнать, каким именно способом достигаются эти возможности и как хранятся данные в VHD и VHDX файлах — добро пожаловать под кат.
Фиксированные диски
Виртуальный диск — это, обычно, простой файл внутри которого хранится все, что записывает виртуальная машина на некое дисковое устройство. Под фиксированные диски сразу выделяется файл полного объема, который в дальнейшем не изменяется в размере.
Однако, тут следует оговориться, и вспомнить про возможности многих файловых систем создавать «сжатые» файлы. Обычно сжатие достигается за счет того, что не хранятся заполненные нулями блоки файла (например, так делают NTFS, XFS и VMFS). Даже если в вашей файловой системе свободно 500ГБ, вы легко можете создать создать фиксированный виртуальных диск на 1ТБ и работать с ним, пока не исчерпаете свободное место.
Фиксированные диски могут храниться двумя способами:
- Простые файлы-образы. Они же RAW, они же flat (*flat.vmdk например). Тут из названия все понятно. Такие файлы (почти) не содержат никаких специфических метаданных. Фиксированный VHD может содержать 512 байт своих метаданных в конце файла. В остальном его не отличить, от копии «реального» диска в файл.
- Вырожденные динамические диски. Такие диски хранятся в том же формате, что и динамические, только все требуемое пространство выделяется сразу при создании. Как будто динамический диск сразу после создания прописали от начала до конца. Такой файл вы получите, если создадите фиксированный VHDX.
Динамические VHD
Файловые системы ведут запись на диск в хаотичном порядке. Чтобы в таких условиях обеспечивать постепенное увеличение файла виртуального диска, необходима система трансляции. Один из самых простых способов трансляции — это таблица, которая для каждого логического блока укажет его размещение внутри файла или скажет, что такой блок еще не был выделен.
Именно такая идея заложена в формате динамических VHD (и не только). Логическое пространство виртуального диска (то, что ОС внутри виртуальной машины видит как диск) разбито на блоки равного размера, например, по 2 мегабайта, которые адресуются с помощью BAT – Block Allocation table.
При создании snapshot'ов может потребоваться наделить статусом «пустой-выделенный» не отдельный блок, а отдельный сектор в блоке. Поэтому каждый блок снабжается bitmap'ом, который записывается перед блоком. При размере логического сектора 512 байт и размере блока 2 мегабайта, bitmap для блока будет занимать ровно 1 сектор (512*8 = 2 097 152 / 512). Т.е. один обобщенный блок будет занимать 4097 секторов.
Помимо BAT и обобщенных блоков файл VHD содержит еще структуры Hard Disk Footer (512байт) в самом конце и копию в самом начале. И Dynamic Disk Header (1024байта) в начале файла. В них хранятся различные метаданные о виртуальном диске: его размер, версию формата, метки времени, размер блока, смещение BAT, количество записей в ней и тд.
Если обобщить, то содержимое VHD файла выглядит так (пропорции условны):
Динамические VHDX
Формат динамического VHDX общей идеей похож на VHD — логическое пространство также разбивается на блоки, которые адресуются специальной таблицей трансляции, тут также есть bitmap'ы, чтобы уточнить статус отдельного сектора. Но в деталях отличий много.
Начну с того, что в VHDX размер одного bitmap'а фиксированный — 1 мегабайт. И покрывает он уже несколько блоков. Например, при размере логического сектора 512 байт (VHDX также может «отдавать» сектор 4096 байт) и размере блока 2 мегабайта, один bitmap «покрывает» 2 048 блоков. Это значение еще называется chunk ratio.
Второе отличие — блок с bitmap'ом самостоятельно адресуется из BAT. Сначала идут 2048 ячеек (chunk ratio), которые адресуют соответствующие блоки данных, потом идет ячейка, адресующая блок bitmap и так далее.
Следующее отличие в том, что запись в BAT теперь хранит еще и статус блока. У блока данных это:
- NOT_PRESENT – отсутствует;
- UNDEFINED – неопределенный (в файле выделено место, но там неактуальные данные);
- ZERO – заполнен нулями (место в файле не выделяется);
- UNMAPPED – для всех секторов блока была выполнена команда UNMAP;
- FULLY_PRESENT – блок полностью присутствует:
- PARTIALLY_PRESENT – блок частично присутствует.
Запись для блока bitmap'а может иметь только два статуса:
- NOT_PRESENT — блок bitmap'а отсутствует;
- PRESENT — блок bitmap присутствует.
Bitmap'ы и частично присутствующие блоки данных могут быть только в разностных дисках, которые появляются при создании snapshot'ов (о них раскажу ниже). В остальных случаях bitmap'ы отсутствуют, а блоки данных имеют другие статусы.
В общем виде структура VHDX файла выглядит примерно так:
Коротко про оставшиеся секции:
- В самом начале диска лежит структура FileIdentifier — она содержит сигнатуру и комментарий о приложении, создавшем VHDX файл. Это она открыта в HEX-редакторе на скриншоте в начале статьи;
- Далее идут две версии (для защиты от сбоя) заголовка. В нем указаны смещение и размер лога, а также некоторые другие параметры;
- Лог — это циклический буфер, через который проводятся все операции над метаданными, кроме Header'ов. Сделано это, опять же, для защиты от внезапных отключений;
- Введено понятие регионов. В спецификации перечислены всего 2 типа регионов: BAT и Metadata, но, подразумевается, что их может быть больше. Регионы адресуются с помощью таблицы регионов, которая хранится в двух экземплярах (и тут защита от сбоев);
- В регионе Metadata хранятся записи о метаданных, они адресуются с помощью таблицы метаданных, в которую приложения могут добавлять метаданные своих типов. Согласно спецификации здесь мы должны найти записи о размере блока, размере логического сектора, размере диска и другие.
Snapshot'ы
Snapshot — это моментальный снимок состояния виртуального диска на какой-то момент времени. Имея такой снимок мы можем откатить все изменения, сделанные после этого момента.
Если речь идет о VHD и VHDX дисках, то при создании snapshot'а создается новый файл, в котором фиксируются все последующие изменения. Такой файл называют «дельтой» или «разностным диском» (от англ. Differencing).
Ранее мы говорили, что формат динамических дисков позволяет хранить только записанные данные. Этот же формат прекрасно подходит для того, чтобы хранить только измененные данные. Да, файлы дельт имеют абсолютно такой же формат, что и динамические диски. Изменяется только интерпретация свободных блоков. Для дельты свободный блок означает, что надо не просто вернуть нули, а попытаться прочитать блок с предыдущего слоя — если есть предыдущая дельта, то с нее, а если нет, то с базового диска.
Если убрать верхнюю дельту — получим предыдущее зафиксированное состояние, а если обе, то самое раннее.
Взгляд со стороны восстановления данных
С точки зрения восстановления данных виртуальные диски плохи прежде всего тем, что между файлом и диском вводятся дополнительные уровни трансляции.
Каждый уровень — это дополнительное перемешивание данных, которое увеличивает фрагментацию, и потенциальная точка отказа. У какого-нибудь BAD сектора теперь гораздо больше возможностей наделать много проблем.
В общем случае, чтобы прочитать данные некоторого файла с виртуального диска необходимо иметь
- метаданные файловой системы физического диска, которые описывают размещение файла виртуального диска;
- метаданные самого виртуального диска (BAT и прочее);
- метаданные файловой системы на виртуальном диске, описывающие размещение файла.
Если очень «повезет», то задача восстановления данных может превратиться в сборку паззла без образца. Не то чтобы я отговаривал пользоваться виртуальными дисками, но чем проще хранятся данные, то тем легче их будет восстановить.
Loxmatiymamont
>> Если речь идет о VHD и VHDX дисках, то при создании snapshot'а создается новый файл, в котором фиксируются все последующие изменения.
Все изменения сразу пишутся в базовый диск, а в дельту выносятся замещённые данные (copy-on-write снапшот). Изменения в снапшоты пишут vmdk.
al_ace Автор
Спасибо за замечание, попробую сейчас проверить.
ildarz
TechNet с вами не согласен.
al_ace Автор
Вот и у меня, честно говоря, не получилось такого добиться. C Hyper-V дела не задались, а новый VirtualBox пишет новые данные в разностный диск (как на картинке в статье). Такая же ситуация была и нескольких случаях при восстановлении данных, но в поломанных данных может случиться все, что угодно.
navion
Это точно про чекпоинты Hyper-V, а не про снепшоты VSS?