您的位置:首页 > 运维架构 > Linux

Linux内核---43.文件系统的挂载

2016-07-09 10:22 531 查看
一. 临时文件系统的挂载过程

系统开始时先挂载了一个临时的文件系统,通过这个临时的文件系统

init/main.c

start_kernel

{

    vfs_caches_init(totalram_pages);  ;在fs/dcache.c:创建一个虚拟的文件系统

        --> mnt_init                  ;在fs/namespace.c中
  

            --> init_rootfs           ;1.在fs/ramfs/inode.c中

            --> init_mount_tree();    ;2.在fs/namespace.c中

}

1.在fs/ramfs/inode.c中

int __init init_rootfs(void)

{

    bdi_init(&ramfs_backing_dev_info);       //初始化ramfs_backing_dev_info结构体

    register_filesystem(&rootfs_fs_type);    //1.1注册rootfs_fs_type,

}                                               即把rootfs_fs_type添加到全局变量中

static struct backing_dev_info ramfs_backing_dev_info = {

    .name        = "ramfs",

    .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 rootfs_fs_type = {

    .name        = "rootfs",

    .mount        = rootfs_mount,

    .kill_sb    = kill_litter_super,

};

1.1全局变量file_systems链表中将参数fs添加进来

int register_filesystem(struct file_system_type * fs)

{

    struct file_system_type ** p;

    INIT_LIST_HEAD(&fs->fs_supers);

    write_lock(&file_systems_lock);

    p = find_filesystem(fs->name, strlen(fs->name)); //1.1.1在全局变量file_system中查找  

    if (*p)              //如果在全局变量中能够找到,*p!=NULL说明这个文件系统己经注册过了

        res = -EBUSY;

    else                 //如果在全局变量中不能找到,*p==NULL,说明这个文件系统没有注册可以使用

        *p = fs;         //使得file_systems.next=fs,链表中增加一项

    write_unlock(&file_systems_lock);

    return res;

}

1.1.1在全局变量文件系统类型的链表中查找有没有名字等于参数name的文件系统类型

static struct file_system_type **find_filesystem(const char *name, unsigned len)

{

    struct file_system_type **p;

    for (p=&file_systems; *p; p=&(*p)->next)

        if (strlen((*p)->name) == len &&            //符合的条件是:名字与长度都相同

         strncmp((*p)->name, name, len) == 0)

            break;

    return p;

}

2.在fs/namespace.c中

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);   //2.1

    ns = create_mnt_ns(mnt);                           
//为新的文件系统创建namespace

    init_task.nsproxy->mnt_ns = ns;

    get_mnt_ns(ns);

    root.mnt = ns->root;

    root.dentry = ns->root->mnt_root;

    set_fs_pwd(current->fs, &root);                   //将进程0的当前路径设为rootfs的root

    set_fs_root(current->fs, &root);                  //将进程0的fs设为rootfs的root

}

2.1在fs/namespace.c中

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

{

    //从全局变量file_systems中找出刚刚注册的"rootfs"的地址

    struct file_system_type *type = get_fs_type(fstype); 

    struct vfsmount *mnt;

    if (!type)

        return ERR_PTR(-ENODEV);

    mnt = vfs_kern_mount(type, flags, name, data);   //2.1.1

    put_filesystem(type);                  //空函数

    return mnt;

}

2.1.1 rootfs的mount过程

在fs/namespace.c中

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

{

    struct vfsmount *mnt;

    struct dentry *root;

    if (!type)

        return ERR_PTR(-ENODEV);

    mnt = alloc_vfsmnt(name);                  //申请并初始化vfsmount结构体

    //这儿flags==0

    if (flags & MS_KERNMOUNT)

        mnt->mnt_flags = MNT_INTERNAL;

    root = mount_fs(type, flags, name, data);  //2.1.2

    mnt->mnt_root = root;

    mnt->mnt_sb = root->d_sb;

    mnt->mnt_mountpoint = mnt->mnt_root;

    mnt->mnt_parent = mnt;

    return mnt;

}

2.1.2调用具体文件系统的mount
在fs/super.c中

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

{

    struct dentry *root;

    struct super_block *sb;

    //file_system_type rootfs_fs_type 中定义.mount
= rootfs_mount,

    root = type->mount(type, flags, name, data);    //调用具体文件系统的mount

    sb = root->d_sb;

    sb->s_flags |= MS_BORN;

    up_write(&sb->s_umount);   

    return root;

}

2.1.3在fs/ramfs/inode.c中

static struct dentry *rootfs_mount(struct file_system_type *fs_type,

    int flags, const char *dev_name, void *data)

{

    return mount_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super);

}

2.1.4 在fs/super.c中

struct dentry *mount_nodev(struct file_system_type *fs_type, int flags, void *data,

    int (*fill_super)(struct
super_block *, void *, int))

{

    struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);   //2.1.5

    s->s_flags = flags;

    error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);   //2.1.6调用ramfs_fill_super,初始化super_block和root

    s->s_flags |= MS_ACTIVE;

    return dget(s->s_root);         //获取在fill_super中初始化好的root

}

2.1.5 分配一个super_block并做初初化

struct super_block *sget(struct file_system_type *type,

            int (*test)(struct
super_block *,void *),

            int (*set)(struct
super_block *,void *),

            void *data)

{

    struct super_block *s = NULL;

    struct super_block *old;

    int err;

retry: 

    if (!s) {       

        s = alloc_super(type);        //s是空的就需要分配一个super_block结构体

        if (!s)

            return ERR_PTR(-ENOMEM);

        goto retry;

    }

    err = set(s, data);

    s->s_type = type;

    strlcpy(s->s_id, type->name, sizeof(s->s_id));

    list_add_tail(&s->s_list, &super_blocks);

    list_add(&s->s_instances, &type->fs_supers);

    spin_unlock(&sb_lock);

    get_filesystem(type);

    return s;

}

2.1.6 初始化super_block并初始化root

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; 

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

    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结构体并初始化inode->i_ino=1

    inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);

    //初始化root的dentry结构体

    root = d_alloc_root(inode);

    sb->s_root = root;

    return 0;

}

二. 真正的文件系统的挂载过程

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: