Linux file system initialization process (2) --- mount rootfs file system

First, the purpose

    This article mainly describes the first stage of the linux3.10 file system initialization process: mounting the rootfs file system.

    Rootfs is a memory-based file system, and all operations are done in memory; there is no actual storage device, so device drivers are not required. Based on the above reasons, Linux uses the rootfs file system during the startup phase. When the disk driver and disk file system are successfully loaded, the linux system will switch the system root directory from rootfs to the disk file system.

 

Second, the main function call process

    Figure 1 describes the function call relationship of mounting rootfs (the red part in the figure), which is convenient for subsequent analysis.

    It is found from the figure that sysfs will be mounted before rootfs is mounted. The reason for this is to ensure that sysfs can fully record the device driver model.

    sysfs_init() completes the function of registering and mounting the sysfs file system; init_rootfs() is responsible for registering rootfs, init_mount_tree() is responsible for mounting rootfs, and linking the namespace of init_task to it.

                                   figure 1

 

Three, linux file system initialization

    vfs_cache_init() first establishes and initializes the directory hash table dentry_hashtable and the inode hash table inode_hashtable; then sets the maximum number of files that the kernel can open; finally calls mnt_init() to complete the registration and mounting of the sysfs and rootfs file systems.

    Linux uses a hash table to store directories and index nodes to improve the search efficiency of directories and index nodes; dentry_hashtable is the directory hash table, and inode_hashtable is the index node hash table.

 

Fourth, mount the sysfs file system

    sysfs is used to record and display the linux driver model. sysfs is mounted before rootfs to prepare for the comprehensive display of the linux driver model.

    mnt_init() calls sysfs_init() to register and mount the sysfs file system, and then calls kobject_create_and_add() to create the "fs" directory.

 

2735 err = sysfs_init();  
2736 if (err)  
2737 printk(KERN_WARNING "%s: sysfs_init error: %d\n",  
2738 __func__, err);  
2739 fs_kobj = kobject_create_and_add("fs", NULL);  
2740 if (!fs_kobj)  
2741 printk(KERN_WARNING "%s: kobj create error\n", __func__);  

 

    The following details the mounting process of the sysfs file system:

    1. sysfs_init() calls register_filesystem() to register the file system type sysfs_fs_type, and adds it to the global singly linked list file_systems. The sysfs_fs_type is defined as follows. The .mount member function is responsible for the creation and initialization of the super block, the root directory, and the index node.

 

