Роберт Лав - Разработка ядра Linux
Объект суперблок представляется с помощью структуры struct super_block, которая определена в файле <linux/fs.h>. Она выглядит следующим образом (комментарии описывают назначение каждого поля).
struct super_block {
struct list_head s_list; /* список всех суперблоков */
dev_t s_dev; /* идентификатор */
unsigned long s_blocksize; /* размер блока в байтах */
unsigned long s_old_blocksize; /* старый размер блока
в байтах */
unsigned char s_blocksize_bits; /* размер блока в битах */
unsigned char s_dirt; /* флаг того,
что суперблок изменен */
unsigned long long s_maxbytes; /* максимальный размер файла */
struct file_system_type *s_type; /* тип файловой системы */
struct super_operations *s_op; /* операции суперблока */
struct dquot_operations *dq_op; /* операции с квотами */
struct quotactl_ops *s_qcop; /* операции управления квотами */
struct export_operations *s_export_op; /* операции экспортирования */
unsigned long s_flags; /* флаги монтирования */
unsigned long s_magic; /* магический номер файловой системы */
struct dentry *s_root; /* каталог, точка монтирования */
struct rw_semaphore s_umount; /* семафор размонтирования */
struct semaphore s_lock; /* семафор суперблока */
int s_count; /* счетчик ссылок на суперблок */
int s_syncing; /* флаг синхронизации
файловой системы */
int s_need_sync_fs; /* флаг того, что файловая
система еще не синхронизирована */
atomic_t s_active; /* счетчик активных ссылок */
void *s_security; /* модуль безопасности */
struct list_head s_dirty; /* список измененных индексов */
struct list_head s_io; /* список обратной записи */
struct hlist_head s_anon; /* анонимные элементы каталога
для экспортирования */
struct list_head s_files; /* список связанных файлов */
struct block_device *s_bdev; /* соответствующий драйвер
блочного устройства */
struct list_head s_instances; /* список файловых систем
данного типа */
struct quota_info s_dquot; /* параметры квот */
char s_id[32]; /* текстовое имя */
void *s_fs_info; /* специфическая информация
файловой системы */
struct semaphore s_vfs_rename_sem; /* семафор переименования */
};
Код для создания, управления и ликвидации объектов суперблок находится в файле fs/super.c. Объект суперблок создается и инициализируется в функции alloc_super(). Эта функция вызывается при монтировании файловой системы, которая считывает суперблок файловой системы с диска и заполняет поля объекта суперблок.
Операции суперблока
Наиболее важный элемент суперблока — это поле s_op, которое является указателем на таблицу операций суперблока. Таблица операций суперблока представлена с помощью структуры struct super_operations, которая определена в файле <linux/fs.h>. Она выглядит следующим образом.
struct super_operations {
struct inode *(*alloc_inode)(struct super_block *sb);
void (*destroy_inode)(struct inode*);
void (*read_inode)(struct inode*);
void (*dirty_inode)(struct inode*);
void (*write_inode)(struct inode*, int);
void (*put inode)(struct inode*);
void (*drop_inode)(struct inode*);
void (*delete_inode)(struct inode*);
void (*put_super)(struct super_block*);
void (*write_super)(struct super block*);
int (*sync_fs)(struct super_block*, int);
void (*write_super_lockfs)(struct super_block*);
void (*unlockfs)(struct super_block*);
int (*statfs)(struct super_block*, struct statfs*);
int (*remount_fs)(struct super_block*, int*, char*);
void (*clear_inode)(struct inode*);
void (*umount_begin)(struct super block*);
int (*show_options)(struct seq_file*, struct vfsmount*);
};
Каждое поле этой структуры представляет собой указатель на функцию, которая работает с объектом суперблок. Операции суперблока выполняют низкоуровневые действия с файловой системой и ее файловыми индексами.
Когда для файловой системы необходимо выполнить операции с суперблоком, то выполняется разыменование указателя на суперблок, и далее получается указатель на необходимый метод. Например, если файловой системе необходимо записать суперблок, то вызывается следующая функция.
sb->s_op->write_super(sb);
где параметр sb — это указатель на суперблок файловой системы. Следуя по указателю s_op, получаем таблицу операций суперблока и, наконец, необходимую функцию write_super(), которая вызывается непосредственно. Следует обратить внимание на то, что вызову функции write_super() необходимо передать указатель на суперблок в качестве параметра, несмотря на то что метод связан с суперблоком. Это происходит от того, что язык программирования С не объектно-ориентирован. В C++ аналогичный вызов может быть выполнен следующим образом.
sb.write_super();
В языке С нет простого способа получить указатель на объект, для которого вызван метод, поэтому его необходимо передавать явно.
Рассмотрим операции суперблока, которые описаны в структуре super_operations.
• struct inode* alloc_inode(struct super_block *sb) — эта функция создает и инициализирует новый объект файлового индекса, связанного с данным суперблоком.
• void destroy_inode(struct inode *inode) — эта функция уничтожает данный объект индекса файла.
• void read_inode(struct inode *inode) — эта функция считывает с диска файловый индекс с номером inode->i_ino и заполняет все остальные поля структуры данных индекса.
• void dirty_inode(struct inode *inode) — эта функция вызывается подсистемой VFS, когда в индекс вносятся изменения (dirty). Журналируемые файловые системы (как, например, ext3) используют эту функцию для обновления журнала.
• void write_inode(struct inode inode*, int wait) — эта функция записывает указанный индекс на диск. Параметр wait указывает, должна ли данная операция выполняться синхронно.
• void put_inode(struct inode *inode) — эта функция освобождает указанный индекс.
• void drop_inode(struct inode *inode) — эта функция вызывается подсистемой VFS, когда исчезает последняя ссылка на индекс. Обычные файловые системы Unix никогда не определяют эту функцию, в таком случае подсистема VFS просто удаляет индекс. Вызывающий код должен удерживать блокировку inode_lock.
• void delete_inode(struct inode *inode) — эта функция удаляет индекс файла с диска.
• void put_super(struct super_block *sb) — эта функция вызывается подсистемой VFS при размонтировании файловой системы, чтобы освободить указанный суперблок.
• void write_super(struct super_block *sb) — эта функция обновляет суперблок на диске данными из указанного суперблока. Подсистема VFS вызывает эту функцию для синхронизации измененного суперблока в памяти с данными суперблока на диске.
• int sync_fs(struct super_block *sb, int wait) — эта функция синхронизирует метаданные файловой системы с данными на диске. Параметр wait указывает, должна ли операция быть синхронной или асинхронной.
• void write_super_lockfs(struct super_block *sb) — эта функция предотвращает изменения файловой системы и затем обновляет данные суперблока на диске данными из указанного суперблока. Сейчас она используется диспетчером логических томов (LVM, Logical Volume Manager).
• void unlockfs(struct super_block *sb) — эта функция разблокирует файловую систему после выполнения функции write_super_lockfs().
• int statfs(struct super_block *sb, struct statfs *statfs) — эта функция вызывается подсистемой VFS для получения статистики файловой системы, Статистика указанной файловой системы записывается в структуру statfs.
• int remount_fs(struct super_block *sb, int *flags, char *data) — эта функция вызывается подсистемой VFS, когда файловая система монтируется с другими параметрами монтирования.
• void clear_inode(struct inode*) — эта функция вызывается подсистемой VFS для освобождения индекса и очистки всех страниц памяти, связанных с индексом.