Помощь · Поиск · Пользователи · Календарь
Полная версия этой страницы: А где же файлы?
Форум BiT-Team > Системы > Всё о Никсах
DanGer
Думаю теория файловых систем никому не помешает. Особенно тем, кто заботится об их целостности и сохранности. Взято отсюда

Цитата
БЕЗОПАСНОСТЬ ФАЙЛОВОЙ СИСТЕМЫ EXT2


Michael Shaffer

Вступление

Если попросить назвать пять наиболее значимых особенностей ядра Linux с точки зрения обеспечения безопасности, то большинство администраторов, вероятно, не упомянут дополнительные атрибуты для файлов и каталогов, которые поддерживает файловая система ext2. Несмотря на то, что концепция большинства полезных флагов была реализована еще в ядрах начиная с серии 1.1, эти относительно простые дополнительные возможности используется редко. В основном в экзотических и недавно появившихся утилитах для поддержки целостности системы, таких как LIDS, Tripwire и т.д.

Что такое атрибуты файловой системы ext2?

В файловой системе Linux присутствует поддержка дополнительных флагов или по другому "атрибутов" для файлов, начиная в ядрах начиная с серии 1.1.Файловая система в ядрах серий 2.2 и 2.4. позволяет работать со следующим набором атрибутов:


A Atime система не апдейтит atime(access time) для данного файла.

S Sync система фиксирует все изменения, происходящие в данном
файле на физическиом диске синхронно с приложением
изменяющим данный файл.

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

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

d No Dump программе создающей дампы дается указание
игнорировать данный файл во время создания backup.

c Compress система применяет прозрачную компрессию для данного
файла. Т.е. чтение из него дает уже декомпрессованые
данные и предварительно перед записью на диск
производится их сжатие.

s Secure Deletion удаление такого файла сопровождается
перезаписью блоков диска,на которых он располагался
нулями.

u Undelete когда приложение запрашивает файл на удаление,
система должна сохранить блоки на диске, на которых
расположен данный файл, чтобы потом его можно было
восстановить.


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

В таблице ниже приведено соответствие, как различные версии ядра учитывают каждый атрибут:

* позволяет устанавливать флаг и учитывает его значение
i позволяет устанавливать флаг,но игнорирует его значение
- полностью игнорирует флаг

1.0 1.2 2.0 2.2 2.4
A - - * * *
S * * * * *
a - * * * *
i - * * * *
d - * * * *
c i i i i i
s * * i i i
u i i i i i



Хотя ядра более ранних версий учитывают флаг 'secure deletion', но во время создания серии 1.3 разработчики исключили этот атрибут из последующих серий, поскольку, на их взгляд, его использование повышает общую безопасность лишь незначительно. А в худшем случае создает ложное чувство безопасности у пользователей незнакомых с проблемами свойственными для любой схемы 'secure deletion'.

Флаг 'A' или 'atime' для определенных файлов может дать некоторую прибавку производительности, так как избавляет систему от необходимости апдейтить access time для этих файлов каждый раз, когда их открывают на чтение.

Атрибут 'S' или 'synchronous предоставляет новый уровень поддержки целостности данных. Но поскольку все изменения в файлах немедленно сохраняются на диске несколько понижается производиельность.

Основное внимание мы уделим флагу 'a' ('append only') и 'i' ('immutable'), так как их использование дает наиболее ощутимые приемущества в плане обеспечения безопасности и целостности файловой системы.

Различные open source BSD системы, такие как FreeBSD и OpenBSD, с некоторых пор поддерживают аналогичные флаги в своих файловых системах (UFS и FFS соответственно) и частично решение о реализации аналогичных спецвозможностей в Linux основывается на этом положительном опыте.

Какие команды используются для установки и чтения атрибутов в ext2?

Стандартная команда ls не показывает эти расширенные атрибуты. Наборе утилит для ext2, однако, содержит две утилиты специально предназначенные для установки и чтения данных атрибутов: chattr и lsattr.

Поскольку ext2 рассматривается как основная рабочая файловая система Linux, почти все дистрибутивы содержат package 'e2fsprogs', инсталлированый по умолчанию. Если по какой-либо причине конкретная инсталляция Linux не содержит этих утилит, то вот URL ,где можно взять исходники:

The Ext2fs Home Page: http://e2fsprogs.sourceforge.net/ext2.html

Команда lsattr поддерживает очень небольшой набор опций, вот наиболее важные:

-a вывод листинга всех директорий и файлов
-d листинга директорий, но без вывода их содержимого

Результа использования этих опций похож на команду ls. Я обычно создаю шел alias, делая 'la' эквивалентным 'lsattr -a', поскольку последняя становится нудной в случае частого использования.

Команда chattr может использоваться тремя различными способами: chattr +Si test.txt -- установить флаги sync и immutable для файла test.txt chattr -ai test.txt -- убрать флаги append-only и immutable у test.txt chattr =aiA test.txt -- установить ограничение на использование только флагов a, i и A Наконец, обе команды поддерживают опцию -R ,т.е. рекурсивная работа.

Как отличаются атрибуты ext2 от обычных прав доступа?

Большинство администраторов хорошо знакомы со стандартным управлением правами доступа в unix:
[root@typhoid shaffer]# ls -al test*

-rw-rw-r-- 1 shaffer users 0 Nov 17 17:02 test.conf
-rw-rw-r-- 1 shaffer users 0 Nov 17 17:02 test.logM
-rw-rw-r-- 1 shaffer users 0 Nov 16 19:41 test.txt

Вывод команды ls показывает, что владелец всех файлов test* - shaffer и члены группы имеют право на чтение и запись в эти файлы. Прочим пользователям эти файлы доступны для чтения. Команда lsattr примененая к той же группе файлов выдаст уже другие данные:

[root@typhoid shaffer]# lsattr -a test*
---i-------- test.conf
----a------- test.log
------------ test.txt

Она показывает, что test.log имеет флаг append-only, а test.conf имеет флаг immutable.


Копцепция поведения, при которой root или процесс запущенный от имени root в обычных условиях могут игнорировать расширенные атрибуты, была реализована во многих unix системах и является одной из основных причин успешной работы многих локальных и удаленных exploit'ов.

С другой стороны атрибуты ext2 учитываются различными системными вызовами, такими как sys_open() и sys_truncate(), причем вне зависимости от uid процесса их вызывающего или каких-либо других условий. Присутствие флага immutable в inode приводит к тому, что все системные вызовы, касающиеся модификации файлов перестают работать в не зависимости от других условий.

Наличие данных атрибутов и специальных режимов работы ядра в Linux позволяет администратору просто и эффективно укрощать традиционно абсолютные возможности, которые дает uid 0. Цель комплексной настройки заключается в том, чтобы флаги a и i должны накладывать ограничения для всех процессов безотносительно их правам доступа и уровню привилегий.

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

Наконец, использование для защиты критичных файлов атрибутов файловой системы само по себе является полумерой. Хотя атрибуты a и i предотвратят изменение защищенных ими файлов даже со стороны процессов, владельцем которых является root, в обычных обстоятельствах super user все равно может убрать эти флаги и продолжить работу уже без этой помехи. То есть вся проблема в обычных обстоятельствах свелась бы к тому, что в большинстве exploits перед основной работой добавилась бы проверка на то, что эти атрибуты сняты.

В ядрах серий до 2.1, свойство ядра 'secure level' (уровень безопасности) использовалось 'узким кругом' администраторов, поскольку его значение большее нуля означало запрет на любые изменения в файлах с атрибутами a и i.

Для этих ранних версиях ядер, уровень безопасности пределялось через переменную sysct "kernel.securelevel". Если ее значение выставлялось во время загрузки единицей или более высоким уровнем безопасности, то тогда система не позволяла изменять файлы с атрибутами immutable и append-only до момента перегрузки в режим single-user .

В ядрах версий выше 2.0, новая более гибкая система настройки параметров ядра позволяет конфигурировать систему в похожем режиме полной защиты файлов с атрибутами immutable и append-only.

Утилита lcap(8) позволяет конфигурировать множество параметров ядра, в том числе те, которые определяют работу ext2 с расширенными атрибутами. Вот наиболее важные вызовы lcap, которые нас будут интересовать: lcap CAP_LINUX_IMMUTABLE lcap CAP_SYS_RAWIO Первый параметр убирает привилегию у процесов root изменять флаги a и i, второй - запрещает низкоуровневый доступ к блочным устройствам, таким как диски, чтобы предотвратить изменение флагов, используя прямой доступ к файлам. Свойство CAP_SYS_RAWIO всегда необходимо убирать в начале процесса загрузки, если вы собираетесь испльзовать специальные возможности ядра, поскольку в противном случае процесс, владельцем которого является root, может изменить установки параметров ядра ('kernel capability bounding set') обращаясь напрямую к памяти через /dev/kmem.

Если запустить lcap без параметров, то она выдаст полный список 'kernel capability bounding set' и выделит в нем те , которые в данный момент доступны. Ссылка на статью, где обсуждаются kernel capabilities приводится ниже.

После того, как помощью lcap был изменен какой-либо параметр из 'kernel capability bounding set', его повторное изменение возможно только после перезагрузки системы. Эта особенность дает уверенность (для правильно сконфигурированных систем), что в система не могут незаметно производиться изменения без получения физического доступа и перезагрузки в режиме single user.
Дополнительная информация по lcap также как ее исходный код доступны здесь:

LCAP - Linux Kernel Capabilities Bounding Set Editor: http://pw1.netcom.com/~spoon/lcap/

Вещи, для которых обычно используют 'chattr'

Когда я конфигурирую системы, которые будут затем напрямую подключены к Internet и на которых предполагается хостить shell аккаунты или службы типа http и ftp, то обычно после настройки всего необходимого ПО и пользовательских аккаунтов выполняю следующие команды: chattr -R +i /bin /boot /etc /lib /sbin chattr -R +i /usr/bin /usr/include /usr/lib /usr/sbin chattr +a /var/log/messages /var/log/secure (...) Если новые аккаунты добавляются, изменяются, удаляются относительно редко, тогда установка на /home(но не на содержащиеся в нем личные каталоги пользователей) атрибута immutable не вызывет особых проблем. Во многих случаях на все поддерево /usr можно поставить атрибут immutable. Дополнительно, помимо 'chattr -R +i /usr', я обычно располагаю /usr на отдельной разделе и монтирую его как read-only c опцией 'ro' в /etc/fstab. Установка флага append-only на системные лог файлы будет значительным препятствием для потенциального взломщика, пытающегося скрыть свое присутствия и действия в системе.

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

Инсталляция и апгрейд ПО

Для инсталляции и апгрейда необходимо удалить флаги a и i у тех каталогов и файлов, которые будут подвергаться изменению. В системах , где используется rpm, команда:

