В корпоративных информационных системах хранятся важные сведения, которые всегда должны быть под рукой. Однако от аварийных сбоев не застрахован никто. После такой аварии быстро восстановить работу компьютера часто не удается — операционная система должна предварительно проверить, не произошло ли нарушения целостности записанной на диске информации.
Процедура анализа записанных на диске данных о файлах, каталогах и другой служебной информации может занять продолжительное время, которое терять совсем не хочется. Чтобы обеспечить быстрое восстановление работы файловой системы после сбоя, можно воспользоваться идеологией транзакций, которая хорошо разработана для баз данных. Правда, если для баз данных транзакции обеспечивают целостность пользовательских данных, то для файловых систем нужно обеспечить целостность служебной информации. Именно на этих принципах базируется технология журналируемых файловых систем.
Журнал гарантирует целостность
Практически все многозадачные операционные системы используют буферизацию данных при работе с файловой системой. Это значит, что данные, которые приложение сохраняет на диске, попадают сначала в буфер операционной системы, а потом по необходимости переносятся на диск. Тем самым ускоряется работа с файловой системой, поскольку приложениям не приходится ждать завершения достаточно медленных дисковых операций. Однако буферизация может привести к тому, что информация, хранимая на диске и в буферах операционной системы, будет не синхронизирована. Если в этот момент произойдет сбой и работа компьютера прекратится, то возникает вероятность, что данные на диске записаны некорректно.
Именно поэтому при выключении компьютера или отключении носителя нужно размонтировать соответствующую файловую систему. Если же работа компьютера была аварийно остановлена, то ОС, обнаружив не размонтированный том, должна проверить его целостность. Для этого перед монтированием тома надо выполнить для него процедуру проверки целостности файловой структуры: для Windows такая утилита называется ScanDisk, для Linux — fsck. Утилита проверяет каждый блок информации, сохраненный на диске, и определяет корректность описывающих его метаданных, структуру каталогов и состояние служебной информации. Эта процедура оказывается весьма ресурсоемкой. Только после этого утилита проверки приводит файловую систему в непротиворечивое состояние, ее можно считать готовой к дальнейшему использованию. При этом может оказаться, что некоторые фрагменты данных потеряны или модифицированы.
Основная идея файловой системы с журналированием — записывать в специальный системный журнал все изменения в метаданных, чтобы после аварии можно было анализировать не весь диск, а только места последних изменений файловой системы. Идеология такого журнала базируется на концепции транзакции — неделимой последовательности элементарных операций. Транзакция должна быть либо полностью выполнена, либо полностью аннулирована. Основным свойством транзакции с метаданными файловой системы является то, что она должна переводить состояние диска из одного непротиворечивого состояния в другое. Это свойство позволяет операционной системе не проверять после сбоя корректность метаданных, а отменить изменения, произведенные незавершенными транзакциями. Сделать это значительно быстрее, поскольку в системном журнале уже содержится вся необходимая для этого информация, и нет надобности считывать весь диск.
Следует отметить, что использование журналирования при записи содержимого буферов на диск замедляет работу с диском, поскольку кроме собственно действий над пользовательскими данными нужно также запротоколировать транзакции, сопровождающие эти действия. Таким образом, мы получаем дополнительную возможность быстрого восстановления работы после сбоев за счет уменьшения производительности файловой системы в штатном режиме. Однако в новых файловых системах, таких как ReiserFS, JFS и XFS, для компенсации этого эффекта используются дополнительные механизмы ускорения работы файловой системы. В то же время при добавлении механизма журналирования в традиционные файловые системы, как это сделано в ext3fs, ее производительность может снизиться.
Работа с журналом
Давайте разберемся, как с помощью записи транзакций в специальный журнал можно сохранить целостность метаданных файловой системы. Для этого сам журнал также нужно хранить на диске, а не в оперативной памяти. После сбоя в работе важно правильно определить, какие транзакции уже завершены, а какие еще нет. Для этого можно использовать метки времени, которые указывают, когда произошла синхронизация буферов операционной системы и содержимого дисков с помощью стандартного для Unix системного вызова sync, который предписывает сохранить на диске содержимое всех буферов. После вызова sync в журнале записывается время синхронизации файловой системы. Можно также записывать старое и новое состояние метаданных, а при восстановлении файловой системы либо присваивать новые значения для завершенной транзакции, либо старые — для незавершенной. Чтобы определить, на выполнении какой операции случилась авария, нужно после выполнения каждого элементарного действия записывать в журнал признак его завершения. По состоянию признаков завершения операции программа восстановления файловой системы определяет момент аварийного останова и вычисляет все незавершенные транзакции, которые затем аннулируются.
Рассмотрим, какие изменения метаданных записываются в журнале. В файловых системах Unix основой единицей метаданных является описатель inode, который содержит всю служебную информацию о соответствующем ему файле или каталоге. Содержание inode, карта их размещения и таблица свободных inode и являются теми метаданными, изменение которых должно протоколироваться в журнале транзакций. Кроме того, сами данные на диске хранятся в виде блоков фиксированной длины, для которых файловая система также должна иметь карту их размещения. Все перечисленные метаданные хранятся в суперблоке файловой системы (если ее корректно размонтировать). Изменение метаданных происходит в случае создания или модификации файла или каталога, а также при создании, изменении и удалении ссылок на файлы. Кроме того, есть операции по изменению атрибутов файлов, таких как изменение прав доступа к файлу или имени владельца. Поскольку эти атрибуты также хранятся в структуре inode, то они тоже должны протоколироваться в журнале транзакций. При чтении данных и метаданных изменений в файловой структуре не происходит.
Восстановление файловой системы после сбоя происходит в момент ее монтирования. Времени на восстановление метаданных по журналу требуется не очень много, поэтому для пользователей операция восстановления практически не заметна; она занимает максимум несколько секунд. При восстановлении выполняются следующие действия: если файловая система не синхронизирована, то читается журнал транзакций для метаданных и по нему восстанавливается их корректность, после чего можно приступать к собственно монтирования файловой системы для дальнейшего использования. По журналу транзакций определяются те из них, которые не были завершены, и для них производятся операция восстановления исходного состояния («откат»). Сами данные, содержащиеся в файлах, и их изменения в журнал транзакций не записываются, поэтому восстановить их система не сможет. После восстановления метаданных содержимое файлов, изменение которых было прервано аварийной остановкой, может быть испорчено.
У различных файловых систем и набор метаданных разный. Скажем, в файловой системе NTFS, которая используется Windows NT/2000, нет таких конструкций, как inode. В то же время, сейчас начинают появляться файловые системы, которые пользуются техниками ускорения работы файловой системы: сбалансированные деревья (BTree, B+Tree, B*Tree) и объединение последовательных блоков. В том случае, если некоторая часть метаданных может быть вычислена в процессе анализа журнала транзакций, то ее можно и не протоколировать. Например, в файловой системе JFS карта свободных inode не протоколируется, а вычисляется в процессе восстановления. Аналогично восстанавливается и вся рабочая информация, которая хотя и используется для работы файловой системы, но на диске не сохраняется.
Файловые системы с журналированием
Первые файловые системы с журналированием появились еще в середине 80-х: Veritas, Tolerant и JFS, разработанная IBM. Они были разработаны для крупных информационных систем на платформе Unix, обеспечивали быстрое восстановление после сбоев, кроме журналирования, поддерживали также работу с файлами большого размеры и были полностью 64-разрядными. Вскоре к этому набору добавилась и файловая система XFS, разработанная компанией SGI. Как правило, каждая из них работала только с вариантом Unix соответствующего производителя.
Ситуация изменилась, когда в 1999 году компания SGI, а в 2000 году и IBM опубликовали исходные тексты своих файловых систем. В результате появилась возможность переноса их на платформу Linux. Компания Veritas также объявила о планах по переносу своей файловой системы в среду Linux, однако ее исходный код, скорее всего, доступен не будет.
Кроме этих унаследованных файловых систем Хансом Райзером специально для Linux была разработана файловая система ReiserFS. Кроме журналирования в ней использованы технологии ускорения работы файловой системы с помощью сбалансированных деревьев и объединения последовательных блоков. Кроме того, сотрудником компании Red Hat Стефеном Твиди разработана файловая система ext3fs, которая совместима с ext2fs по структуре метаданных, но в нее будет встроен механизм журналирования. Перенос данных в ней из уже существующих систем будет достаточно прост, но из-за использования журналирования ее производительность, скорее всего, будет ниже, чем у ext2fs.
Получает также развитие новая технология, которая основана на концепции структурированных журналов (Log-Structured). В такой файловой системе каждый файл рассматривается как системный журнал, все изменения которого дописываются в его конец. Все операции с файлом представлены в такой файловой системе в виде транзакций; старое содержимое файла хранится в нем еще некоторое время. Такой подход к хранению информации также позволяет решить проблему быстрого восстановления файловой системы после сбоев, но добавляет и новые уникальные возможности — сохранение не только метаданных, но и самих данных, поддержку версионности файлов и возможность динамического изменения размеров тома. Сейчас для Linux реализована версия такой файловой системы, LinLogFS.