Основная цель, которая преследуется при создании журналируемых файло-вых систем, состоит в том, чтобы обеспечить как можно большую вероят-ность быстрого восстановления системы после сбоев (например, после по-тери питания). Дело в том, что если происходит сбой, то часть информации о расположении файлов теряется, поскольку система не успевает записать все изменения из буфера на диск. После сбоя утилита, например, fsck должна прове-рить все диски, которые не были корректно демонтированы, с целью вос-становления потерянной информации. При современных объемах жестких дисков, на проверку двух-трех таких дис-ков может уйти слишком много времени. Кроме того, нет гарантии, что все данные удастся восстановить.

В журналируемых файловых системах для решения этой проблемы приме-няют транзакции, которые хорошо известны всем программистам баз дан-ных. Идея транзакции достаточно проста — существует набор связанных операций, называемых транзакцией, и эта группа операций является ато-марной (неделимой). Таким образом, транзакция является успешной (завершенной) в том случае, если все операции, составляющие транзакцию, завершились успешно. Но это еще не все. Система ведет журнал, в котором отражаются все действия с данными и все изменения данных протоколиру-ются. В случае сбоя на основании журнала можно вернуть систему в без-ошибочное состояние.

Основное отличие транзакций из области баз данных от транзакций, при-меняемых в журналируемых файловых системах, состоит в том, что в базах данных в журнале сохраняются изменяемые данные и вся управляющая ин-формация, а в файловых системах — только метаданные: индексные деск-рипторы изменяемых файлов, битовые карты распределения свободных бло-ков и свободных индексных дескрипторов.

Пример1. Файловая система Ext3

По большому счету, файловая система Ext3 не была новой файловой системой. Это похоже на ситуацию с файловой системой FAT 16/FAT 32 — они совместимы, но проблема решена экстенсивным путем. Было необхо-димо срочно создать журналируемую файловую систему. Если начинать с нуля — долго и накладно, тогда сделали для Ext2 несколько десятков специ-альных функций и назвали все это Ext3 — получился непонятный гибрид.

Файловая система ext3 имеет несколько опций, которые позволяют выбрать, сколько информации нужно журналировать. В системе Red Hat Linux, чтобы прочитать и восстановить данные из обычного журнала, требуется около секунды. Время, необходимое для восстановления журнальной файловой системы после неправильного выключения компьютера, зависит не от размера файловой системы, а от того, сколько данных содержится в журнале.

В файловой системе ext3, как и в остальных журналируемых файловых системах, нет необходимости осуществлять традиционную проверку с помощью программы fsck. Тем не менее, fsck еще используется в других журнальных файловых системах.

При выборе опций журналирования можно отключить проверку целостности данных при пересылке, чтобы увеличить скорость выполнения операций в файловой системе; из-за конструкции файловой системы нужно выбирать что-то одно: либо обеспечение целостности, либо скорость. Можно повысить скорость обработки данных, установив для них режим Writeback. Но при этом данные могут повредиться, если во время операции над ними произойдет аварийное выключение компьютера. Или же можно пожертвовать скоростью выполнения операций, но обеспечить целостность данных.

В файловой системе ext3 доступны 3 режима работы с данными:

  • Writeback - позволяет старым данным оставаться в системе, при этом операции над этими данными, как правило, выполняются быстрее. Этот режим не предусматривает планирование каких-либо операций над данными.
  • Ordered - хранит данные в согласованном состоянии, однако скорость выполнения операций над данными падает (этот режим установлен по умолчанию).
  • Journal - требует дополнительного пространства на диске для выполнения журналирования. При этом может упасть производительность, поскольку данные записываются дважды.

Для большинства пользователей наилучшим режимом будет Ordered , который выбран по умолчанию. Режим выбирается с помощью соответствующей опции монтирования в файле /etc/fstab.

Пример2. Файловая система ReiserFS

Кроме проблемы быстрого восстановления после сбоев, в файловой системе Ext2 имеется еще несколько нерешенных проблем. Из самых основных — нерациональное использование дискового пространства, ограничение на размер файла, неоптимальный поиск.

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

В системе ReiserFS применяются так называемые "сбалансированные дере-вья" или "B+Trees", время поиска в которых пропорционально не количест-ву объектов, а логарифму этого числа. В сбалансированном дереве все ветви имеют одинаковую длину. ReiserFS использует сбалансированные деревья для хранения всех объектов файловой системы: файлов в каталогах, данных о свободных блоках и т.д. Это позволяет существенно повысить производи-тельность обращения к дискам.

