zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    java MessageFormat来生成模板字符串
    linux 用户身份切换
    linux 账号管理
    java 模块化
    mysql 存储过程执行while循环 Lost connection to MySQL server during query
    git 加速
    测试目录
    centos 安装gitblit
    centos7 安装mongoDB
    MySQL 批量修改库、表、列的排序规则,处理数据库大小写不敏感问题。
  • 原文地址:https://www.cnblogs.com/linengier/p/2991106.html
Copyright © 2011-2022 走看看