感谢支持
我们一直在努力

Linux虚拟文件系统(内核初始化<一>)

Linux虚拟文件系统在内核初始化的start_kernel()函数中主要调用两个函数来实现。

[cpp]


  1. asmlinkage void __init start_kernel(void)  

  2. {  

  3.     ……  

  4.     vfs_caches_init_early();  

  5.     ……  

  6.     vfs_caches_init(totalram_pages);  

  7.     ……  

  8. }  

一、早期初始化


虚拟文件系统的早期初始化有函数vfs_caches_init_early()实现,主要负责dentryinodehashtable的初始化工作。

[cpp]


  1. /*在start_kernel中调用,用于文件系统中早期的初始化*/  

  2. void __init vfs_caches_init_early(void)  

  3. {  

  4.     /*初始化两个hashtable*/  

  5.     dcache_init_early();  

  6.     inode_init_early();  

  7. }  

1.1 dcache

[cpp]


  1. static void __init dcache_init_early(void)  

  2. {  

  3.     int loop;  

  4.   

  5.     /* If hashes are distributed across NUMA nodes, defer 

  6.      * hash allocation until vmalloc space is available. 

  7.      */  

  8.     if (hashdist)  

  9.         return;  

  10.     /*dentry hashtable的空间分配*/  

  11.     dentry_hashtable =  

  12.         alloc_large_system_hash(“Dentry cache”,  

  13.                     sizeof(struct hlist_head),  

  14.                     dhash_entries,  

  15.                     13,  

  16.                     HASH_EARLY,  

  17.                     &d_hash_shift,  

  18.                     &d_hash_mask,  

  19.                     0);  

  20.     /*hashtable的各个链表初始化*/  

  21.     for (loop = 0; loop < (1 << d_hash_shift); loop++)  

  22.         INIT_HLIST_HEAD(&dentry_hashtable[loop]);  

  23. }  

1.2  inode

[cpp]


  1. /* 

  2.  * Initialize the waitqueues and inode hash table. 

  3.  */  

  4. void __init inode_init_early(void)  

  5. {  

  6.     int loop;  

  7.   

  8.     /* If hashes are distributed across NUMA nodes, defer 

  9.      * hash allocation until vmalloc space is available. 

  10.      */  

  11.     if (hashdist)  

  12.         return;  

  13.     /*从cache中分配inode hashtable的内存空间*/  

  14.     inode_hashtable =  

  15.         alloc_large_system_hash(“Inode-cache”,  

  16.                     sizeof(struct hlist_head),  

  17.                     ihash_entries,  

  18.                     14,  

  19.                     HASH_EARLY,  

  20.                     &i_hash_shift,  

  21.                     &i_hash_mask,  

  22.                     0);  

  23.     /*初始化hashtable 的各个链表*/  

  24.     for (loop = 0; loop < (1 << i_hash_shift); loop++)  

  25.         INIT_HLIST_HEAD(&inode_hashtable[loop]);  

  26. }  

二、后期初始化


这阶段对inodedentrymount、字符设备驱动模型以及块设备驱动模型做了相应的初始化。

[cpp]


  1. /*vfs初始化,在start_kernel中调用*/  

  2. void __init vfs_caches_init(unsigned long mempages)  

  3. {  

  4.     unsigned long reserve;  

  5.   

  6.     /* Base hash sizes on available memory, with a reserve equal to 

  7.            150% of current kernel size */  

  8.   

  9.     reserve = min((mempages – nr_free_pages()) * 3/2, mempages – 1);  

  10.     mempages -= reserve;  

  11.     /*为路径名申请的cache*/  

  12.     names_cachep = kmem_cache_create(“names_cache”, PATH_MAX, 0,  

  13.             SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);  

  14.     /*dentry及其相关内容初始化*/  

  15.     dcache_init();  

  16.     inode_init();/*inode初始化*/  

  17.     files_init(mempages);/*文件相关信息初始化,包括文件描述符表初始化*/  

  18.     mnt_init();/*mount 的初始化*/  

  19.     bdev_cache_init();  

  20.     /*字符设备驱动模型的初始化*/  

  21.     chrdev_init();  

  22. }  

2.1 dentry初始化

