Що під капотом у віртуальних дисків? (на прикладі VHD і VHDX)



Ви коли-небудь працювали з віртуальними машинами, створювали віртуальні диски? Якщо так, то напевно ви звернули увагу на такі зручні функції, як динамічне збільшення розміру диска (можливість зберігати тільки те, що було записано) і можливість створення 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's
Snapshot — це моментальний знімок стану віртуального диска на якийсь момент часу. Маючи такий знімок ми можемо відкотити всі зміни, зроблені після цього моменту.

Якщо мова йде про VHD і VHDX дисках, то при створенні snapshot'а створюється новий файл, в якому фіксуються всі наступні зміни. Такий файл називають «дельтою» або «різницевим диском» (від англ. Differencing).

Раніше ми говорили, що формат динамічних дисків дозволяє зберігати тільки записані дані. Цей же формат чудово підходить для того, щоб зберігати тільки змінені дані. Так, файли дельт мають абсолютно такий же формат, що і динамічні диски. Змінюється тільки інтерпретація вільних блоків. Для дельти вільний блок означає, що треба не просто повернути нулі, а спробувати прочитати блок з попереднього шару — якщо є попередня дельта, то з неї, а якщо ні, то з базового диска.



Якщо прибрати верхню дельту — отримаємо попереднє зафіксоване стан, а якщо обидві, то найперша.

Погляд з боку відновлення даних
З точки зору відновлення даних віртуальні диски погані насамперед тим, що між файлом і диском вводяться додаткові рівні трансляції.



Кожен рівень — це додаткове перемішування даних, яке збільшує фрагментацію, і потенційна точка відмови. У якого-небудь BAD сектора тепер набагато більше можливостей наробити багато проблем.

У загальному випадку, щоб прочитати дані деякого файлу з віртуального диска необхідно мати
  • метадані файлової системи фізичного диска, які описують розміщення файлу віртуального диска;
  • метадані самого віртуального диска (BAT тощо);
  • метадані файлової системи на віртуальному диску, що описують розміщення файлу.
Якщо дуже пощастить», то завдання відновлення даних може перетворитися на складання пазла без зразка. Не те щоб я відмовляв користуватися віртуальними дисками, але чим простіше зберігаються дані, то тим легше їх буде відновити.

Література
  1. Virtual Hard Disk Image Format Specification
  2. VHDX Format Specification v1.00

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.