收藏 分享(赏)

EXT4 inode 分配策略.pdf

上传人:精品资料 文档编号:10670540 上传时间:2019-12-18 格式:PDF 页数:9 大小:563.94KB
下载 相关 举报
EXT4 inode 分配策略.pdf_第1页
第1页 / 共9页
EXT4 inode 分配策略.pdf_第2页
第2页 / 共9页
EXT4 inode 分配策略.pdf_第3页
第3页 / 共9页
EXT4 inode 分配策略.pdf_第4页
第4页 / 共9页
EXT4 inode 分配策略.pdf_第5页
第5页 / 共9页
点击查看更多>>
资源描述

1、2016/10/10 EXT4 inode 分配策略http:/beanli.github.io/EXT4Inodeorlov/ 1/9EXT4 inode 分配策略2016-04-18 | 分类 linux | 标签 linux 前言EXT4文件系统的inode是非常多的,按照Inodes Per Block Group 4096而言,1T空间能提供出32M个inode左右,当我们创建一个目录,或者创建一个文件时,EXT4会怎么选择inode呢?在2002年发表的The Orlov block allocator一文中提到,影响文件系统性能的因素有很多,但是文件在磁盘上的分布非常关键。有一个

2、总体的原则:相关的数据寻处位置相近。因为位置相近甚至连续,那么花在磁盘寻道上的时间机会少,从而提高性能。但是实际情况下,还有一种特殊情况,对于文件系统的顶层目录,尽量要伸展开,分离开,否则顶层目录挤在一起,底层目录更具局部性原理也挤在一起,最终就会导致文件系统,从远到近地线性展开,很多文件与其父目录的位置隔得很远,从而损坏性能。因此,一个很重要的原则是,顶层目录尽量在整个存储空间铺开,而目录树深处的目录相关的目录尽量靠近。这个原则是不难理解的。Linux采用了一种叫做Orlov allocator的算法来负责选择inode的位置。该算法时由 Grigory Orlov提出,在EXT2和EXT3

3、 就开始使用该算法,但是EXT4由于支持flex_bg,所以算法上也有了一点点变化或者变异内核实现对于EXT4文件系统,无论是创建文件(create),还是创建目录,还是创建软链接,都会牵扯到inode分配(如图所示)。茫茫无数inode,到底选用那一个?这个_ext4_new_inode是EXT4非常重要的一个函数,它的内容有400行之多,占据了fs/ext4/ialloc.c的四分之一以上的篇幅。本文重点介绍选择inode分配给新的文件或目录的这个流程。其实我们不难想到,由于EXT4支持flex block group这种战斗小组,选择inode可以分解成3步1. which flex b

