超级块对象
记录已安装文件系统的整体信息,由于具体的文件系统来实现,它对应于具体文件系统的超级块或控制块,存储在磁盘的特定扇区上,如果不是基于磁盘的文件系统,比如sysfs,会生成临时的超级块,保存在内存当中。
01struct super_block {
02 struct list_head s_list; /* Keep this first */
03 dev_t s_dev; /* search index; _not_ kdev_t */
04 unsigned long s_blocksize;
05 unsigned char s_blocksize_bits;
06 unsigned char s_dirt;
07 unsigned long long s_maxbytes; /* Max file size */
08 struct file_system_type *s_type;
09 const struct super_operations *s_op;
10 struct dquot_operations *dq_op;
11 struct quotactl_ops *s_qcop;
12 const struct export_operations *s_export_op;
13 unsigned long s_flags;
14 unsigned long s_magic;
15 struct dentry *s_root;
16 struct rw_semaphore s_umount;
17 struct mutex s_lock;
18 int s_count;
19 int s_need_sync_fs;
20 atomic_t s_active;
21#ifdef CONFIG_SECURITY
22 void *s_security;
23#endif
24 struct xattr_handler **s_xattr;
25
26 struct list_head s_inodes; /* all inodes */
27 struct list_head s_dirty; /* dirty inodes */
28 struct list_head s_io; /* parked for writeback */
29 struct list_head s_more_io; /* parked for more writeback */
30 struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */
31 struct list_head s_files;
32 /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */
33 struct list_head s_dentry_lru; /* unused dentry lru */
34 int s_nr_dentry_unused; /* # of dentry on lru */
35
36 struct block_device *s_bdev;
37 struct mtd_info *s_mtd;
38 struct list_head s_instances;
39 struct quota_info s_dquot; /* Diskquota specific options */
40
41 int s_frozen;
42 wait_queue_head_t s_wait_unfrozen;
43
44 char s_id[32]; /* Informational name */
45
46 void *s_fs_info; /* Filesystem private info */
47 fmode_t s_mode;
48 struct mutex s_vfs_rename_mutex; /* Kludge */
49
50 /* Granularity of c/m/atime in ns.
51 Cannot be worse than a second */
52 u32 s_time_gran;
53
54 char *s_subtype;
55
56 char *s_options;
57 struct list_head s_async_list;
58};
第2行指向超级块链表的指针
第3行设备标识符
第4行以字节为单位的块大小
第5行以位为单位的块大小
第6行修改标志
第7行文件的最长长度
第8行文件系统类型
第9行超级块方法
第10行磁盘限额处理方法
第11行磁盘限额管理方法
第12行网络文件系统使用的输出操作
第13行安装标志
第14行文件系统的魔数
第15行文件系统根目录的目录项对象
第16行卸载所用的信号量
第17行超级块信息量
第18行引用计数器
第19行对超级块的已安装文件系统进行同步的标志
第20行次级引用计数器
第22行指向超级块安全数据结构的指针
第24行指向超级块扩展属性结构的指针
第26行所有索引节点的链表
第27行改进型索引节点的链表
第28行等待被写入磁盘的索引节点的链表
第30行用于处理远程网络文件系统的匿名目录项的链表
第31行文件对象的链表
第36行指向块设备驱动程序描述符的指针
第38行用于给定文件系统类型的超级块对象链表的指针
第39行磁盘限额的描述符
第41行冻结文件系统时使用的标志
第42行进程挂起的等待队列,直到文件系统被解冻
第46行指向特定文件的超级块信息的指针
第52行时间戳的粒度
超级块的操作方法
01struct super_operations {
02 struct inode *(*alloc_inode)(struct super_block *sb);
03 void (*destroy_inode)(struct inode *);
04
05 void (*dirty_inode) (struct inode *);
06 int (*write_inode) (struct inode *, int);
07 void (*drop_inode) (struct inode *);
08 void (*delete_inode) (struct inode *);
09 void (*put_super) (struct super_block *);
10 void (*write_super) (struct super_block *);
11 int (*sync_fs)(struct super_block *sb, int wait);
12 int (*freeze_fs) (struct super_block *);
13 int (*unfreeze_fs) (struct super_block *);
14 int (*statfs) (struct dentry *, struct kstatfs *);
15 int (*remount_fs) (struct super_block *, int *, char *);
16 void (*clear_inode) (struct inode *);
17 void (*umount_begin) (struct super_block *);
18
19 int (*show_options)(struct seq_file *, struct vfsmount *);
20 int (*show_stats)(struct seq_file *, struct vfsmount *);
21#ifdef CONFIG_QUOTA
22 ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
23 ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
24#endif
25 int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
26};
第2行为索引节点对象分配空间,包括具体文件系统的数据所需要的空间。
第3行撤消索引节点对象。
第5行当索引节点标记为修改(脏)时调用。
第6行用通过传递参数指定的索引节点对象的内容更新一个文件系统的索引节点。索引节点对象的i_ino字段标识所涉及磁盘上文件系统的索引节点。flag参数表示I/O操作是否应当同步。
第7行撤消索引节点时调用
第8行在必须撤消索引节点时调用。删除内存中的VFS索引节点和磁盘上的文件数据及元数据
第9行释放通过传递的参数指定的超级块对象
第10行用指定对象的内容更新文件系统的超级块
第11行在清除文件系统来更新磁盘上的具体文件系统数据时调用。
第14行将文件系统的统计信息返回,填写在buf缓存区中。
第15行用新选项重新安装文件系统
第16行当撤消磁盘索引节点执行具体文件操作时调用。
第17行中断一个安装操作
第19行用来显示特定文件系统的选项
第22行限额系统使用该方法从文件中读取数据。
第23行限额系统使用该方法将数据写入文件中
索引节点对象
存放关于具体文件的一般信息。对基于磁盘的文件系统,通常对应于存放在磁盘上的文件控制块。每个索引节点对象都有一个索引节点号,这个节点号唯一的标识文件系统中的文件。。
01struct inode {
02 struct hlist_node i_hash;
03 struct list_head i_list;
04 struct list_head i_sb_list;
05 struct list_head i_dentry;
06 unsigned long i_ino;
07 atomic_t i_count;
08 unsigned int i_nlink;
09 uid_t i_uid;
10 gid_t i_gid;
11 dev_t i_rdev;
12 u64 i_version;
13 loff_t i_size;
14#ifdef __NEED_I_SIZE_ORDERED
15 seqcount_t i_size_seqcount;
16#endif
17 struct timespec i_atime;
18 struct timespec i_mtime;
19 struct timespec i_ctime;
20 unsigned int i_blkbits;
21 blkcnt_t i_blocks;
22 unsigned short i_bytes;
23 umode_t i_mode;
24 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
25 struct mutex i_mutex;
26 struct rw_semaphore i_alloc_sem;
27 const struct inode_operations *i_op;
28 const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
29 struct super_block *i_sb;
30 struct file_lock *i_flock;
31 struct address_space *i_mapping;
32 struct address_space i_data;
33#ifdef CONFIG_QUOTA
34 struct dquot *i_dquot[MAXQUOTAS];
35#endif
36 struct list_head i_devices;
37 union {
38 struct pipe_inode_info *i_pipe;
39 struct block_device *i_bdev;
40 struct cdev *i_cdev;
41 };
42 int i_cindex;
43
44 __u32 i_generation;
45
46#ifdef CONFIG_DNOTIFY
47 unsigned long i_dnotify_mask; /* Directory notify events */
48 struct dnotify_struct *i_dnotify; /* for directory notifications */
49#endif
50
51#ifdef CONFIG_INOTIFY
52 struct list_head inotify_watches; /* watches on this inode */
53 struct mutex inotify_mutex; /* protects the watches list */
54#endif
55
56 unsigned long i_state;
57 unsigned long dirtied_when; /* jiffies of first dirtying */
58
59 unsigned int i_flags;
60
61 atomic_t i_writecount;
62#ifdef CONFIG_SECURITY
63 void *i_security;
64#endif
65 void *i_private; /* fs or device private pointer */
66};
第2行用于散列链表的指针
第3行用于描述索引节点当前状态的链表的指针
第4行用于超级块的索引节点链表的指针
第5行引用索引节点的目录项对象链表的头
第6行索引节点号
第7行引用计数器
第8行硬链接数目
第9行所有者标识符
第10行组标识符
第11行实设备标识符
第13行文件的字节数
第17行上次访问文件的时间
第18行上次写文件的时间
第19行上次修改索引节点的时间
第20行块的字节数
第21行文件的块数
第26行在直接I/O文件操作中避免出现竞争条件的读/写信号量
第27行索引节点的操作
第28行缺省文件操作
第29行指向超级块对象的指针
第30行指向文件锁链表的指针
第31行指向address_space对象
第32行文件的address_space对象
第34行索引节点磁盘限额
第36行用于具体的字符或块设备索引节点链表的指针
第38行管道文件使用
第39行指向块设备驱动程序的指针
第40行指向字符设备驱动程序的指针
第42行拥有一组次设备号的设备文件的索引
第44行索引节点版本号
第47行目录通知事件的位掩码
第48行用于目录通知
第56行索引节点的状态标志
第57行索引节点的弄脏时间
第59行文件系统的安装标志
第61行用于写进程的引用计数器
第63行指向索引节点安全结构的指针
索引结点的操作方法
01struct inode_operations {
02 int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
03 struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
04 int (*link) (struct dentry *,struct inode *,struct dentry *);
05 int (*unlink) (struct inode *,struct dentry *);
06 int (*symlink) (struct inode *,struct dentry *,const char *);
07 int (*mkdir) (struct inode *,struct dentry *,int);
08 int (*rmdir) (struct inode *,struct dentry *);
09 int (*mknod) (struct inode *,struct dentry *,int,dev_t);
10 int (*rename) (struct inode *, struct dentry *,
11 struct inode *, struct dentry *);
12 int (*readlink) (struct dentry *, char __user *,int);
13 void * (*follow_link) (struct dentry *, struct nameidata *);
14 void (*put_link) (struct dentry *, struct nameidata *, void *);
15 void (*truncate) (struct inode *);
16 int (*permission) (struct inode *, int);
17 int (*setattr) (struct dentry *, struct iattr *);
18 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
19 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
20 ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
21 ssize_t (*listxattr) (struct dentry *, char *, size_t);
22 int (*removexattr) (struct dentry *, const char *);
23 void (*truncate_range)(struct inode *, loff_t, loff_t);
24 long (*fallocate)(struct inode *inode, int mode, loff_t offset,
25 loff_t len);
26 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
27 u64 len);
28};
第2行为与目录项对象相关的普通文件创建一个新的磁盘索引节点
第3行为包含在一个目录项对象中的文件名对应的索引节点查找目录
第4行创建一个新的名为new_dentry的硬链接,它指向dir目录下名为old_dentry的文件。
第5行从一个目录中删除目录项对象所指定文件的硬链接
第6行在某个目录下,为与目录项对象相关的符号链接创建一个新的索引节点
第7行在某个目录下,为与目录项对象相关的目录创建一个新的索引节点
第8行从一个目录删除子目录,子目录的名称包含在目录项对象中。
第9行在某个目录中,为与目录项对象相关的特定文件创建一个新磁盘索引节点。
第10行将old_dir目录下由old_entry标识的文件移动new_dir目录下。
第12行将目录项所指定的符号链接中对应的文件路径名拷贝到buffer所指定的用户态内存区
第13行解析索引节点对象所指定的符号链接
第14行释放由follow_link方法分配的用于解析符号链接的所有临时数据结构
第15行修改与索引节点相关的文件长度
第16行检查是否允许对索引节点所指的文件进行指定模式的访问。
第17行在触及索引节点属性后通知一个”修改事件”
第18行由一些文件系统用于读取索引节点属性
第19行获取扩展属性名称的整个链表
第20行删除索引节点的扩展属性。
目录项对象
存放目录项与对应文件进行链接的有关信息。每个磁盘文件系统都以自己特有的方式将该类信息存在磁盘上。
VFS把目录项当作目录文件来对待,路径中的每个组成部分有一个索引结点表示,虽然它们可以由索引结点表示,但VFS经常需要执行目录相关操作,比如路径的查找等。为了查找方便,VFS引入了目录项这个概念,每个目录项代表路径中一个特定部分。
01struct dentry {
02 atomic_t d_count;
03 unsigned int d_flags; /* protected by d_lock */
04 spinlock_t d_lock; /* per dentry lock */
05 int d_mounted;
06 struct inode *d_inode; /* Where the name belongs to – NULL is
07 * negative */
08 /*
09 * The next three fields are touched by __d_lookup. Place them here
10 * so they all fit in a cache line.
11 */
12 struct hlist_node d_hash; /* lookup hash list */
13 struct dentry *d_parent; /* parent directory */
14 struct qstr d_name;
15
16 struct list_head d_lru; /* LRU list */
17 /*
18 * d_child and d_rcu can share memory
19 */
20 union {
21 struct list_head d_child; /* child of parent list */
22 struct rcu_head d_rcu;
23 } d_u;
24 struct list_head d_subdirs; /* our children */
25 struct list_head d_alias; /* inode alias list */
26 unsigned long d_time; /* used by d_revalidate */
27 const struct dentry_operations *d_op;
28 struct super_block *d_sb; /* The root of the dentry tree */
29 void *d_fsdata; /* fs-specific data */
30
31 unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
32};
第2行目录项对象引用计数器
第3行目录项高速缓存标志
第4行保护目录项对象的自旋锁
第6行与文件名关联的索引节点
第13行父目录的目录项对象
第14行文件名
第16行用于未使用目录项链表的指针
第21行对目录而言,用于同一父目录中的目录项链表的指针
第24行对目录而言,子目录项链表的头
第25行用于与同一索引节点相关的目录项链表的指针
第26行由d_revalidate方法使用
第27行目录项方法
第28行文件的超级块对象
第29行依赖于文件系统的数据
第31行存放短文件名的空间
每个目录项对象都有四种状态,只能处于下列状态中的一种
空闲状态
处于该状态的目录对象不包括有效的信息,且还没有被VFS使用。
未使用状态
处于该状态的目录项对象当前还没有被内核使用。
正使用状态
处于该状态的目录项对象当前正在被内核使用。
负状态
与目录项关联的索引节点不复存在,那是因为相应的磁盘索引节点被删除,或者因为目录项对象是通过解析一个不存在文件的路径名创建的。
目录项的操作方法
01struct dentry_operations {
02 int (*d_revalidate)(struct dentry *, struct nameidata *);
03 int (*d_hash) (struct dentry *, struct qstr *);
04 int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
05 int (*d_delete)(struct dentry *);
06 void (*d_release)(struct dentry *);
07 void (*d_iput)(struct dentry *, struct inode *);
08 char *(*d_dname)(struct dentry *, char *, int);
09};
第2行把目录项对象转制为一个文件路径名之前,判定该目录项对象是否仍然有效。
第3行生成一个散列值,这是用于目录项散列表的,特定于具体文件系统的散列函数
第4行比较两个文件名。
第5行当对目录项对象的最后一个引用被删除时,调用这个方法
第6行当要释放一个目录项对象是,调用这个方法
第7行当一个目录项对象变为”负状态”时,调用这个方法
文件对象
文件对象描述进程怎样与一个打开的文件进行交互。文件对象是在文件被打开时创建的。文件对象在磁盘上没有对应的映像。
01struct file {
02 /*
03 * fu_list becomes invalid after file_free is called and queued via
04 * fu_rcuhead for RCU freeing
05 */
06 union {
07 struct list_head fu_list;
08 struct rcu_head fu_rcuhead;
09 } f_u;
10 struct path f_path;
11#define f_dentry f_path.dentry
12#define f_vfsmnt f_path.mnt
13 const struct file_operations *f_op;
14 spinlock_t f_lock; /* f_ep_links, f_flags, no IRQ */
15 atomic_long_t f_count;
16 unsigned int f_flags;
17 fmode_t f_mode;
18 loff_t f_pos;
19 struct fown_struct f_owner;
20 const struct cred *f_cred;
21 struct file_ra_state f_ra;
22
23 u64 f_version;
24#ifdef CONFIG_SECURITY
25 void *f_security;
26#endif
27 /* needed for tty driver, and maybe others */
28 void *private_data;
29
30#ifdef CONFIG_EPOLL
31 /* Used by fs/eventpoll.c to link all the hooks to this file */
32 struct list_head f_ep_links;
33#endif /* #ifdef CONFIG_EPOLL */
34 struct address_space *f_mapping;
35#ifdef CONFIG_DEBUG_WRITECOUNT
36 unsigned long f_mnt_write_state;
37#endif
38};
第11行与文件相关的目录项对象
第12行含有文件的已安装文件系统
第13行指向文件操作表的指针
第15行文件对象的引用计数器
第16行当打开文件时所指定的标志
第17行进程的访问模式
第18行当前的文件位移量
第19行通过信号进行I/O事件通知的数据
第21行文件预读状态
第23行版本号
第25行指向文件对象的安全结构的指针
第28行指向特定系统或设备驱动程序所需要的数据的指针
第32行文件的事件轮询等待者链表的头
第34行指向文件地址空间对象的指针
文件的操作方法
01struct file_operations {
02 struct module *owner;
03 loff_t (*llseek) (struct file *, loff_t, int);
04 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
05 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
06 ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
07 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
08 int (*readdir) (struct file *, void *, filldir_t);
09 unsigned int (*poll) (struct file *, struct poll_table_struct *);
10 int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
11 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
12 long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
13 int (*mmap) (struct file *, struct vm_area_struct *);
14 int (*open) (struct inode *, struct file *);
15 int (*flush) (struct file *, fl_owner_t id);
16 int (*release) (struct inode *, struct file *);
17 int (*fsync) (struct file *, struct dentry *, int datasync);
18 int (*aio_fsync) (struct kiocb *, int datasync);
19 int (*fasync) (int, struct file *, int);
20 int (*lock) (struct file *, int, struct file_lock *);
21 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
22 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
23 int (*check_flags)(int);
24 int (*flock) (struct file *, int, struct file_lock *);
25 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
26 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
27 int (*setlease)(struct file *, long, struct file_lock **);
28};
第3行更新文件指针
第4行从文件的offset处读出count个字节
第5行从文件的offset处写入count个字节
第6行启动一个异步I/O操作。读数据
第7行启动一个异步I/O操作,写数据
第8行返回一个目录的下一个目录项。
第9行检查是否在一个文件上有操作发生,如果没有则睡眠,直到这个文件上有操作发生
第10行向一个基本硬件设备发送命令
第11行与ioctl方法类似,但它不用获得大内核锁
第12行64位的内核使用该方法执行32位的系统调用
第13行执行文件的内存映射,并将映射放入进程的地址空间
第14行通过创建一个新的文件而打开一个文件。
第15行当打开文件的引用被关闭时调用
第16行释放文件对象
第17行将文件所缓存的全部数据写入磁盘
第18行启动一次异步I/O刷新操作。
第19行通过信号来启用或禁止I/O事件通告
第20行对file文件申请一个锁
第23行当设置文件的状态标志时,fcntl()系统调用的服务例程调用这个方法执行附加的检查。
第24行用于定制flock()系统调用的行为。
每个注册的文件系统都用一个类型为file_system_type的对象来表示,该对象的字段如下。
01struct file_system_type {
02 const char *name;
03 int fs_flags;
04 int (*get_sb) (struct file_system_type *, int,
05 const char *, void *, struct vfsmount *);
06 void (*kill_sb) (struct super_block *);
07 struct module *owner;
08 struct file_system_type * next;
09 struct list_head fs_supers;
10
11 struct lock_class_key s_lock_key;
12 struct lock_class_key s_umount_key;
13
14 struct lock_class_key i_lock_key;
15 struct lock_class_key i_mutex_key;
16 struct lock_class_key i_mutex_dir_key;
17 struct lock_class_key i_alloc_sem_key;
18};
第2行文件系统名
第3行文件系统类型标志
第4行读超级块的方法
第6行删除超级块的方法
第7行指向实现文件系统的模块的指针
第8行指向文件系统类型链表中下一个元素的指针
第9行具有相同文件系统类型的超级块对象链表的头。
对于每个安装操作,内核必有在内存中保存安装点和安装标志,以及要安装文件系统与其它已安装文件系统之间的关系,这样的信息保存在已安装文件系统描述符中,这个描述符就是vfsmount类型的数据结构,其字段如下
01struct vfsmount {
02 struct list_head mnt_hash;
03 struct vfsmount *mnt_parent; /* fs we are mounted on */
04 struct dentry *mnt_mountpoint; /* dentry of mountpoint */
05 struct dentry *mnt_root; /* root of the mounted tree */
06 struct super_block *mnt_sb; /* pointer to superblock */
07 struct list_head mnt_mounts; /* list of children, anchored here */
08 struct list_head mnt_child; /* and going through their mnt_child */
09 int mnt_flags;
10 /* 4 bytes hole on 64bits arches */
11 const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */
12 struct list_head mnt_list;
13 struct list_head mnt_expire; /* link in fs-specific expiry list */
14 struct list_head mnt_share; /* circular list of shared mounts */
15 struct list_head mnt_slave_list;/* list of slave mounts */
16 struct list_head mnt_slave; /* slave list entry */
17 struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */
18 struct mnt_namespace *mnt_ns; /* containing namespace */
19 int mnt_id; /* mount identifier */
20 int mnt_group_id; /* peer group identifier */
21 /*
22 * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
23 * to let these frequently modified fields in a separate cache line
24 * (so that reads of mnt_flags wont ping-pong on SMP machines)
25 */
26 atomic_t mnt_count;
27 int mnt_expiry_mark; /* true if marked for expiry */
28 int mnt_pinned;
29 int mnt_ghosts;
30 /*
31 * This value is not stable unless all of the mnt_writers[] spinlocks
32 * are held, and all mnt_writer[]s on this mount have 0 as their ->count
33 */
34 atomic_t __mnt_writers;
35};
第2行用于散列表链表的指针
第3行指向父文件系统。
第4行指向这个文件系统安装点目录的dentry
第5行指向这个文件系统根目录的dentry
第6行指向这个文件系统的超级块对象
第7行包含所有文件系统描述符链表的头
第8行用于已安装文件系统链表mnt_mounts的指针
第9行标志
第11行设备文件名
第13行如果文件系统标记为到期,那么就设置该标志为true