Chinaunix首页 | 论坛 | 博客
  • 博客访问: 152847
  • 博文数量: 101
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 9
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-17 08:11
文章分类
文章存档

2017年(91)

2016年(10)

我的朋友

分类: LINUX

2017-03-13 14:09:09

原文地址:VFS的rootfs初始化 作者:xingzuzi

Linux系统中,每个文件系统都会以数据结构来表示,定义为:

Code.1

struct file_system_type {

const char *name; //文件系统名称,如ext2

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;

};

注册文件系统就是将各种文件系统实例化,形成链表,内核中使用一个名为file_systems的全局变量来指向该链表表头。

Code.2

static struct file_system_type *file_systems;

VFS建立目录树首先要初始化rootfs,然后将其挂接。

对于rootfs类型,其文件系统实例结构定义为:

Code.3

static struct file_system_type rootfs_fs_type = {

        .name       = "rootfs",

        .get_sb     = rootfs_get_sb, //get_sb的方法为rootfs_get_sb,这个在init_mnt_tree中会用到

        .kill_sb    = kill_litter_super,

    };

此时用图来表示为:

一个独立的file_systems指针,一个file_system_typerootfs

首先要初始化rootfs

Code.4

int __init init_rootfs(void) //初始化rootfs

{

    return register_filesystem(&rootfs_fs_type); //注册rootfs

}

其中

Code.4.1

int register_filesystem(struct file_system_type * fs)

{

    int res = 0;

    struct file_system_type ** p;

   

    if (fs->next)

        return -EBUSY;

    INIT_LIST_HEAD(&fs->fs_supers);//初始化LIST_HEAD fs->fs_supers

    write_lock(&file_systems_lock); //

    p = find_filesystem(fs->name); //检查文件系统是否被注册,下面的详细说明

    if (*p)

        res = -EBUSY;

    else

        *p = fs; //没有被注册,将file_systems的链表指向此fs,形成注册的文件系统的链表结构

    write_unlock(&file_systems_lock);

    return res;

}

下面是find_filesystem的实现:

Code.4.1.1

static struct file_system_type **find_filesystem(const char *name)

    {

    struct file_system_type **p;

    for (p=&file_systems; *p; p=&(*p)->next) //file_systems是全局变量指向文件系统类型

        if (strcmp((*p)->name,name) == 0) //查找文件系统是否被注册过,如果没有,那么p最后为file_systems链尾的next,如果被注册过,那么返回指向这个文件系统的指针

          break;

    return p;

}

这样,rootfs就注册成功了,此时可表示为:

File_systemsr指向file_system_type(ramfs)

然后是初始化树,init_mount_tree

init_mount_tree首先会调用do_kern_mount("rootfs", 0, "rootfs", NULL);进行rootfs的挂接。

Code.5

struct vfsmount *

do_kern_mount(const char *fstype, int flags, const char *name, void *data)

{

    struct file_system_type *type = get_fs_type(fstype); //通过ramfs得到ramfsfile_system_type

    struct vfsmount *mnt;

    if (!type)

        return ERR_PTR(-ENODEV);

    mnt = vfs_kern_mount(type, flags, name, data);//开始干正事了

    put_filesystem(type);

    return mnt;

}

只保留主干代码的vfs_kern_mount

Code.5.1

struct vfsmount *

vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)

{

    struct vfsmount *mnt;

    int error;

    mnt = alloc_vfsmnt(name); //初始化一个struct vfsmount mnt,并初始化struct中的LIST_HEADmnt->mnt_count=1;mnt->mnt_devname=name

    error = type->get_sb(type, flags, name, data, mnt);//建立一个superblock,然后与mnt建立上关系,下面会有说明

    if (error < 0)

        goto out_free_secdata;

    mnt->mnt_mountpoint = mnt->mnt_root;

    mnt->mnt_parent = mnt;//parent指向自己

    return mnt;

}

type->get_sb的实例在此时应该为ramfs_get_sb

Code.5.1.1

int ramfs_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, data, ramfs_fill_super, mnt);

//使用ramfs_fill_super来写superblock的相关数据

}

Code.5.1.1.1

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);//初始化一个super block,设置s->s_devs->s_type=type,s->s_id=type->name,super_blocks指向s->s_list,将type->fs_super指向s->s_instances

    error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);//这里的fill_super即是ramfs_fill_super,下面详细说明

    s->s_flags |= MS_ACTIVE;

    return simple_set_mnt(mnt, s);

}

Code.5.1.1.1.1

static int ramfs_fill_super(struct super_block * sb, void * data, int silent)

{

    struct inode * inode;

    struct dentry * root;

    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;//这里定义的ramfs_ops

/*

static const struct super_operations ramfs_ops = {

        .statfs     = simple_statfs,

        .drop_inode = generic_delete_inode,

};

*/

    sb->s_time_gran = 1;

    inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0);//初始化一个inode,并将与sb建立关系,设置inode各种属性

    root = d_alloc_root(inode);//分配dentry root

    if (!root) {

        iput(inode);

        return -ENOMEM;

    }

    sb->s_root = root;

    return 0;

}

这样do_kern_mount就结束了,此时用图可表示为:
阅读(672) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~