Кроме того, система ReiserFS является журналируемой, т.е. в ней решена проблема быстрого восстановления после сбоев. Решена в ReiserFS и про-блема с ограничением на размер файла.

NTFS - отказоустойчивая система, которая вполне может привести себя в корректное состояние при практически любых реальных сбоях. Любая современная файловая система основана на таком понятии, как транзакция - действие, совершаемое целиком и корректно или не совершаемое вообще. У NTFS просто не бывает промежуточных (ошибочных или некорректных) состояний - квант изменения данных не может быть поделен на до и после сбоя, принося разрушения и путаницу - он либо совершен, либо отменен.

Пример 1: осуществляется запись данных на диск. Вдруг выясняется, что в то место, куда мы только что решили записать очередную порцию данных, писать не удалось - физическое повреждение поверхности. Поведение NTFS в этом случае довольно логично: транзакция записи откатывается целиком - система осознает, что запись не произведена. Место помечается как сбойное, а данные записываются в другое место - начинается новая транзакция.

Пример 2: более сложный случай - идет запись данных на диск. Вдруг, отключается питание и система перезагружается. На какой фазе остановилась запись, где есть данные, а где нет? На помощь приходит другой механизм системы - журнал транзакций. Дело в том, что система, осознав свое желание писать на диск, пометила в метафайле $LogFile это свое состояние. При перезагрузке это файл изучается на предмет наличия незавершенных транзакций, которые были прерваны аварией и результат которых непредсказуем - все эти транзакции отменяются: место, в которое осуществлялась запись, помечается снова как свободное, индексы и элементы MFT приводятся в с состояние, в котором они были до сбоя, и система в целом остается стабильна. Ну а если ошибка произошла при записи в журнал? Тоже ничего страшного: транзакция либо еще и не начиналась (идет только попытка записать намерения её произвести), либо уже закончилась - то есть идет попытка записать, что транзакция на самом деле уже выполнена. В последнем случае при следующей загрузке система сама вполне разберется, что на самом деле всё и так записано корректно, и не обратит внимания на "незаконченную" транзакцию.

И все-таки помните, что журналирование - не абсолютная панацея, а лишь средство существенно сократить число ошибок и сбоев системы.

Опыт показывает, что NTFS восстанавливается в полностью корректное состояние даже при сбоях в очень загруженные дисковой активностью моменты. Вы можете даже оптимизировать диск и в самый разгар этого процесса нажать reset - вероятность потерь данных даже в этом случае будет очень низка. Важно понимать, однако, что система восстановления NTFS гарантирует корректность файловой системы , а не ваших данных. Если вы производили запись на диск и получили аварию - ваши данные могут и не записаться, но всегда есть их копия.

Сжатие

Файлы NTFS имеют один довольно полезный атрибут - "сжатый". Дело в том, что NTFS имеет встроенную поддержку сжатия дисков - то, для чего раньше приходилось использовать Stacker или DoubleSpace. Любой файл или каталог в индивидуальном порядке может хранится на диске в сжатом виде - этот процесс совершенно прозрачен для приложений. Сжатие файлов имеет очень высокую скорость и только одно большое отрицательное свойство - огромная виртуальная фрагментация сжатых файлов, которая, правда, никому особо не мешает. Сжатие осуществляется блоками по 16 кластеров и использует так называемые "виртуальные кластеры" - опять же предельно гибкое решение, позволяющее добиться интересных эффектов - например, половина файла может быть сжата, а половина - нет. Это достигается благодаря тому, что хранение информации о компрессированности определенных фрагментов очень похоже на обычную фрагментацию файлов: например, типичная запись физической раскладки для реального, несжатого, файла:

кластеры файла с 1 по 43-й хранятся в кластерах диска начиная с 400-го

кластеры файла с 44 по 52-й хранятся в кластерах диска начиная с 8530-го...

Физическая раскладка типичного сжатого файла:

кластеры файла с 1 по 9-й хранятся в кластерах диска начиная с 400-го

кластеры файла с 10 по 16-й нигде не хранятся

кластеры файла с 17 по 18-й хранятся в кластерах диска начиная с 409-го

кластеры файла с 19 по 36-й нигде не хранятся

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

Журналирование NTFS

