Linux mount程式碼分析

來源:互聯網
上載者:User
1.    資料結構

vfsmount

struct vfsmount {
                struct list_head mnt_hash;          // hash表
                struct vfsmount*mnt_parent;   /* fs we are mounted on */
                struct dentry*mnt_mountpoint;              /* dentry ofmountpoint */
                struct dentry *mnt_root;              /* root of the mounted tree */|
                struct super_block*mnt_sb;      /* pointer to superblock */
                struct list_headmnt_mounts;    /* list of children,anchored here */
                struct list_headmnt_child;         /* and going throughtheir mnt_child */
                int mnt_flags;
                /* 4 bytes hole on 64bitsarches */
                const char *mnt_devname;         /* Name of device e.g. /dev/dsk/hda1 */
                struct list_head mnt_list;
                struct list_headmnt_expire;      /* link in fs-specificexpiry list */
                struct list_headmnt_share;        /* circular list ofshared mounts */
                struct list_headmnt_slave_list;/* list of slave mounts */
                struct list_headmnt_slave;         /* slave list entry */
                struct vfsmount*mnt_master;  /* slave is onmaster->mnt_slave_list */
                struct mnt_namespace*mnt_ns;             /* containingnamespace */
                int mnt_id;                                         /*mount identifier */
                int mnt_group_id;                           /* peer groupidentifier */
                /*
                 * We put mnt_count & mnt_expiry_mark atthe end of struct vfsmount
                 * to let these frequently modified fields in aseparate cache line
                 * (so that reads of mnt_flags wont ping-pongon SMP machines)
                 */
                atomic_t mnt_count;
                int mnt_expiry_mark;                    /* true if marked for expiry*/
                int mnt_pinned;
                int mnt_ghosts;
                int mnt_writers;
};

namespace

struct mnt_namespace {
                atomic_t                              count;
                struct vfsmount *            root;
                struct list_head                list;
                wait_queue_head_t poll;
                int event;
};

2.    初始化

void __init mnt_init(void)
                init_rwsem(&namespace_sem);
                static struct kmem_cache *mnt_cache =
                                kmem_cache_create("mnt_cache",sizeof(struct vfsmount),
                                                0, SLAB_HWCACHE_ALIGN |SLAB_PANIC, NULL);
                static struct list_head * mount_hashtable= (struct list_head *)__get_free_page(GFP_ATOMIC);
                for (u = 0; u <HASH_SIZE; u++)
                                INIT_LIST_HEAD(&mount_hashtable[u]);
                // 下面這行是初始化sysfs,放在這裡其實不太好,但由於初始化sysfs時用到了mount操作,而下面做其它檔案系統mount時又用到sysfs,所以也只能放這裡。
                sysfs_init();       
                fs_kobj =kobject_create_and_add("fs", NULL); //在sysfs中加上fs節點
                init_rootfs();
                init_mount_tree();

mnt_init最後調用了init_rootfs和init_mount_tree兩個函數,下面分別來看一下。

2.1 init_rootfs

int __init init_rootfs(void)
                int err;
                err =bdi_init(&ramfs_backing_dev_info);
                // 註冊rootfs檔案系統
                        err =register_filesystem(&rootfs_fs_type);

rootfs_fs_type定義在fs/ramfs/inode.c。

static struct file_system_type rootfs_fs_type = {
                .name                   = "rootfs",
                .get_sb                 = rootfs_get_sb,
                .kill_sb                 =kill_litter_super,
};

2.2 init_mount_tree

static void __init init_mount_tree(void)

                // 得到rootfs的vfsmount結構,設定裡面的超級塊等資訊,見下文

                structvfsmount *mnt =do_kern_mount("rootfs",0, "rootfs", NULL);

                // 根據mnt建立一個mnt_namespace,見下文

                structmnt_namespace *ns =create_mnt_ns(mnt);

                init_task.nsproxy->mnt_ns= ns;

                get_mnt_ns(ns);

                root.mnt= ns->root;

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

                // 由於調init_mount_tree時init進程還沒啟動,下面的current宏由最開始時設定的棧指標決定,應該就是init_task的taskstruct結構體。

                set_fs_pwd(current->fs,&root);

                set_fs_root(current->fs,&root);

 

do_kern_mount的作用是分配一個vfsmount,同時裡面初始化了super block。

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

                structfile_system_type *type = get_fs_type(fstype);

                structvfsmount *mnt;

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

                put_filesystem(type);

                returnmnt;

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

                structvfsmount * mnt = alloc_vfsmnt(name);

                type->get_sb(type,flags, name, data, mnt);

                //mnt_mountpoint設定為mnt_root,即掛載點為自己

                mnt->mnt_mountpoint= mnt->mnt_root;

                // mnt_parent設成自己

                mnt->mnt_parent= mnt;

struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)

                structmnt_namespace *new_ns = alloc_mnt_ns();

                mnt->mnt_ns= new_ns;

                new_ns->root= mnt;

                list_add(&new_ns->list,&new_ns->root->mnt_list);

3.    檔案系統載入

mount操作包括remount,move_mount, mount塊裝置,mountloop裝置等,都由核心功能do_mount完成。本質上,mount操作的過程就是建立一個vfsmount結構,然後將此結構和掛載點關聯。關聯之後,目錄尋找時就能沿著vfsmount掛載點一級級向下尋找檔案了。

關於如何經過vfsmount尋找檔案,可以看函數kern_path。kern_path的作用為根據路徑得到dentry和inode結構,裡面會調用到path_walk,最終調用__follow_mount。

 

下面看一下mount塊裝置的實現。
long do_mount(char *dev_name, char *dir_name, char *type_page,
                                unsignedlong flags, void *data_page)

                struct path path;

                // 得到掛載點的vfsmount和dentry結構,儲存在structpath中。

                kern_path(dir_name,LOOKUP_FOLLOW, &path);

                。。。

                // 對塊裝置,調用到do_new_mount

                do_new_mount(&path, type_page, flags,mnt_flags, dev_name, data_page);

 

static int do_new_mount(struct path *path, char *type, int flags, int mnt_flags, char*name, void *data)

                struct vfsmount * mnt =do_kern_mount(type, flags, name, data);

                do_add_mount(mnt, path,mnt_flags, NULL);

 

int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags, structlist_head *fslist)

    // 找到該目錄的當前掛載點的vfsmount和dentry結構

    while (d_mountpoint(path->dentry)&& follow_down(path))             ;

                // graft_tree主要作用是將新的vfsmount加到mounttree。

                graft_tree (newmnt, path);

 

loopmount與mount塊裝置類似,根據被載入裝置的superblock、dentry結構建立一個vfsmount結構,將該vfsmount掛到mounttree上。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.