Перейти до вмісту

A6. Файлова система через FUSE

просунутийспирається на модуль 15

Щоб остаточно зрозуміти, що ім’я файлу лежить у каталозі, а не в inode, найкраще реалізувати обидві структури самому. Після цього жорсткі посилання перестають бути дивиною: це просто другий запис у каталозі з тим самим номером.

FUSE дає змогу зробити все це в режимі користувача (модуль 15), тож помилка завершить вашу програму, а не систему.

Terminal window
./mkfs.myfs disk.img 64M # створити порожню ФС у файлі
./myfs disk.img /mnt/my # змонтувати
fusermount3 -u /mnt/my # відмонтувати

Усередині мають працювати mkdir, touch, echo > file, cat, ls -l, ln, rm, stat.

Мінімальний, але справжній:

Ділянка Що містить
Суперблок сигнатура, розмір блока, кількість inode і блоків, зміщення решти ділянок
Бітова карта inode по біту на inode: зайнятий чи ні
Бітова карта блоків по біту на блок даних
Таблиця inode тип, права, розмір, лічильник посилань, часи, вказівники на блоки
Блоки даних вміст файлів і записи каталогів

Каталог — звичайний файл, вміст якого є послідовністю записів «довжина імені, номер inode, ім’я».

  1. mkfs. Створити образ, записати суперблок, обнулити бітові карти, створити кореневий каталог із записами . і ...

  2. Монтування й читання. Реалізувати getattr, readdir, open, read. На цьому етапі ФС уже видно в ls, хоч записувати ще не можна.

    getattr — найважливіша операція: без неї не працює нічого, і саме на ній зазвичай застрягають.

  3. Запис. create, write, truncate, unlink. Тут з’являється робота з бітовою картою блоків і зростання файлу.

  4. Каталоги. mkdir, rmdir. rmdir має відмовляти на непорожньому каталозі — перевірте, що ваша перевірка не рахує . і ...

  5. Жорсткі посилання. link збільшує лічильник, unlink зменшує; inode звільняється лише на нулі.

    Обов’язкова перевірка: створити файл, зробити на нього посилання, видалити оригінал, прочитати за другим іменем. Дані мають бути на місці.

  6. Стійкість до перезапуску. Відмонтуйте, змонтуйте знову, переконайтеся, що все на місці. Якщо ні — ви щось тримали лише в пам’яті.

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

Terminal window
cd labs/a6-filesystem
./check.sh ./myfs ./mkfs.myfs

Скрипт створює образ, монтує його у тимчасовий каталог, проганяє сценарії з файлами, каталогами й посиланнями, відмонтовує й монтує знову, щоб перевірити збереження стану.

Жорсткі посилання «не працюють», хоча код правильний. Найдорожча пастка цієї роботи, і вона не у вашому коді. За замовчуванням libfuse підставляє власні номери inode замість тих, що ви повертаєте з getattr, і кешує атрибути на секунду. Тому stat показує два різні inode для двох імен одного файлу й застарілий nlink.

Лікується обробником init:

static void *fs_init(struct fuse_conn_info *conn, struct fuse_config *cfg) {
cfg->use_ino = 1; // брати st_ino з нашого getattr
cfg->attr_timeout = 0; // не кешувати атрибути
cfg->entry_timeout = 0;
return NULL;
}

Кеш можна лишити ввімкненим у готовій ФС — але поки ви її налагоджуєте, він приховує половину помилок.

getattr повертає неправильний розмір. Тоді cat читає зайве або обрізає файл. Розмір беруть з inode, а не з кількості блоків.

Каталог не має . і ... На них розраховує чимало утиліт, тож ls почне поводитися дивно.

Блоки не звільняються. Місце тікатиме при кожному видаленні. Перевірити просто: створіть і видаліть файл сто разів, а потім подивіться на вільні блоки.

Немає перевірки меж. Ім’я, довше за максимальне, або запис за межу файлу зіпсують сусідні структури. Це та сама помилка, що й у A4, тільки на диску.

Додати непрямі блоки й подивитися, як зростає максимальний розмір файлу (модуль 15). Або журнал — і перевірити, що ФС переживає обрив на середині запису.