173     err = register_filesystem(&sysfs_fs_type);  
174     if (!err) {  
175         sysfs_mnt = kern_mount(&sysfs_fs_type);  
176         if (IS_ERR(sysfs_mnt)) {  
177             printk(KERN_ERR "sysfs: could not mount!\n");  
178             err = PTR_ERR(sysfs_mnt);  
179             sysfs_mnt = NULL;  
180             unregister_filesystem(&sysfs_fs_type);  
181             goto out_err;  
182         }   

 

 

 
152 static struct file_system_type sysfs_fs_type = {  
153     .name       = "sysfs",  
154     .mount      = sysfs_mount,  
155     .kill_sb    = sysfs_kill_sb,  
156     .fs_flags   = FS_USERNS_MOUNT,  
157 };  
 

 

 

    2. sysfs_init()->kern_mount()->vfs_kern_mount() creates and initializes the struct mount mount point, and uses the global variable sysfs_mnt to save the mount item (mnt member) of the mount point.

 
783     mnt = alloc_vfsmnt(name);  
784     if (!mnt)  
785         return ERR_PTR(-ENOMEM);  
 

 

    3. kern_mount() calls the .mount member sysfs_mount() of sysfs_fs_type to create and initialize data structures such as the super block, the root directory'/', and the index node of the root directory; and add the super block to the global single-linked list super_blocks to add the index node Add to the hash table inode_hashtable and the inode linked list of the super block.

    At present, we can draw an important conclusion: kern_mount() mainly completes the creation and initialization of mount points, super blocks, root directories, and index nodes. It can be regarded as an atomic operation. This function will be used frequently in the future.

 

790     root = mount_fs(type, flags, name, data);  
1091 struct dentry *  
1092 mount_fs(struct file_system_type *type, int flags, const char *name, void*data)  
1093 {  
1094     struct dentry *root;  
              ...  
1108   
1109     root = type->mount(type, flags, name, data);  

 

 

 
107 static struct dentry *sysfs_mount(struct file_system_type *fs_type,   
108 int flags, const char *dev_name, void *data)   
109 {...   
112 struct super_block *sb;   
                  ...   
125 sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);   
            ...   
130 if (!sb->s_root) {   
131 error = sysfs_fill_super(sb, data, flags & MS_SILENT? 1: 0);   
      4. vfs_kern_mount() initializes the root directory and super of the mount point Piece.

 

 

 

 

 

796 mnt->mnt.mnt_root = root;  
797 mnt->mnt.mnt_sb = root->d_sb;  
798 mnt->mnt_mountpoint = mnt->mnt.mnt_root;  
799 mnt->mnt_parent = mnt;  
 

    5、mnt_init()调用kobject_create_and_add()创建"fs"目录。

 

 

 

    Through the above steps, the view of the sysfs file system in the VFS is shown in Figure 2: The mount point points to the super block and the root directory; the super block is in the super_blocks singly linked list, and all index nodes belonging to the file system are linked; the root The directory'/' and the directory "fs" point to their respective index nodes; in order to improve the search efficiency, the index nodes are stored in the hash table.

                    figure 2

 

Five, mount the rootfs file system

    mnt_init() calls init_rootfs() to register rootfs, and then calls init_mount_tree() to mount rootfs.

    The following details the mounting process of the rootfs file system:
    1. mnt_init() calls init_rootfs() to register the file system type rootfs_fs_type, and adds it to the global singly linked list file_systems.

The rootfs_fs_type is defined as follows. The mount member function is responsible for the establishment and initialization of the super block, the root directory, and the index node.

 

265 static struct file_system_type rootfs_fs_type = {  
266     .name       = "rootfs",  
267     .mount      = rootfs_mount,  
268     .kill_sb    = kill_litter_super,  
269 };  

 

    2. Init_mount_tree() calls vfs_kern_mount() to mount the rootfs file system. The detailed mounting process is similar to that of the sysfs file system and will not be repeated.

    3. Init_mount_tree() calls create_mnt_ns() to create a namespace, and sets the mount point of the namespace to the mount point of rootfs, and at the same time links the mount point of rootfs to the doubly linked list of the namespace.

 

 

2459 static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)  
2460 {  
2461     struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);  
2462     if (!IS_ERR(new_ns)) {  
2463         struct mount *mnt = real_mount(m);  
2464         mnt->mnt_ns = new_ns;  
2465         new_ns->root = mnt;  
2466         list_add(&mnt->mnt_list, &new_ns->list);  
2467     }   
 

 

 

    4. Init_mount_tree() sets the namespace of init_task, and calls set_fs_pwd() and set_fs_root() to set the current directory and root directory of the init_task task to the root directory'/' of rootfs.

 

 

2696     ns = create_mnt_ns(mnt);  
2697     if (IS_ERR(ns))  
2698         panic("Can't allocate initial namespace");  
2699   
2700     init_task.nsproxy->mnt_ns = ns;  
2701     get_mnt_ns(ns);  
2702   
2703     root.mnt = mnt;  
2704     root.dentry = mnt->mnt_root;  
2705   
2706     set_fs_pwd(current->fs, &root);  
2707     set_fs_root(current->fs, &root);  

 

 

    Through the above analysis, we found that the difference between sysfs and rootfs is that although the system has both the sysfs and rootfs file systems mounted, only the rootfs is in the namespace of the init_task process, which means that the system currently uses the rootfs file system.

    At this time, the view of sysfs and rootfs in VFS is shown in Figure 3: In order to highlight the main relationship, the mount point is omitted to point to the super block and the root directory.
It can be seen from the figure that rootfs is in the namespace of the process, and the root and pwd of the fs_struct data structure of the process point to the root directory'/' of rootfs, so the user actually uses the rootfs file system. In addition, rootfs provides the'/' root directory for VFS, so file operations and file system mounting operations can be performed on VFS.

                   image 3

 

Six, summary

    When the linux file system is initialized, the sysfs and rootfs file systems are mounted at the same time, but only the rootfs is in the namespace of the process, and the root directory and pwd directory of the process point to the root directory of the rootfs. At this point, the root directory of the Linux VFS has been prepared (the root directory of rootfs'/'), and the user can use the system call to expand the VFS tree.

Guess you like

Origin blog.csdn.net/daocaokafei/article/details/114873016