Что такое файловая система lfs
Обновлено: 21.11.2024
Несмотря на экспоненциальное увеличение скорости процессора и объема оперативной памяти, стоимость доступа к диску росла гораздо медленнее. Это требует файловой системы, которая фокусируется на производительности записи, использует последовательную полосу пропускания и эффективно работает как при записи на диск, так и при обновлении метаданных. Именно здесь мотивация заключается в том, что Log-Structured File System (LFS) укоренена.
Хотя все операции чтения невозможно выполнить последовательно (поскольку любой файл может быть доступен в любой момент времени), мы можем использовать эффективность последовательной записи. LFS хранит небольшой буфер всех операций записи в сегменте памяти. Журнал — это просто структура данных, которая записывается только в начале (можно представить весь диск как журнал). После заполнения журнала он последовательно записывается в неиспользуемую часть диска. Новые данные и метаданные (иноды, каталоги) накапливаются в буферном кеше и записываются сразу большими блоками (например, сегментами по 0,5 М или 1 М).
- Inodes:
Как и в Unix, inodes содержат указатели физических блоков на файлы. - Карта индексных дескрипторов:
В этой таблице указано расположение каждого индексного дескриптора на диске. Карта индексных дескрипторов записывается в самом сегменте. - Сводка по сегменту.
Содержит информацию о каждом блоке в сегменте. - Таблица использования сегментов.
Это говорит нам об объеме данных в блоке.
Последовательная запись на диск:
Рассмотрите следующий рисунок, на котором показан блок данных D, записанный на диск в ячейке A0. Наряду с блоком данных находится индексный дескриптор, который указывает на блок данных D. Обычно блоки данных имеют размер 4 КБ, а индексные дескрипторы имеют размер около 128 байт.
Эффективная последовательная запись на диск.
Однако простой последовательной записи на диск недостаточно для достижения эффективности. Чтобы понять проблему, представим, что мы записали блок данных D по адресу A0 в момент времени T. Теперь, когда мы получаем следующий блок данных в момент времени T+t для записи по адресу A0+1, диск уже повернулся. некоторыми единицами. Если время вращения диска равно , мы должны подождать - \delta" width="" height="" />
перед записью второго блока, чтобы два адреса (A0, A0+1) были смежными.
Решение этой проблемы простое — вместо ожидания - \delta" width="" height="" />
после каждых двух последовательных записей блока данных мы можем просто сгруппировать некоторые из последовательных записей и временно хранить их в сегменте, а затем записывать их все вместе на диск Таким образом, вместо того, чтобы ждать, пока диск переместится после каждого блока данных, мы ждем, пока он переместится после каждого x блоков данных, где x - емкость сегмент. На рисунке ниже показана эта концепция.
, D_, D_" width="" height="" />
и " width="" height="" />
— это 4 обновления одного и того же файла j, которые записываются сразу на диск. Это одно из множества обновлений, буферизованных в LFS. " width="" height="" />
— это обновление файла k, которое записывается на диск при следующем вращении.
- Каждая запись приводит к добавлению новых блоков в буфер текущего сегмента в памяти.
- Когда сегмент заполнен, он записывается на диск.
LFS также устраняет вышеупомянутую проблему с малой записью в RAID-4 и RAID-5, поскольку вместо небольших блоков данных записываются целые сегменты.
Проблемы.
Одна из возникающих проблем заключается в том, что сегменты в журнале имеют тенденцию к фрагментации, поскольку старые блоки файлов заменяются новыми. Поскольку LFS создает старые копии данных, разбросанных по разным сегментам диска, их необходимо периодически очищать. Для этого более чистый процесс «очищает» старые сегменты. Этот очиститель берет несколько неполных сегментов и сжимает их, создавая один полный сегмент, тем самым освобождая место.
Файловая система с журнальной структурой (LFS) предлагает совершенно другой подход к управлению файловой системой.
Основная идея LFS заключается в том, что блоки никогда не изменяются; всякий раз, когда операция концептуально изменяет файл, операция вместо этого помещает блок new в конец журнала. Записи всегда идут в конец диска.
Например, предположим, что я хочу изменить первый байт файла. Я бы создал новую копию прямого блока, содержащего этот байт, и поместил бы ее в конец журнала. Поскольку адрес этого блока теперь изменился, я бы также создал копию индексного дескриптора для файла.
Это может потребовать от меня создания новой копии любого каталога, содержащего этот файл (поскольку адрес индексного дескриптора изменился). Однако это сложно и дорого (учитывайте жесткие ссылки), поэтому вместо этого мы добавляем дополнительный уровень косвенности. Записи каталогов в LFS содержат номера инодов для содержащихся в них файлов, а не дисковые адреса самих инодов.
Эти номера инодов затем просматриваются в глобальной карте инодов, которая сопоставляет номера инодов с текущим расположением инодов.
Диск разбит на большие сегменты. Каждый сегмент содержит большое количество (~ 1000) блоков данных и инодов, а также самую последнюю копию карты инодов. Чтобы отслеживать текущий сегмент файловой системы (т. е. конец журнала), назначенный «суперблок» в начале файловой системы содержит ссылку на самый последний записанный сегмент.
Периодически (или когда текущий сегмент заполнен) текущий сегмент записывается на диск, а номер начального сегмента в суперблоке обновляется для перехода к следующему сегменту. Это называется контрольно-пропускным пунктом; после записи суперблока файловая система теперь отражает все, что произошло до контрольной точки.
Обратите внимание, что без сборки/сжатия мусора (описанных ниже) все состояние файловой системы в любой контрольной точке в прошлом можно восстановить, просто изменив ссылку заголовка на эту контрольную точку. Файловая система с журнальной структурой сохраняет историю, что является хорошей функцией.
Сжатие
Недостаток хранения всей истории заключается в том, что диск может легко заполниться старыми версиями. Чтобы очистить неиспользуемые сегменты, файловая система может периодически сжимать конец журнала.
Чтобы сжать сегмент, вы проверяете каждый блок (блок данных или inode) в сегменте. Изучив текущую таблицу индексов, вы можете определить, являются ли эти блоки последними версиями. Если они есть, вы можете скопировать их в заголовок журнала (и их иноды, и таблицу инодов), точно так же, как если бы вы перезаписывали их новыми данными. Сделав это, вы можете безопасно использовать сегмент повторно, так как все хранящиеся в нем блоки теперь устарели.
Чтобы определить, устарел ли блок, необходимо знать его идентификатор. Это хранится в дополнительной части сегмента, называемой таблицей сегментов. Таблица сегментов содержит запись для каждого блока в сегменте, которая определяет, частью какого файла (номер inode) является блок и какой частью он является (например, "прямой блок 37" или "inode").
Преимущества и недостатки LFS
данные могут быть потеряны, если они были записаны, но не отмечены контрольной точкой. Это можно смягчить, уменьшив время между контрольными точками или разрешив приложениям запрашивать ожидание до следующей контрольной точки, прежде чем продолжить.
большая часть операций чтения поглощается кешем; записи всегда добавляются в журнал, поэтому они выполняются последовательно и очень быстро.
блоки расположены на диске точно (или почти точно) в том порядке, в котором они были записаны в последний раз. Даже если операции чтения пропустят кеш, они будут иметь хорошую локальность, если порядок чтения файлов имитирует порядок их записи.
Система LFS хороша для флэш-памяти (твердотельных или твердотельных накопителей): качество флэш-памяти ухудшается с каждой последующей записью, но LFS естественным образом равномерно распределяет записи по всем сегментам.
Для твердотельных накопителей также требуются операции записи в очень больших сегментах; написание сегментов очень хорошо соответствует этим характеристикам использования.
Я украл у Digital несколько диаграмм, чтобы объяснить, чем LFS отличается от стандартных файловых систем. На первом рисунке показан блок данных некоторого файла (серый) и информация о нем (время модификации, указатели на блоки данных и т. д.) в обычной файловой системе, а также то, что происходит при изменении данных в этом файле:
р>
На втором рисунке показан аналогичный файл в LFS и что происходит при его изменении:
Обратите внимание, что ВСЕ изменения записываются в КОНЕЦ журнала. Во-первых, это намного быстрее, так как диску не нужно искать по всему диску для записи в части файла, но также это намного безопаснее, потому что исходные блоки данных файла не «теряются» до тех пор, пока log успешно записал «новые» блоки данных. Это приводит к очень стабильным файловым системам, практически не требующим времени после сбоя.
Это немного отредактированная версия письма, которое я отправил с разъяснением LFS:
Большинство файловых систем основаны на идее размещения статических данных. У вас есть карта местоположений "inode". Эти индексы указывают на блоки данных и блоки каталогов. Блоки каталогов содержат списки других индексных дескрипторов и связанные с ними имена файлов. Индексный дескриптор содержит информацию о владельце и разрешениях, а также указатель на то, где на диске располагаются блоки данных для файла.
Представьте, что у вас есть файл "foo.bar", содержимое которого вы собираетесь изменить. Инод для "foo.bar" содержит, скажем, 4 блока данных. Данные для "foo.bar" лежит на диске с адресами 3110, 3111, 3506 и 3507. Первое, на что следует обратить внимание, это то, что этот файл фрагментирован. Жесткому диску придется искать диапазон 3100, читать два блока, затем искать диапазон 3500 и читать два блока, чтобы прочитать весь файл. Допустим, вы изменили 3-й блок. Файловая система прочитает третий блок, внесет ваши изменения и перезапишет третий блок, все еще расположенный в 3506. Если вы добавите файл, у вас могут быть блоки размещается где угодно.
Представьте, что вы обновляете запись каталога. Вы только что изменили 15 файловых записей в 5-м блоке какой-то гигантской записи каталога. Так как диск находится в середине для записи этого блока, вы теряете питание, и теперь блок не завершен и полностью недействителен.
Во время перезагрузки на компьютерах UNIX запускается программа под названием "fsck" (проверка файловой системы), которая проходит через входную файловую систему, проверяя все записи и проверяя правильность размещения блоков и т. д., и т. п. Она найдет эту запись каталога и попытается чтобы отремонтировать его. Кто знает, насколько это будет успешным. Вполне возможно, что вы могли потерять все записи каталога после изменения одной, если что-то действительно запуталось.
Для больших файловых систем проверка fsck может занять очень много времени. Спросите любого администратора сетевых новостей о сбое его новостной машины и узнайте, сколько времени требуется для fsck их 10-гигабайтной файловой системы новостей. Я слышал вещи в диапазоне от 2 до 3 часов.
Существует другой тип файловой системы, известный как "журнальная" или "журналируемая" файловая система. Эти файловые системы отслеживают _изменения_, а не «текущее» содержимое файла. («Журналируемые» файловые системы отслеживают только изменения инодов, тогда как журналирующие файловые системы отслеживают изменения, внесенные как в данные, так и в иноды.) В моем первом примере с файлом «foo.bar» вместо изменения данных в блоке 3506 , файловая система журнала будет хранить копию индексного дескриптора foo.bar и третьего блока в новых местах на диске. Список индексных дескрипторов в памяти будет изменен, чтобы указать «foo.bar» на новый индексный дескриптор. Все изменения, добавления и удаления будут регистрироваться в растущей части файловой системы, известной как «журнал». Время от времени файловая система "проверяла" и обновляла список индексных дескрипторов на диске, а также освобождала "неиспользуемые" части файлов (например, исходный третий блок "foo.bar").
Эти файловые системы после сбоя почти сразу возвращаются в оперативный режим, потому что нужно проверять только файловую систему после последней контрольной точки. Все изменения в журнале можно быстро воспроизвести, а «плохой» частью диска всегда будет последнее добавленное в журнал изменение, которое можно выбросить, так как оно будет недействительным, и никакие данные не будут потеряны, кроме изменение, которое было потеряно при отключении питания. Та же самая 10-гигабайтная новостная файловая система потребует 4 или 5 секунд для fsck после сбоя.
Основная проблема с журналированием файловых систем заключается в том, что они легко фрагментируются. У всех есть решение этой проблемы, и все они разные.
Файловые системы ведения журналов имеют почти одинаковую скорость чтения, поскольку блоки файловых данных по-прежнему легко обнаруживаются. Карта инодов имеет списки блоков, и их можно быстро прочитать. Файловая система журналов _резко_ повышает скорость записи, потому что она добавляется только к одной и той же области диска и никогда не нуждается в поиске блоков на диске.
Поскольку скорость записи улучшается, а время восстановления улучшается (скорее, время восстановления _не существует_ и гарантируется отсутствие потерь), а время чтения сравнимо (возможно, немного медленнее из-за большей фрагментации), я думаю это очень полезная файловая система. Машины AIX используют журналируемые файловые системы, и они меня очень впечатляют. Это главная причина, по которой я хочу увидеть файловые системы журналирования для Linux.
Файловая система с журнальной структурой (LFS) предлагает совершенно другой подход к управлению файловой системой.
Основная идея LFS заключается в том, что блоки никогда не изменяются; всякий раз, когда операция концептуально изменяет файл, операция вместо этого помещает блок new в конец журнала. Записи всегда идут в конец диска.
Например, предположим, что я хочу изменить первый байт файла. Я бы создал новую копию прямого блока, содержащего этот байт, и поместил бы ее в конец журнала. Поскольку адрес этого блока теперь изменился, я бы также создал копию индексного дескриптора для файла.
Это может потребовать от меня создания новой копии любого каталога, содержащего этот файл (поскольку адрес индексного дескриптора изменился). Однако это сложно и дорого (учитывайте жесткие ссылки), поэтому вместо этого мы добавляем дополнительный уровень косвенности. Записи каталогов в LFS содержат номера инодов для содержащихся в них файлов, а не дисковые адреса самих инодов.
Эти номера инодов затем просматриваются в глобальной карте инодов, которая сопоставляет номера инодов с текущим расположением инодов.
Диск разбит на большие сегменты.Каждый сегмент содержит большое количество (~ 1000) блоков данных и инодов, а также самую последнюю копию карты инодов. Чтобы отслеживать текущий сегмент файловой системы (т. е. конец журнала), назначенный «суперблок» в начале файловой системы содержит ссылку на самый последний записанный сегмент.
Периодически (или когда текущий сегмент заполнен) текущий сегмент записывается на диск, а номер начального сегмента в суперблоке обновляется для перехода к следующему сегменту. Это называется контрольно-пропускным пунктом; после записи суперблока файловая система теперь отражает все, что произошло до контрольной точки.
Обратите внимание, что без сборки/сжатия мусора (описанных ниже) все состояние файловой системы в любой контрольной точке в прошлом можно восстановить, просто изменив ссылку заголовка на эту контрольную точку. Файловая система с журнальной структурой сохраняет историю, что является хорошей функцией.
Сжатие
Недостаток хранения всей истории заключается в том, что диск может легко заполниться старыми версиями. Чтобы очистить неиспользуемые сегменты, файловая система может периодически сжимать конец журнала.
Чтобы сжать сегмент, вы проверяете каждый блок (блок данных или inode) в сегменте. Изучив текущую таблицу индексов, вы можете определить, являются ли эти блоки последними версиями. Если они есть, вы можете скопировать их в заголовок журнала (и их иноды, и таблицу инодов), точно так же, как если бы вы перезаписывали их новыми данными. Сделав это, вы можете безопасно использовать сегмент повторно, так как все хранящиеся в нем блоки теперь устарели.
Чтобы определить, устарел ли блок, необходимо знать его идентификатор. Это хранится в дополнительной части сегмента, называемой таблицей сегментов. Таблица сегментов содержит запись для каждого блока в сегменте, которая определяет, частью какого файла (номер inode) является блок и какой частью он является (например, "прямой блок 37" или "inode").
Преимущества и недостатки LFS
данные могут быть потеряны, если они были записаны, но не отмечены контрольной точкой. Это можно смягчить, уменьшив время между контрольными точками или разрешив приложениям запрашивать ожидание до следующей контрольной точки, прежде чем продолжить.
большая часть операций чтения поглощается кешем; записи всегда добавляются в журнал, поэтому они выполняются последовательно и очень быстро.
блоки расположены на диске точно (или почти точно) в том порядке, в котором они были записаны в последний раз. Даже если операции чтения пропустят кеш, они будут иметь хорошую локальность, если порядок чтения файлов имитирует порядок их записи.
Система LFS хороша для флэш-памяти (твердотельных или твердотельных накопителей): качество флэш-памяти ухудшается с каждой последующей записью, но LFS естественным образом равномерно распределяет записи по всем сегментам.
Для твердотельных накопителей также требуются операции записи в очень больших сегментах; написание сегментов очень хорошо соответствует этим характеристикам использования.
Читайте также: