
Протоколирование транзакций
Восстанавливаемость ФС в NTFS обеспечивается при помощи техники обработки транзакций, называемой протоколированием (logging). В процессе протоколирования, прежде чем выполнить над содержимым диска какую-либо подоперацию транзакции, изменяющей важные структуры файловой системы, NTFS записывает ее в файл журнала транзакций. Таким образом, в случае сбоя системы незавершенные транзакции можно повторить или отменить после перезагрузки машины. В NTFS транзакция (transaction) определена как операция ввода-вывода, изменяющая данные ФС или структуру каталогов тома. Эти операции, к которым относятся, в частности, запись на диск или удаление файла, могут состоять из нескольких подопераций.
В состав средств протоколирования NTFS входят два важных компонента: собственно журнал транзакций (log file) и сервис журнала транзакций (log file service, LFS). Журнал транзакций — это системный файл, создаваемый командой Format, a LFS — набор системных процедур, которые NTFS использует для доступа к журналу транзакций. Отделение LFS от ФС позволит другим системным компонентам или будущим приложениям создавать собственные журналы для реализации восстанавливаемости на уровне прикладной программы, как это делается в системах обработки транзакций.
Сервис журнала транзакций
Хотя LFS разработан, чтобы обеспечить средства протоколирования и восстановления более чем для одного клиента, первоначально он доступен только для ФС через интерфейсы режима ядра (kernel-mode interfaces). Вызывающая программа, в данном случае NTFS, передает LFS указатель на открытый файловый объект — файл, который будет использоваться как журнал транзакций. LFS либо инициализирует новый журнал, либо вызывает диспетчер КЭШа Windows NT для доступа к существующему журналу через кэш, как показано на рис. 4-1.
Рис. 4-1. Журнал транзакций.
LFS делит файл журнала на две части: область рестарта (restart area) и "бесконечную" область протоколирования (logging area), как показано на рис. 4-2.
NTFS вызывает LFS для чтения и записи области рестарта. В этой области NTFS хранит информацию контекста, такую как позиция в области протоколирования, откуда она будет начинать чтение при восстановлении после сбоя системы. На тот случай, что область рестарта будет разрушена или станет по каким-либо причинам недоступной, LFS создает ее копию. Остальная часть журнала транзакций — это область протоколирования, в которой находятся записи транзакций, обеспечивающие NTFS восстановление тома после сбоя. LFS создает иллюзию бесконечности журнала транзакций путем его циклического повторного использования (в то же время, гарантируя, что нужная информация не будет затерта). Для идентификации записей, помещенных в журнал, LFS использует номера логической последовательности (logical sequence number, LSN). Циклически используя журнал, LFS увеличивает значения LSN. Число возможных LSN настолько велико, что практически может считаться бесконечным.
NTFS никогда не выполняет чтение-запись транзакций в журнал напрямую. LSN обеспечивает сервисы, которые NTFS вызывает для открытия файла журнала, помещения в журнал записей, считывания записей из журнала в прямом и в обратном порядке, сброса записей журнала до заданного LSN или продвижения логического начала журнала на больший LSN. В процессе восстановления NTFS вызывает LSN для чтения записей журнала в прямом направлении, чтобы повторить все транзакции, которые были запротоколированы в журнале, но не записаны на диск к моменту сбоя. NTFS также обращается к LSN для чтения записей в обратном направлении, чтобы отменить (или откатить) все транзакции, которые не были полностью запротоколированы перед аварией системы,
Рис. 4-2. Журнал транзакций.
Кроме того, NTFS вызывает LSN для продвижения логического начала журнала на запись с большим LSN, когда ей становятся не нужны старые записи журнала. Система обеспечивает восстановление тома следующим образом:
Сначала NTFS вызывает LFS для записи в (кэшированный) файл журнала любых транзакций, модифицирующих структуру тома.
NTFS модифицирует том (также в кэше).
Диспетчер кэша вызывает LFS для уведомления о необходимости сбросить журнал транзакций на диск (этот сброс реализуется LFS при помощи обратного вызова диспетчера кэша с указанием страниц памяти, подлежащих выводу на диск; см. последовательность вызовов на рис. 4-1).
Сбросив на диск журнал транзакций, диспетчер кэша записывает на диск изменения тома (сами транзакции).
Эта последовательность действий гарантирует, что если не удастся выполнить изменения ФС, то соответствующие транзакции можно будет считать из журнала и либо повторить, либо отменить в процессе восстановления ФС.
Восстановление ФС начинается автоматически при первом обращении к тому после перезагрузки машины. NTFS проверяет, применялись ли к тому транзакции, запротоколированные в журнале до сбоя, и если нет, то повторяет их. NTFS гарантирует также отме1ту тех транзакций, которые не были полностью запротоколированы до сбоя, так что вызванные ими изменения не появятся на томе.
Журнал транзакций
Прежде чем модифицировать том, NTFS обращается к LFS для регистрации в журнале любой транзакции, которая изменит структуру тома. Действуя, таким образом, NTFS использует технику обеспечения восстанавливаемости, известную в теории обработки транзакций как опережающее протоколирование (write-ahead logging).
LFS позволяет своим клиентам помещать в журналы транзакций записи любого типа. NTFS использует несколько типов записей, два из которых — записи модификации (update record) и записи контрольной точки (check-point records) — описаны ниже.
Записи модификации
Большинство записей, которые NTFS помещает в журнал транзакций, представляют собой записи модификации. Каждая такая запись содержит два вида информации:
Информация для повтора (redo information) — как вновь применить! тому одну подоперацию полностью запротоколированной ("подтвержденной") транзакции, если сбой системы произошел до того, как транзакция была переписана из кэша на диск.
Информация для отмены (undo information) — как устранить изменения, вызванные одной подоперацией транзакции, которая в момент сбоя была запротоколирована лишь частично ("не подтверждена").
На рис. 4-3 показаны три записи модификации в журнале транзакций. Каждая запись представляет собой одну подоперацию транзакции, создающей
новый файл. Данные повтора в каждой записи сообщают NTFS, как повторно применить данную подоперацию к тому, а данные отмены — как откатить (отменить) эту подоперацию.
После протоколирования транзакции (в данном примере, вызывая LFS для помещения трех записей модификации в журнал транзакций) NTFS выполняет ее подоперации непосредственно над томом — в кэше. По окончании обновления кэша NTFS помещает в журнал еще одну запись, которая помечает всю транзакцию как завершенную. Эта подоперация известна как подтверждение транзакции (committing a transaction). После того как транзакция подтверждена, NTFS гарантирует, что все вызванные ею модификации будут отражены на томе, даже если после подтверждения произойдет сбой ОС.
При восстановлении после сбоя системы NTFS просматривает журнал и повторяет все подтвержденные транзакции. Даже если NTFS и завершила транзакцию до момента сбоя системы, ей неизвестно, были ли изменения тома своевременно переписаны на диск диспетчером кэша. Модификации, выполненные в кэше, могли быть потеряны при сбое. Следовательно, NTFS выполняет подтвержденную транзакцию снова, дабы гарантировать, что диск находится в актуальном состоянии.
После повтора всех подтвержденных транзакций NTFS отыскивает в журнале такие, которые не были подтверждены к моменту сбоя, и откатывает (отменяет) каждую запротоколированную подоперацию. В случае, изображенном на рис. 4-3, NTFS вначале должна была бы отменить подоперацию Т1, после чего перейти по указателю назад и отменить Т1^. Переход по указателям в обратном направлении и отмена подопераций продолжались бы до тех пор, пока NTFS не достигла бы первой подоперации транзакции. Двигаясь по указателям, NTFS может определить, сколько и какие записи модификации нужно отменить для того, чтобы откатить транзакцию.
Рис. 4-3. Записи модификации в журнале транзакций.
Информация для повтора и отмены может быть выражена либо физически, либо логически. Физическое описание задает модификации тома как диапазоны байт на диске, которые следует изменить, переместить и т.д. Логическое описание представляет модификации в терминах операций, например "удалить файл A.DAT". Будучи самым низким уровнем программного обеспечения, поддерживающим структуру ФС, NTFS использует записи модификации с физическими описаниями. Однако для программного обеспечения обработки транзакций и других приложений записи модификации в логическом виде могут быть удобнее, поскольку логическое представление обновлений тома компактнее физических. Логическое описание с необходимостью полагается на NTFS в понимании того, что именно выполняют такие операции, как удаление файла.
NTFS генерирует записи модификации (обычно несколько) для каждой из следующих транзакций:
создание файла
удаление файла
расширение файла
урезание файла
установка файловой информации
переименование файла
изменение прав доступа к файлу.
Информация для повтора и отмены в записи модификации должна быть тщательно подобрана, потому что при отмене транзакции, восстановлении после сбоя системы или даже в ходе нормальной работы NTFS может попытаться повторить транзакцию, которая уже была выполнена, или, наоборот, отменить транзакцию, которая никогда не выполнялась либо уже отменена. Аналогично, NTFS может попытаться повторить или отменить транзакцию, состоящую из нескольких записей модификации, из которых не все были применены к диску. Формат записей модификации должен гарантировать, что излишние операции повтора или отмены будут идемпотентными (idempotent), т. е. иметь нейтральный эффект: например, установка бита, который уже установлен, не оказывает никакого действия, но изменение на противоположное значения бита, которое уже было изменено, оказывает. ФС обязана также корректно обрабатывать переходные состояния тома.