rpm -qpl newpackage.rpm

выдаст список файлов в устанавливаемом package. Для большинства инсталляций с использованием rpm необходимо иметь права на запись в следующие каталоги: /bin /sbin /usr/bin /usr/sbin /usr/man /lib /etc Обратите внимание, чтобы надлещащим образом организовать замену файла /usr/sbin/someprogram обычно потребуется убрать флаги immutable как с самого файла, так и c содержащей его директории /usr/sbin.

Управление пользовательскими и групповыми аккаунтами

Все из нижеперечисленного
/etc /etc/.pwd.lock /etc/passwd /etc/passwd- /etc/shadow /etc/shadow- /etc/group /etc/group- /etc/gshadow /etc/gshadow- должно остаться доступным на запись и удаление, поскольку команды passwd, chsh, chfn, vipw, vigr и useradd используют эти файлы. Они создают их временную копию в /tmp, модифицируют ее, затем удаляют исходный файл и записывают на его место копию.

Вещи, для которых никогда не следует применять chattr:

/

Это создаст множество проблем(в особенности для syslog). В первую чередь проблемы коснутся syslogd. У него не будет возможности записывать в логи ошибки, появляющиеся в результате работы других приложений. В результате мы получим головоломную проблему. Когда я впервые стал эспериментировать с атрибутами ext2, то потратил целый день на разгребание проблем после того, как дал команду 'chattr +i /'.

/dev

Syslog удаляет и создает заново сокет /dev/log во время своего старта и установка флага immutable или append only на /dev не позволит выполнить это. Кроме этого, когда скрипт запуска выполняет syslogd с опцией '-p', которая задает альтернативный сокет, такой как /var/run/syslog.sock.

Более того даже, когда syslog запускается с опцией '-p', приложения использующие syslog будут все равно предполагать , что сокет расположен в /dev/log, поэтому необходимо создать символьную ссылку , указывающую на место реального сокета. Наконец, даже этого не будет достаточно для систем, которые используют lpd, поскольку package lpr содержит /dev/printer в качестве жесткой ссылки на lpd service socket. И lpd пытается удалить и создать заново свой сокет перед запуском. Изменение этого пути требует перекомпиляции всего пакета lpr.

/tmp

Установка атрибутов на данный каталог будет препятствием для всех приложений, которые хранят какие-либо временные файлы в нем.

/var

Атрибуты append only и immutable в /var относительно редко следует применять к файлам, для которых их установка не вызывает побочных эффектов. Например, применение chattr +a для большинства файлов /var/log не создаст проблем, за некоторым исключением(logrotate). Контрпример: файл /var/log/sendmail.st должен остаться доступным для записи и удаления, поскольку sendmail не просто добавляет в него статистику, но и периодически урезает и перезаписывает.
DanGer
Кто-нибудь интересовался когда-либо файловой системой UFS? Я тоже думал, что никто, но я ошибся biggrin.gif . И рад, что ошибся. Данная статья не совсем является описанием файловой системы, но дает о ней более-менее полную информацию. В общем, читайте, критикуйте.

КРИС КАСПЕРСКИ АКА МЫЩЪХ
Спецвыпуск: Хакер, номер #069, стр. 069-054-1


Цитата
искусственное дыхание
________________________________________

ВОССТАНОВЛЕНИЕ УДАЛЕННЫХ ФАЙЛОВ


КТО НЕ УДАЛЯЛ ФАЙЛОВ И ПОТОМ ГОТОВ БЫЛ ПОВЕСИТЬСЯ, ЧТОБЫ ВЕРНУТЬ ИХ ОБРАТНО? ОСОБЕННО ЛЕГКО УДАЛЯТЬ ДАННЫЕ С ПОМОЩЬЮ КОМАНДНОЙ СТРОКИ, КОГДА ЛИШНИЙ ПРОБЕЛ ИЛИ СИМВОЛ ЗВЕЗДОЧКИ ТРУТ ВСЕ ПОДЧИСТУЮ. ХОЧЕШЬ УЗНАТЬ, КАК ЭТОМУ ПРОТИВОСТОЯТЬ?

xBSD поддерживает множество файловых систем: FAT16/32, ext2fs/ext3fs, ISO 9660, UDF, NFS, SMBFS, NTFS, ReiserFS, XF, AFS, LFS, но основной системой, устанавливаемой по умолчанию, была и остается UFS/UFS2.
Многие коммерческие UNIX'ы также используют либо саму UFS, либо нечто очень на нее похожее. В противоположность ext2fs, исхоженной вдоль и поперек, UFS (равно как и ее наследница FFS) практически недокументированна и в доступной литературе описана поверхностно. Единственным источником информации становятся исходные тексты, в которых не так-то просто разобраться!
Существует множество утилит, восстанавливающих уничтоженные данные (или, во всяком случае, пытающихся делать это), но на проверку все они оказываются неработоспособными (или обнаруживают не все файлы), что, в общем-то, и неудивительно, поскольку автоматическое восстановление удаленных файлов под UFS невозможно в принципе. Тем не менее, это достаточно легко сделать вручную, если, конечно, знать, как.

[немного истории.]
UFS расшифровывается как UNIX File System и ведет свою историю от S5 FS — самой первой файловой системы, написанной для UNIX в далеком 1974 году. S5 FS была крайне простой и неповоротливой (по некоторым данным - 2%-5% от «сырой» производительности голого диска), но понятия суперблока (super-block), файловых записей (inodes) и блоков данных (blocks) в ней уже существовали.
В процессе работы над дистрибутивом 4.2 BSD, вышедшим в 1983 году, ординальная файловая система претерпела некоторые улучшения. Были добавлены длинные имена, символические ссылки и т. д. Так родилась UFS.
В 4.3 BSD, увидевшей свет уже в следующем году, улучшения носили намного более радикальный, если не сказать революционный, характер. Появились концепции фрагментов (fragments) и групп цилиндров (cylinder groups). Быстродействие файловой системы существенно возросло, что и определило ее название FFS – Fast File System (быстрая файловая система).
Все последующие версии линейки 4.x BSD прошли под знаменем FFS, но в 5.x BSD файловая система вновь изменилась. Для поддержки дисков большого объема ширину всех адресных полей пришлось удвоить: 32-битная нумерация фрагментов уступила место 64-битной. Были внесены и другие менее существенные усовершенствования.
Фактически, мы имеем дело с тремя различными файловыми системами, не совместимыми друг с другом на уровне базовых структур данных. Однако некоторые источники склонны рассматривать FFS как надстройку над UFS. Из Little UFS2 FAQ следует, что «UFS/UFS2 определяет раскладку данных на диске. FFS реализована поверх UFS 1 или 2 и отвечает за структуру директорий и некоторых дисковых оптимизаций». Действительно, если заглянуть в исходные тексты файловой системы, можно обнаружить два подкаталога — /ufs и /ffs. В /ffs находится определение суперблока (базовой структуры, отвечающей за раскладку данных), а в /ufs – определение inode и структуры директорий, что опровергает данный тезис, с точки зрения которого все должно быть с точностью до наоборот.
Чтобы не увязнуть в болоте терминологических тонкостей, под UFS мы будем понимать основную файловую систему 4.5 BSD, а под UFS2 – основную файловую систему 5.х BSD.

