Linux Kernal FS-SuperBlock(1)

The first part of the artical has nothing to do with our topic, please pay attention.

 

Trying to start the topic of file system in Linux kernal is difficult for me.So It's better to start with a story.Also I have to announce that I am not writting a technical essay, so there is no necessity to avoid the usage of I or WE.My blog, my rules.

One of my friend went to Shanhai few years ago entering university, and what he was leaning was quite different from mine, and that do has nothing to do with programming.However my friend loves programming and he will do anything to become a hard-working programmer.Therefore he learnt java and python, attended several projects and got some money as reward.He's been working for companies using java for web projects that runs on servers, and he was playing a part of less importance.They were using SpringBoot actually to create all those work and programms.Before I got to know what SpringBoot is, it remains to be a mysterious thing to me because I don't really make a whole project on my own.I was having some school work that requires some web apps, controller, receiver, GUI, blabla.At that time, the only thing I could do is program with java and do all the work along, including designing the GUIs and making backward programms to connect with users.

Linux Kernal FS-SuperBlock(1)

Yet my friend called me one day to tell me about his issue, he was young and always has creative mind, so he don't wanna be like a 'robot' to do all those unneccery jobs.He talked like anyone could do it with little training even he is not a 'programmer'.I was kind of confused.He suddenly told me that I should learn SpringBoot myself to see how it worked, so I managed to use it at once.

You probably know what happened next.SpringBoot is amazing as well as stupid, it it amazing beacuse it can handle all those problems you don't want to meet, such as creating javabeans and its methods, connecting to the database and use SQL for selecting data, mapping, and so on.Bad thing is your work were actually limited.You just need to focus on your service code instead of these logical connections.I know I needn't build wheels, but it occurs to me that I am so replaceable if I keep doing work like this.Anyone can do the same thing which means anyone will take your job since they are more hard-working and likely to enjoy their overtime work.

So what do programmers, those real programmers who does not only create methods and algorithms but build a great thing that we tap on everyday look like?

Linux Kernal FS-SuperBlock(1)

It's hard to believe, but it's real thing that these code below were written by these geeks at 1990s, which is almost 30 years ago, and our Linux are still running with these code!Of course these code changes a lot since they were created, may be rewritten even, but they are still there.Who knows what is going to happen in the next 30 years?

SuperBlock

fs/super.c

It takes some time to finally discover fs.h where superblock struct was originally located.Superblock is a gate for vfs and fs to communicate their data in storage, which means every filesystem would have to realize its superblock structure as well as functions.But in vfs, superblock was defined in include/linux/fs.h as below.

Linux Kernal FS-SuperBlock(1)

struct super_block {
	struct list_head	s_list;		/* Keep this first */
	dev_t			s_dev;		/* search index; _not_ kdev_t */
	unsigned char		s_blocksize_bits;
	unsigned long		s_blocksize;
	loff_t			s_maxbytes;	/* Max file size */
	struct file_system_type	*s_type;
	const struct super_operations	*s_op;
	const struct dquot_operations	*dq_op;
	const struct quotactl_ops	*s_qcop;
	const struct export_operations *s_export_op;
	unsigned long		s_flags;
	unsigned long		s_iflags;	/* internal SB_I_* flags */
	unsigned long		s_magic;
	struct dentry		*s_root;
	struct rw_semaphore	s_umount;
	int			s_count;
	atomic_t		s_active;
#ifdef CONFIG_SECURITY
	void                    *s_security;
#endif
	const struct xattr_handler **s_xattr;
#ifdef CONFIG_FS_ENCRYPTION
	const struct fscrypt_operations	*s_cop;
	struct key		*s_master_keys; /* master crypto keys in use */
#endif
#ifdef CONFIG_FS_VERITY
	const struct fsverity_operations *s_vop;
#endif
#ifdef CONFIG_UNICODE
	struct unicode_map *s_encoding;
	__u16 s_encoding_flags;
#endif
	struct hlist_bl_head	s_roots;	/* alternate root dentries for NFS */
	struct list_head	s_mounts;	/* list of mounts; _not_ for fs use */
	struct block_device	*s_bdev;
	struct backing_dev_info *s_bdi;
	struct mtd_info		*s_mtd;
	struct hlist_node	s_instances;
	unsigned int		s_quota_types;	/* Bitmask of supported quota types */
	struct quota_info	s_dquot;	/* Diskquota specific options */

	struct sb_writers	s_writers;

	/*
	 * Keep s_fs_info, s_time_gran, s_fsnotify_mask, and
	 * s_fsnotify_marks together for cache efficiency. They are frequently
	 * accessed and rarely modified.
	 */
	void			*s_fs_info;	/* Filesystem private info */

	/* Granularity of c/m/atime in ns (cannot be worse than a second) */
	u32			s_time_gran;
	/* Time limits for c/m/atime in seconds */
	time64_t		   s_time_min;
	time64_t		   s_time_max;
#ifdef CONFIG_FSNOTIFY
	__u32			s_fsnotify_mask;
	struct fsnotify_mark_connector __rcu	*s_fsnotify_marks;
#endif

	char			s_id[32];	/* Informational name */
	uuid_t			s_uuid;		/* UUID */

	unsigned int		s_max_links;
	fmode_t			s_mode;

	/*
	 * The next field is for VFS *only*. No filesystems have any business
	 * even looking at it. You had been warned.
	 */
	struct mutex s_vfs_rename_mutex;	/* Kludge */

	/*
	 * Filesystem subtype.  If non-empty the filesystem type field
	 * in /proc/mounts will be "type.subtype"
	 */
	const char *s_subtype;

	const struct dentry_operations *s_d_op; /* default d_op for dentries */

