您的位置:首页 > 其它

文件系统学习3 注册和加载 以及路径解析

2017-11-30 07:30 507 查看
文件系统注册

注册fs:国家允许开银行/国企/股份制公司,把他们的性质特征写在法律里面公开,大家可以查阅。

加载fs:开工商银行,神华公司等。需要登记公司地址和联系方式(mnt),法人(sb)等信息

module_init(init_ext3_fs)
=>init_ext3_xattr();
=>init_inodecache();
=>register_filesystem(&ext3_fs_type);//如果在链表则返回,否则加入链表
static struct file_system_type ext3_fs_type = {
.owner      = THIS_MODULE,
.name       = "ext3",
.get_sb     = ext3_get_sb,
.kill_sb    = kill_block_super,
.fs_flags   = FS_REQUIRES_DEV,
};


加载,共有两个路径,都需要解析

sys_mount
=>retval = do_mount((char *)dev_page, dir_page, (char *)type_page, flags, (void *)data_page);
=>retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
=>do_path_lookup(AT_FDCWD, name, flags, nd);//加载的路径解析
=>if (*name=='/')
==>nd->mnt = mntget(fs->rootmnt);
==>nd->dentry = dget(fs->root);
=>else if (dfd == AT_FDCWD)
==>nd->mnt = mntget(fs->pwdmnt);
==>nd->dentry = dget(fs->pwd);
=>retval = path_walk(name, nd);                         }
=>retval = do_new_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page);
=>struct vfsmount *mnt = do_kern_mount(type, flags, name, data);
=>struct file_system_type *type = get_fs_type(fstype);
=>struct vfsmount *mnt = vfs_kern_mount(type, flags, name, data);//3大功能 分配mnt;分配sb(如果没有分配的话);填充mnt基本信息
=>mnt = alloc_vfsmnt(name);//第一功能
=>error = type->get_sb(type, flags, name, data, mnt);//Super.c (c:\linux\linux-2.6.23\fs\ext2): .get_sb     = ext2_get_sb,//第二功能
=>ext2_get_sb
=>get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt);
=>bdev = open_bdev_excl(dev_name, flags, fs_type);
=>struct block_device *bdev = lookup_bdev(path);
=>error = path_lookup(path, LOOKUP_FOLLOW, &nd);
=>do_path_lookup(AT_FDCWD, name, flags, nd);//设备节点路径解析
=>inode = nd.dentry->d_inode;
=>bdev = bd_acquire(inode);
=>s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
=>if (s->s_root)
close_bdev_excl(bdev);//如果已经有super block,那么不需要重新申请和填充
=>else
sb_set_blocksize(s, block_size(bdev));
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);//调用ext2_fill_super回调函数
=>sb_block = get_sb_block(&data);//默认是1,如果mount参数有sb=xxx则用用户参数,extx文件系统超级块有备份,默认超级块故障可以用备份超级块mount进行恢复
=>sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);//分配超级快
sb->s_fs_info = sbi;
=>blocksize = sb_min_blocksize(sb, BLOCK_SIZE);//估算最小逻辑块大小,为读取超级块做准备
=>bh = sb_bread(sb, logic_sb_block)//读取超级块,结果放在bh磁盘高速缓存里面
=>es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);//解析ext2磁盘超级块,并将高速缓存的sb信息填充到sbi里面
sbi->s_es = es;
sb->s_magic = le16_to_cpu(es->s_magic);
=>for (i = 0; i < db_count; i++)
block = descriptor_loc(sb, logic_sb_block, i);
sbi->s_group_desc[i] = sb_bread(sb, block);
=>sb->s_op = &ext2_sops;//赋值超级块的方法
sb->s_export_op = &ext2_export_ops;
=>ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
=>mnt->mnt_mountpoint = mnt->mnt_root;//第三功能
mnt->mnt_parent = mnt;
=>do_add_mount(mnt, nd, mnt_flags, NULL);//将mnt放到对应的一坨各种链表里面
=>while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry));//抽丝剥茧,找到堆叠的最底层的dentry,详见《mount过程分析之七(do_add_mount)》
=>err = graft_tree(newmnt, nd))//加入链表


全路径查找是核心

static int fastcall path_walk(const char * name, struct nameidata *nd)
=>link_path_walk(name, nd);
=>result = __link_path_walk(name, nd);
=>inode = nd->dentry->d_inode;

4000
=>for(;;) //每一次循环,剥离一层目录,通过hash抽丝剥茧找到以此找到下一个entry
==>this.name = name;//初始化hash和剥离出/~/之间的第一个name字符串,指向起始地址,通过len决定长度
c = *(const unsigned char *)name;

hash = init_name_hash();
do {
name++;
hash = partial_name_hash(c, hash);
c = *(const unsigned char *)name;
} while (c && (c != '/'));
this.len = name - (const char *) this.name;//this.len等于两个/之间的长度,即一个目录
this.hash = end_name_hash(hash);
==>nd->dentry->d_op->d_hash(nd->dentry, &this);//如果fs有私有hash,则选用私有hash,这个是dentry的方法
==>do_lookup(nd, &this, &next);
=>struct dentry *dentry = __d_lookup(nd->dentry, name);
=>dentry = real_lookup(nd->dentry, name, nd);
=>result = d_lookup(parent, name);
=>struct hlist_head *head = d_hash(parent,hash);
=>hlist_for_each_entry_rcu(dentry, node, head, d_hash)//命中哈希后,在哈希的链表里面遍历
==>qstr = &dentry->d_name;//匹配entry,如果有私有的方法,则用私有,这个是dentry的方法,否则字符串匹配
if (parent->d_op && parent->d_op->d_compare) {
if (parent->d_op->d_compare(parent, qstr, name))
goto next;
} else {
if (qstr->len != len)
goto next;
if (memcmp(qstr->name, str, len))
goto next;
}
==>found = dentry;//找到则返回
=>if (!result)//如果缓存没有找到,则需要从磁盘高速缓存读取
==>result = dir->i_op->lookup(dir, dentry, nd);//inode的方法
=>ext2_lookup
=>ino = ext2_inode_by_name(dir, dentry);
=>struct ext2_dir_entry_2 * de = ext2_find_entry (dir, dentry, &page);
=>do {
page = ext2_get_page(dir, n);
=>page = read_mapping_page(mapping, n, NULL);
=>filler_t *filler = (filler_t *)mapping->a_ops->readpage;
=>return read_cache_page(mapping, index, filler, data);
=>page = read_cache_page_async(mapping, index, filler, data);
=>page = __read_cache_page(mapping, index, filler, data);
=>page = find_get_page(mapping, index);//读磁盘高速缓存,否则分配page,通过fill回调函数读取磁盘刷新page
=>if (!page)
if (!cached_page)
cached_page = page_cache_alloc_cold(mapping);
=>page = cached_page;
=>err = filler(data, page);
=>err = filler(data, page);
}//do
=>inode = iget(dir->i_sb, ino);
=>sb->s_op->read_inode(inode);//.read_inode = ext2_read_inode,
=>struct ext2_inode * raw_inode = ext2_get_inode(inode->i_sb, ino, &bh);//高速缓存读取ext2_inode节点
=>将读取的raw_inode信息赋值给inode内存模型
=>d_splice_alias(inode, dentry);
==>if ((lookup_flags & LOOKUP_FOLLOW) && inode && inode->i_op && inode->i_op->follow_link)
====>err = do_follow_link(&next, nd);
====>inode = nd->dentry->d_inode;
==>else
====>path_to_nameidata(&next, nd);
=>nd->mnt = path->mnt;
nd->dentry = path->dentry;


文件系统错误修复实例(1)

http://blog.csdn.net/ChuiGeDaQiQiu/article/details/24138875

卸载文件系统失败的时候可以通过fuser检查和杀死访问磁盘的进程

fuser命令详解(原创)

http://czmmiao.iteye.com/blog/1733722

e2fsprogs编译问题

http://blog.csdn.net/sanwenyublog/article/details/52817796

mount过程分析之六——挂载关系(图解)

http://blog.csdn.net/ZR_Lang/article/details/40343899

mount过程分析之七(do_add_mount)

http://blog.csdn.net/ZR_Lang/article/details/40325241
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  文件系统 ext
相关文章推荐