[cpp]


  1. static void __init dcache_init(void)  

  2. {  

  3.     int loop;  

  4.   

  5.     /*  

  6.      * A constructor could be added for stable state like the lists, 

  7.      * but it is probably not worth it because of the cache nature 

  8.      * of the dcache.  

  9.      *//*从cache中申请目录cache*/  

  10.     dentry_cache = KMEM_CACHE(dentry,  

  11.         SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);  

  12.     /*注册一个shrinker*/  

  13.     register_shrinker(&dcache_shrinker);  

  14.   

  15.     /* Hash may have been set up in dcache_init_early */  

  16.     if (!hashdist)  

  17.         return;  

  18.     /*下面的操作在前面的初始化中已经做了*/  

  19.     dentry_hashtable =  

  20.         alloc_large_system_hash(“Dentry cache”,  

  21.                     sizeof(struct hlist_head),  

  22.                     dhash_entries,  

  23.                     13,  

  24.                     0,  

  25.                     &d_hash_shift,  

  26.                     &d_hash_mask,  

  27.                     0);  

  28.   

  29.     for (loop = 0; loop < (1 << d_hash_shift); loop++)  

  30.         INIT_HLIST_HEAD(&dentry_hashtable[loop]);  

  31. }  

2.2 inode初始化

[cpp]


  1. void __init inode_init(void)  

  2. {  

  3.     int loop;  

  4.   

  5.     /* inode slab cache */  

  6.     /*slab中分配inode缓存*/  

  7.     inode_cachep = kmem_cache_create(“inode_cache”,  

  8.                      sizeof(struct inode),  

  9.                      0,  

  10.                      (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|  

  11.                      SLAB_MEM_SPREAD),  

  12.                      init_once);  

  13.     /*注册icache shrinker,将参数对应的shrinker加入指定队列*/  

  14.     register_shrinker(&icache_shrinker);  

  15.   

  16.     /* Hash may have been set up in inode_init_early */  

  17.     if (!hashdist)  

  18.         return;  

  19.     /*分配数组对应空间*/  

  20.     inode_hashtable =  

  21.         alloc_large_system_hash(“Inode-cache”,  

  22.                     sizeof(struct hlist_head),  

  23.                     ihash_entries,  

  24.                     14,  

  25.                     0,  

  26.                     &i_hash_shift,  

  27.                     &i_hash_mask,  

  28.                     0);  

  29.     /*初始化链表组*/  

  30.     for (loop = 0; loop < (1 << i_hash_shift); loop++)  

  31.         INIT_HLIST_HEAD(&inode_hashtable[loop]);  

  32. }  

2.3 files初始化

[cpp]


  1. void __init files_init(unsigned long mempages)  

  2. {   

  3.     int n;   

  4.     /*申请文件cache*/  

  5.     filp_cachep = kmem_cache_create(“filp”sizeof(struct file), 0,  

  6.             SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);  

  7.   

  8.     /* 

  9.      * One file with associated inode and dcache is very roughly 1K. 

  10.      * Per default don’t use more than 10% of our memory for files.  

  11.      */   

  12.   

  13.     n = (mempages * (PAGE_SIZE / 1024)) / 10;  

  14.     files_stat.max_files = n; /*更新文件统计信息*/  

  15.     if (files_stat.max_files < NR_FILE)  

  16.         files_stat.max_files = NR_FILE;  

  17.     files_defer_init();/*释放文件描述符表*/  

  18.     percpu_counter_init(&nr_files, 0);  

  19. }   

2.4 mount初始化

[cpp]


  1. void __init mnt_init(void)  

  2. {  

  3.     unsigned u;  

  4.     int err;  

  5.   

  6.     init_rwsem(&namespace_sem);  

  7.     /*mnt cache初始化*/  

  8.     mnt_cache = kmem_cache_create(“mnt_cache”sizeof(struct vfsmount),  

  9.             0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);  

  10.     /*mount hashtable内存申请*/  

  11.     mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);  

  12.   

  13.     if (!mount_hashtable)  

  14.         panic(“Failed to allocate mount hash table\n”);  

  15.   

  16.     printk(“Mount-cache hash table entries: %lu\n”, HASH_SIZE);  

  17.   

  18.     for (u = 0; u < HASH_SIZE; u++)  

  19.         INIT_LIST_HEAD(&mount_hashtable[u]);/*初始化hashtable链表*/  

  20.   

  21.     err = sysfs_init();/*sysfs文件系统初始化*/  

  22.     if (err)  

  23.         printk(KERN_WARNING “%s: sysfs_init error: %d\n”,  

  24.             __func__, err);  

  25.     fs_kobj = kobject_create_and_add(“fs”, NULL);  

  26.     if (!fs_kobj)  

  27.         printk(KERN_WARNING “%s: kobj create error\n”, __func__);  

  28.     init_rootfs();/*初始化ramfs和rootfs*/  

  29.     init_mount_tree();/*初始化mount tree*/  

  30. }  

