免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3206 | 回复: 4
打印 上一主题 下一主题

[内核模块] 文件系统超级块分配算法 [复制链接]

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-05-10 12:50 |只看该作者 |倒序浏览
*/
419struct super_block *sget(struct file_system_type *type,
420                        int (*test)(struct super_block *,void *),
421                        int (*set)(struct super_block *,void *),
422                        void *data)
423{
424        struct super_block *s = NULL;
425        struct hlist_node *node;
426        struct super_block *old;
427        int err;
428
429retry:
430        spin_lock(&sb_lock);
431        if (test) {
            432-449:  从该文件系统的超级块list里搜寻是否已经有人产生过同样的超级块
432                hlist_for_each_entry(old, node, &type->fs_supers, s_instances) {
433                        if (!test(old, data))
434                                continue;
435                        if (!grab_super(old))
436                                goto retry;
437                        if (s) {
第一次就找到一个同名的超级快时这段代码不会执行
因为s=NULL
第一次没找到,分配一个新的超级块,然后回头再找时, 如果第二次找到了一个同名超级块,就用别人已经产生的,把新的释放掉
438                                up_write(&s->s_umount);
439                                destroy_super(s);
440                                s = NULL;
441                        }
442                        down_write(&old->s_umount);
443                        if (unlikely(!(old->s_flags & MS_BORN))) {
444                                deactivate_locked_super(old);
445                                goto retry;
446                        }
447                        return old;
448                }
449        }
450        if (!s) {
            前面没有找到,就创建一个新的
451                spin_unlock(&sb_lock);
452                s = alloc_super(type);
453                if (!s)
454                        return ERR_PTR(-ENOMEM);
455                goto retry;    然后回头到429行,在文件系统的超级块链表里再找一遍
456        }
457               
458        err = set(s, data);
459        if (err) {
460                spin_unlock(&sb_lock);
461                up_write(&s->s_umount);
462                destroy_super(s);
463                return ERR_PTR(err);
464        }
465        s->s_type = type;
466        strlcpy(s->s_id, type->name, sizeof(s->s_id));
467        list_add_tail(&s->s_list, &super_blocks);
468        hlist_add_head(&s->s_instances, &type->fs_supers);
469        spin_unlock(&sb_lock);
470        get_filesystem(type);
471        register_shrinker(&s->s_shrink);
472        return s;
473}
474
475EXPORT_SYMBOL(sget);

这种算法就是:
先在list里找,看有没有别人创建一个同名的模块,如果有,就用现成的
如果没有, 就创建一个新的
创建完了后,要回到list,重新找一遍;还是没找到,就用新的。
如果第二次找到一个同名一创建的模块,还用旧的,把新的释放掉。
文件系统里super block/inode都用这样一种算法。

感觉这样的算法不是很严谨,有点撞大运的成分。

ps 顺便请教如何贴代码?

论坛徽章:
0
2 [报告]
发表于 2012-05-10 15:20 |只看该作者
为什么不严谨呢?我觉得挺严谨的呀~

整个过程基本上都对sb_lock上了锁的,唯一没有上锁的地方就是alloc_super,因为它可能会睡眠。
也正是因为alloc_super的时候没有上锁,所以可能有不止一个流程在alloc同样的super,所以要retry。

当然,这个过程写得是有点绕。最简单的写法是,进入函数,无论如何先alloc_super,然后后面的过程就都在临界区里面去做,不需要alloc+retry。不过代价是无味的alloc_super/destroy_super,而这显然是不可接受的。

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
3 [报告]
发表于 2012-05-10 21:34 |只看该作者
回复 1# linuxfellow
严谨一词可能用得不合适。应该说这个算法不是很高明。就跟100米赛跑一样,所有的人都埋头跑,跑到终点撞了线,回头在来看有没有人在我前面。

   

论坛徽章:
0
4 [报告]
发表于 2012-05-11 09:51 |只看该作者
回复 3# linuxfellow


我能想到的更“高明”的算法就是2楼所说的这个,不过这样做肯定是不靠谱的:
最简单的写法是,进入函数,无论如何先alloc_super,然后后面的过程就都在临界区里面去做,不需要alloc+retry。不过代价是无味的alloc_super/destroy_super,而这显然是不可接受的。

不知道兄台有何高见~

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
5 [报告]
发表于 2012-05-11 10:19 |只看该作者
本帖最后由 linuxfellow 于 2012-05-11 10:20 编辑

回复 4# kouu
2楼的方法就是读起来好懂一些,但作冤枉工的机会比目前linux的这个难懂的算法大得多。2楼算法只要有重名时,alloc memory就是冤枉工;而目前linux的算法,必须同时创建同名文件系统才做冤枉工,相比较之下,这样几率就小的多。
我自己也没啥高招,只是觉得这个算法读起来怪怪的。

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP