rootfs文件系统的建立

因为linux支持模块机制,所以我们可以将文件系统编译为模块,所以文件系统系统类型的注册的注册有多种方式:要么已经包含在内核映像中,要么作为一个模块被动态加载。

在内核的加载函数中start_kernel-->vfs_caches_init(totalram_pages);完成对文件系统sysfs,ramfs,rootfs文件系统的注册;

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);
	dcache_init();//目录项的缓存初始化
	inode_init(); //初始化inode_hashtable索引节点的缓存
	files_init(mempages);//file的缓存
	mnt_init(); // 外设的挂载点的初始化
	bdev_cache_init();  //块设备的缓存
	chrdev_init();//字符设备的初始化
}

mnt_init:

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();//sysfs文件系统初始化
	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();//rootfs文件系统初始化
	init_mount_tree();
}

 sys_init()

fs/sysfs/symlink.c 
static struct file_system_type sysfs_fs_type = {
    .name        = "sysfs",
    .get_sb     = sysfs_get_sb,//创建并初始化super_block
    .kill_sb    = kill_anon_super,
};
int __init sysfs_init(void) { int err = -ENOMEM; sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache",sizeof(struct sysfs_dirent), 0, 0, NULL); if (!sysfs_dir_cachep) goto out; err = sysfs_inode_init(); if (err) goto out_err; err = register_filesystem(&sysfs_fs_type);//把sysfs文件系统,添加到file_systems链表中; if (!err) { sysfs_mount = kern_mount(&sysfs_fs_type); if (IS_ERR(sysfs_mount)) { printk(KERN_ERR "sysfs: could not mount!\n"); err = PTR_ERR(sysfs_mount); sysfs_mount = NULL; unregister_filesystem(&sysfs_fs_type); goto out_err; } } else goto out_err; out: return err; out_err: kmem_cache_destroy(sysfs_dir_cachep); sysfs_dir_cachep = NULL; goto out; }

 init_rootfs()

static struct file_system_type rootfs_fs_type = {
    .name        = "rootfs",
    .get_sb        = rootfs_get_sb,
    .kill_sb    = kill_litter_super,
};
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; }

 init_mount_tree

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);//申请vfsmount结构,并调用到具体的相应文件系统的mount函数
	if (IS_ERR(mnt))
		panic("Can't create rootfs");
        /*设置mnt_namespace命名空间*/ ns = kmalloc(sizeof(*ns), GFP_KERNEL);//分配命名空间 if (!ns) panic("Can't allocate initial namespace"); atomic_set(&ns->count, 1);    //namespace的引用计数(共享命名空间的进程数) INIT_LIST_HEAD(&ns->list);    //list指向所有已安装文件系统描述链表的头 init_waitqueue_head(&ns->poll);  //namespace等待队列初始化 ns->event = 0; list_add(&mnt->mnt_list, &ns->list); ns->root = mnt;   //root指向命名空间根目录的已安装文件系统描述符  struct vfsmount * root; mnt->mnt_ns = ns; init_task.nsproxy->mnt_ns = ns; //设置进程1的命名空间; 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); }

 do_kern_mount

struct vfsmount *
do_kern_mount(const char *fstype, int flags, const char *name, void *data)
{
	struct file_system_type *type = get_fs_type(fstype);//根据文件系统的名称,查找相应的结构体,获取rootfs文件系统的类型(rootfs_fs_type);
	struct vfsmount *mnt;
	if (!type)
		return ERR_PTR(-ENODEV);
	mnt = vfs_kern_mount(type, flags, name, data);
	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
	    !mnt->mnt_sb->s_subtype)
		mnt = fs_set_subtype(mnt, fstype);
	put_filesystem(type);
	return mnt;
}

 vfs_kern_mount

struct vfsmount *vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
	struct vfsmount *mnt;
	char *secdata = NULL;
	int error;
	if (!type)
		return ERR_PTR(-ENODEV);
	error = -ENOMEM;
	mnt = alloc_vfsmnt(name);
	if (!mnt)
		goto out;
	if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
		secdata = alloc_secdata();
		if (!secdata)
			goto out_mnt;
		error = security_sb_copy_data(data, secdata);
		if (error)
			goto out_free_secdata;
	}
	error = type->get_sb(type, flags, name, data, mnt);//调用具体文件系统的super_block创建和初始化函数
	if (error < 0)
		goto out_free_secdata;
	BUG_ON(!mnt->mnt_sb);

 	error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
 	if (error)
 		goto out_sb;

	mnt->mnt_mountpoint = mnt->mnt_root;
	mnt->mnt_parent = mnt;
	up_write(&mnt->mnt_sb->s_umount);
	free_secdata(secdata);
	return mnt;
out_sb:
	dput(mnt->mnt_root);
	deactivate_locked_super(mnt->mnt_sb);
out_free_secdata:
	free_secdata(secdata);
out_mnt:
	free_vfsmnt(mnt);
out:
	return ERR_PTR(error);
}

 rootfs_get_sb

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);
}