[cpp]


  1. static void __init init_mount_tree(void)  

  2. {  

  3.     struct vfsmount *mnt;  

  4.     struct mnt_namespace *ns;  

  5.     struct path root;  

  6.   

  7.     mnt = do_kern_mount(“rootfs”, 0, “rootfs”, NULL);  

  8.     if (IS_ERR(mnt))  

  9.         panic(“Can’t create rootfs”);  

  10.     ns = create_mnt_ns(mnt);/*为mnt创建命名空间*/  

  11.     if (IS_ERR(ns))  

  12.         panic(“Can’t allocate initial namespace”);  

  13.     /*初始化进程的相关命名空间*/  

  14.     init_task.nsproxy->mnt_ns = ns;  

  15.     get_mnt_ns(ns);/*命名空间的进程数加一*/  

  16.     /*更新root的相关字段*/  

  17.     root.mnt = ns->root;  

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

  19.     /*设置fs的当前路径和当前root*/  

  20.     set_fs_pwd(current->fs, &root);  

  21.     set_fs_root(current->fs, &root);  

  22. }  

2.4.1 创建命名空间

[cpp]


  1. /** 

  2.  * create_mnt_ns – creates a private namespace and adds a root filesystem 

  3.  * @mnt: pointer to the new root filesystem mountpoint 

  4.  */  

  5. struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)  

  6. {  

  7.     struct mnt_namespace *new_ns;  

  8.   

  9.     new_ns = alloc_mnt_ns();/*分配命名空间*/  

  10.     if (!IS_ERR(new_ns)) {  

  11.         /*下面为和mnt建立关系*/  

  12.         mnt->mnt_ns = new_ns;  

  13.         new_ns->root = mnt;  

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

  15.     }  

  16.     return new_ns;  

  17. }  

[cpp]


  1. static struct mnt_namespace *alloc_mnt_ns(void)  

  2. {  

  3.     struct mnt_namespace *new_ns;  

  4.     /*从cache中分配命名空间*/     

  5.     new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);  

  6.     if (!new_ns)  

  7.         return ERR_PTR(-ENOMEM);  

  8.     /*下面为相关字段的初始化*/  

  9.     atomic_set(&new_ns->count, 1);  

  10.     new_ns->root = NULL;  

  11.     INIT_LIST_HEAD(&new_ns->list);  

  12.     init_waitqueue_head(&new_ns->poll);  

  13.     new_ns->event = 0;  

  14.     return new_ns;  

  15. }     

2.4.2 创建mount

[cpp]


  1. struct vfsmount *  

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

  3. {  

  4.     struct file_system_type *type = get_fs_type(fstype);  

  5.     struct vfsmount *mnt;  

  6.     if (!type)  

  7.         return ERR_PTR(-ENODEV);  

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

  9.     if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&  

  10.         !mnt->mnt_sb->s_subtype)  

  11.         mnt = fs_set_subtype(mnt, fstype);  

  12.     put_filesystem(type);  

  13.     return mnt;  

  14. }  

[cpp]


  1. struct vfsmount *  

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

  3. {  

  4.     struct vfsmount *mnt;  

  5.     char *secdata = NULL;  

  6.     int error;  

  7.   

  8.     if (!type)  

  9.         return ERR_PTR(-ENODEV);  

  10.   

  11.     error = -ENOMEM;  

  12.     /*从slab中分配一个mnt*/  

  13.     mnt = alloc_vfsmnt(name);  

  14.     if (!mnt)  

  15.         goto out;  

  16.   

  17.     if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {  

  18.         secdata = alloc_secdata();  

  19.         if (!secdata)  

  20.             goto out_mnt;  

  21.   

  22.         error = security_sb_copy_data(data, secdata);  

  23.         if (error)  

  24.             goto out_free_secdata;  

  25.     }  

  26.     /*调用文件系统控制结构体的get_sb()*/  

  27.     error = type->get_sb(type, flags, name, data, mnt);  

  28.     if (error < 0)  

  29.         goto out_free_secdata;  

  30.     BUG_ON(!mnt->mnt_sb);  

  31.   

  32.     error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);  

  33.     if (error)  

  34.         goto out_sb;  

  35.   

  36.     /* 

  37.      * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE 

  38.      * but s_maxbytes was an unsigned long long for many releases. Throw 

  39.      * this warning for a little while to try and catch filesystems that 

  40.      * violate this rule. This warning should be either removed or 

  41.      * converted to a BUG() in 2.6.34. 

  42.      */  

  43.     WARN((mnt->mnt_sb->s_maxbytes < 0), “%s set sb->s_maxbytes to “  

  44.         “negative value (%lld)\n”, type->name, mnt->mnt_sb->s_maxbytes);  

  45.     /*初始化mnt相关字段*/  

  46.     mnt->mnt_mountpoint = mnt->mnt_root;  

  47.     mnt->mnt_parent = mnt;  

  48.     up_write(&mnt->mnt_sb->s_umount);  

  49.     free_secdata(secdata);  

  50.     return mnt;  

  51. out_sb:  

  52.     dput(mnt->mnt_root);  

  53.     deactivate_locked_super(mnt->mnt_sb);  

  54. out_free_secdata:  

  55.     free_secdata(secdata);  

  56. out_mnt:  

  57.     free_vfsmnt(mnt);  

  58. out:  

  59.     return ERR_PTR(error);  

  60. }  

