/////////////////////////////////////////////////////////////////
asmlinkage void __init start_kernel(void)
{
// 省略很多
vfs_caches_init_early();
        thread_info_cache_init();
//省略
       vfs_caches_init(num_physpages);
ftrace_init();

/* Do the rest non-__init'ed, we're now alive */
rest_init();
}
////////////////////////////////////////////////////////////////////
fs/dcache.c

本函数由init/main.c的asmlinkage void __init start_kernel(void)函数调用
void __init vfs_caches_init(unsigned long mempages)
{
unsigned long reserve;

/* Base hash sizes on available memory, with a reserve equal to
           150% of current kernel size */

reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
mempages -= reserve;

names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);

filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);

dcache_init();
inode_init();
files_init(mempages);
mnt_init();
bdev_cache_init();
chrdev_init();

////////////////////////////////////////
fs/namespace.c
void __init mnt_init(void)
{
unsigned u;
int err;

init_rwsem(&namespace_sem);

mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount),
0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);

mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);

if (!mount_hashtable)
panic("Failed to allocate mount hash table\n");

printk("Mount-cache hash table entries: %lu\n", HASH_SIZE);

for (u = 0; u < HASH_SIZE; u++)
INIT_LIST_HEAD(&mount_hashtable[u]);

err = sysfs_init();
if (err)
printk(KERN_WARNING "%s: sysfs_init error: %d\n",
__func__, err);
fs_kobj = kobject_create_and_add("fs", NULL);
if (!fs_kobj)
printk(KERN_WARNING "%s: kobj create error\n", __func__);
init_rootfs();
init_mount_tree();
}
/////////////////////////////////////////////////////////////////////////////////////////////////
 
fs/ramfs/inode.c
module_init(init_ramfs_fs)
module_exit(exit_ramfs_fs)
 
int __init init_rootfs(void)
{
int err;

err = bdi_init(&ramfs_backing_dev_info);
if (err)
return err;

err = register_filesystem(&rootfs_fs_type);
if (err)
bdi_destroy(&ramfs_backing_dev_info);

return err;
}
////////////////////////////////


////////////////////////////// 
 
//////////////////////////////////
fs/namespace.c
//见mount系统调用日志
static void __init init_mount_tree(void)
{
struct vfsmount *mnt;
struct mnt_namespace *ns;
struct path root;

mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
if (IS_ERR(mnt))
panic("Can't create rootfs");
                //为进程号0的命名空间分配一个namespace对象 
ns = kmalloc(sizeof(*ns), GFP_KERNEL);
if (!ns)
panic("Can't allocate initial namespace");
atomic_set(&ns->count, 1);
INIT_LIST_HEAD(&ns->list);
init_waitqueue_head(&ns->poll);
ns->event = 0;
            //将分配到的namespace插入到由do_kern_mount()函数返回的已安装文件系统描述符中 
list_add(&mnt->mnt_list, &ns->list);
ns->root = mnt;
mnt->mnt_ns = ns;

init_task.nsproxy->mnt_ns = ns;
get_mnt_ns(ns);

root.mnt = ns->root;
root.dentry = ns->root->mnt_root;
//将进程0的根目录和当前工作目录设置为根文件系统,后面会有安装实际根文件系统
set_fs_pwd(current->fs, &root);
set_fs_root(current->fs, &root);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
fs/ramfs/inode.c
static struct    backing_dev_info      ramfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
.capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK |
 BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
 BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
}; 
///
static struct file_system_type      ramfs_fs_type = {
.name = "ramfs",
.get_sb = ramfs_get_sb,
.kill_sb = kill_litter_super,
};
/// fs/ramfs/inode.c
static struct file_system_type     rootfs_fs_type = {
.name = "rootfs",
.get_sb = rootfs_get_sb,
.kill_sb = kill_litter_super,
}; 
///

///
include/linux/backing-dev.h
struct     backing_dev_info {
unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */
unsigned long state; /* Always use atomic bitops on this */
unsigned int capabilities; /* Device capabilities */
congested_fn *congested_fn; /* Function pointer if device is md/dm */
void *congested_data; /* Pointer to aux data for congested func */
void (*unplug_io_fn)(struct backing_dev_info *, struct page *);
void *unplug_io_data;

struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS];

struct prop_local_percpu completions;
int dirty_exceeded;

unsigned int min_ratio;
unsigned int max_ratio, max_prop_frac;

struct device *dev;