get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super, mnt);

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);//find or create a superblock
	if (IS_ERR(s))return PTR_ERR(s);
	s->s_flags = flags;
	error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
	if (error) {
		deactivate_locked_super(s);
		return error;
	}
	s->s_flags |= MS_ACTIVE;
     /*vfsmount和super_block建立联系*/ simple_set_mnt(mnt, s); return 0; }
void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
{
    mnt->mnt_sb = sb;  //指向具体文件系统的超级块对象
    mnt->mnt_root = dget(sb->s_root);//指向这个文件系统的根目录的dentry
}

ramfs_fill_super

static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
{
	struct ramfs_fs_info *fsi;
	struct inode *inode = NULL;
	struct dentry *root;
	int err;

	save_mount_options(sb, data);

	fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL);
	sb->s_fs_info = fsi;
	if (!fsi) {
		err = -ENOMEM;
		goto fail;
	}

	err = ramfs_parse_options(data, &fsi->mount_opts);
	if (err)
		goto fail;

	sb->s_maxbytes		= MAX_LFS_FILESIZE;
	sb->s_blocksize		= PAGE_CACHE_SIZE;
	sb->s_blocksize_bits	= PAGE_CACHE_SHIFT;
	sb->s_magic		= RAMFS_MAGIC;
	sb->s_op		= &ramfs_ops;
	sb->s_time_gran		= 1;

	inode = ramfs_get_inode(sb, S_IFDIR | fsi->mount_opts.mode, 0);
	if (!inode) {
		err = -ENOMEM;
		goto fail;
	}

	root = d_alloc_root(inode);
	sb->s_root = root;
	if (!root) {
		err = -ENOMEM;
		goto fail;
	}

	return 0;
fail:
	kfree(fsi);
	sb->s_fs_info = NULL;
	iput(inode);
	return err;
}

 ramfs_get_inode

struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
{
	struct inode * inode = new_inode(sb);

	if (inode) {
		inode->i_mode = mode;
		inode->i_uid = current_fsuid();
		inode->i_gid = current_fsgid();
		inode->i_mapping->a_ops = &ramfs_aops;
		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
		mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
		mapping_set_unevictable(inode->i_mapping);
		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
		switch (mode & S_IFMT) {
		default:
			init_special_inode(inode, mode, dev);
			break;
		case S_IFREG:
			inode->i_op = &ramfs_file_inode_operations;
			inode->i_fop = &ramfs_file_operations;
			break;
		case S_IFDIR:
			inode->i_op = &ramfs_dir_inode_operations;
			inode->i_fop = &simple_dir_operations;

			/* directory inodes start off with i_nlink == 2 (for "." entry) */
			inc_nlink(inode);
			break;
		case S_IFLNK:
			inode->i_op = &page_symlink_inode_operations;
			break;
		}
	}
	return inode;
}

 d_alloc_root

struct dentry * d_alloc_root(struct inode * root_inode)
{
	struct dentry *res = NULL;

	if (root_inode) {
		static const struct qstr name = { .name = "/", .len = 1 };
		res = d_alloc(NULL, &name);
		if (res) {
			res->d_sb = root_inode->i_sb;
			res->d_parent = res;
			d_instantiate(res, root_inode);
		}
	}
	return res;
}

d_alloc

struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
{
	struct dentry *dentry;
	char *dname;

	dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
	if (!dentry)
		return NULL;

	if (name->len > DNAME_INLINE_LEN-1) {
		dname = kmalloc(name->len + 1, GFP_KERNEL);
		if (!dname) {
			kmem_cache_free(dentry_cache, dentry); 
			return NULL;
		}
	} else  {
		dname = dentry->d_iname;
	}	
	dentry->d_name.name = dname;

	dentry->d_name.len = name->len;
	dentry->d_name.hash = name->hash;
	memcpy(dname, name->name, name->len);
	dname[name->len] = 0;

	atomic_set(&dentry->d_count, 1);
	dentry->d_flags = DCACHE_UNHASHED;
	spin_lock_init(&dentry->d_lock);
	dentry->d_inode = NULL;
	dentry->d_parent = NULL;
	dentry->d_sb = NULL;
	dentry->d_op = NULL;
	dentry->d_fsdata = NULL;
	dentry->d_mounted = 0;
	INIT_HLIST_NODE(&dentry->d_hash);
	INIT_LIST_HEAD(&dentry->d_lru);
	INIT_LIST_HEAD(&dentry->d_subdirs);
	INIT_LIST_HEAD(&dentry->d_alias);

	if (parent) {
		dentry->d_parent = dget(parent);
		dentry->d_sb = parent->d_sb;
	} else {
		INIT_LIST_HEAD(&dentry->d_u.d_child);
	}

	spin_lock(&dcache_lock);
	if (parent)
		list_add(&dentry->d_u.d_child, &parent->d_subdirs);
	dentry_stat.nr_dentry++;
	spin_unlock(&dcache_lock);

	return dentry;
}
原文地址:https://www.cnblogs.com/linengier/p/2991106.html