[cpp]


  1. struct vfsmount *alloc_vfsmnt(const char *name)  

  2. {  

  3.     /*从slab中获得mnt*/  

  4.     struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);  

  5.     /*下面进行对mnt的初始化*/  

  6.     if (mnt) {  

  7.         int err;  

  8.   

  9.         err = mnt_alloc_id(mnt);  

  10.         if (err)  

  11.             goto out_free_cache;  

  12.   

  13.         if (name) {  

  14.             mnt->mnt_devname = kstrdup(name, GFP_KERNEL);  

  15.             if (!mnt->mnt_devname)  

  16.                 goto out_free_id;  

  17.         }  

  18.   

  19.         atomic_set(&mnt->mnt_count, 1);  

  20.         INIT_LIST_HEAD(&mnt->mnt_hash);  

  21.         INIT_LIST_HEAD(&mnt->mnt_child);  

  22.         INIT_LIST_HEAD(&mnt->mnt_mounts);  

  23.         INIT_LIST_HEAD(&mnt->mnt_list);  

  24.         INIT_LIST_HEAD(&mnt->mnt_expire);  

  25.         INIT_LIST_HEAD(&mnt->mnt_share);  

  26.         INIT_LIST_HEAD(&mnt->mnt_slave_list);  

  27.         INIT_LIST_HEAD(&mnt->mnt_slave);  

  28. #ifdef CONFIG_SMP   

  29.         mnt->mnt_writers = alloc_percpu(int);  

  30.         if (!mnt->mnt_writers)  

  31.             goto out_free_devname;  

  32. #else   

  33.         mnt->mnt_writers = 0;  

  34. #endif   

  35.     }  

  36.     return mnt;  

  37.   

  38. #ifdef CONFIG_SMP   

  39. out_free_devname:  

  40.     kfree(mnt->mnt_devname);  

  41. #endif   

  42. out_free_id:  

  43.     mnt_free_id(mnt);  

  44. out_free_cache:  

  45.     kmem_cache_free(mnt_cache, mnt);  

  46.     return NULL;  

  47. }  

2.5 块设备驱动模型初始化

[cpp]


  1. void __init bdev_cache_init(void)  

  2. {  

  3.     int err;  

  4.     struct vfsmount *bd_mnt;  

  5.     /*block cache初始化*/  

  6.     bdev_cachep = kmem_cache_create(“bdev_cache”sizeof(struct bdev_inode),  

  7.             0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|  

  8.                 SLAB_MEM_SPREAD|SLAB_PANIC),  

  9.             init_once);  

  10.     /*注册block dev*/  

  11.     err = register_filesystem(&bd_type);  

  12.     if (err)  

  13.         panic(“Cannot register bdev pseudo-fs”);  

  14.     bd_mnt = kern_mount(&bd_type);  

  15.     if (IS_ERR(bd_mnt))  

  16.         panic(“Cannot create bdev pseudo-fs”);  

  17.     /* 

  18.      * This vfsmount structure is only used to obtain the 

  19.      * blockdev_superblock, so tell kmemleak not to report it. 

  20.      */  

  21.     kmemleak_not_leak(bd_mnt);  

  22.     blockdev_superblock = bd_mnt->mnt_sb;    /* For writeback */  

  23. }  

2.6 字符设备驱动模型初始化

[cpp]


  1. void __init chrdev_init(void)  

  2. {  

  3.     cdev_map = kobj_map_init(base_probe, &chrdevs_lock);  

  4.     /*字符设备驱动初始化*/  

  5.     bdi_init(&directly_mappable_cdev_bdi);  

  6. }  

这里对linux虚拟文件系统的初始化工作做了整体的梳理,后面将对涉及到的细节做补充,包括inodedentry cache shrinker的注册、sysfs的初始化等。

赞(0) 打赏
转载请注明出处:服务器评测 » Linux虚拟文件系统(内核初始化<一>)
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