В NTFS применяется журналирование логических структур, а не данных пользователя - отсюда и идет фраза, что сохранность данных не гарантируется, но, тем не менее, корректное состояние самой системы будет поддерживаться. То, что NTFS не журналирует данные файлов, приводит на практике к одному варианту потери данных - в том же гипотетическом случае записи трех мегабайт, в случае сбоя в процессе записи никогда уже не удастся установить, какая часть данных записалась, а какая осталась неизменна. Операции, которые, тем не менее, журналируются системой - это операции со структурами самой системы, то есть с файлами и каталогами: добавление файлов, переименование, перенос, создание и удаление (освобождение свободного места). Журналируются также и операции дефрагментации - то есть перемещения фрагментов файлов. Одним словом, все логические операции журналированы.

Отложенная запись и контрольные точки журналирования

Известно, что любая современная система для ускорения файловых операций вынуждена использовать кэширование, в том числе - кэширование операций записи. Так называемая отложенная запись - принцип кэширования, при котором данные, предназначенные для записи на диск, некоторое время сохраняются в КЭШе и лишь в свободное от других занятий время сохраняются физически. Отложенная запись существенно повышает эффективность дисковых операций, так как такое кэширование группирует множество операций в одну - это особенно эффективно, если запись производится в компактные участки диска. Еще один плюс отложенной записи - не мешать более нужным операциям чтения, и осуществлять запись только тогда, когда система свободна и ей не требуется доступ к диску для других нужд. Как согласовать отложенную запись с журналированием? Это довольно сложный вопрос, так как откладывание записи делает возможным потерю тех данных, которые находились в очереди на физическую запись и не успели записаться на диск до сбоя. Самое неприятное здесь даже не потеря данных, а то, что происходит рассогласование времени записи: какие-то служебные области могут быть обновлены, а какие-то смежные по смыслу - еще нет, так как их обновление могло отложится еще на пару секунд и не состоятся из-за сбоя.

NTFS справляется с этими проблемами с помощью смысловой интеграции операций отложенной записи и ведения журнала. При попытке начать журналируемую операцию в лог тут же записывается намерение - например, стереть файл. Это случается без задержек - на этом этапе отложенная запись не работает: это плата за присутствие журналирования, которой нельзя избежать. Но вот все остальные операции уже идут в задержанном режиме - то есть они могут состояться частично или не состоятся вообще. Единственная задержанная операция, работа которой несколько отличается от простой записи - запись в лог об удачном завершении предыдущих транзакций, так называемая контрольная точка. Через определенные промежутки времени - обычно через каждые несколько секунд - система в обязательном порядке сбрасывает абсолютно все задержанные операции на диск. После произведения этой операции в журнал записывается простейшая запись - контрольная точка, - которая говорит о том, что все предыдущие операции выполнены корректно на всех уровнях - как на логическом, так и на физическом.

Такой режим работы - с помощью записей и контрольных точек - с одной стороны, по прежнему гарантирует полностью корректную работу журналирования, а с другой стороны практически совершенно не приводит к замедлению работы: простановка контрольных точек производится, считай, мгновенно, а запись в журнал о начале операции соответствует по трудозатратам записи самих данных без отложенного кэширования. Реальная же запись, осуществляемая позже, в подавляющем числе случаев не мешает никаким операциям и не идет в ущерб производительности системы.

Изначально стандартной файловой системой для Linux была Ext2fs. Ext2 основана на структуре i-node. I-node содержит информацию о файле и указатели на блоки данных, в которых расположен файл. Для повышения быстродействия операций ввода/вывода данные временно располагаются в оперативной памяти. Проблема возникает, если сбой происходит до того, как данные из кэша перепишутся на диск. Это вызывает несоответствие в файловой системе. Например, возникает ссылка на файл, еще не созданный на диске, или файлы были уже удалены, но их i-nodes и блоки данных остались на диске. Fsck (File system check – проверка файловой системы) – стандартная программа для устранения несоответствий. Единственный способ это сделать – просканировать весь диск, и проверить все зависимости между i-nodes, блоками данных и содержанием директорий. С увеличением объемов дисков эта процедура стала занимать огромное количество времени – серьезная проблема для серверов, которые должны работать постоянно.

Это и стало главной причиной внедрения в файловые системы технологии транзакций, взятой из баз данных, и технологии восстановления, и это привело к появлению журналируемых файловых систем.

