伪文件系统bdev

来源:互联网 发布:多层级网络拓扑 编辑:程序博客网 时间:2024/05/22 10:54

整理了下伪文件系统bdev:


 517static struct file_system_type bd_type = { 518        .name           = "bdev", 519        .get_sb         = bd_get_sb, 520        .kill_sb        = kill_anon_super, 521}; 522 523static struct vfsmount *bd_mnt __read_mostly; 524struct super_block *blockdev_superblock;


这三个是文件系统的代表成员。文件系统类型、挂载点和超级块。

下面这个函数,应该是bdev文件系统的初始化函数:

1、为bdev_inode结构体创建slab缓存:kmem_cache_create

2、把文件系统类型注册进系统:register_filesystem








说下系统启动的时候,伪文件系统的启动流程:

start_kernel

vfs_caches_init

bdev_cache_init

所以这个函数就是伪文件系统的初始过程,我们也可以看到,在系统启动的时候,伪文件系统已经启动起来了。

 493void __init bdev_cache_init(void) 494{ 495        int err; 496        struct vfsmount *bd_mnt; 497 498        bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode), 499                        0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| 500                                SLAB_MEM_SPREAD|SLAB_PANIC), 501                        init_once); 502        err = register_filesystem(&bd_type); 503        if (err) 504                panic("Cannot register bdev pseudo-fs"); 505        bd_mnt = kern_mount(&bd_type); 506        if (IS_ERR(bd_mnt)) 507                panic("Cannot create bdev pseudo-fs"); 508        /* 509         * This vfsmount structure is only used to obtain the 510         * blockdev_superblock, so tell kmemleak not to report it. 511         */ 512        kmemleak_not_leak(bd_mnt); 513        blockdev_superblock = bd_mnt->mnt_sb;   /* For writeback */ 514}


kern_mount是挂载文件系统的函数,按道理,我们的伪文件系统bdev是无法挂载的阿。

架构p450:

内核提供了装载标志MS_NOUSER,防止此类文件系统被装载。

所有的文件系统机制,都适用于伪文件系统。

内核可以调用1804#definekern_mount(type)kern_mount_data(type,NULL)

这两个函数来“挂载”bdev文件系统。

(架构P443

通常意义上的挂载(用户空间的)会调用

sys_mount->do_mount->do_new_mount->

-->>vfs_kern_mount把文件系统集成到VFS中去
-->>graft_tree
把文件系统的文件和目录集成到用户可见的表示中



我们这里伪文件系统bdev会通过上面提到的两个函数,调用vfs_kern_mount,把自身集成到vfs中去,供内核使用。但是它调用graft_tree的时候,因为设置了装载标志位MS_NOUSER,所以这个函数什么都不干。

文件系统的使用

这样以来,伪文件系统就初始化好了。一个挂载的文件系统对应三个全局变量:

523staticstructvfsmount*bd_mnt__read_mostly;

524structsuper_block*blockdev_superblock;

517staticstructfile_system_typebd_type= {

考虑到两点:

1、一种类型的文件系统,在系统中可能同时存在多种。比如说/目录和/home目录可能都挂载了ext3类型的文件系统,在内存中存在的文件系统类型变量却是只有一个的。
2
、一个块设备,对应着一个超级块,可以挂载在多个目录上。

超级块对应的是一个块设备,对应这结构体supter_block

一个文件系统挂载一次,对应着一个结构体vfs_mount



所以我们不可以使用这两个结构体来操作我们欲操作的文件系统

523staticstructvfsmount*bd_mnt__read_mostly;

517staticstructfile_system_typebd_type= {

当我们查找一个文件系统的文件的时候,或者添加,或者删除文件,(本质上都是操作inode),我们都是以超级块来标志我们要操作的文件系统的。

524structsuper_block*blockdev_superblock;



bdev文件系统这就创建好了,我们下面需要知道两点:

1、他内部的节点是什么时候创建的bdev文件系统中的节点。

2、我们什么时候访问,和如何访问里面的节点。

其实内核中使用了这么一种机制:把查找和创建做成了一个接口,可能很多时候在创建的时候都需要判断是否已经存在,所以他很多东西的创建都是以查找函数为接口的,当查找不到的时候,再创建他,反正查找和创建返回的是一个东西。



目前我知道的踪迹是这个:(这个是创建的时候)

add_disk->

register_disk->

bdget_disk->

bdget(设备号)->

 566struct block_device *bdget(dev_t dev) 567{ 568        struct block_device *bdev; 569        struct inode *inode; 570 571        inode = iget5_locked(bd_mnt->mnt_sb, hash(dev), 572                        bdev_test, bdev_set, &dev); 573 574        if (!inode) 575                return NULL; 576 577        bdev = &BDEV_I(inode)->bdev; 578 579        if (inode->i_state & I_NEW) { 580                bdev->bd_contains = NULL; 581                bdev->bd_inode = inode; 582                bdev->bd_block_size = (1 << inode->i_blkbits); 583                bdev->bd_part_count = 0; 584                bdev->bd_invalidated = 0; 585                inode->i_mode = S_IFBLK; 586                inode->i_rdev = dev; 587                inode->i_bdev = bdev; 588                inode->i_data.a_ops = &def_blk_aops; 589                mapping_set_gfp_mask(&inode->i_data, GFP_USER); 590                inode->i_data.backing_dev_info = &default_backing_dev_info; 591                spin_lock(&bdev_lock); 592                list_add(&bdev->bd_list, &all_bdevs); 593                spin_unlock(&bdev_lock); 594                unlock_new_inode(inode); 595        } 596        return bdev; 597} 571        inode = iget5_locked(bd_mnt->mnt_sb, hash(dev), 572                        bdev_test, bdev_set, &dev); 577        bdev = &BDEV_I(inode)->bdev;


看到这里两个东西,我们知道了,571这个必然是创建了一个inode,一个block_device,一个bdev_inode(后面这两个要跟到源码中看下)

因为577这个bdev本质上就等效是bdev =bdev_inode->block_device。借助container_of(inode)这个宏来实现的效果。

所以可以看到,我们的代表整个硬盘的block_device是这个时候被创建的。

下一步来研究我们每个分区的block_device是什么时候创建的。







原创粉丝点击