Файлові системи
Навіщо це
Section titled “Навіщо це”Файлова система — найдовговічніша абстракція в операційних системах. Вона перетворює нумерований масив блоків (модуль 14) на дерево імен, яким користуються і люди, і програми.
Практичних питань, відповіді на які лежать тут, чимало. Чому видалений
файл не звільнив місце? Чому du і df показують різне? Чому копіювання
мільйона дрібних файлів у сотні разів повільніше за копіювання одного
великого такого самого розміру? Чому контейнер запускається миттєво,
хоча образ важить гігабайт?
Передумови. Блочні пристрої (модуль 14), дескриптори файлів (модуль 6), кеш сторінок (модуль 13).
У системі одночасно працюють ext4 на диску, tmpfs у пам’яті, NFS по мережі й procfs узагалі без сховища. А програма звертається до всіх них однаково.
Віртуальна файлова система — це рівень усередині ядра, який визначає
спільний інтерфейс: відкрити, прочитати, записати, отримати атрибути.
Кожна конкретна файлова система реалізує ці операції по-своєму, а read()
лишається тим самим.
Прийом той самий, що й з драйверами: єдиний інтерфейс зверху, різні
реалізації знизу. Завдяки VFS /proc і виглядає як файли, ними не будучи
(модуль 6).
В inode зберігається все про файл: тип, права, власник, розмір, часові позначки, лічильник посилань і розташування даних. Ідентифікують його номером у межах файлової системи.
Прямі вказівники дають доступ до початку файлу за одне звернення, а більшість файлів якраз маленькі. Великі платять додатковими зверненнями за непрямі рівні. Схема несиметрична навмисно, бо оптимізує поширений випадок.
Каталог є файлом, який містить пари «ім’я → номер inode». Звідси випливає все інше:
- Жорстке посилання — це ще одна така пара, що вказує на той самий inode. Не копія й не ярлик, обидва імені абсолютно рівноправні. Файл існує доти, доки лічильник посилань не впаде до нуля.
- Символьне посилання є окремим файлом, який містить шлях у вигляді тексту. Воно може вказувати в нікуди й може перетинати межі файлових систем.
- Права на видалення файлу належать каталогу, а не самому файлу. Тому цілком можна видалити файл, у який не маєш права записати.
Розподіл блоків
Section titled “Розподіл блоків”Як узагалі записати, де саме лежать дані файлу?
Список блоків, тобто класичний inode, добре працює для малих файлів і роздувається для великих: файлу на 10 ГіБ знадобляться мільйони записів.
Екстенти замість цього зберігають діапазон: початок і 20 000 блоків підряд. Один запис замість тисяч. Так працюють ext4, XFS і NTFS. Платимо тим, що фрагментований файл цю перевагу втрачає, бо діапазонів стає багато.
Дерева з копіюванням під час запису, як у btrfs і ZFS, не змінюють блок на місці: новий вміст пишеться в нове місце, а вказівники оновлюються знизу вгору. Звідси й майже безкоштовні знімки, бо старі блоки просто лишаються де були.
Журналювання
Section titled “Журналювання”Запис файлу складається з кількох операцій: змінити inode, позначити блоки зайнятими, дописати запис у каталог, записати самі дані. Якщо живлення зникне посередині, файлова система лишиться в суперечливому стані — блоки позначені зайнятими, а посилається на них ніхто.
Перевіряти після кожного збою всю файлову систему неприйнятно, бо на багатотерабайтному томі це години.
Журнал розв’язує задачу так: спершу записати намір у журнал, а вже потім виконати. Після збою досить прочитати журнал і або доробити операції, які встигли записатися повністю, або відкинути незавершені.
Режими журналювання відрізняються тим, що саме в цей журнал потрапляє:
| Режим | У журналі | Наслідок |
|---|---|---|
writeback |
лише метадані | найшвидший; після збою метадані цілі, а вміст файлу може бути сміттям |
ordered |
метадані, але дані пишуться першими | типовий для ext4: розумний баланс |
journal |
і метадані, і дані | найнадійніший, усе пишеться двічі |
Сучасні файлові системи
Section titled “Сучасні файлові системи”ext4 стоїть за замовчуванням у більшості дистрибутивів. Екстенти, журналювання, передбачувана поведінка. Знімків і контрольних сум даних не вміє.
XFS орієнтована на великі файли й високий паралелізм, типова для RHEL. Розширювати її можна, а зменшувати ні.
btrfs дає копіювання під час запису, знімки, контрольні суми даних, вбудований RAID, стиснення й підтоми.
ZFS робить те саме плюс бере на себе керування томами: файлова система й менеджер томів в одному. Історично сильна саме цілісністю даних.
Найважливіше в двох останніх — контрольні суми даних. ext4 і XFS перевіряють метадані, але не вміст, тож тихе пошкодження блока лишиться непоміченим. btrfs і ZFS його помітять, а за наявності надлишковості ще й виправлять.
overlayfs і FUSE
Section titled “overlayfs і FUSE”overlayfs об’єднує кілька каталогів в один: нижні доступні тільки для читання, верхній для запису. Запис у файл із нижнього рівня спричиняє копіювання цього файлу нагору.
На цьому й побудовані контейнери (модуль 17): шари образу лежать нижніми рівнями, спільними для всіх контейнерів, а зміни конкретного контейнера потрапляють у верхній. Тому контейнер із гігабайтного образу запускається миттєво й майже не займає місця — нічого не копіюється, поки нічого не змінюється.
FUSE дозволяє реалізувати файлову систему звичайною програмою в режимі
користувача. Працює вона повільніше за ядерну через перетини межі
(модуль 3), зате помилка не валить систему. Так зроблені
sshfs, монтування хмарних сховищ і більшість експериментальних ФС.
Права доступу
Section titled “Права доступу”Класична модель Unix має три набори прав — для власника, групи й решти —
по три біти r, w, x у кожному.
Для каталогу ці біти означають зовсім не те, що для файлу. r дозволяє
читати список імен, w — створювати й видаляти записи, x — заходити
всередину й звертатися до вмісту за іменем. Каталог із r, але без x
дасть побачити імена й нічого з ними не зробити.
Є ще особливі біти. setuid змушує програму виконуватися від імені
власника файлу, і саме так працює passwd. setgid робить те саме
з групою. sticky у каталозі /tmp дозволяє видаляти файл лише
його власникові.
ACL дають те, чого модель із трьох наборів не вміщає: окремі права
конкретним користувачам. Наявність ACL видно за + у виводі ls -l.
Як це насправді в Linux
Section titled “Як це насправді в Linux”stat /etc/hostnameУсе, що лежить в inode: номер, розмір, кількість блоків, права, лічильник посилань і три часові позначки.
df -h /; df -i /Зайнятість у байтах і в inode окремо. Місце може скінчитися за inode при вільних терабайтах — класична ситуація на файловій системі з мільйонами дрібних файлів.
du -sh /var/log 2>/dev/null; df -h /vardu рахує те, на що є імена; df — реально зайняте. Різниця —
це видалені, але ще відкриті файли.
sudo lsof +L1 2>/dev/null | headФайли з нульовим лічильником посилань, які досі відкриті. Саме вони пояснюють, куди зникло місце після видалення журналів.
echo test > /tmp/a; ln /tmp/a /tmp/b; ln -s /tmp/a /tmp/cstat -c '%i %h %n' /tmp/a /tmp/b /tmp/c; rm /tmp/a; cat /tmp/b; cat /tmp/cЖорстке посилання й символьне поруч. Після видалення оригіналу
b читається, c — ні: перше є повноцінним іменем того самого inode,
друге лише зберігало шлях.
findmnt -t ext4,xfs,btrfs,overlay -o TARGET,SOURCE,FSTYPE,OPTIONSЗмонтовані файлові системи з опціями. У системі з контейнерами
тут буде overlay.
filefrag -v /var/log/syslog 2>/dev/null | head -8Екстенти конкретного файлу: скільки суцільних діапазонів він займає.
Типові помилки розуміння
Section titled “Типові помилки розуміння”«Ім’я файлу зберігається у файлі». Ім’я лежить у каталозі, а inode його не містить. Тому одному inode і можуть відповідати кілька імен.
«Видалив файл, місце звільнилося». Звільниться воно, коли лічильник посилань стане нулем і файл при цьому ніхто не триматиме відкритим.
«Жорстке посилання — це ярлик». Це рівноправне ім’я того самого inode. Ярликом є символьне посилання: воно зберігає шлях і ламається, коли ціль зникає.
«Не маю права писати у файл, отже не зможу його видалити». Видалення змінює каталог, тож вирішують саме права на каталог.
«Журналювання захищає дані». У типовому режимі ordered журналюються
метадані. Файлова система лишиться несуперечливою, а от вміст файлу після
збою може виявитися неповним.
«Місце є, а записати не можу, отже файлова система зламана».
Подивіться df -i: імовірно, скінчилися inode.
«btrfs і ext4 відрізняються лише швидкістю». Головна відмінність у контрольних сумах даних і знімках. ext4 не помітить тихого пошкодження вмісту.
Перевір себе
Лабораторна
Section titled “Лабораторна”A6 — файлова система у файлі. Власний формат із суперблоком, таблицею inode і бітовою картою блоків, змонтований через FUSE. Обов’язкова частина — реалізувати жорсткі посилання й переконатися, що видалення одного імені не знищує файл.
Джерела
Section titled “Джерела”- OSTEP: File System Implementation, Journaling
- Silberschatz, Operating System Concepts, розділи 13–14
man 7 inode,man 2 unlink,man 5 ext4,man 8 mount- Documentation/filesystems — VFS і конкретні ФС