[структура UFS.]
В начале диска расположен boot-сектор (на незагрузочных разделах он может быть пустым), а все остальное пространство поделено на несколько зон одинакового размера, называемых группами цилиндров (cylinder groups). Каждая группа цилиндров имеет свой суперблок (super-block), свою таблицу inode (Index-node) и свою группу блоков данных, совершенно независимую от всех остальных зон. Другим словами, inode описывает блоки данных той и только той зоны, к которой она принадлежит. Это увеличивает быстродействие файловой системы (головка жесткого диска совершает более короткие перемещения) и упрощает процедуру восстановления при значительном разрушении данных, поскольку, как показывает практика, обычно гибнет только первая группа inode. Чтобы погибли все группы... что же такого с жестким диском нужно сделать?! Под пресс положить, наверно.
Каждый блок, в свою очередь, разбит на несколько фрагментов фиксированного размера, предотвращающих потерю свободного пространства в хвостах файлов. Благодаря этому, использование блоков большого размера уже не кажется расточительной идей: напротив, это увеличивает производительность и уменьшает фрагментацию. Если файл использует более одного фрагмента в двух несмежных блоках, он автоматически перемещается на новое место, в наименее фрагментированный регион свободного пространства. Поэтому фрагментация в UFS очень мала или же совсем отсутствует, что существенно облегчает восстановление удаленных файлов и разрушенных данных.
Адресация ведется либо по физическим смещениям, измеряемым в байтах и отсчитываемым от начала группы цилиндров (реже — от UFS-раздела), либо по номерам фрагментов, отсчитываемым от тех же самых точек. Допустим, размер блока составляет 16 Кбайт, разбитых на 8 фрагментов. Тогда сектор 69 будет иметь смещение 512 х 69 = 35328 байт или 1024 x (16/8)/512 x 69 = 276 фрагментов.
В USF первый cуперблок располагается по смещению 8192 байт от конца загрузочного сектора, что соответствует 17-му сектору. В UFS2 он «переехал» на 65536 байт (129 секторов) от начала, освобождая место для дисковой метки и первичного загрузчика операционной системы. А для действительно больших (в исходных текстах — piggy, то есть «свинских») систем предусмотрена возможность перемещения суперблока по адресу 262144 байт (целых 513 секторов).
Вслед за суперблоком идут одна или несколько групп цилиндров, описываемых дескрипторами групп (group descriptors), карты свободного пространства (в просторечии — битмапы, block bitmap/inode bitmap) и таблицы inode. Для перестраховки копия суперблока дублируется в каждой группе. Загрузочный сектор не дублируется, но по соображениям унификации под него просто выделяется место. Таким образом, относительная адресация блоков в каждой группе остается неизменной.
Среди прочей информации суперблок содержит:
- cblkno — смещение первой группы блока цилиндров, измеряемый в фрагментах, отсчитываемых от начала раздела;
- fs_iblkno — смещение первой inode в первой группе цилиндров (фрагменты от начала раздела);
- fs_dblkno — смещение первого блока данных в первой группе цилиндров (фрагменты от начала раздела);
- fs_ncg — количество групп цилиндров (штуки);
- fs_bsize – размер одного блока в байтах;
- fs_fsize — размер одного фрагмента в байтах;
- fs_frag — количество фрагментов в блоке;
- fs_fpg – размер каждой группы цилиндров, выраженный в блоках (может быть найден через fs_cgsize);
Для перевода смещений, выраженных в фрагментах, в номера секторов служит следующая формула: sec_n(fragment_offset) = fragment_offset * (fs_bsize / fs_frag / 512). Или ее более короткая разновидность: sec_n(fragment_offset) = fragment_offset * fs_fsize / 512.
Формат суперблока (определен в файле /src/ufs/ffs/fs.h, второстепенные поля опущены)
struct fs {
/* 0x00 */ int32_t fs_firstfield; /* historic file system linked list, */
/* 0x04 */ int32_t fs_unused_1; /* used for incore super blocks */
/* 0x08 */ ufs_daddr_t fs_sblkno; /* addr of super-block in filesys */
/* 0x0C */ ufs_daddr_t fs_cblkno; /* offset of cyl-block in filesys */
/* 0x10 */ ufs_daddr_t fs_iblkno; /* offset of inode-blocks in filesys */
/* 0x14 */ ufs_daddr_t fs_dblkno; /* offset of first data after cg */
/* 0x18 */ int32_t fs_cgoffset; /* cylinder group offset in cylinder */
/* 0x1C */ int32_t fs_cgmask; /* used to calc mod fs_ntrak */
/* 0x20 */ time_t fs_time; /* last time written */
/* 0x24 */ int32_t fs_size; /* number of blocks in fs */
/* 0x28 */ int32_t fs_dsize; /* number of data blocks in fs */
/* 0x2C */ int32_t fs_ncg; /* number of cylinder groups */
/* 0x30 */ int32_t fs_bsize; /* size of basic blocks in fs */
/* 0x34 */ int32_t fs_fsize; /* size of frag blocks in fs */
/* 0x38 */ int32_t fs_frag; /* number of frags in a block in fs */
/* these are configuration parameters */
/* 0x3С */ int32_t fs_minfree; /* minimum percentage of free blocks */
/* 0x40 */ int32_t fs_rotdelay; /* num of ms for optimal next block */
/* 0x44 */ int32_t fs_rps; /* disk revolutions per second */
/* sizes determined by number of cylinder groups and their sizes */
/* 0x98 */ ufs_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
/* 0x9C */ int32_t fs_cssize; /* size of cyl grp summary area */
/* 0xA0 */ int32_t fs_cgsize; /* cylinder group size */
/* these fields can be computed from the others */
/* 0xB4 */ int32_t fs_cpg; /* cylinders per group */
/* 0xB8 */ int32_t fs_ipg; /* inodes per group */
/* 0xBC */ int32_t fs_fpg; /* blocks per group * fs_frag */
/* these fields are cleared at mount time */
/* 0xD0 */ int8_t fs_fmod; /* super block modified flag */
/* 0xD1 */ int8_t fs_clean; /* file system is clean flag */
/* 0xD2 */ int8_t fs_ronly; /* mounted read-only flag */
/* 0xD3 */ int8_t fs_flags; /* see FS_ flags below */
/* 0xD4 */ u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
};
В некотором отдалении от конца суперблока находится первая группа цилиндров. В начале каждой группы расположена служебная структура cg — описатель группы цилиндров, содержащая магическую последовательность 55h 02h 09h, по которой все уцелевшие группы можно найти даже при полностью испорченном суперблоке (стартовые адреса всех последующих групп вычисляются путем умножения номера группы на ее размер, содержащийся в поле fs_cgsize).
Другие важные параметры:
- cg_cgx — порядковой номер группы, отсчитываемый от ноля;
- cg_old_niblk — количество inode в данной группе;
- cg_ndblk — количество блоков данных в рассматриваемой группе;
- csum — количество свободных inode и блоков данных в рассматриваемой группе;
- cg_iusedoff — смещение карты занятых inode, отсчитываемое от начала данной группы и измеряемое в байтах;
- cg_freeoff — смещение карты свободного пространства (байты от начала группы).
Структура описателя группы цилиндров (определена в файле /src/ufs/ffs/fs.h)
#define CG_MAGIC 0x090255
#define MAXFRAG 8
struct cg {
/* 0x00 */ int32_t cg_firstfield; /* historic cyl groups linked list */
/* 0x04 */ int32_t cg_magic; /* magic number */
/* 0x08 */ int32_t cg_old_time; /* time last written */
/* 0x0С */ int32_t cg_cgx; /* we are the cgx'th cylinder group */
/* 0x10 */ int16_t cg_old_ncyl; /* number of cyl's this cg */
/* 0x12 */ int16_t cg_old_niblk; /* number of inode blocks this cg */
/* 0x14 */ int32_t cg_ndblk; /* number of data blocks this cg */
/* 0x18 */ struct csum cg_cs; /* cylinder summary information */
/* 0x28 */ int32_t cg_rotor; /* position of last used block */
/* 0x2С */ int32_t cg_frotor; /* position of last used frag */
/* 0x30 */ int32_t cg_irotor; /* position of last used inode */
/* 0x34 */ int32_t cg_frsum[MAXFRAG]; /* counts of available frags */
/* 0x54 */ int32_t cg_old_btotoff; /* (int32) block totals per cylinder */
/* 0x58 */ int32_t cg_old_boff; /* (u_int16) free block positions */
/* 0x5С */ int32_t cg_iusedoff; /* (u_int8) used inode map */
/* 0x60 */ int32_t cg_freeoff; /* (u_int8) free block map */
/* 0x64 */ int32_t cg_nextfreeoff; /* (u_int8) next available space */
/* 0x68 */ int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */
/* 0x6С */ int32_t cg_clusteroff; /* (u_int8) free cluster map */
/* 0x70 */ int32_t cg_nclusterblks; /* number of clusters this cg */
/* 0x74 */ int32_t cg_niblk; /* number of inode blocks this cg */
/* 0x78 */ int32_t cg_initediblk; /* last initialized inode */
/* 0x7С */ int32_t cg_sparecon32[3]; /* reserved for future use */
/* 0x00 */ ufs_time_t cg_time; /* time last written */
/* 0x00 */ int64_t cg_sparecon64[3]; /* reserved for future use */
/* 0x00 */ u_int8_t cg_space[1]; /* space for cylinder group maps */
/* actually longer */
Между описателем группы цилиндров и группой inode расположена карта занятых inode и карта свободного дискового пространства, которые представляют собой обыкновенные битовые поля, точно такие же, как и в NTFS. При восстановлении удаленных файлов без этих карт никуда! Они существенно сужают круг поиска, что особенно хорошо заметно на дисках, заполненных более чем наполовину.
За картами следует массив inode, смещение которого содержится в поле cg_iusedoff (адрес первой группы inode продублирован в суперблоке). В UFS inode играет ту же самую роль, что и FILE Record в NTFS (в FAT прямых аналогов нет). Здесь сосредоточена вся информация о файле: тип файла (обычный файл, директория, символьная ссылка и т. д.), логический и физический размер, схема размещения на диске, время создания, модификации, последнего доступа и удаления, права доступа и количество ссылок на файл.
По сути, в UFS структура inode ничем не отличается от ext2fs, только расположение полей другое. К тому же имеется только один блок косвенной адресации вместо трех, но это уже детали, в которые не будем углубляться (иначе или зависнем, или завязнем). Лучше рассмотрим назначение фундаментальных полей, к числу которых принадлежат:
- di_nlink — количество ссылок на файл (0 означает «удален»);
- di_size — размер файла в байтах;
- di_atime/di_atimensec — время последнего доступа к файлу;
- di_mtime/di_mtimensec — время последней модификации;
- di_ctime/di_ctimensec – время последнего изменения inode;
- di_db – адреса первых 12-ти блоков данных файла, отсчитываемые в фрагментах от начала группы цилиндров;
- di_ib — адреса блоков косвенной адресации (фрагменты от начала группы).
Структура inode в USF1 (определена в файле /src/ufs/ufs/dinode.h)
struct dinode {
/* 0x00 */ u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
/* 0x02 */ int16_t di_nlink; /* 2: File link count. */
/* 0x04 */ union {
u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */
int32_t inumber; /* 4: Lfs: inode number. */
} di_u;
/* 0x08 */ u_int64_t di_size; /* 8: File byte count. */
/* 0x10 */ int32_t di_atime; /* 16: Last access time. */
/* 0x14 */ int32_t di_atimensec; /* 20: Last access time. */
/* 0x18 */ int32_t di_mtime; /* 24: Last modified time. */
/* 0x1C */ int32_t di_mtimensec; /* 28: Last modified time. */
/* 0x20 */ int32_t di_ctime; /* 32: Last inode change time. */
/* 0x24 */ int32_t di_ctimensec; /* 36: Last inode change time. */
/* 0x28 */ ufs_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */
/* 0x58 */ ufs_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
/* 0x64 */ u_int32_t di_flags; /* 100: Status flags (chflags). */
/* 0x68 */ int32_t di_blocks; /* 104: Blocks actually held. */
/* 0x6C */ int32_t di_gen; /* 108: Generation number. */
/* 0x70 */ u_int32_t di_uid; /* 112: File owner. */
/* 0x74 */ u_int32_t di_gid; /* 116: File group. */
/* 0x78 */ int32_t di_spare[2]; /* 120: Reserved; currently unused */
};
В UFS2 формат inode был существенно изменен — появилось множество новых полей, удвоилась ширина адресных полей и т. д. Что это обозначает в практическом плане? Смещения всех полей изменились, только и всего, а общий принцип работы остался прежним.
Структура inode в USF2
struct ufs2_dinode {
/* 0x00 */ u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
/* 0x02 */ int16_t di_nlink; /* 2: File link count. */
/* 0x04 */ u_int32_t di_uid; /* 4: File owner. */
/* 0x08 */ u_int32_t di_gid; /* 8: File group. */
/* 0x0C */ u_int32_t di_blksize; /* 12: Inode blocksize. */
/* 0x10 */ u_int64_t di_size; /* 16: File byte count. */
/* 0x18 */ u_int64_t di_blocks; /* 24: Bytes actually held. */
/* 0x20 */ ufs_time_t di_atime; /* 32: Last access time. */
/* 0x28 */ ufs_time_t di_mtime; /* 40: Last modified time. */
/* 0x30 */ ufs_time_t di_ctime; /* 48: Last inode change time. */
/* 0x38 */ ufs_time_t di_birthtime; /* 56: Inode creation time. */
/* 0x40 */ int32_t di_mtimensec; /* 64: Last modified time. */
/* 0x44 */ int32_t di_atimensec; /* 68: Last access time. */
/* 0x48 */ int32_t di_ctimensec; /* 72: Last inode change time. */
/* 0x4C */ int32_t di_birthnsec; /* 76: Inode creation time. */
/* 0x50 */ int32_t di_gen; /* 80: Generation number. */
/* 0x54 */ u_int32_t di_kernflags; /* 84: Kernel flags. */
/* 0x58 */ u_int32_t di_flags; /* 88: Status flags (chflags). */
/* 0x5C */ int32_t di_extsize; /* 92: External attributes block. */
/* 0x60 */ ufs2_daddr_tdi_extb[NXADDR];/* 96: External attributes block. */
/* 0x70 */ ufs2_daddr_tdi_db[NDADDR]; /* 112: Direct disk blocks. */
/* 0xD0 */ ufs2_daddr_tdi_ib[NIADDR]; /* 208: Indirect disk blocks. */
/* 0xE8 */ int64_t di_spare[3]; /* 232: Reserved; currently unused */
};
Имена файлов хранятся в директориях. В inode их нет. С точки зрения UFS, директории являются обыкновенными файлами (ну, не совсем обыкновенными) и могут храниться в любом месте, принадлежащем группе цилиндров. Файловая система UFS поддерживает несколько типов хеширования директорий, однако на структуре хранения имен это никак не отражается. Имена хранятся в блоках, называемых DIRBLKSIZ в структурах типа direct, выровненных по 4-байтовой границе.
Структура direct определена в файле /src/ufs/ufs/dir.h и содержит: номер inode, описывающий данный файл, тип файла, его имя, а так же длину самой структуры direct, используемую для нахождения следующего direct'а в блоке.
Структура direct, отвечающая за хранение имен файлов и директорий
struct direct {
/* 0x00 */ u_int32_t d_ino; /* inode number of entry */
/* 0x04 */ u_int16_t d_reclen; /* length of this record */
/* 0x06 */ u_int8_t d_type; /* file type, see below */
/* 0x07 */ u_int8_t d_namlen; /* length of string in d_name */
/* 0x08 */ char d_name[MAXNAMLEN + 1];/* name with length <= MAXNAMLEN */
};

[что происходит при удалении файла.]
При удалении файла на UFS-разделе происходит следующее (события перечислены в порядке расположения соответствующих структур в разделе и могут не совпадать с порядком их возникновения):
1 В суперблоке обновляется поле fs_time (время последнего доступа к разделу).
2 В суперблоке обновляется структура fs_cstotal (количество свободных inode и блоков данных в разделе).
3 В группе цилиндров обновляются карты занятых inode и блоков данных. Inode и все блоки данных удаляемого файла помечаются как освобожденные.
4 В inode материнского каталога обновляются поля времени последнего доступа и модификации.
5 В inode материнского каталога обновляется поле времени последнего изменения inode.
6 В inode удаляемого файла поля di_mode (IFMT, permissions), di_nlink (количество ссылок на файл) и di_size (размер файла) варварски обнуляются.
7 В inode удаляемого файла поля di_db (массив указателей на 12 первых блоков файла) и di_ib (указатель на блок косвенной адресации) безжалостно затираются нулями.
8 В inode удаляемого файла обновляются поля времени последней модификации и изменения inodе. Время последнего доступа при этом остается неизменным.
9 В inode удаляемого файла обновляется поле di_spare. В исходных текстах оно помечено как «Reserved; currently unused», но просмотр дампа показывает, что это не так. Судя по всему, здесь хранится нечто вроде последовательности обновления (update sequence), используемой для контроля целостности inode. Но это только предположение.
10 В директории удаленного файла размер предшествующей структуры direct увеличивается на d_reclen. В результате чего она как бы «поглощает» имя удаляемого файла, но его затирания не происходит. Во всяком случае, оно затирается не сразу, а только тогда, когда в этом возникнет реальная необходимость.

[подготовка к восстановлению.]
Если ты только что удалил файл, то лучшим способом восстановления будет RESET. Без шуток! Система сбрасывает дисковые буферы не сразу, а спустя некоторое время, поэтому своевременная перезагрузка или отключение питания спасут ситуацию, и после загрузки файл окажется целым и невредимым, правда, на самом диске могут образоваться значительные разрушения, так что риск неблагоприятного исхода очень велик, и лучше воспользоваться более традиционными средствами восстановления smile.gif.
Первым делом размонтируй (unmount) дисковый раздел или перемонтируй его «только на чтение». Лечение активных разделов обычно заканчивается очень печально. Если восстанавливаемые файлы находятся в системном разделе, можно прибегнуть к LiveCD. Лучше всего использовать KNOPPIX. Он поддерживает большое количество оборудования, не требователен к ресурсам (достаточно всего 128 Мбайт памяти) и содержит все необходимые утилиты для восстановления. Опытные пользователи могут сформировать загрузочный CD или даже дискету самостоятельно.
Широко разрекламированный дистрибутив Ferenzy 0.3, основанный на Free BSD, лучше сразу выкинуть в помойку — совсем немного дисковых утилит, да и те ориентированны в основном на ext2fs, а USF/FFS поддерживает постольку поскольку. Тем не менее, для восстановительных работ данный диск вполне пригоден, если ничего другого под рукой нет...
Дисковых редакторов, работающих на уровне секторов, под BSD существует не так уж и много. Обычно для этой цели пользуются BSD-портом LINUX-редактора lde (http://lde.sourceforge.net). Но, к сожалению, когда мы тестировали его на системе 4.5 BSD, он работал крайне нестабильно и не отображал основные структуры данных в удобочитаемом виде, хотя поддержка UFS в нем заявлена. В принципе, можно вставить в привод загрузочный CD-ROM с Windows PE и воспользоваться любым Windows-редактором от Microsoft Disk Probe до Runtime Disk Explorer'а. То же самое справедливо и для Norton Disk Editor'а, запущенного c дискеты из-под MS-DOS (правда, ни диски большого объема, ни SCSI-устройства он не поддерживает). Еще можно запустить KNOPPIX или любой Live LINUX, ориентированный на восстановление, но дело в том, что, редактируя диск напрямую, его легко испортить. Одно неверное движение руки — и гигабайты данных обращаются в прах.
При наличии свободного места рекомендуется создать копию раздела и все дальнейшие опыты проводить уже над ней. В мире Windows для этой цели требуются специальные утилиты (например Norton Ghost), которые, кстати говоря, стоят нехилых денег. Но BDS – совсем другое дело. Здесь все необходимое находится под рукой. Копию раздела проще всего создать командой cp /dev/ad0s1a dump, где ad0s1a – имя устройства, а dump — имя файла-дампа, для работы с которым сгодится любой hex-редактор (например, biew - http://biew.sourceforge.net).

[техника ручного восстановления файлов.]
Начнем с грустного. Поскольку при удалении файла ссылки на 12 первых блоков и 3 блока косвенной адресации необратимо затираются, автоматическое восстановление данных невозможно в принципе. Найти удаленный файл можно только по его содержимому. Искать, естественно, необходимо в свободном пространстве. Вот тут-то нам и пригодятся карты, расположенные за концом описателя группы цилиндров.
Если нам повезет, и файл окажется нефрагментированным (а на UFS, как уже отмечалось, фрагментация обычно отсутствует или крайне невелика), остальное будет делом техники. Просто выделяешь группу секторов и записываешь ее на диск, но только ни в коем случае не на сам восстанавливаемый раздел! К примеру, файл можно передать на соседнюю машину по сети. К сожалению, поле длины файла безжалостно затирается при его удалении, и актуальный размер приходится определять «на глазок». Звучит намного страшнее, чем выглядит. Неиспользуемый хвост последнего фрагмента всегда забивается нулями, что дает хороший ориентир. Проблема в том, что некоторые типы файлов содержат в своем конце некоторое количество нулей, при отсечении которых их работоспособность нарушается, поэтому тут приходится экспериментировать.
А если файл фрагментирован? Первые 13 блоков (именно блоков, а не фрагментов!) придется собирать руками. В идеале это будет один непрерывный регион. Хуже, если первый фрагмент расположен в «чужом» блоке (то есть блоке, частично занятом другим файлом), а оставшиеся 12 блоков находятся в одном или нескольких регионах. Вообще-то, достаточно трудно представить себе ситуацию, в которой первые 13 блоков были бы сильно фрагментированы (а поддержка фоновой дефрагментации в UFS на что?!). Такое может произойти только при интересной «перегруппировке» большого количеств файлов, что в реальной жизни практически никогда не встречается, разве только если ты задумал навести порядок на своем жестком диске smile.gif. Короче, будем считать, что 13-ый блок файла найден. В массив непосредственной адресации он уже не влезает (там содержатся только 12 блоков), и ссылка на него, как и на все последующие блоки файла, должна содержаться в блоках косвенной адресации, которые при удалении файла помечаются как свободные, но не затираются. Точнее затираются, но не сразу. Большинство файлов обходятся только одним косвенным блоком, что существенно упрощает нашу задачу.
Как найти этот блок на диске? Вычисляем смещение 13-го блока файла от начала группы цилиндров, переводим его в фрагменты, записываем получившееся число задом наперед (так, чтобы младшие байты располагались по меньшим адресам) и осуществляем контекстный поиск в свободном пространстве. Отличить блок косвенной адресации от всех остальных типов данных очень легко — он представляет собой массив указателей на блоки, а в конце идут нули. Остается только извлечь эти блоки с диска и записать их в файл, обрезая его по нужной длине. Внимание! Если ты нашел несколько «кандидатов» в блоки косвенной адресации, это означает, что 13-ый блок удаленного файла в разное время принадлежал различным файлам (а так, скорее всего, и будет). Не все косвенные блоки были затерты - вот ссылки и остались.
Как отличить «наш» блок от «чужих»? Если хотя бы одна из ссылок указывает на уже занятый блок данных (что легко определить по карте), такой блок можно сразу откинуть. Оставшиеся блоки перебираются вручную до получения работоспособной копии файла. Имя файла, если оно еще не затерто, можно извлечь из директории. Естественно, при восстановлении нескольких файлов ты не можешь однозначно сказать, какое из имен какому файлу принадлежит. Тем не менее, это все же лучше, чем совсем ничего. Директории восстанавливаются точно так же, как и обыкновенные файлы, хотя, по правде говоря, в них кроме имен файлов нечего восстанавливать...

[заключение.]
Описанный метод восстановления данных страдает кучей ограничений. В частности, при удалении большого количества сильно фрагментированных двоичных файлов, он говорит «пас» и уходит в кусты. Ты только убьешь свое время, но вряд ли найдешь среди обломков файловой системы что-то полезное. Но как бы там ни было, другого выхода просто нет (если, конечно, не считать резервной копии, которой тоже нет).
DanGer
Долго думал, куда же отнести стандарт файловой системы для *никс-систем. Благо, благодаря В.А.Костромину мы имеем возможность лицезреть этот самый стандарт в русском переводе. Сам документ занимает не одну страницу печатного документа (и веб-страниц тоже, кстати), потому я не привожу его текст здесь. А дам только линк. Всем, кто решил углубить свои знания в области *никс-архитектур и программистов для них же к чтению обязательно.
Стандарт на структуру каталогов файловой системы. (Filesystem Hierarchy Standard)
DanGer
Да уж... Много времени прошло с тех пор, как в последний раз обновлялась эта веточка форума. Сегодня я, наконец, нашел достаточно весомую и емкую информацию еще об одной файловой системе для *никс-подобных систем - XFS.

Оригинал статьи

Цитата
Большие файлы в Unix

Анатолий Ракалин
rtolik@yahoo.com

На прошлогодней выставке LinuxExpo компания SGI объявила о передаче своей технологии файловой системы с протоколированием XFS сообществу сторонников свободно распространяемых программ.

Данная файловая система долгое время оставалась одной из наиболее совершенных реализаций файловых систем для UNIX, решающих одну из основных проблем, ограничивавших распространение Linux в критически важных средах – отсутствие файловой системы с ведением журнала. Кроме того, XFS поддерживает все 64-разрядные функции для работы с файлами, что позволит масштабировать Linux для поддержки файловой системы, содержащей 18 млн. Тбайт данных и файлов размером до 9 млн. Тбайт. Данный шаг оказал существенное влияние на будущее Linux как платформы для приложений уровня предприятия. Любопытно посмотреть, как вообще в UNIX организована работа с большими файлами.

Файловая система XFS

Необходимость в масштабировании ОС и файловых систем возникла в конце 80-х, когда емкость дисков начала приближаться к 2 Гбайт – пределу существовавших тогда файловых систем и стало ясно, что в скором времени пользователям понадобятся новые системы, способные работать с большими файлами (таблица 1). Первыми на этот призыв откликнулись SGI и Digital Equipment, компании наиболее близко стоявшие тогда к корпоративным пользователям.

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

Масштабируемость. XFS может масштабироваться для удовлетворения требований к объему хранения и скорости операций ввода/вывода при доступе к памяти. Изначально XFS проектировалась для очень высоких уровней производительности, так что потоки свыше 300 Мбайт/с были продемонстрированы еще на системах CHALLENGE. Обычно, традиционные файлы, каталоги и файловые системы по мере роста обычно снижают производительность системы – файловая система XFS была спроектирована таким образом, что ее производительность не зависит от ее размера. Например, неизменная производительность была показана в тестах на XFS-каталогах емкостью до 32 миллионов файлов.

Поддержка больших файловых систем и больших файлов. XFS дает возможность управлять файловыми системами и отдельными файлами размером до 1 эксабайт (1018), то есть в миллионы раз больше, чем самые крупные из современных файловых систем. При этом обеспечивается совместимость с популярными 64-разрядными платформами. Например, версия от SGI сетевой файловой системы NFS 5.3 позволяет экспортировать 64-разрядные файловые системы в другие типы файловых систем. Можно использовать поставляемый с XFS интерфейс для работы с 32-разрядными программами, которые в результате могут работать с 64-разрядными позициями и размерами файлов. Используя комбинацию NFS и XFS можно плавно преодолеть ограничения 32-разрядных систем, а все существующее программное обеспечение будет работать без перекомпиляции с XFS-файлами размером до 2 Гбайт. Однако, для работы с файлами большего размера могут потребоваться некоторые изменения.

XFS позволяет создавать файловые системы с размером блока от 512 байт до 1 Мбайт. Пользователь может задавать конфигурацию экстентов (непрерывных данных) файла в момент его создания, за счет чего обеспечивается непрерывность записи данных на диск и увеличение скорости операций ввода/вывода. Как результат, нет задержек при доступе данных за счет перехода от одного экстента файла к другому. Максимальный размер одного экстента может достигать 1 Тбайт.

Управление большими каталогами с большим числом файлов. По мере роста размеров файловых систем, старый способ поиска файлов, предусматривающий линейный перебор, выполняется настолько медленно, что оказывается практически бесполезным. Для решения этой задачи в XFS включены большие каталоги, позволяющие динамически резервировать индексное пространство для файлов.

Программа управления томами XFS (менеджер XLV) является надстройкой над программой-менеджером логических томов и поддерживает стандартный набор операций для дискового массива RAID (striping, concatenation, mirroring). XLV «умеет» поддерживать «зеркальное» отображение корневого раздела (root partition). Кроме этого, XLV поддерживает «на лету» динамические изменения параметров томов, включая изменения размера монтированной файловой системы. XLV может использовать разделы диска для хранения разных типов файловых систем (XFS и EFS), а утилиты обеспечивают конвертирование логических томов без необходимости операций дампирования и восстановления данных.

Производительность на операциях ввода/вывода. Современные серверы используют большие распределенные дисковые массивы, способные обеспечивать совокупную полосу пропускания в сотни мегабайт в секунду. Ключевым моментом оптимизации производительности при работе с такими массивами становится требуемая мощность систем ввода/вывода и требуемая степень параллелизма операций ввода/вывода. Система XFS обеспечивает «гарантированную скорость операций ввода/вывода, что позволяет приложениям резервировать заданную пропускную способность файловой системы на ввод или вывод данных. Файловая система может определять наличную «пропускную способность» и гарантировать, что запрошенный уровень производительности может быть достигнут в заданное время. Это освобождает программистов от необходимости предсказывать производительность проектируемой системы, что особенно важно для таких систем, как пересылка видео по запросу или ввод данных.

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

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

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

Сегодня просто необходимо реализовать в Linux файловую технологию, позволяющую реализовывать корпоративные решения по хранению информации. Например, компания Caldera Systems постоянно получает от корпоративных потребителей запросы на подобные решения, особенно от компаний, работающих с графикой. Можно предположить, что подобное «вливание» в Linux значительно ускорит продвижение этой операционной системы на рынок больших корпоративных систем. По крайней мере, SGI сильно на это рассчитывает, если судить по тому, что в фирменных учебных центрах число предлагаемых курсов по Linux уже близко к числу курсов по собственной операционной системе IRIX.
Конкретная жизнь больших файлов на примере UnixWare

Сегодня считается дурным тоном не поддерживать в операционной системе работу с большими файлами, поэтому в описаниях Solaris, AIX и HP-UX также можно встретить указания на то, что эти системы работают с файлами до 1 Тбайт. Например, основная новая черта SCO UnixWare 7 – поддержка файлов размером почти 1 Тбайт (максимальный размер самой файловой системы установлен также на уровне 1 Тбайт).

Работа с большими файлами UnixWare возможна только в файловой системе vxfs, включаемой в момент создания файловой системы по команде

Код
# mkfs .... -o largefiles


Если нет уверенности в том, какого типа файловая система была создана, то можно для исследования этого вопроса использовать команду

Код
mkfs «-m»


Будет возвращена командная строка, которая использовалась для создания файловой системы. Аналогичным способом можно проверить, какая файловая система была создана при инсталляции операционной системы, например:

Код
# mkfs -F vxf -m


Если вы не использовали команду mkfs с флагом «о» или хотите модифицировать файловую систему позднее (система в этот момент должна быть размонтирована), используйте, например, команду:

Код
# fsadm -F vxfs -o largefiles
dev/rdsk/c0b0t0d0s1


Для работы с монтированной системой в дополнение к команде fsadm нужна специальная лицензия на использование расширенных возможностей (Advanced Feature License). Если же у вас такой лицензии нет, использование упомянутой команды вызывает сообщение, что данная опция поддерживается на версии 3 или более поздней.

Установив в системе параметр «largefiles», можно приступать к работе с большими файлами. Для этого можно воспользоваться специальным API-интерфейсом, не забыв включить соответствующие описания в тексты программ. Чтобы найти функции, не имеющие соответствующих деклараций, можно скомпилировать программу с флагом «-v»:

Код
cc -v ....prog.c


Если все декларации сделаны правильно, надо скомпилировать приложение с опцией, позволяющей переопределить некоторые функции ввода/вывода для работы с 64-разрядным интерфейсом вместо 32-разрядного, используемого по умолчанию:

Код
cc ...-D _FILE_OFFSET_BITS=64 ...


Следует отметить, что дескрипторы файлов (например, stdin, stderr и stdout), наследуемые из родительских процессов, должны быть открыты для работы с большими файлами.

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

Другие, менее очевидные, ограничения могут возникать при работе со следующими конструкциями:

Код
unsigned long l;
unsigned long long ll;
int ss=10;
ll = (l << ss);


Результатом операции (l << ss) являются старшие биты, которые будут отброшены, так как результат операции перед тем, как он будет присвоен переменной ll, сначала запоминается во временной 32-разрядной переменной. Данная проблема может быть решена следующим путем:

Код
ll = ((unsigned long long)l << ss);


Строка ll = (unsigned long long)(l << ss) не дает корректного решения, так как результат операции (l << ss) все еще запоминается во временной 32-разрядной переменной.

Можно также использовать флаг O_LARGEFILE при вызове функции open(), что обеспечит 64-разрядный доступ к файлу. Альтернативным решением является прямой вызов API-интерфейса, поддерживающего работу с большими файлами, вместо того, чтобы возлагать переименование функций на _FILE_OFFSET_BITS (подробную информацию можно получить по команде #man -k 64).

Ограничения на размер файла отменяются из командной строки

Код
ulimit -f unlimited,


хотя ksh будет сообщать о размере файла в 4194303 байт. Ограничения на размер файла могут быть проверены по команде

Код
ulimit -f


или

Код
getrlimit().


Чтобы работать с большими файловыми системами не требуется дополнительной настройки ядра операционной системы – внутренний параметр VXFS управляет поддержкой больших файлов. Существуют ограничения на размеры файла для пользователя, устанавливаемые командой idtune(). Если параметры SFSZLIM и HFSZLIM установлены на максимальное значение (0x7FFFFFFF, определяемое также как RLIM_INFINITY), пользователю разрешается создавать большие файлы. В противном случае, большие файлы может создавать только привилегированный пользователь (superuser).

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

1. Установить для файловой системы (например, vxfs) опции работы с большими файлами.
2. Установить ограничение на размер файла ulimit, указав параметр «бесконечность» (infinity).
3. Использовать 64-разрядные API-интерфейсы либо задавая _FILE_OFFSET_BITS=64, либо вызывая 64-разрядные функции, например open64().

Таблица 1. Развитие файловых систем UNIX
Код
Годы.............Файловая система
Начало 70-х......Файловая система Version 7
Начало 1980-х...."Быстрая" файловая система FFS (Berkeley)
Середина 80-х....Ранние журнальные файловые системы (Veritas/Tolerant/IBM JFS)
Середина 90-х....XFS


Самый простой способ сгенерировать большой файл в UnixWare

Имеются специальные программы для генерации файлов любого размера:

Код
/dev/zero – генерирует файл, содержащий одни нули.

/dev/byte/hex/ff – генерирует файл, содержащий одни единицы.


Для создания файла используется команда:

Код
dd if=/dev/ of=// bs=1024k count=


где

– имя одной из перечисленных программ генерации файлов.

// – имя создаваемого файла.

– размер файла в мегабайтах.

Например, 250-мегабайтный файл из одних единиц с именем bigfile.ff может быть создан по команде:

Код
dd if=/dev/byte/hex/ff of=/tmp/bigfile.ff

bs=1024k count=250


Спецификация файловой системы XFS

Технология поддержки файловой системы – журнальная 64-разрядная.

Максимальный размер файла – 9,223,372,036,854,775,807 байт (9 млн. Тбайт).

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

Размер блока – выбирается в момент создания файловой системы (с помощью команды mkfs_512) и может составлять от 512 до 64 Кбайт для обычных данных и до 1 Мбайт для данных в системах реального времени. Экстенты файловой системы могут конфигурироваться во время создания файла и кратны размеру блока файловой системы. Размер физического сектора на диске поддерживается с учетом совместимости с 512-байтными секторами NFS. 64-разрядные файловые системы могут быть экспортированы в другие системы, поддерживающие протокол NFS V3. Системы с протоколом NFS V2 могут получать доступ к XFS-файлам внутри 32-разрядных ограничений поддерживаемого протокола.

Резервное копирование/восстановление – утилиты Dump/restore, bru, cpio, tar; IRIS NetWorker для IRIX.

Совместимость дампов – можно восстанавливать как дампы XFS, так и дампы EFS с преобразованием типа файловой системы. Может быть создан дамп активной файловой системы XFS с учетом произошедших в ней изменений в процессе создания резервной копии. Поддерживается параллельное выполнение операций создания резервных копий и восстановления.

Поддержка иерархической памяти – интерфейс DMIG (Data Management API) позволяет применять программное обеспечение управления иерархическими системами хранения данных без модификации ядра системы.

Файлы подкачки (Swap) – поддерживаются.

Гарантированная скорость операций ввода/вывода – на аппаратном (при отключении самодиагностики дисков) и программном уровнях.

Производительность – более высокая по сравнению с EFS (свыше 500 Мбайт/с).

Дополнительные возможности – XFS обеспечивает гарантированную скорость операций ввода/вывода для четырех потоков и выше.

Файлы небольшого объема могут размещаться непосредственно в информационных узлах (inode), не занимая дополнительного пространства на диске.

Команды XFS:

* xfs_estimate – оценка объема дискового пространства, необходимого для размещения файловой системы XFS, в которую требуется преобразовать существующую файловую систему EFS;
* mkfs, mkfs_xfs – создание файловой системы XFS;
* xfs_check – проверка состояния файловой системы XFS;
* xfs_growfs – расширение существующей файловой системы XFS;
* xfsdump – дампирование файловой системы;
* xfsrestore восстановление файловой системы из дампа.

Файл-менеджер логических томов XLV

Поддерживаемая топология – запись с чередованием (stripping), зеркальное дублирование (mirroring), слияние физических томов (concatenation). Каждый том может состоять из трех подтомов: тома реального времени, тома журнала, тома данных. Для обеспечения максимальной производительности журнал файловой системы может храниться в одном разделе (partition), а сама файловая система XFS – в другом.

Максимальное число дисков на файловую систему – каждый том может иметь до четырех независимых зеркальных копий, при записи с чередованиями для обеспечения наивысшей производительности может использоваться до 128 томов, можно объединять в один логический том до 128 томов-экстентов. Другие ограничения могут быть обусловлены аппаратными возможностями оборудования.

Корневой раздел (root partition) может также иметь зеркальную копию. Запись с чередованием и объединение томов для ранних реализаций XLV не поддерживаются. Для раздела /usr и всех других, кроме корневого, такого ограничения нет.

Динамическое изменение – добавление или удаление зеркальной копии, увеличение размера тома, замена сбойного сегмента на зеркальной копии.

Специфика XLV – зеркальные копии томов, запись с чередованием и логическое объединение томов поддерживаются базовым программным обеспечением.
Команды XLV:

* lv_make – создание нового логического тома, приписывая метки логического тома входящим в него устройствам;
* lv_to_xlv – грамматический разбор файла, описывающего логические тома, используемые локальными машинами, генерация необходимых команд;
* xlv_assemble – сканирование всех дисков локальной системы с целью поиска меток логических томов и сбора всех логических томов для генерации новой конфигурации структуры данных;
* xlv_labd – установка логических томов для дисков;
* xlv_plexed – создание «зеркальных» томов;
* xlvd – обработка ввода/вывода на «зеркальных томах и выполнение восстановления данных в случае возникновения ошибок;
* xlv_admin – модификация объектов файловой системы XLV (тома, «зеркальные» копии, элементы томов, метки логических дисков XLV).

Ограничения

* Чувствительность к аппаратным ошибкам при работе без использования зеркальных копий.
* Еще не реализовано квотирование дисков – индивидуальных ограничений для пользователя на дисковое пространство.

Установка XFS

1. Установить операционную систему с поддержкой XFS, сделать дампы всех существующих файловых систем.
2. Назначить зеркальные тома XFS, выбрать размеры блоков, выбрать размер и тип журнала XFS.
3. Выполнить проверки на наличие адекватного свободного пространства на физических носителях.
4. Выполнить разбиение дисков на разделы.
5. Создать новую файловую систему XFS с использованием команды
6. mkfs_xfs.
7. Восстановить необходимые данные из дампа с преобразованием их в файловые системы XFS.
8. Перезагрузить компьютер и получить удовольствие от работы с XFS.
DanGer
Странно выглядит структура данного раздела, но все же... Предлагаю прочитать (и осмыслить) статью (одна из целого цикла) Дрю Лавинь про файловую систему UNIX. Сразу скажу, что статья для начинающих. Но, как говорится: повторенье - мать ученья.
Цитата
Введение в файловые системы UNIX


Dru Lavigne
перевод Станислава Лапшанского
Впервые опубликован: http://www.computerra.ru.

21 июня 2005 г

Оригинал статьи находится по адресу: Understanding Unix Filesystems.

В первой статье цикла мы рассматривали содержимое BIOS'овской и UNIX'овой таблиц разделов при помощи, соответственно, утилит fdisk и disklabel. В этой статье мы продолжим разговор и рассмотрим использование утилиты newfs, а так же поговорим об индексных таблицах.

Программа newfs занимается форматированием вашего слайса в файловую систему, которую вы указали перед этим утилитой disklabel. Давайте начнем с того, что разберемся, что из себя представляют форматирование и файловые системы вообще, для того что бы впоследствии лучше представлять, что делает утилита newfs.

Существуют два способа форматирования жестких дисков. Когда вы приобретаете новый жесткий диск, то, в большинстве случаев, он поставляется уже отформатированным на низком уровне (low level format). При помощи низкоуровневого форматирования на диске создаются треки и сектора, в паре они создают пространство адресуемых физических блоков по 512 байт.

Вторым способом форматирования, как нетрудно догадаться, является высокоуровневое (high level) форматирование. Во время такого форматирования при помощи таких утилит как format (в системе DOS) или newfs (в системе FreeBSD), на разделе жесткого диска как раз и создается определенная файловая система. Примерами файловых систем могут служить FAT16, FAT32, NTFS и FFS. Разные файловые системы могут отличаться по целому ряду показателей – например по производительности, однако, как минимум две функции совпадают у всех файловых систем: Каждая файловая система имеет таблицу для отображения файлов с данными пользователя на физические блоки винчестера. Файловая система может использовать свою «логическую» адресацию блоков, для того что бы пытаться оптимизировать производительность запросов ввода-вывода.

Давайте представим, что вы являетесь файловой системой. Ваша цель – быстро сохранять (записать) и находить (читать) данные. На вас действуют следующие ограничения:

1. Вы имеете доступ к площади, называемой цилиндром.
2. Ваш цилиндр имеет 255 горизонтальных строк (треки) и 63 вертикальных столбцов, которые называются секторами.
3. На пересечении этих строк находятся блоки, в которых вы можете сохранять по 512 байт данных.

Итак, подсчитаем, какое количество блоков содержится на цилиндре:

Код
255 * 63 = 16,065


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

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

К сожалению, простота приводит к крайне нерациональному использованию дискового пространства. Дело в том, что запись файлов в 512 байтные блоки приводит к отличным результатам, когда все файлы имеют размеры 512 байт. Однако жизненный опыт подсказывает нам, что файлы имеют самые разнообразные размеры, от нескольких байт до сотен мегабайт.

Поставьте себя на место файловой системы и подумайте, как вы запишете файл размером 10 байт. Если просто поместить этот файл в блок жесткого диска, то вы потеряете 412 байт полезного пространства. Сохранив большое количество маленьких файлов, вы отправите в мусор целую кучу свободного места. Что произойдет, если вы запишете на диск 16065 файлов размером 1 байт? Вы используете все имеющиеся у вас блоки жесткого диска, записав всего 16065 байт полезных данных. Несмотря на несколькомегабайтный размер цилиндра на вашем жестком диске, вы не сможете найти ни одного свободного блока для ваших файлов. Это так называемая ситуация отсутствия индексных элементов (или отсутствия места в индексной таблице, что тоже самое). Очевидно, что возникновение такой ситуации в реальных условиях крайне нежелательно.

Продолжая думать как файловая система, можно придти к выводу, что имеет смысл не отдавать целый блок для одного маленького файла. Однако, сейчас самое время подумать, каким образом вы организуете вашу таблицу в условиях того, что в одном блоке может быть более одного файла. Если вы просто начнете набивать в блок столько файлов, сколько можно разместить в 512 байтах, то каким образом вы будете отслеживать, где заканчивается один файл и начинается другой? Что будет, если вы удалите файл размером 10 байт, а на его место запишите файл размером 8 байт и куда вы запишите информацию об оставшихся 2 байтах в случае, если вы захотите записать туда два однобайтовых файла? Сразу видно, что подобная схема быстро теряет работоспособность.

Большинство файловых систем пользуются концепцией фрагментации. Фрагмент - это логическая часть блока. Каждый фрагмент может быть адресован, т.е. о нем может быть сделана запись в индексной таблице. Например, файловая система может разбивать каждый блок на четыре фрагмента. Таким образом, количество доступных блоков умножается на четыре, одновременно уменьшая их размер в четыре раза. Например если изначально было доступно 16065 блоков, по 512 байт в каждом, то после такой фрагментации их количество возрастет до 64260, при размере блока 128 байт. Каждый фрагмент может интерпретироваться как блок для хранения данных и, таким образом, может содержать один файл, следовательно, теперь в индексной таблице 64260 элементов и при этом нет необходимости беспокоиться о том, как отслеживать несколько файлов в одном логическом блоке.

Давайте посмотрим, что у нас находится на другой чаше весов. Что произойдет, если вам понадобится записывать файлы, размер которых больше, чем размер физического или логического блока данных? Для сохранения на диске такого файла, вам, разумеется, придется задействовать более одного блока данных. Предположим, что вы хотите сохранить файл объемом 1000 байт. Для этого потребуются два физических блока по 512 байт, и, соответственно, в вашей индексной таблице будут две записи. Вам также придется подумать над тем, как вносить туда эти записи, поскольку теперь важен порядок их внесения. В данной ситуации недостаточно просто знать, что файл находится, скажем, в блоках 3 и 4. Вам обязательно надо быть уверенными, что первые 512 байт файла находятся именно в блоке номер три, а остальное в четвертом блоке.

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

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

Давайте суммируем все то, о чем мы говорили, обсуждая файловую систему:

1. Она представляет собой конечное количество блоков для хранения данных, которые связаны с адресуемым списком, который в файловых системах для операционных систем UNIX имеет название «индексная таблица».
2. Если вы исчерпываете число элементов этой таблицы и, тем самым, число доступных блоков данных, то вы не можете создавать новые файлы, несмотря на то, сколько свободного места на вашем диске.
3. Если вы предполагаете сохранение большого количества маленьких файлов, вам необходимо фрагментировать блоки данных, для того чтобы увеличить размер индексной таблицы.
4. Однако, если вы хотите увеличить производительность операции чтения, вам необходимо увеличить размер логического блока данных, для того, чтобы за одну операцию чтения в память считывалось больше данных.

Теперь давайте поглядим, как все вышеизложенное применимо к FreeBSD. Когда вы пользуйтесь утилитой newfs, вы форматируете ваш слайс в файловую систему FFS (Berkeley Fast File System – быстрая файловая система Беркли). Давайте посмотрим кусочки из страницы руководства по утилите newfs, для того, чтобы узнать, какие установки «по умолчанию» предусмотрены для этой файловой системы:

Код
man 8 newfs


Нас интересуют только некоторые ключи. Начнем с ключа «-b»:

Код
-b размер_блока


Указывает размер блока в файловой системе в байтах. Он должен быть степенью числа 2. По умолчанию размер 8192 байта. Наименьший возможный размер 4096 байтов.

Обратите внимание, что это размер блока файловой системы. Физический блок всегда имеет размер 512 байтов. 8192 байта - это на самом деле 16 физических блоков. Таким образом, этот параметр задает размер логического блока, т.е. какой объем данных будет считан в оперативную память за один раз. Помните, что этот параметр создан для увеличения скорости чтения и является одной из причин, почему в названии файловой системы FreeBSD присутствует слово «быстрый».

Ключ «-f»:

Код
-f размер_фрагмента


Указывает размер фрагмента файловой системы в байтах. Значение должно лежать в пределах от размер_блока/8 до размер_блока и быть степенью числа 2. По умолчанию используется размер 1024 байта.

FFS использует фрагментирование, однако фрагментируется логический, а не физический блок. По умолчанию размер фрагмента равен двум физическим блокам.

Теперь рассмотрим ключ «-i»:

Код
-i количество_байт_на_элемент_индексной_таблицы


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

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

Вот еще два параметра, о которых следует здесь упомянуть, поскольку они влияют на производительность операции чтения/записи файловой системы FFS. Во-первых, ключ -m:

Код
-m свободное_место %


Процент свободного места, резервируемого на файловой системе, т.е. порог минимального свободного пространства. Значение по умолчанию, определяется константой MINFREE модуля <ufs/ffs/fs.h>>. В настоящее время это значение равно 8%. Читайте man 8 tunefs для полного описания этого параметра.

Производительность любой файловой системы начинает «проседать», когда ей не хватает свободных блоков для хранения данных. Дело в том, что файловые системы «предпочитают» сохранять файлы одного каталога в смежных блоках (т.е. рядом друг с другом), а это становится затруднительным, когда количество свободных блоков уменьшается и системе приходится тратить время на их поиск. Создатели FFS указывают, что ее производительность резко падает, когда диск заполняется на более чем 90%. Когда файловая система достигает порога, установленного для объема свободного места (по умолчанию 8%), для обычных пользователей происходит блокирование записи любых файлов. Пользователи будут получать сообщения об ошибке, и, вероятно, напомнят администратору о сложившейся ситуации. Суперпользователь сохраняет возможность записи информации на диск и использования оставшихся свободными блоков, однако в этот момент лучше заняться разработкой плана спасения файловой системы, а не дожидаться, пока на ней кончится место.

Теперь давайте разберемся со вторым ключом, имеющим дело со свободным местом:

Код
-o способ_оптимизации


Варианты – «space» и «time». Файловая система может либо пытаться уменьшить время, необходимое для выделения блоков данных, либо попробовать минимизировать фрагментацию дискового пространства. Если значение параметра minfree (см. выше) меньше 8%, то по умолчанию принимается оптимизация по фрагментации (space), а если больше или равно 8%, файловая система пытается оптимизировать время доступа (time). Для полного описания этого параметра почитайте man 8 tunefs.

Большинство файловых систем используют специальные алгоритмы для того, чтобы определить, какие файлы должны занимать какие блоки на диске. Этот ключ используется для определения, какой стратегии оптимизации должен придерживаться алгоритм FFS для размещения файлов. В ситуации достатка свободного дискового пространства можно использовать оптимизацию по скорости (time). Однако когда объем свободного места на диске переходит предел, определяемый ключом «-m», оптимизация фрагментации (space) становится более важной задачей, чем скорость.

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

Сейчас вы вероятно уже узнали о файловых системах больше, чем допускали в начале статьи, поэтому давайте остановимся. В следующей части цикла мы рассмотрим группы цилиндров, суперблоки, а так же реальное содержимое записей индексной таблицы.
DanGer
Ну не мог я не привести здесь следующюю статью Дрю Лавинь про "группы цилиндров, суперблоки, а так же реальное содержимое записей индексной таблицы". Посему, прошу лю... читать и вникать. Авось пригодится wink.gif
Цитата
Введение в индексные таблицы файловых систем


Dru Lavigne
перевод Станислава Лапшанского
Впервые опубликован: http://www.computerra.ru.

21 июня 2005 г

Оригинал статьи находится по адресу: http://www.onlamp.com/pub/a/bsd/2001/03/07...BSD_Basics.html.

В первых двух частях мы рассматривали структуру таблицы разделов и файловой системы. Мы узнали, что компьютер находит слайс FreeBSD при помощи информации, содержащейся в BIOS'овской таблице разделов. Слайс FreeBSD, в свою очередь, содержит UNIX'овую таблицу разделов, в которой записана «разметка диска». Она описывает расположение файловых систем на слайсе. В этой статье мы, наконец, сможем рассмотреть элементы индексной таблицы (inodes), что они из себя представляют и какую информацию о них может предоставить FreeBSD.

Давайте рассмотрим вывод программы disklabel, запущенной на одной из моих машин. Я немного обрезала вывод так, что бы была видна только информация о разделах:
Код
disklabel ad0
<вырезано>

8 partitions:
# size offset fstype [fsize bsize bps/cpg]
a: 102400 0 4.2BSD 0 0 0 # (Cyl. 0 - 6*)
b: 270976 102400 swap # (Cyl. 6*- 23*)
c: 6538455 0 unused 0 0 # (Cyl. 0 - 406)
e: 40960 373376 4.2BSD 0 0 0 # (Cyl. 23*- 25*)
f: 6124119 414336 4.2BSD 0 0 0 # (Cyl. 25*- 406*)


Обратите внимание, что тип файловой системы, в которой отформатированы разделы «a», «e» и «f» – «4.2BSD», этой аббревиатурой обозначается Berkeley fast file system (FFS – быстрая файловая система Беркли). Следует обратить внимание на то, что каждый раздел определен интервалом принадлежащих ему цилиндров. Видно, что раздел «a» использует цилиндры 0-6, раздел «e» размещается на цилиндрах 23-25, и, наконец, раздел «f» занимает 25-406 цилиндры. Символом «*» обозначаются разделы, начало или конец которых не выровнены по границе цилиндра.

Что же такое цилиндр? Если вы не слишком хорошо знаете как работает жесткий диск, то вас может заинтересовать эта статья (и имеющиеся в ней картинки).

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

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

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

* Каждая файловая система отвечает за одну группу цилиндров.
* Группа цилиндров может иметь только одну индексную таблицу.

Любой раздел, содержащий файловую систему, разделен на три части:

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

В суперблоке записаны параметры файловой системы, такие как количество блоков, их размер, размер фрагмента, а так же количество записей в индексной таблице. (Если вам любопытно, что еще хранится в суперблоке, прочитайте страницу руководства man 5 fs.) Эти параметры были определены в команде newfs, при помощи ключей, которые вы задали при создании файловой системы. Это означает, что если по прошествии некоторого времени вы обнаружите, что на файловой системе заканчиваются записи индексной таблицы или свободные блоки, то для смены этих параметров вам придется заново пересоздать всю файловую систему. Перед этим создайте и протестируйте резервную копию ваших данных, поскольку утилита newfs уничтожит все данные, содержащиеся на разделе.

За суперблоком размещается индексная таблица, содержащая записи обо всех данных находящихся на разделе. Каждая запись в таблице занимает 128 байт и содержит информацию о соответствующем файле. Это так называемые метаданные. Вы можете сами посмотреть, что содержат эти метаданные, заглянув в файл /usr/include/ufs/ufs/dinode.h. Несмотря на то, что этот файл на языке Си, он хорошо прокомментирован и его легко прочитать. Вот что хранится в каждой из записей:

* права доступа к файлу
* количество ссылок на файл
* номер записи в индексной таблице
* размер файла в байтах
* время последнего обращения к файлу (atime)
* время последнего изменения файла (mtime)
* время последнего изменения записи о файле в индексной таблице (ctime)
* ссылка на прямые дисковые блоки
* ссылка на косвенные дисковые блоки
* флаги статуса (chflags)
* количество реально занятых блоков
* генерация файла
* владелец файла
* группа владельцев файла

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

Немало метаданных вы сможете посмотреть при помощи «длинного» формата просмотра содержимого каталога. Давайте посмотрим вывод содержимого корневого каталога в «длинном» формате, при помощи команды ls -l:

ls -l /

Код
total 6429
-r--r--r-- 1 root wheel 4735 Nov 20 07:03 COPYRIGHT
drwxr-xr-x 2 root wheel 1024 Dec 21 19:09 bin
drwxr-xr-x 3 root wheel 512 Dec 21 12:27 boot
drwxr-xr-x 2 root wheel 512 Dec 21 10:19 cdrom
lrwxr-xr-x 1 root wheel 11 Dec 21 12:27 compat -> /usr/compat
drwxr-xr-x 3 root wheel 13824 Feb 25 09:15 dev
drwxr-xr-x 15 root wheel 2048 Dec 22 18:20 etc
drwxr-xr-x 1 root wheel 7168 Jan 1 1980 floppy
lrwxrwxrwx 1 root wheel 9 Dec 21 12:29 home -> /usr/home
-r-xr-xr-x 1 root wheel 3258128 Nov 20 08:02 kernel
-r-xr-xr-x 1 root wheel 3258128 Nov 20 08:02 kernel.GENERIC
drwxr-xr-x 2 root wheel 512 Nov 20 06:56 mnt
drwxr-xr-x 2 root wheel 2560 Dec 21 10:33 modules
dr-xr-xr-x 1 root wheel 512 Feb 25 10:32 proc
drwxr-xr-x 2 root wheel 512 Dec 23 08:30 root
drwxr-xr-x 2 root wheel 2048 Dec 21 19:09 sbin
drwxr-xr-x 4 root wheel 1024 Dec 21 10:19 stand
lrwxrwxrwx 1 root wheel 11 Dec 21 12:22 sys -> usr/src/sys
drwxrwxrwt 2 root wheel 512 Feb 25 09:15 tmp
drwxr-xr-x 19 root wheel 512 Feb 11 19:04 usr
drwxr-xr-x 18 root wheel 512 Nov 20 08:13 var


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

* права доступа к файлу
* количество ссылок на файл
* владелец
* группа владельцев
* размер в байтах
* время последнего изменения файла
* имя файла

Первые шесть столбцов отражают содержимое метаданных в соответствующих элементах индексной таблицы.

Если необходимо, вы можете посмотреть номер элемента индексной таблицы для каждого файла, добавив в команду ls ключ «i»:

ls -li /

Код
total 6429
441 -r--r--r-- 1 root wheel 4735 Nov 20 07:03 COPYRIGHT
46 drwxr-xr-x 2 root wheel 1024 Dec 21 19:09 bin
6323 drwxr-xr-x 3 root wheel 512 Dec 21 12:27 boot
44 drwxr-xr-x 2 root wheel 512 Dec 21 10:19 cdrom
444 lrwxr-xr-x 1 root wheel 11 Dec 21 12:27 compat -> /usr/compat
6272 drwxr-xr-x 3 root wheel 13824 Feb 25 09:15 dev
36 drwxr-xr-x 15 root wheel 2048 Dec 22 18:20 etc
236 drwxr-xr-x 1 root wheel 7168 Jan 1 1980 floppy
451 lrwxrwxrwx 1 root wheel 9 Dec 21 12:29 home -> /usr/home
443 -r-xr-xr-x 1 root wheel 3258128 Nov 20 08:02 kernel
442 -r-xr-xr-x 1 root wheel 3258128 Nov 20 08:02 kernel.GENERIC
241 drwxr-xr-x 2 root wheel 512 Nov 20 06:56 mnt
242 drwxr-xr-x 2 root wheel 2560 Dec 21 10:33 modules
2 dr-xr-xr-x 1 root wheel 512 Feb 25 10:32 proc
358 drwxr-xr-x 2 root wheel 512 Dec 23 08:30 root
363 drwxr-xr-x 2 root wheel 2048 Dec 21 19:09 sbin
5 drwxr-xr-x 4 root wheel 1024 Dec 21 10:19 stand
440 lrwxrwxrwx 1 root wheel 11 Dec 21 12:22 sys -> usr/src/sys
2 drwxrwxrwt 2 root wheel 512 Feb 25 09:15 tmp
2 drwxr-xr-x 19 root wheel 512 Feb 11 19:04 usr
2 drwxr-xr-x 18 root wheel 512 Nov 20 08:13 var


Обратите внимание – в листинге появился новый столбец. Число в первом столбце как раз и является номером элемента в индексной таблице для этого файла. Элемент номер 2 встречается несколько раз: он присутствует в строках proc, tmp, usr и var. Элемент с номером 2 всегда является первым в файловой системе и отражает корневую (стартовую) точку файловой системы. Список смонтированных файловых систем мы можем посмотреть при помощи команды df:

df
Код
Filesystem 1K-blocks Used Avail Capacity Mounted on
/dev/ad0s2a 49583 27729 17888 61% /
/dev/ad0s2f 2967289 737169 1992737 27% /usr
/dev/ad0s2e 19815 3647 14583 20% /var
procfs 4 4 0 100% /proc
mfs:27 131231 1 120732 0% /tmp


Мы видим ожидаемую картину – usr, var, proc и tmp являются смонтированными файловыми системами. Не забывайте, что каждая файловая система имеет свою индексную таблицу, поэтому элемент номер 2 для системы usr является записью совсем другой таблицы, чем, например, элемент номер 2 в системе var. Их сходство заканчивается только номером, а так же тем, что оба они являются корневыми элементами для соответствующих файловых систем.

В утилите df (disk free) имеется ключ, который позволяет вам узнать, сколько всего элементов в индексной таблице конкретной файловой системы. Давайте еще раз выполним команду df, теперь с ключом «-i»:

df -i

Код
Filesystem 1K-blocks Used Avail Capacity iused ifree %iused Mounted on
/dev/ad0s2a 49583 27729 17888 61% 1074 11468 9% /
/dev/ad0s2f 2967289 739993 1989913 27% 90852 655130 12% /usr
/dev/ad0s2e 19815 3645 14585 20% 391 4663 8% /var
procfs 4 4 0 100% 25 507 5% /proc
mfs:27 131231 1 120732 0% 1 33277 0% /tmp


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

Напоследок я упомяну о mtime, atime, and ctime, параметрах, в которых содержится различная информация, связанная со временем.

Параметр «mtime» отражает время последнего изменения файла. Оно показывает, когда в последний раз изменялось содержимое файла. Например, если вы откроете файл в вашем текстовом редакторе и добавите или удалите несколько строк, тем самым вы измените содержимое файла. Параметр «mtime» поменяется, в момент сохранения файла на диск. Запомните, что команда «ls -l» показывает именно «mtime».

Параметр «atime» показывает, когда к файлу последний раз обращались. Например, если вы просматриваете файл при помощи команды more, вы осуществляете доступ к файлу, тем самым изменяя параметр «atime». Для того, чтобы посмотреть параметр «mtime», вместо стандартного «atime», используйте команду ls с ключами «-lut»:

ls -lut /

Код
total 6429
dr-xr-xr-x 1 root wheel 512 Feb 26 14:06 proc
drwxr-xr-x 2 root wheel 1024 Feb 26 14:03 bin
drwxr-xr-x 2 root wheel 2048 Feb 26 14:03 sbin
drwxr-xr-x 3 root wheel 13824 Feb 26 13:54 dev
drwxrwxrwt 2 root wheel 512 Feb 26 13:54 tmp
drwxr-xr-x 19 root wheel 512 Feb 25 14:02 usr
drwxr-xr-x 18 root wheel 512 Feb 20 02:01 var
drwxr-xr-x 2 root wheel 512 Feb 20 01:59 root
drwxr-xr-x 4 root wheel 1024 Feb 20 01:59 stand
drwxr-xr-x 15 root wheel 2048 Feb 20 01:59 etc
drwxr-xr-x 2 root wheel 512 Feb 20 01:59 cdrom
drwxr-xr-x 3 root wheel 512 Feb 20 01:59 boot
drwxr-xr-x 2 root wheel 512 Feb 20 01:59 mnt
drwxr-xr-x 2 root wheel 2560 Feb 20 01:59 modules
lrwxrwxrwx 1 root wheel 9 Dec 21 12:29 home -> /usr/home
lrwxr-xr-x 1 root wheel 11 Dec 21 12:27 compat -> /usr/compat
lrwxrwxrwx 1 root wheel 11 Dec 21 12:22 sys -> usr/src/sys
-r-xr-xr-x 1 root wheel 3258128 Nov 20 08:02 kernel
-r-xr-xr-x 1 root wheel 3258128 Nov 20 08:02 kernel.GENERIC
-r--r--r-- 1 root wheel 4735 Nov 20 07:03 COPYRIGHT
drwxr-xr-x 1 root wheel 7168 Jan 1 1980 floppy


Параметр «ctime» обновляется каждый раз, когда меняются данные в самом элементе индексной таблицы. Например, если вы изменяете права доступа, владельца или группу владельца, то этим самым вы изменяете содержимое записи в индексной таблице, а также параметр «ctime». Значение «ctime» можно узнать при помощи ключей «-lc» команды ls:

ls -lc /

Код
total 6429
-r--r--r-- 1 root wheel 4735 Dec 21 12:22 COPYRIGHT
drwxr-xr-x 2 root wheel 1024 Dec 21 19:09 bin
drwxr-xr-x 3 root wheel 512 Dec 21 12:27 boot
drwxr-xr-x 2 root wheel 512 Dec 21 10:19 cdrom
lrwxr-xr-x 1 root wheel 11 Dec 21 12:27 compat -> /usr/compat
drwxr-xr-x 3 root wheel 13824 Feb 26 13:54 dev
drwxr-xr-x 15 root wheel 2048 Dec 22 18:20 etc
drwxr-xr-x 1 root wheel 7168 Jan 1 1980 floppy
lrwxrwxrwx 1 root wheel 9 Dec 21 12:29 home -> /usr/home
-r-xr-xr-x 1 root wheel 3258128 Dec 21 12:27 kernel
-r-xr-xr-x 1 root wheel 3258128 Feb 11 19:04 kernel.GENERIC
drwxr-xr-x 2 root wheel 512 Dec 21 10:27 mnt
drwxr-xr-x 2 root wheel 2560 Dec 21 10:33 modules
dr-xr-xr-x 1 root wheel 512 Feb 26 14:07 proc
drwxr-xr-x 2 root wheel 512 Dec 23 08:30 root
drwxr-xr-x 2 root wheel 2048 Dec 21 19:09 sbin
drwxr-xr-x 4 root wheel 1024 Dec 21 10:19 stand
lrwxrwxrwx 1 root wheel 11 Dec 21 12:22 sys -> usr/src/sys
drwxrwxrwt 2 root wheel 512 Feb 26 13:54 tmp
drwxr-xr-x 19 root wheel 512 Feb 11 19:04 usr
drwxr-xr-x 18 root wheel 512 Dec 21 19:15 var


Если вы внимательно посмотрите на эти три листинга команды ls, то, несомненно, увидите, что указанное время на них различно, поскольку они отражают значение трех различных параметров.
Русская версия IP.Board © 2001-2012 IPS, Inc.