This article is based on linux3.10 an embedded system, the file system configuration options are set as follows:
Figure 1.1 Root File System configuration option settings
The two lines are configured as follows:
[*] Initial Ramfilesystem and RAM disk (INITRAMFS/INITRD) support
(usr/rootfs.cpio.gz) Initramfs source file (s)
The meaning of both lines is to enable the Initramfs file system and to use the usr/roorfs.cpio.gz in the source directory as the root file system. The kernel loads the filesystem into memory and mounts the file system as the root file system.
Under the WinDOS usually have C disk, d disk, such as partitions, can be the root file system under Linux "/" to understand as a C disk such devices, for the embedded scenario described here, this device is a whole NAND FLASH, It looks something like Figure 1.1, where the root file system is mounted to invoke Rootfs_mount to read the Super block information on Flash and build the VFS layer's Super block information based on that information. Super Block information acquisition is achieved through the MTD layer interface, in fact, the bottom is through the CPU NAND Flash controller to achieve NAND flash read and write.
Fig. 1.2 NAND device with only one root node
In the Linux boot-linux 3.10 kernel and the virtual file system (VFS)-based on linux3.10, the loading process and the file system mount are described separately, and some of these pointcuts originate from these two articles.
The first is the Start_kernel () function, which is described in the startup, which calls the Vfs_caches_init () function, then calls Inode_init () initializes the index node, and then calls the Mnt_init () function to mount the root file system. The Mount_init () function calls the Init_rootfs function.
Figure 1.3 The root file system mount function call flow
Calling the Init_rootfs function does not pass arguments, so it is much easier to parse. BDI is the abbreviation for Backing_dev_info, Bdi_init used to initialize some of the fields in the backing store, which include writeback lists, write-back locks, and read-write policies, and are not related to mount relationships. Register_filesystem in the virtual file system (VFS)-based on linux3.10 explicitly indicates that a file system wants to use a file system that must first be loaded to represent the parameters of that filesystem Rootfs_fs_ Type includes the Mount method for the file file system.
<fs/ramfs/inode.c>
277 int __init init_rootfs (void)
278 {
279 int err;
280 err = Bdi_init (&ramfs_backing_dev_info);
281 if (err)
282 return err;
283
284 err = Register_filesystem (&rootfs_fs_type);
285 if (err)
286 Bdi_destroy (&ramfs_backing_dev_info);
287
return err;
289}
The structure of the root file system that corresponds here is defined as follows:
<fs/ramfs/inode.c>
static struct File_system_type Rootfs_fs_type = {
. Name = "Rootfs",
. Mount = Rootfs_mount,
. KILL_SB = Kill_litter_super,
};
Init_mount_tree () also does not have to pass the parameter, the Get_fs_type function in the VFS that article mentioned, here is obtains the parameter "Rootfs" the corresponding file system type, If you find that the current file system does not register the file system, you will try to mount the file system as a module. A file system can be registered only once, but multiple devices may be mounted as a device of the same file system type.
<fs/namespace.c> 2686 static void __init init_mount_tree (void) 2687 {2688 struct vfsmount *mnt
;
2689 struct Mnt_namespace *ns;
2690 struct path root;
2691 struct File_system_type *type;
2692 2693 type = Get_fs_type ("Rootfs");
2694 if (!type) 2695 panic ("Can ' t find rootfs type");
2696 mnt = vfs_kern_mount (type, 0, "Rootfs", NULL);
2697 Put_filesystem (type);
2698 if (Is_err (MNT)) 2699 Panic ("Can ' t create Rootfs");
2700 2701 ns = Create_mnt_ns (MNT);
2702 if (Is_err (NS)) 2703 Panic ("Can ' t allocate initial");
2704 2705 Init_task.nsproxy->mnt_ns = ns;
2706 Get_mnt_ns (NS);
2707 2708 root.mnt = mnt;
2709 root.dentry = mnt->mnt_root;
2710 2711 set_fs_pwd (Current->fs, &root);
2712 Set_fs_root (Current->fs, &root); 2713}
The
2694 line determines whether the file system is found, because the Mount method is required to mount the root file system when it is used, and the Mount method exists in the file system type, so 2693 rows must be looked up first, and if not found, 2695 lines will show panic. This is a very serious error in the kernel, which indicates that the device will be down. 2696 lines are in the actual sense of the mount.
struct vfsmount * vfs_kern_mount (struct file_system_type *type, int flags, const char *name, void *data)
{struct mount *mnt;
struct Dentry *root;
if (!type) return err_ptr (-enodev);
/* Allocates and initializes a mount structure that stores several information about the mount, including the mount point (directory entry), the parent mount point, several mount lists, etc./mnt = ALLOC_VFSMNT (name);
if (!MNT) return err_ptr (-ENOMEM);
if (Flags & ms_kernmount) mnt->mnt.mnt_flags = mnt_internal; Root = Mount_fs (type, flags, name, data);
The true Mount function, if the mount succeeds, will return the directory entry if (Is_err (root)) {free_vfsmnt (MNT);
return err_cast (root); } mnt->mnt.mnt_root = root;
mount point directory entry printk (Kern_emerg "mnt->mnt.mnt_root:%s", root->d_iname);
MNT->MNT.MNT_SB = root->d_sb;//mount point Super block mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt;//Parent directory information Br_write_lock (&vfsmount_lock);
Add the newly mounted root file system to the List_add_tail of the Super block on the Mount list (&mnt->mnt_instance, &root->d_sb->s_mounts);
Br_write_unlock (&vfsmount_lock);
Return &mnt->mnt; }
Mount_fs's job is to complete the mount of the root file system, which is actually reading the Flash Super block and populating the VFS layer with its own super block.
<fs/super.c>
1086 struct dentry *
1087 mount_fs (struct file_system_type *type, int flags, const char *name, void *data)
1088 {
1089 struct dentry *root;
1090 struct Super_block *sb;
1091 char *secdata = NULL;
1092 int error =-ENOMEM;
... 1103//This is the Mount method that calls the root file system.
1104 root = Type->mount (type, flags, name, data);
1105 if (Is_err (root)) {
1106 error = Ptr_err (root);
1107 Goto Out_free_secdata;
1108 }
1109 sb = root->d_sb;
... 1137 return err_ptr (error);
1138}
The Rootfs_mount function is actually the encapsulation of the Mount_nodev, and it's easy to understand the naming method here, because the filesystem is not actually a physical device, and it really only exists in memory. The last parameter, Ramfs_fill_super, specifies the fill method for the Super block.
static struct dentry *rootfs_mount (struct file_system_type *fs_type, int flags, const char *dev_name, VO ID *data) {return Mount_nodev (Fs_type, Flags|ms_nouser, data, ramfs_fill_super);} Mount_nodev first Call Sget to get the super block,
Then call the pointer function argument fill_super to populate it. struct Dentry *mount_nodev (struct file_system_type *fs_type, int flags, void *data, int (*fill_super) (struct super_block
*, void *, int)) {int error;
struct Super_block *s = sget (Fs_type, NULL, set_anon_super, flags, NULL);
if (Is_err (s)) return err_cast (s);
Error = Fill_super (s, data, Flags & Ms_silent 1:0);
if (Error) {deactivate_locked_super (s);
return err_ptr (Error);
} s->s_flags |= ms_active;
Return Dget (S->s_root); }