4、lock group2. which block group3. which inode这些步骤中,第一步决定了目录是分散还是聚集在一起。文件和目录的规则是不同的:if (S_ISDIR(mode) ret2 = find_group_orlov(sb, dir, else ret2 = find_group_other(sb, dir, 从上面代码也不难看出,对于目录和文件,选择group的规则是不同的。对于目录而言,使用find_group_orlov函数来寻找合适的2016/10/10 EXT4 inode 分配策略http:/beanli.github.io/EXT4Inodeorlo

5、v/ 2/9group,该函数使用了前面提到的orlov allocator算法,而对于文件,软链接等则 使用了find_group_other来寻找合适的group。目录的inode分配首先介绍目录文件的inode分配,目录inode分配,调用的是find_group_orlov函数。static int find_group_orlov(struct super_block *sb, struct inode *parent, ext4_group_t *group, umode_t mode,const struct qstr *qstr)ext4_group_t parent_grou

6、p = EXT4_I(parent)i_block_group; struct ext4_sb_info *sbi = EXT4_SB(sb);/*获取块组的个数,存放到real_ngroups变量中*/ ext4_group_t real_ngroups = ext4_get_groups_count(sb); int inodes_per_group = EXT4_INODES_PER_GROUP(sb); unsigned int freei, avefreei, grp_free;ext4_fsblk_t freeb, avefreec; unsigned int ndirs;int

7、max_dirs, min_inodes; ext4_grpblk_t min_clusters;ext4_group_t i, grp, g, ngroups; struct ext4_group_desc *desc;struct orlov_stats stats; int flex_size = ext4_flex_bg_size(sbi);struct dx_hash_info hinfo;ngroups = real_ngroups; /*如果文件系统打开了flex_bg选项,就以逻辑块组为单位分配*/if (flex_size 1) ngroups = (real_ngroups

8、 + flex_size 1) sbis_log_groups_per_flex; parent_group = sbis_log_groups_per_flex;freei = percpu_counter_read_positive( avefreei = freei / ngroups;freeb = EXT4_C2B(sbi, percpu_counter_read_positive(avefreec = freeb; do_div(avefreec, ngroups);ndirs = percpu_counter_read_positive(if (S_ISDIR(mode) int

9、 ret = 1;if (qstr) hinfo.hash_version = DX_HASH_HALF_MD4;hinfo.seed = sbis_hash_seed; ext4fs_dirhash(qstrname, qstrlen, grp = hinfo.hash; elsegrp = prandom_u32(); parent_group = (unsigned)grp % ngroups;for (i = 0; i = best_ndir)continue; if (stats.free_inodes = real_ngroups)break; desc = ext4_get_gr

10、oup_desc(sb, grp+i, NULL);if (desc return 0; goto fallback;max_dirs = ndirs / ngroups + inodes_per_group / 16; min_inodes = avefreei inodes_per_group*flex_size / 4;if (min_inodes i_last_alloc_group != 0) parent_group = EXT4_I(parent)i_last_alloc_group;if (flex_size 1) parent_group = sbis_log_groups_

11、per_flex;for (i = 0; i = max_dirs)continue; if (stats.free_inodes i_block_group; for (i = 0; i = avefreei) *group = grp;2016/10/10 EXT4 inode 分配策略http:/beanli.github.io/EXT4Inodeorlov/ 4/9return 0; if (avefreei) /* The freeinodes counter is approximate, and for really small * filesystems the above t

12、est can fail to find any blockgroups*/ avefreei = 0;goto fallback_retry; return 1;这么一大段代码,概括来讲可以描述为以下情况1. 采用spread out 策略让目录散开2. 根据局部性原理,让兄弟目录,父子目录尽可能的靠近当然这两种搜索都可能失败,那么就忘记战斗小组,各个块组地毯式搜索。OK,我们开始进入代码细节。首先如果文件系统使用了flex_bg就以战斗小组为单位分配,率先需要确定inode所在的战斗小组,即ngroup的值为文件系统中包含的所有逻辑块组的个数,当然了,如果并没有采用flex_bg,就退化成

13、普通的块组。接下来,对文件系统的总体使用情况做一个评估,我们如果是伸展开的策略,那么我们希望我们的inode分布在一个试用情况低于平均水平的逻辑块组。这样各个逻辑块组使用才能均衡。freei = percpu_counter_read_positive( avefreei = freei / ngroups;freeb = EXT4_C2B(sbi, percpu_counter_read_positive(avefreec = freeb; do_div(avefreec, ngroups);ndirs = percpu_counter_read_positive( 接下来的情况是何时采用伸

14、展开的策略,何时采用靠近的策略。if (S_ISDIR(mode) int ret = 1;if (qstr) hinfo.hash_version = DX_HASH_HALF_MD4;hinfo.seed = sbis_hash_seed; ext4fs_dirhash(qstrname, qstrlen, grp = hinfo.hash; elsegrp = prandom_u32(); parent_group = (unsigned)grp % ngroups;for (i = 0; i = best_ndir)continue; if (stats.free_inodes i_l

15、ast_alloc_group != 0) parent_group = EXT4_I(parent)i_last_alloc_group;if (flex_size 1) parent_group = sbis_log_groups_per_flex;2016/10/10 EXT4 inode 分配策略http:/beanli.github.io/EXT4Inodeorlov/ 6/9for (i = 0; i = max_dirs)continue; if (stats.free_inodes i_last_alloc_group;中的值。本次选择的group会记录在父目录inode的i_

16、last_alloc_group中,当在同一个父目录下创建目录是,i_last_alloc_group就是搜索的起点,因为尽可能均衡的条件放送了,只要不太过分,再次创建的目录很可能和上一次创建的目录在同一个逻辑块组中。if (S_ISDIR(mode) ret2 = find_group_orlov(sb, dir, else ret2 = find_group_other(sb, dir, got_group: EXT4_I(dir)i_last_alloc_group = group;找到逻辑块组之后,同样是采用first-fit的策略进行选择块组。无论是采用spread-out策略还是聚

17、集的策略,都可能失败,如果失败,就一律化整为零,不再以逻辑块组为单位搜索了,而是以细粒度的块组为单位搜索。第一次目标是低于平均值即可,如果这个目标也达不到,只要有free inode即可。fallback: ngroups = real_ngroups;avefreei = freei / ngroups;fallback_retry:parent_group = EXT4_I(parent)i_block_group; for (i = 0; i = avefreei) *group = grp;return 0; if (avefreei) /* The freeinodes counte

18、r is approximate, and for really small * filesystems the above test can fail to find any blockgroups*/ avefreei = 0;goto fallback_retry; 其它文件的inode分配在文件系统中,目录文件有点特殊,它是文件系统的骨架,或者是一颗树的枝干,而普通文件是一颗树的树叶。因此目录文件分2016/10/10 EXT4 inode 分配策略http:/beanli.github.io/EXT4Inodeorlov/ 7/9配inode,单拎出来,由专门的函数处理。其它文件in

19、ode分配由find_group_other函数实现.在这个函数中,我们主要讲enable flex_bg feature时采用的策略。原因是随着硬盘空间越来越大,flex_bg几乎总是enable的。static int find_group_other(struct super_block *sb, struct inode *parent, ext4_group_t *group, umode_t mode) ext4_group_t parent_group = EXT4_I(parent)i_block_group;ext4_group_t i, last, ngroups = ex

20、t4_get_groups_count(sb); struct ext4_group_desc *desc;int flex_size = ext4_flex_bg_size(EXT4_SB(sb);/* * Try to place the inode is the same flex group as its* parent. If we cant find space, use the Orlov algorithm to * find another flex group, and store that information in the* parent directorys ino

21、de information so that use that flex * group for future allocations.*/ if (flex_size 1) int retry = 0;try_again: parent_group last = parent_group + flex_size; if (last ngroups)last = ngroups; for (i = parent_group; i i_last_alloc_group != 0) retry = 1;parent_group = EXT4_I(parent)i_last_alloc_group;

22、 goto try_again; /* If this didnt work, use the Orlov search algorithm * to find a new flex group; we pass in the mode to* avoid the topdir algorithms. */*group = parent_group + flex_size; if (*group ngroups)*group = 0; return find_group_orlov(sb, parent, group, mode, NULL);/* * Try to place the ino

23、de in its parent directory*/ *group = parent_group;desc = ext4_get_group_desc(sb, *group, NULL); if (desc /* * Were going to place this inode in a different blockgroup from its* parent. We want to cause files in a common directory to all land in * the same blockgroup. But we want files which are in

24、a different* directory which shares a blockgroup with our parent to land in a * different blockgroup.* * So add our directorys i_ino into the starting point for the hash.*/ *group = (*group + parenti_ino) % ngroups;2016/10/10 EXT4 inode 分配策略http:/beanli.github.io/EXT4Inodeorlov/ 8/9/* * Use a quadra

25、tic hash to find a group with a free inode and some free* blocks. */for (i = 1; i = ngroups) *group = ngroups;desc = ext4_get_group_desc(sb, *group, NULL); if (desc /* * That failed: try linear search for a free inode, even if that group* has no free blocks. */*group = parent_group; for (i = 0; i =

26、ngroups) *group = 0;desc = ext4_get_group_desc(sb, *group, NULL); if (desc return 1;主旋律是很明确的,就是靠近。注释信息说的很清楚了,即首先在父目录的逻辑块组(flex block groups)中寻找有没有可用的inode:parent_group last = parent_group + flex_size;if (last ngroups) last = ngroups;for (i = parent_group; i i_last_alloc_group != 0) retry = 1;parent_

27、group = EXT4_I(parent)i_last_alloc_group; goto try_again;如果还没有,那就只能用 find_group_orlov函数来搜索。注意搜索的时候,会将mode 传入,因为S_ISDIR(mode)总是false,因此,为文件搜索inode的时候,并不会采用展开的策略,还是采用尽可能靠近的策略。*group = parent_group + flex_size; if (*group ngroups)*group = 0; return find_group_orlov(sb, parent, group, mode, NULL);上一篇 下一篇Powered by Jekyll GitHub | 2016 - 2016 Bean Li | cublogs2016/10/10 EXT4 inode 分配策略http:/beanli.github.io/EXT4Inodeorlov/ 9/9

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报