Роберт Лав - Разработка ядра Linux
• void umount_begin(struct super_block *sb) — эта функция вызывается подсистемой VFS для прерывания операции монтирования. Она используется сетевыми файловыми системами, такими как NFS.
Все рассмотренные функции вызываются подсистемой VFS в контексте процесса. Все они при необходимости могут блокироваться.
Некоторые из этих функций являются необязательными. Файловая система может установить их значения в структуре операций суперблока равными NULL. Если соответствующий указатель равен NULL, то подсистема VFS или вызывает общий вариант функции, или не происходит ничего, в зависимости от операции.
Объект inode
Объект inode содержит всю информацию, которая необходима ядру для манипуляций с файлами и каталогами. В файловых системах в стиле Unix вся информация просто считывается из дисковых индексов и помещается в объект inode подсистемы VFS. Если файловые системы не имеют индексов, то эту информацию необходимо получить из других дисковых структур[70].
Объект индекса файла представляется с помощью структуры struct inode, которая определена в файле <linux/fs.h>. Эта структура с комментариями, описывающими назначение каждого поля, имеет следующий вид.
struct inode {
struct hlist_node i_hash; /* хешированный список */
struct list_head i_list; /* связанный список индексов */
struct list_head i_dentry; /* связанный список объектов dentry */
unsigned long i_ino; /* номер индекса */
atomic_t i_count; /* счетчик ссылок */
umode_t i_mode; /* права доступа */
unsigned int i_nlink; /* количество жестких ссылок */
uid_t i_uid; /* идентификатор пользователя-владельца */
gid_t i_gid; /* идентификатор группы-владельца */
kdev_t i_rdev; /* связанное устройство */
loff_t i_size; /* размер файла в байтах */
struct timespec i_atime; /* время последнего доступа к файлу */
struct timespec i_mtime; /* время последнего изменения файла */
struct timespec i_ctime; /* время изменения индекса */
unsigned int i_blkbits; /* размер блока в битах */
unsigned long i_blksize; /* размер блока в байтах */
unsigned long i_version; /* номер версии */
unsigned long i_blocks; /* размер файла в блоках */
unsigned short i_bytes; /* количество использованных байтов */
spinlock_t i_lock; /* блокировка для защиты полей */
struct rw_semaphore i_alloc_sem /* вложенные блокировки при
захваченной i_sem */
struct semaphore i_sem; /* семафор индекса */
struct inode_operations *i_op; /* таблица операций с индексом */
struct file_operations *i_fop; /* файловые операции */
struct super_block *i_sb; /* связанный суперблок */
struct file_lock *i_flock; /* список блокировок файлов */
struct address_space *i_mapping; /* соответствующее адресное
пространство */
struct address_space i_data; /* адресное пространство устройства */
struct dquot *i_dquot[MAXQUOTAS]; /* дисковые квоты
для индекса */
struct list_head i_devices; /* список блочных устройств */
struct pipe_inode_info *i_pipe; /* информация конвейера */
struct block_device *i_bdev; /* драйвер блочного устройства */
unsigned long i_dnotify_mask; /* события каталога */
struct dnotify_struct *i_dnotify; /* информация о событиях каталога */
unsigned long i_state; /* флаги состояния */
unsigned long dirtied_when /* время первого изменения */
unsigned int i_flags; /* флаги файловой системы */
unsigned char i_sock; /* сокет или нет? */
atomic_t i_writecount; /* счетчик использования
для записи */
void *i_security; /* модуль безопасности */
__u32 i_generation; /* номер версии индекса */
union {
void *generic_ip; /* специфическая информация
файловой системы */
} u;
};
Для каждого файла в системе существует представляющий его индекс (хотя объект файлового индекса создается в памяти только тогда, когда к файлу осуществляется доступ). Это справедливо и для специальных файлов, таких как файлы устройств или конвейеры. Следовательно, некоторые из полей структуры struct inode относятся к этим специальным файлам. Например, поле i_pipe указывает на структуру данных именованного конвейера. Если индекс не относится к именованному конвейеру, то это поле просто содержит значение NULL Другие поля, связанные со специальными файлами, — это i_devices, i_bdev, i_cdev.
Может оказаться, что та или иная файловая система не поддерживает тех свойств, которые присутствуют в объекте inode. Например, некоторые файловые системы не поддерживают такого атрибута, как время создания файла. В этом случае файловая система может реализовать это свойство как угодно. Например, поле i_ctime можно сделать нулевым или равным значению поля i_mtime.
Операции с файловыми индексами
Так же как и в случае операций суперблока, важным является поле inode_operations, в котором описаны функции файловой системы, которые могут быть вызваны подсистемой VFS для объекта файлового индекса. Как и для суперблока, операции с файловыми индексами могут быть вызваны следующим образом.
i->i_op->truncate(i);
где переменная i содержит указатель на определенный объект файлового индекса. В данном случае для индекса i выполняется операция truncate(), которая определена для файловой системы, в которой находится указанный файловый индекс i. Структура inode_operations определена в файле <linux/fs.h>, как показано ниже.
struct inode_operations {
int (*create)(struct inode*, struct dentry*, int);
struct dentry* (*lookup)(struct inode*, struct dentry*);
int (*link)(struct dentry*, struct inode*, struct dentry*);
int (*unlink)(struct inode*, struct dentry*);
int (*symlink)(struct inode*, struct dentry*, const char*);
int (*mkdir)(struct inode*, struct dentry*, int);
int (*rmdir)(struct inode*, struct dentry*);
int (*mknod)(struct inode*, struct dentry*, int, dev_t);
int (*rename)(struct inode*, struct dentry*,
struct inode*, struct dentry*);
int (*readlink)(struct dentry*, char*, int);
int (*follow_link)(struct dentry*, struct nameidata*);
int (*put_link)(struct dentry*, struct nameidata*);
void (*truncate)(struct inode*);
int (*permission)(struct inode*, int);
int (*setattr)(struct dentry*, struct iattr*);
int (*getattr)(struct vfsmount*, struct dentry*, struct kstat*);
int (*setxattr)(struct dentry*, const char*,
const void*, size_t, int);
ssize_t (*getxattr)(struct dentry*, const char*, void*, size_t);
ssize_t (*listxattr)(struct dentry*, char*, size_t);
int (*removexattr)(struct dentry*, const char*);
};
Рассмотрим указанные операции более подробно.
• int create(struct inode *dir, struct dentry *dentry, int mode);
Эта функция вызывается подсистемой VFS из системных вызовов creat() и open() для создания нового файлового индекса, который имеет указанный режим доступа (mode) и связан с указанным элементом каталога (dentry).
• struct dentry* lookup(struct inode *dir, struct dentry *dentry);
Эта функция производит поиск файлового индекса в указанном каталоге. Файловый индекс должен соответствовать имени файла, хранящемуся в указанном объекте элемента каталога.
• int link(struct dentry *old_dentry, struct inode *dir,
struct dentry *dentry);
Эта функция вызывается из системного вызова link() для создания жесткой ссылки (hard link) на файл, соответствующий элементу каталога old_dentry в каталоге dir. Новая ссылка должна иметь имя, которое хранится в указанном элементе каталога dentry.
• int unlink(struct inode *dir, struct dentry *dentry);
Эта функция вызывается из системного вызова unlink() для удаления файлового индекса, соответствующего элементу каталога dentry в каталоге dir.
• int symlink(struct inode *dir, struct dentry *dentry,
const char *symname);
Эта функция вызывается из системного вызова symlink() для создания символьной ссылки с именем symname на файл, которому соответствует элемент каталога dentry в каталоге dir.