	/*
	 * Saved pool identifier for cleancache (-1 means none)
	 */
	int cleancache_poolid;

	struct shrinker s_shrink;	/* per-sb shrinker handle */

	/* Number of inodes with nlink == 0 but still referenced */
	atomic_long_t s_remove_count;

	/* Pending fsnotify inode refs */
	atomic_long_t s_fsnotify_inode_refs;

	/* Being remounted read-only */
	int s_readonly_remount;

	/* per-sb errseq_t for reporting writeback errors via syncfs */
	errseq_t s_wb_err;

	/* AIO completions deferred from interrupt context */
	struct workqueue_struct *s_dio_done_wq;
	struct hlist_head s_pins;

	/*
	 * Owning user namespace and default context in which to
	 * interpret filesystem uids, gids, quotas, device nodes,
	 * xattrs and security labels.
	 */
	struct user_namespace *s_user_ns;

	/*
	 * The list_lru structure is essentially just a pointer to a table
	 * of per-node lru lists, each of which has its own spinlock.
	 * There is no need to put them into separate cachelines.
	 */
	struct list_lru		s_dentry_lru;
	struct list_lru		s_inode_lru;
	struct rcu_head		rcu;
	struct work_struct	destroy_work;

	struct mutex		s_sync_lock;	/* sync serialisation lock */

	/*
	 * Indicates how deep in a filesystem stack this SB is
	 */
	int s_stack_depth;

	/* s_inode_list_lock protects s_inodes */
	spinlock_t		s_inode_list_lock ____cacheline_aligned_in_smp;
	struct list_head	s_inodes;	/* all inodes */

	spinlock_t		s_inode_wblist_lock;
	struct list_head	s_inodes_wb;	/* writeback inodes */
} __randomize_layout;

In other file systems such as ext2/ext3 which is basically used as fs for linux system also has a fs.h to realize such struct.If the storage isn't disk related, which means no superblock was presented , a new superblock will be created and loaded to the RAM.In other cases, superblock was stored along with other blocks on a hardware.

struct list_head s_list A link that lead to all superblocks.The head node of the list.

unsigned char s_blocksize_bits/s_blocksize Register the size of each block(bits of bytes.)

 const structsuper_operations   *s_op;  Most important part of the structure which calls the functions to operate the block.Will be discussed later.

structlist_head    s_inodes; headers of inodes list.

The functions for creating or operating the superblocks were located in fs/super.c.Be aware that there are also super.cs in other fs such as ntfs,ext4, which means they have to realize the functions with their own rules. These will be discussed in later blogs.

A superblock is being created by alloc_super() in super.c, right after a filesystem is installed, a vfs will use such funtion to access the filesystem and get its superblock, then store the data to the newly created superblock in RAM.If no such superblock in the filesystem(when the 'filesystem' isn't a real disk but some other hardwares.), a superblock will also be created and the data needed will be filled.

Linux Kernal FS-SuperBlock(1)

super.c will also be discussed later.

fs.h/s_op(super_operations)

Just as its name says, s_op listed operations for superblocks that VFS might call while running.

super_operations was also defined in fs.h, right below superblock itself.

struct super_operations {
   	struct inode *(*alloc_inode)(struct super_block *sb);
	void (*destroy_inode)(struct inode *);
	void (*free_inode)(struct inode *);

   	void (*dirty_inode) (struct inode *, int flags);
	int (*write_inode) (struct inode *, struct writeback_control *wbc);
	int (*drop_inode) (struct inode *);
	void (*evict_inode) (struct inode *);
	void (*put_super) (struct super_block *);
	int (*sync_fs)(struct super_block *sb, int wait);
	int (*freeze_super) (struct super_block *);
	int (*freeze_fs) (struct super_block *);
	int (*thaw_super) (struct super_block *);
	int (*unfreeze_fs) (struct super_block *);
	int (*statfs) (struct dentry *, struct kstatfs *);
	int (*remount_fs) (struct super_block *, int *, char *);
	void (*umount_begin) (struct super_block *);

	int (*show_options)(struct seq_file *, struct dentry *);
	int (*show_devname)(struct seq_file *, struct dentry *);
	int (*show_path)(struct seq_file *, struct dentry *);
	int (*show_stats)(struct seq_file *, struct dentry *);
#ifdef CONFIG_QUOTA
	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
	struct dquot **(*get_dquots)(struct inode *);
#endif
	long (*nr_cached_objects)(struct super_block *,
				  struct shrink_control *);
	long (*free_cached_objects)(struct super_block *,
				    struct shrink_control *);
};

   struct inode *(*alloc_inode)(struct super_block *sb);  Alloc a inode.

An inode contains all data required for VFS while operating files and indexes.If the physical file system accuire an inode, it can be loaded directly, if not, however the data were stored in the disk, an inode has to be alloced and filled.Most of the time an inode only stand for one file, device or pipe in the file system, but since the inode is made for VFS in RAM, it is only created while a file is to be accessed.(will also be discussed later.)

void (*destroy_inode)(struct inode *); destroy the inode and realise the resources.

void (*dirty_inode) (struct inode *, int flags); Indexes dirty inode(a dirty inode means it's changed recently)

int (*write_inode) (struct inode *, struct writeback_control *wbc); Write the data of the inode to the disk.The latter parameter shows the way of saving. 

int (*drop_inode) (struct inode *); VFS will call this function while the last quota towards the inode is released.

int (*remount_fs) (struct super_block *, int *, char *); Reinstall filesystem.

#ifdef->endif block:quota shows the limited space a disk allowed and space already used.

These functions will be called by VFS while running.

end of line.

上一篇:子类继承中使用super()调用父类方法


下一篇:this和super的总结