Журналируемая файловая система – это устойчивая к сбоям файловая система, в которой целостность данных гарантирована, потому что обновления в meta-данных файлов записываются в log на диске перед любыми изменениями в структуре файловой системы. В случае сбоя журналируемая файловая система гарантирует восстановление всех потерянных данных. Самый распространенный подход – это метод журналирования или логгирования meta-данных файлов. Его суть в том, что информация о любом изменении записывается в зарезервированную область файловой системы, и только после этого совершается само изменение.

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

Linux имеет три основные журналируемые FS – это ReiserFS от Namesys, XFS от SGI, и Ext3, разработанная Stephen Tweedie, участвовавшим в создании Ext2.

Самый простой инструмент для улучшенного по сравнению с традиционными Unix-системами быстродействия – это избежание использования связанных списков или bitmaps, которые содержат в себе проблему масштабируемости и неприменимы для новых дисков с огромной вместимостью. Все новые системы используют Balanced Trees (B-Trees), или их вариацию (B+Trees).

Дерево состоит из внутренних и листовых узлов. Каждый узел (node) – это дисковый блок. Каждому объекту (файлу, каталогу) назначается уникальный ключ, аналогичный номеру inode в других файловых системах. Внутренние узлы, главным образом, состоят из ключей и указателей на узлы-потомки. Узел, который начинает дерево, известен как корень; узлы, которые сидят на конце ветви дерева иногда называются листьями.

Время поиска в B+Trees пропорционально не количеству объектов (файлов в каталоге или числа блоков на диске), а логарифму этого числа. В сбалансированном дереве все ветви (пути от корня до «листа») имеют одинаковую (или примерно одинаковую) длину.

ReiserFS базируется на B+Tree в организации объектов файловой системы. ReiserFS предоставляет только журналирование meta-данных. В случае незапланированной перезагрузки данные в блоках, используемых во время сбоя, могут быть повреждены, так что ReiserFS не гарантирует того, что после сбоя данные останутся неповрежденными.

ReiserFS также имеет ряд особенностей, нацеленных специально для улучшения работы с маленькими файлами. Одна из специальных возможностей ReiserFS – это Tail Packing. Tail – это файл, размер которого меньше, чем логический блок, или какие-то части файлов, занимающие меньше, чем один блок. Для сохранения свободного места ReiserFS использует сжатие tail-файлов, и это позволяет примерно на 5 % увеличить свободное место по сравнению с Ext2. Для увеличения скорости, ReiserFS способен хранить содержимое файлов непосредственно внутри b*tree, а не в виде указателя на дисковый блок.

XFS была создана в начале 90-х (1992–1993) фирмой Silicon Grapgics (сейчас SGI) для мультимедийных компьютеров с ОС Irix. Файловая система была ориентирована на очень большие файлы и файловые системы. 1 мая 2001 года SGI выпустила первый релиз XFS для Linux.

Для увеличения масштабируемости файловой системы XFS обширно использует B+Trees. XFS допускает хранение журнала на другом блочном устройстве.

XFS имеет такую возможность, как delayed allocation (Отложенное размещение) – вместо того, что бы выделять блоки файлу в момент его записи в кэш, XFS просто резервирует блоки в файловой системе, размещая данные в специальных виртуальных зонах (virtual extents). Когда весь файл содержится в памяти, то он обычно может быть размещен в одном куске непрерывного дискового пространства. Тем самым предотвращается фрагментация файлов.

Максимальный размер файла – 9 млн. Тбайт

В ReiserFS неожиданная перезагрузка может иметь результатом попадание в изменяемый файл фрагмента из когда-то удаленного файла. Помимо очевидной потери данных, гипотетически это может иметь более серьезные последствия. В XFS имеется гарантия, что любые «недозаписанные» блоки заполнены нулями. Так как блоки с нулевыми байтами в системных файлах игнорируются, устраняется лазейка в безопасности.

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

Журнал располагаться в любой другой файловой системе. Возможно иметь несколько файловых систем Ext3 с совместным журналом.

Типы журналирования поддерживаемые Ext3, которые могут быть активированы из файла /etc/fstab:

  • data=journal (full data journaling mode) – все новые данные сначала пишутся в журнал и только после этого переносятся на свое постоянное место. В случае аварийного отказа журнал можно повторно перечитать, приведя данные и метаданные в непротиворечивое состояние. Самый медленный, но самый надежный.
  • data=ordered – записываются изменения только метаданных файловой системы, но логически metadata и data блоки группируются в единый модуль, называемый transaction. Перед записью новых метаданных на диск, связанные data блоки записываются первыми. Этот режим установлен по умолчанию. При добавлении данных в конец файла режим data=ordered гарантированно обеспечивает целостность (как при full data journaling mode). Однако, если данные в файл пишутся поверх существующих, то есть вероятность перемешивания «оригинальных» блоков с модифицированными. Это результат того, что data=ordered не отслеживает записи, при которых новый блок ложится поверх существующего и не вызывает модификации метаданных.
  • data=writeback (metadata only) – записываются только изменения метаданных файловой системы. Самый быстрый метод журналирования. Аналогичен используемому в XFS и ReiserFS.

Файловая система NTFS начала свое существование вместе с Windows NT 3.5 в 1993 году. Она умеет управлять дисками размером до нескольких сотен терабайт.

Каждый файл на томе NTFS представлен записью в специальном файле, называемом главной файловой таблицей (MFT – master file table). Первая запись этой таблицы описывает непосредственно главную файловую таблицу;

За ней следует зеркальная запись (mirror record) MFT. Если первая запись MFT разрушена, то NTFS читает вторую запись для отыскания зеркального файла MFT.

Третья запись MFT – файл регистрации (log file); содержит список шагов транзакции, используемых Log File System для восстановления файлов в случае сбоя. Семнадцатая и последующие записи главной файловой таблицы используются собственно файлами и каталогами.

Небольшие файлы и каталоги могут полностью содержаться внутри записи главной файловой таблицы. Большие каталоги организованы в B-tree, имея записи с указателями на внешние кластеры, содержащие элементы каталога, которые не могли быть записаны внутри структуры MFT.

Журналируемые файловые системы - это класс файловых систем, характерная черта которых - ведение журнала, хранящего список изменений, в той или иной степени помогающего сохранить целостность файловой системы.

Запуск проверки системы (например, fsck) на больших файловых системах может занять много времени, что очень плохо для сегодняшних высокоскоростных систем. Причиной отсутствия целостности в файловой системе может быть некорректное размонтирование, например, если в момент прекращения работы на диск велась запись. Приложения могли обновлять данные, содержащиеся в файлах, и система могла обновлять метаданные файловой системы, которые являются «данными о данных файловой системы», иными словами, информация о том, какие блоки связаны с какими файлами, какие файлы размещены в каких директориях и тому подобное. Ошибки (отсутствие целостности) в файлах данных - это плохо, но куда хуже ошибки в метаданных файловой системы, что может привести к потерям файлов и другим серьезным проблемам.

Для минимизации проблем, связанных с целостностью, и минимизации времени перезапуска системы, журналируемая файловая система хранит список изменений, которые она будет проводить с файловой системой перед фактической записью изменений. Эти записи хранятся в отдельной части файловой системы, называемой «журналом», или «логом». Как только изменения файловой системы безопасно внесены в журнал, журналируемая файловая система применяет эти изменения к файлам или метаданным, а затем удаляет эти записи из журнала. Записи журнала организованы в наборы связанных изменений файловой системы, что очень похоже на то, как изменения добавляемые в базу данных организованы в транзакции.

Наличие журнала повышает вероятность сохранения целостности файловой системы, потому что записи в лог-файл ведутся до проведения фактических изменений, и эти записи хранятся до тех пор, пока они не будут целиком и безопасно применены. При перезагрузке компьютера программа монтирования может гарантировать целостность журналируемой файловой системы простой проверкой лог-файла на наличие ожидаемых, но не произведенных изменений и последующей записью их в файловую систему. Т.о. при наличии журнала в большинстве случаев системе не нужно проводить проверку целостности файловой системы, а это означает, что компьютер будет доступен для работы практически сразу после перезагрузки. Соответственно, шансы потери данных в связи с проблемами в файловой системе значительно снижаются.

Существует несколько журналируемых файловых систем, доступных в Linux. Наиболее известные из них:

    XFS, журналируемая файловая система разработанная Silicon Graphics, но сейчас выпущенная открытым кодом (open source);

    ReiserFS, журналируемая файловая система разработанная специально для Linux;

    JFS, журналируемая файловая система первоначально разработанная IBM, но сейчас выпущенная как открытый код;

    xt3 - журналируемое расширение файловой системы ext2, используемой на большинстве версий GNU/Linux. Уникальная особенность системы ext3 - возможность перехода на неё с ext2 без переформатирования диска. Разработана доктором Стефаном Твиди (Stephan Tweedie).

    В семействе ОС Microsoft Windows к журналируемым относится файловая система NTFS. В Mac OS X - HFS+.