#ifdef CONFIG_DEBUG_FS
struct dentry *debug_dir;
struct dentry *debug_stats;
#endif
};
/// include/linux/fs.h
struct file_system_type {
const char *name;
int fs_flags;
int (*get_sb) (struct file_system_type *, int,
      const char *, void *, struct vfsmount *);
void (*kill_sb) (struct super_block *);
struct module *owner;
struct file_system_type * next;
struct list_head fs_supers;

struct lock_class_key s_lock_key;
struct lock_class_key s_umount_key;

struct lock_class_key i_lock_key;
struct lock_class_key i_mutex_key;
struct lock_class_key i_mutex_dir_key;
struct lock_class_key i_alloc_sem_key;
}; 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////
 fs/ramfs/inode.c
 
static int rootfs_get_sb(struct file_system_type *fs_type,
                         int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super,
   mnt);
}
//////////////////////////////////
fs/super.c
int get_sb_nodev(struct file_system_type *fs_type,
                                  int flags, void *data,
                                    int (*fill_super)(struct super_block *, void *, int),
                                        struct vfsmount *mnt)
{
int error;
struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);

if (IS_ERR(s))
return PTR_ERR(s);

s->s_flags = flags;

error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
if (error) {
up_write(&s->s_umount);
deactivate_super(s);
return error;
}
s->s_flags |= MS_ACTIVE;
return simple_set_mnt(mnt, s);
} 
////////////////////////////////////

/////////////////////////////////实际安装根文件系统///////////////////////////////////////////////////////////////////////////////

static void noinline __init_refok rest_init(void)
__releases(kernel_lock)
{
int pid;

kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
numa_default_policy();
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
unlock_kernel();

/*
* The boot idle thread must execute schedule()
* at least once to get things moving:
*/
init_idle_bootup_task(current);
preempt_enable_no_resched();
schedule();
preempt_disable();

/* Call into cpu_idle with preempt disabled */
cpu_idle();
}
///
init/main.c
static int __init kernel_init(void * unused)
{
lock_kernel();
/*
* init can run on any cpu.
*/
set_cpus_allowed_ptr(current, CPU_MASK_ALL_PTR);
/*
* Tell the world that we're going to be the grim
* reaper of innocent orphaned children.
*
* We don't want people to have to make incorrect
* assumptions about where in the task array this
* can be found.
*/
init_pid_ns.child_reaper = current;

cad_pid = task_pid(current);

smp_prepare_cpus(setup_max_cpus);

do_pre_smp_initcalls();
start_boot_trace();

smp_init();
sched_init_smp();

cpuset_init_smp();

do_basic_setup();

/*
* check if there is an early userspace init.  If yes, let it do all
* the work
*/

if (!ramdisk_execute_command)
ramdisk_execute_command = "/init";

if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
ramdisk_execute_command = NULL;
prepare_namespace();
}

/*
* Ok, we have completed the initial bootup, and
* we're essentially up and running. Get rid of the
* initmem segments and start the user-mode stuff..
*/
stop_boot_trace();
init_post();
return 0;
}
////
/*
 * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
 */
 init/do_mounts.c
void __init prepare_namespace(void)
{
int is_floppy;

if (root_delay) {
printk(KERN_INFO "Waiting %dsec before mounting root device...\n",
      root_delay);
ssleep(root_delay);
}

/* wait for the known devices to complete their probing */
while (driver_probe_done() != 0)
msleep(100);

md_run_setup();

if (saved_root_name[0]) {
root_device_name = saved_root_name;
if (!strncmp(root_device_name, "mtd", 3) ||
   !strncmp(root_device_name, "ubi", 3)) {
mount_block_root(root_device_name, root_mountflags);
goto out;
}
                //把 root_device_name变量置为从启动参数"root"中获取的设备文件名
ROOT_DEV = name_to_dev_t(root_device_name);
if (strncmp(root_device_name, "/dev/", 5) == 0)
root_device_name += 5;
}

if (initrd_load())
goto out;

/* wait for any asynchronous scanning to complete */
if ((ROOT_DEV == 0) && root_wait) {
printk(KERN_INFO "Waiting for root device %s...\n",
saved_root_name);
while (driver_probe_done() != 0 ||
(ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
msleep(100);
}

is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;

if (is_floppy && rd_doload && rd_load_disk(0))
ROOT_DEV = Root_RAM0;

mount_root();
out:
        //移动rootfs文件系统根目录上的已安装文件系统的安装点    
          //注意rootfs特殊文件系统没有被卸载,他只是隐藏在基于磁盘的根文件系统下了。 
sys_mount(".", "/", NULL, MS_MOVE, NULL);
sys_chroot(".");
}

////////////////////////////////////////////////实际安装根文件系统end/////////////////////////////////////////////////////////////////////////////////////////////////// 
12-16 20:16