11
5
2014
0

EXT4-design

EXT4 design

Ext3系统已有许实用的缺省状态,有良好的兼容性,可靠性。

Ext4更支持大的文件系统,对大文件支持性更好。

磁盘上的一些结构变了:纳秒级时间戳、extent分配、预分配

写在磁盘崩溃也可以保证可靠性

64bit的JBD

向前兼容文件系统/文件系统可升级

多块分配

延迟分配

第一配额指标的支持 1st Class Quota Support

大的块分配 Large allocation blocks

 

EXT4 Extents

extent对应的是磁盘上和逻辑上都连续的空间,Extents的设计使得更少的元数据管理更多的数据,所以可以做到更快的访问。

Extents在磁盘上的数据结构

/*extent bottom of the tree 的结构*/

struct ext4_extent {

        __le32  ee_block;       /* first logical block extent covers */

        __le16  ee_len;         /* number of blocks covered by extent */

        __le16  ee_start_hi;    /* high 16 bits of physical block */

        __le32  ee_start_lo;    /* low 32 bits of physical block */

}

 

/*extent 除开bottom of the tree 的结构*/

struct ext4_extent_idx {
        __le32  ei_block;       /* index covers logical blocks from 'block' */
        __le32  ei_leaf_lo;     /* pointer to the physical block of the next *
                                 * level. leaf or next index could be there */
        __le16  ei_leaf_hi;     /* high 16 bits of physical block */
        __u16   ei_unused;
};

 

四篇文章链接

FOSS.in 2006 ext4 paper

OLS 2005 ext3 presentation

OLS 2005 ext3 paper

Ext3 for large filesystems

 

本文为https://ext4.wiki.kernel.org/index.php/Ext4_Design的翻译

Category: 文件系统 | Tags:
11
5
2014
0

ext4--经常提到的一些问题

Frequently asked questions

Ext2ext3ext4的关系

三个文件系统可以归为一类文件系统,有很好的前后兼容性,如Mkfs成ext3文件系统,在挂载时可以挂在成ext2,ext4的形式。但是ext4的文件系统,不能挂载成ext2、ext3的形式。Ext3要求有日志,但是ext2中没有日志。Ext4文件系统可以使用无日志的模式mount

 

Why创造ext2

Minx文件系统bug:filename只能在14自符内。Minix支持的最大的file大小为64Mib,而ext文件系统支持2Gb的文件大小,filename可以到256个字符。但是ext2和minix一样只有一个上次更改的时间戳,上次访问时间,上次inode更改时间。它使用链表的形式存储空闲块,这意味着更容易I形成碎片。在1993,ext2文件系统更新版本后,新版本可以支持最大4T的文件大小,增加了可移植的时间戳接口。而且文件系统可扩展,所以可以在文件系统中加入新特性。

 

文件系统的特点:

EXT2:

哈希索引目录:(EXT2_FEATURE_COMPAT_DIR_INDEX) 

扩展属性块(EXT2_FEATURE_COMPAT_EXT_ATTR)

File type in directory entries (EXT2_FEATURE_INCOMPAT_FILETYPE) 

减少块组描述符的备份(EXT2_FEATURE_INCOMPAT_META_BG)

减少超级块的备份(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)

文件可以大于2GB(EXT2_FEATURE_RO_COMPAT_LARGE_FILE)

 

EXT3

扩展属性块、更大的inode结点 (EXT3_FEATURE_COMPAT_EXT_ATTR)

在线文件系统大小更改(EXT3_FEATURE_COMPAT_RESIZE_INODE)

目录项hash索引 (EXT3_FEATURE_COMPAT_DIR_INDEX)

日志file(EXT3_FEATURE_COMPAT_HAS_JOURNAL) 注意:ext3必须有日志的模式,对比ext4

File type in directory entries(EXT3_FEATURE_INCOMPAT_FILETYPE)

日志的恢复(EXT3_FEATURE_INCOMPAT_RECOVER)

减少块组描述符的备份(EXT3_FEATURE_INCOMPAT_META_BG)

减少超级块的备份(EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)

文件可以大于2GB(EXT3_FEATURE_RO_COMPAT_LARGE_FILE)

 

EXT4

扩展属性块、更大的inode(EXT3_FEATURE_COMPAT_EXT_ATTR)

在线文件系统大小更改(EXT3_FEATURE_COMPAT_RESIZE_INODE)

目录项hash索引(EXT3_FEATURE_COMPAT_DIR_INDEX)

日志file(EXT3_FEATURE_COMPAT_HAS_JOURNAL)注意ext4可以以没有日志的形式挂载

File type in directory entries(EXT3_FEATURE_INCOMPAT_FILETYPE)

日志的恢复 (EXT3_FEATURE_INCOMPAT_RECOVER)

文件可以以extents形式分配空间(EXT4_FEATURE_INCOMPAT_EXTENTS)

支持大于2^32个文件块(EXT4_FEATURE_INCOMPAT_64BIT)

灵活的块组Flexible block group(EXT4_FEATURE_INCOMPAT_FLEX_BG)

减少块组描述符的备份 (EXT3_FEATURE_INCOMPAT_META_BG)

减少超级块的备份(EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)

文件可以大于2GB(EXT3_FEATURE_RO_COMPAT_LARGE_FILE)

组描述符的校验和稀疏索引表(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)

目录内容可以多于32000个项 (EXT4_FEATURE_RO_COMPAT_DIR_NLINK)

纳秒级别时间戳和创建时间 (EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)

整个文件大小可以大于2Tb (EXT4_FEATURE_RO_COMPAT_HUGE_FILE)

 

 

如何测试EXT4文件系统

测试文件系统和硬件平台最好的方法是系统上真实的应用。Benchmark只是模拟的测试方式,他们不能反映应用的IO负载

现有的测试工具等见: intertubes

Wiki的一个很棒的文章: Comparison of file systems(不同文件系统比较)

 

Can I undelete files in Ext4?ext4能否恢复删除文件?)

No, in the same way that the ext3 journal requirements to be consistent after a crash prevent undelete of ext3 files, it isn't possible to undelete ext4 files.

 

如何把ext2ext3挂载的系统变为ext4,用到两条指令?

使用tune2fs来使其可以使用ext4特性

# tune2fs -O extents,uninit_bg,huge_file /dev/DEV
# e2fsck -f /dev/DEV

 

如果在把ext2文件系统mount为ext4类型时,想要其具备日志特性,使用指令:

# tune2fs -j /dev/DEV

 

若用指令把ext2、ext3文件系统挂载为ext4形式后,以后就不能再挂在成原来的ext2、ext3形式了。

 

可以使用下列指令使加入日志的ext2文件系统去除日志:

# tune2fs -O ^has_journal /dev/DEV

一些ext4的特性在ext3文件系统中不能体现。

 

/proc/fs/jbd2/partition/history中提供的信息

执行cat /proc/fs/jbd2/partition/history 有如下信息

R/C  tid   wait  run   lock  flush log   hndls  block inlog ctime write drop  close

R    7102  0     5000  0     1424  4     68681  5     6   

R    7103  0     5000  0     1644  4     64579  9     10  

R    7104  0     5000  0     856   32    38719  11    12  

R    7105  0     5000  0     1052  0     47142  12    13  

R    7106  0     5000  0     1172  16    56028  11    12  

R    7107  0     5000  0     1416  4     71047  11    12  

R    7108  0     5000  0     1640  4     81125  5     6   

R    7109  0     5000  0     1616  4     77314  6     7   

R    7110  0     5000  0     1640  0     76111  5     6   

:

:

文件的目的是提供ext4日志的。每个当前日志事件的提交就往这个文件中加入一行。每列的含义如下:

R/C

事物在运行或是提交。(注意目前的JBD2只显示正在运行的事物,不显示提交的数据)

Tid

事物的ID,用以区别不同的JBD2事物

Wait

事物开始所等待的毫秒数。如果应用做同步操作或者事物包含块的最大数量。

Lock

事物等待锁住所花的毫秒数

Flush

number of milliseconds flushing blocks to the filesystem for ordered mode before the transaction can be committed

log

将block的数据写入日志所需要的毫秒数

Hndls

日志事物的handles个数

Block

日志事物的block个数

Inlog

这个事物写入到block的block数目,包括日志的额外开销

 

/proc/fs/jbd2/<partition>/info提供的信息

在cat /proc/fs/jbd2/partition/info提供如下信息:

 

1498 transaction, each up to 8192 blocks

average:

  0ms waiting for transaction

  3924ms running transaction

  0ms transaction was being locked

  0ms flushing data (in ordered mode)

  12ms logging transaction

  14176us average transaction commit time

  289 handles per transaction

  26 blocks per transaction

  27 logged blocks per transaction

这个文件中显示了自mount以来,该文件系统在/proc/fs/jbd2/partition/history目录信息下的统计平均信息

 

如何改变ext4文件系统的大小

ext4在线改变大小的方式和ext3很相似,使用resize2fs或者ext2resize,但是对整个文件系统最大的大小有限制(4TB大小)。在有META_BG标记下这个限制大小可以增大。

 

什么是bitmap 分配器

Ext2和ext3通过遍历块的比特位来查看块是否空闲。十分低效,ext4的block allocator替代了bitmap allocator实现该功能,所以ext4比ext3也快了许多。

 

ext3ext4的主要区别

ext4的新特性在http://sundayhut.is-programmer.com/ 译文中解释过了

 

jdbjdb2的区别

两者大体上相同,但是jdb2增加了几个兼容性的功能:

1.    支持64位的文件系统

2.    日志事务的校验

3.    异步的事务提交块写

另外,对于刷新数据jbd2实施了一种新的ordered模式,它与延时分配结合使用,防止了当有大量数据写入文件系统而阻塞日志事物的提交的情况。这也避免了当有一个大的写(heavy write)时,fsync()延迟过长。

 

能在SSD上使用ext4文件系统吗?

可以,SSD实质上和其他的块设备没有什么区别。在先进的ssd上(主要考虑ssd寿命问题,日志区需要频繁修改),还可以把日志区放在SSD中。参考该链接:you can even put the journal on the SSD as well

链接中提出

  1. 可以把ext4作为无日志的模式挂载。此时系统崩溃就要执行fsck来恢复,恢复的速度取决于你文件系统的碎片化程度,由于ssd本身速度较快,可能恢复在10秒内
  2. 就算把journal放在ssd中也不会有太大问题,作者自己就是这么干的,估摸着在ssd坏了之前自己早就换电脑了。
  3. 自己做了一点小手脚来减少文件系统的写操作。比如说/tmp目录使用tmpfs文件系统、把firefox的缓存放在/tmp目录下。

 

本文为Frequently Asked Questions的翻译

Category: 文件系统 | Tags:
10
22
2014
0

获取日志区访问所占总访问量的百分比

获取文件系统负载工具如postmark,filebench等对文件系统日志区的访问所占访问的百分比。
 
准备工作:格式化测试盘,并将格式化的盘挂载
mkfs -t ext4 /dev/sdd1
mount /dev/sdd1 /home/tss/test-disk
 
 
step1:查看要测试磁盘中日志区的范围
查看/dev/sdd1磁盘中日志区的范围
在ext4中日志区由inode号8来指示,通过debugfs查看inode 8 所向的对应区域
 
debugfs /dev/sdd1
stat <8>
Inode: 8   Type: regular    Mode:  0600   Flags: 0x80000
Generation: 0    Version: 0x00000000:00000000
User:     0   Group:     0   Size: 134217728
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 262144
Fragment:  Address: 0    Number: 0    Size: 0
ctime: 0x54477848:00000000 -- Wed Oct 22 17:26:32 2014
atime: 0x54477848:00000000 -- Wed Oct 22 17:26:32 2014
mtime: 0x54477848:00000000 -- Wed Oct 22 17:26:32 2014
crtime: 0x54477848:00000000 -- Wed Oct 22 17:26:32 2014
Size of extra inode fields: 28
EXTENTS:
(0-32766):15761408-15794174, (32767):15794175
 
上述红色部分表示的是日志结点所对应的磁盘块号。
 
 
step2:运行postmark脚本并用blktrace检测结果
2.1在/home/tss/test-disk中运行如下postmark的脚本
root@f304-PowerEdge-R710:/home/tss/test-disk# postmark postmark.cfg
其中postmark.cfg的脚本内容如下 
set size 1000 5000
set transactions 500
set number 500
run
quit
 
2.2通过blktrace来捕捉postmark的动作
root@f304-PowerEdge-R710:/home/tss/script# ./blktrace.sh postmark
其中blktrace.sh脚本如下
#!/bin/sh
blktrace -d /dev/sdd1 -o -| blkparse -i - -o $1
 
step3:分析blktrace检测结果,得到访问日志区所占访问总量的百分比
blktrace的内容通过脚本分析,提取动作为A的项,并在动作为A的项中统计访问日志区的次数
脚本如下:
#!/bin/sh
awk '{if($6=="A")print ($8-2048)/8;i++}END {print "i="i}' $1>$2
awk '{if(($1>=15761408)&&($1<=15794175)){j++;}}END {print "j="j}' $2
 
其中第一个awk语句把A行所表示的扇区号转化为对应的块号。
其中第二个awk语句根据上述debugfs检查得到的日志区范围进行统计。
 
其中输入文件$1为上述红色标记blktrace捕捉输出文件的名字。
输出文件$2统计动作为A的行,最后一行awk语句记录访问日志区的数目。(通过j= ** 来指示)
由此可以计算出访问日志区占所有访问的比例。(j/i)

 

Category: 文件系统 | Tags:
9
25
2014
2

bio,request,request_queue的学习

bio:代表了一个io请求

request:一个request中包含了一个或多个bio,为什么要有request这个结构呢?它存在的目的就是为了进行io的调度。通过request这个辅助结构,我们来给bio进行某种调度方法的排序,从而最大化地提高磁盘访问速度。

request_queue:每个磁盘对应一个request_queue.该队列挂的就是request请求。

具体如下图:(有颜色方框头表示数据结构的名字)

 

请求到达block层后,通过generic_make_request这个入口函数,在通过调用一系列相关的函数(具体参见我另一篇博客)把bio变成了request。具体的做法如下:如果几个bio要读写的区域是连续的,即积攒成一个request(一个request上挂多个连续的bio,就是我们通常说的“合并bio请求”),如果一个bio跟其他的bio都连不上,那它就自己创建一个新的request,把自己挂在这个request下。当然,合并bio的个数也是有限的,这个可以通过配置文件配置。

对于上段补充一点:上层的一次请求可能跨越了多个扇区,形成不连续的扇区段,那么该请求构造的每个bio对应着一个连续的扇区段。故一个请求可以构造出多个bio。

合并后的request放入每个设备对应的request_queue中。之后设备驱动调用peek_request从request_queue中取出request,进行下一步处理。

这里要注意的是,在实现设备驱动时,厂家可以直接从request_queue中拿出排队好的request,也可以实现自己的bio排队方法,即实现自己的make_request_fn方法,即直接拿文件系统传来的bio来自己进行排队,按需设计,想怎么排就怎么排,像ramdisk,还有很多SSD设备的firmware就是自己排。(这里就和我另一篇博客,说到为什么generic_make_request要设计成一层递归调用联系起来)。

 

网上有个问答也是我的疑惑:这里我写一遍,加强记忆

bio结构中有bio_vec数组结构,该结构的的数组可以指向不同的page单元,那为什么不在bio这一级就做了bio合并工作,即把多个bio合并成一个bio,何必加入一个request这么麻烦?

答:每个bio有自己的end_bio回调,一旦一个bio结束,就会对自己进行收尾工作,如果合并了,或许有些bio会耽误,灵活性差。

 

参考博客:

http://blog.csdn.net/flyingcloud_2008/article/details/5818995

http://www.udpwork.com/item/8437.html

Category: 文件系统 | Tags:
9
22
2014
0
9
22
2014
0

address_space, 页高速缓存

address_space对象是文件系统中关于内存中页高速缓存的核心数据结构。这篇博客以address_space对象为切入点,分析文件系统的页高速缓存。

1背景

在文件系统中,内存中存在着dentry和inode结构,其中其分别的作用可以见我另一篇博客《dentry与inode》。由于这些结构要反复使用,所以内存里开辟了目录项高速缓存以及索引结点高速缓存,提高其访问速度。但这里要提到的是另一种高速缓存:页高速缓存,它是一种对完整的数据页进行操作的磁盘高速缓存,即把磁盘的数据块缓存在页高速缓存中。而address_space对页高速缓存进行管理。

2页高速缓存介绍

linux中几乎所有文件的读和写操作都依赖于页高速缓存。只有在O_DIRECT标志置为才会出现意外:此时,I/O数据的传送绕过了页高速缓存而使用了进程用户态地址空间的缓冲区;另外,少量的数据库软件为了采用自己的磁盘高速缓存算法而使用了O_DIRECT标志。

why设计页高速缓存?

答:1.快速定位所有者相关数据页的位置(基树)。2.区分不同所有者页的不同读写操作,如普通文件、块设备文件、交换区文件读一个数据页必须使用不同的方式实现,故内核根据页的不同所有者进行不同的操作。

3address_space对象

每一个所有者(可以理解为一个具体的文件,一个inode指向的文件)对应着一个address_space对象,页高速缓存的多个页可能属于一个所有者,从而可以链接到一个address_space对象。那么一个页(page)怎么和一个address_space产生关联的呢?

page中有两个字段:mapping和index。其中mapping指向该页所有者的address_mapping(内存inode结构有一个i_mapping指向对应address_space对象),index字段表示所有者地址空间中以页大小为单位的偏移量。用这两个字段就能在页高速缓存中查找也。(这里注意一点,一个页中所包含的磁盘块在物理上不一定是相邻的)

address_space中有一个host字段,该字段指向其所属的inode,也就是address_space中的host字段 与 对应inode中的 i_data字段形成互相指向的关系。若为普通文件,那么inode结点和address_space结构的相应指针的指向关系如下图:

 

4基树

linux支持TB级的文件,ext4甚至支持到了PB级文件,访问大文件时,高速缓存中存在着有关该文件太多的页,故设计了基树这个结构来加快查找。一个address_space对象对应一个基树。

address_space中有一个字段(page_tree)指向是基树的根(radix_tree_node)。基树根中的rnode指向基树的最高层节点(radix_tree_node),基树节点都是radix_tree_node结构,节点中存放的都是指针,叶子节点的指针指向页描述符,上层节点指向存放其他节点的指针。一般一个radix_tree_node最多可以有64个指针,字段count表示该radix_tree_node已用节点数。

怎么快速找到所需页在基树中的位置呢?

回顾本科所学知识:分页系统如何利用页表实现线性地址到物理地址的转换?线性地址的最高20位分为两个10为的字段:第一个字段是页目录的偏移,第二个字段是页目录所指向也表的偏移。

在基树中,类比此方法。若基树深度为1,则只能表示从0至63的索引,则页索引(上文提高的index字段)的低6位进行解析,从而对应成radix_tree_node结构中的slot下标,找到对应的页;若基树深度为2,则页索引的低12位分成0~5,6~11两个字段进行解析。分别找到第一层slot字段和第二层slot字段的值。

Category: 文件系统 | Tags:
8
26
2014
0

ext4文件系统浅析----跨度之大的inode号

最近在研究ext4文件系统,系统同道之人能共同研究、探讨

 

背景:

在根目录底下

root@f303server:/mnt/sde3# ls -i

     14 2.txt   786433 dir1  1048577 dir3        1179649 mkfs

     15 3.txt   917505 dir2       11 lost+found       13 sde3.txt

 

问题:

用黄色标记的几个为目录项,其中lost+found是格式化、挂载文件系统时自带的目录,其余四个是我创建的。那么问题来了,为什么我创建目录结点的inode号那么的大?

 

 

解释:

在ext4中,文件系统为了保证数据能更加均匀地分布在磁盘上,所以在创建目录时,尽量均匀地分布在不同的flexible block_group(flexbg)中。且同一个目录下的文件和这个目录的inode号在一个flexbg中:

 

默认一个flexbg含有16个block group,故 一个flexbg中含有inode结点数为8196 * 16 = 131072 个。所以dir1786433 位于第6flexbg中(131072 * 6 + 1 = 786433,在dir1目录下的1.txt,查看其inode结点号为  786434

 

同理可以计算其他的三个目录分别在第789flexbg

 

 

 

ps:

1怎么查看一个group有多少个inode结点:

debugfs /dev/sde3

stats

显示如下

 

debugfs

Stats
Filesystem volume name:   <none>
Last mounted on:          /mnt/sde3
Filesystem UUID:          fea02b9a-41d1-4bf1-96ce-d3298d67778f
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              1310720
Block count:              5242880
Reserved block count:     262144
Free blocks:              5116587
Free inodes:              1310705
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      1022
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512  #Inode table所占的块数目
Flex block group size:    16         #下面前16个inode bitmap所在
Filesystem created:       Mon Jul 28 08:40:58 2014
Last mount time:          Tue Jul 29 19:53:03 2014
Last write time:          Tue Jul 29 19:53:03 2014
Mount count:              8
Maximum mount count:      -1
Last checked:             Mon Jul 28 08:40:58 2014
Check interval:           0 (<none>)
Lifetime writes:          454 MB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      0da457a4-59ff-402a-9181-c66156ea5991
Journal backup:           inode blocks
Directories:              6
Group  0: block bitmap at 1025, inode bitmap at 1041, inode table at 1057
           23513 free blocks, 8178 free inodes, 2 used directories, 8176 unused inodes
           [Checksum 0x7a6d]
 Group  1: block bitmap at 1026, inode bitmap at 1042, inode table at 1569
           31740 free blocks, 8192 free inodes, 0 used directories, 8192 unused inodes
           [Inode not init, Checksum 0x2c05]
 Group  2: block bitmap at 1027, inode bitmap at 1043, inode table at 2081
           32768 free blocks, 8192 free inodes, 0 used directories, 8192 unused inodes
           [Inode not init, Block not init, Checksum 0x7c29]
 Group  3: block bitmap at 1028, inode bitmap at 1044, inode table at 2593
           31743 free blocks, 8192 free inodes, 0 used directories, 8192 unused inodes
           [Inode not init, Checksum 0x1e2b]延迟初始化
………..
……..
Group 12: block bitmap at 1037, inode bitmap at 1053, inode table at 7201
           32768 free blocks, 8192 free inodes, 0 used directories, 8192 unused inodes
           [Inode not init, Block not init, Checksum 0x30ab]
 Group 13: block bitmap at 1038, inode bitmap at 1054, inode table at 7713
           32768 free blocks, 8192 free inodes, 0 used directories, 8192 unused inodes
           [Inode not init, Block not init, Checksum 0x8f81]
 Group 14: block bitmap at 1039, inode bitmap at 1055, inode table at 8225
           32768 free blocks, 8192 free inodes, 0 used directories, 8192 unused inodes
           [Inode not init, Block not init, Checksum 0x8aa2]
 Group 15: block bitmap at 1040, inode bitmap at 1056, inode table at 8737
           32768 free blocks, 8192 free inodes, 0 used directories, 8192 unused inodes
           [Inode not init, Block not init, Checksum 0x350d]
 Group 16: block bitmap at 524288, inode bitmap at 524304, inode table at 524320
           24544 free blocks, 8192 free inodes, 0 used directories, 8192 unused inodes
           [Inode not init, Checksum 0xb89c]

 

 

2.怎么查看flexbg包含16个block group

从上面的debugfs的group 显示结果可以看出,group 0至group 15的block bitmap,inode bitmap、inode table是连续存放的。而从group 16开始元数据不再连续了,这也说明flexbg为16个block group。

Category: 文件系统 | Tags: ext4
8
26
2014
1

linux中ext4文件系统目录项管理

Ext4文件系统目录项有两种实现方式:

方式一:线性方式

        该方式的目录项以ext4_dir_entry_2的结构一个接连一个直接存储在目录结点所指向的block块中。(缺省配置使用ext4_dir_entry_2这个结构)

 

方式二:Hash树的方式

        若目录下的文件数量很多,则若按照线性方式查找对应文件名的信息则会很低效。Hash树的方式,则可以用文件名来做hash计算,从而定位到对应文件的目录项结构所在的block,从而缩小查找范围、加快查找效率。

 

1.查看文件系统是否开启了方式二的目录管理方式

      root@f303server:~# tune2fs -l /dev/sde3 | grep dir_index

Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg 

  输入如上指令,则可以发现文件系统的目录已经开启了hash树的管理方式。

 

2.hash树管理方式的打开和关闭

      在上述开启状态下,我们可以关闭hash树目录管理方式。关闭之后再打开。

root@f303server:~# tune2fs -O ^dir_index /dev/sde3

tune2fs 1.42.11 (09-Jul-2014)

root@f303server:~# tune2fs -l /dev/sde3 | grep dir_index  # 查找不到了

root@f303server:~# tune2fs -O dir_index /dev/sde3

tune2fs 1.42.11 (09-Jul-2014)

root@f303server:~# tune2fs -l /dev/sde3 | grep dir_index

Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize

root@f303server:~# 

 

 

3.怎么判断某目录是否以hash树的方式管理

 

    文件系统开启了hash树管理目录结点的方式并不意味着所有的目录都按树形结构组织管理。在文件系统中,系统会根据某个目录底下文件的多少来自动进行目录管理方式的选择,只有当文件数量大于某个数时,才会采用hash树管理方式。

 

    怎么判断某目录的管理方式是那种?

   

    若不是hash树的管理方式,则htree中debugfs中则会有如下提示

 

debugfs:  htree linux-2.6.34.14

 

htree: Not a hash-indexed directory

 

 

     若是hash树的管理方式,则

debugfs:  htree linux-2.6.34.14/kernel 显示如下

 

 


Root node dump:
         Reserved zero: 0
         Hash Version: 1
         Info length: 8
         Indirect levels: 0
         Flags: 0
Number of entries (count): 2
Number of entries (limit): 508
Entry #0: Hash 0x00000000, block 1
Entry #1: Hash 0x775173ee, block 2

Entry #0: Hash 0x00000000, block 1
Reading directory block 1, phys 3154297
791969 0x33788c78-7df72ede (20) rtmutex.c   
791971 0x12e2688e-f00920c3 (28) .latencytop.o.cmd   
791973 0x6d76fd8a-f7dad208 (16) futex.o   
791974 0x1f1d389c-0beb6325 (20) ns_cgroup.c   
791975 0x21f726a2-367f43fb (24) .built-in.o.cmd   
791977 0x2a43c4ba-ae0695eb (16) itimer.o   
791978 0x6139ce78-4032f3c2 (16) user.c   
791979 0x615af808-2478500b (24) test_kprobes.c   
791981 0x30feba52-ba8da1e9 (20) audit_tree.c   
791982 0x24bb2b3c-8100eb0d (20) kallsyms.o   
791987 0x71a57d4c-81410e0a (20) .uid16.o.cmd   
791989 0x3e1650ba-3d29a28e (20) freezer.c   
791991 0x0ba6a23a-978af98d (20) spinlock.o   
791992 0x1c6819e6-010b1d97 (24) sched_clock.o   
791997 0x6dc7a2ac-6b0769cb (12) gcov   792005 0x1db5303a-76fff9c7 (16) cpu.o   
792009 0x74def468-a27557c6 (20) .timer.o.cmd   
792010 0x540fdfac-e9e8121b (20) slow-work.o   
792014 0x4c0dc1c8-05179835 (24) Kconfig.preempt   
792018 0x620198da-2fb834e3 (16) cred.c   
792019 0x5973e25e-39b86f3d (32) .cgroup_freezer.o.cmd   
792021 0x1077ffa8-16896967 (16) sys.o   
792025 0x4011172e-63cbf0ec (28) .audit_tree.o.cmd   
792026 0x4c92aabc-1f86d6e5 (20) seccomp.o   
792027 0x5d7f2368-8aaa1cf9 (20) latencytop.c   
792028 0x2ff6ae9c-7b348c25 (24) pid_namespace.o   
792030 0x5f780482-e9fe78e9 (16) groups.o   
792031 0x6079e2b2-acbbff3a (24) rcutree_plugin.h   
792034 0x624e25c0-64cbfd07 (20) stacktrace.o   
792035 0x6e2d0608-09d837e7 (24) .sys_ni.o.cmd   
792036 0x7035c67c-3620d4f6 (16) uid16.o   
792038 0x5b9c06d0-57b802ad (24) .rcutree.o.cmd   
792039 0x356bc37c-95dc4cfb (16) fork.o   
792042 0x46df975e-cef87f2d (16) async.c 

该文如下部分探讨按照方式1组织的目录结构:

1.为了理解后文,首先了解ext4_dir_entry_2的每一个元素

Offset

Size

Name

Description

0x0

__le32

inode

Number of the inode that this directory entry points to.

0x4

__le16

rec_len

Length of this directory entry.

0x6

__u8

name_len

Length of the file name.

0x7

__u8

file_type

File type code, one of:

0x0

Unknown.

0x1

Regular file.

0x2

Directory.

0x3

Character device file.

0x4

Block device file.

0x5

FIFO.

0x6

Socket.

0x7

Symbolic link.

0x8

char

name[EXT4_NAME_LEN]

File name.

 

上表我们可以看到该结构中共5个数据项,前四项占8byte,

通过根目录为例,通过hexdump查看其二进制代码,则“目录项的长度(ren_len)= 文件名长度(name_len) + 8 ”。但是在很多情况下rec_len > = name_len + 8。原因是因为目录项每一项的起始位置必须按照后两位 00 对齐。故有时候会浪费几个字节。

 

 2.通过hexdump指令直接查看二进制内容

先通过

debugfs /dev/sde3

stat .

查找到根目录文件数据所在的块为9249,块大小为4K,故根目录数据所在的起始地址36996k。

 

root@f303server:~# hexdump -C /dev/sde3 -s 36996k -n 4096

02421000  02 00 00 00 0c 00 01 02  2e 00 00 00 02 00 00 00  |................|

02421010  0c 00 02 02 2e 2e 00 00  0b 00 00 00 14 00 0a 02  |................|

02421020  6c 6f 73 74 2b 66 6f 75  6e 64 00 00 01 00 0c 00  |lost+found......|

02421030  0c 00 04 02 64 69 72 31  01 00 0e 00 0c 00 04 02  |....dir1........|

02421040  64 69 72 32 0d 00 00 00  10 00 08 01 73 64 65 33  |dir2........sde3|

02421050  2e 74 78 74 0e 00 00 00  10 00 05 01 32 2e 74 78  |.txt........2.tx|

02421060  74 74 2e 73 11 00 00 00  10 00 05 01 33 2e 74 78  |tt.s........3.tx|

02421070  74 74 2e 73 01 00 10 00  0c 00 04 02 64 69 72 33  |tt.s........dir3|

02421080  01 00 12 00 0c 00 04 02  6d 6b 66 73 0c 00 00 00  |........mkfs....|

02421090  18 00 0e 01 62 6c 6b 74  72 61 63 65 5f 73 74 75  |....blktrace_stu|

024210a0  64 79 65 33 15 00 00 00  18 00 10 01 62 6c 6b 74  |dye3........blkt|

024210b0  72 61 63 65 5f 73 74 75  64 79 2e 63 10 00 00 00  |race_study.c....|

024210c0  14 00 0b 01 67 63 63 5f  62 6c 6b 74 2e 73 68 00  |....gcc_blkt.sh.|

024210d0  0f 00 00 00 10 00 07 01  6e 65 77 2e 74 78 74 63  |........new.txtc|

024210e0  12 00 00 00 1c 00 13 01  62 6c 6b 74 72 61 63 65  |........blktrace|

024210f0  5f 73 74 75 64 79 2d 76  31 2e 63 01 01 00 02 00  |_study-v1.c.....|

02421100  10 00 06 02 4e 65 77 44  69 72 61 63 13 00 00 00  |....NewDirac....|

02421110  1c 00 13 01 62 6c 6b 74  72 61 63 65 5f 73 74 75  |....blktrace_stu|

02421120  64 79 2d 76 32 2e 63 77  14 00 00 00 18 00 0e 01  |dy-v2.cw........|

02421130  64 72 6f 70 5f 63 61 63  68 65 73 2e 73 68 79 2e  |drop_caches.shy.|

02421140  01 00 04 00 10 00 06 02  73 64 65 31 63 70 15 01  |........sde1cp..|

02421150  01 00 08 00 b0 0e 0f 02  6c 69 6e 75 78 2d 32 2e  |........linux-2.|

02421160  36 2e 33 34 2e 31 34 00  00 00 00 00 00 00 00 00  |6.34.14.........|

02421170  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

*

02422000

 

上图中每个颜色表示一个dentry的记录

 

1

观察lost+found目录:

Rec_len = 0x 00 14   name_len = 0a

 

rec_len = name_len +8 +2   则在对齐时浪费了第三行的第1112个字节。

 

2

我们看到2.txt的文件名变成了2.txtt.s

 

原因是最后三个字节是无效字节,在对齐时已经去掉,对齐时三个字节的内容是随便填充的。

 

 

 

 

 

8
1
2014
0

Linux 运行自己的 mkfs 代码

1:背景:

     最近研究文件系统迫切地需要通过直接查看磁盘上的二进制源码来观察inode bitmap,databitmap,inode table,数据区的信息。可是如何知道各个区域在不同文件系统中所占的块大小,起始地址是个头疼的问题。我试着通过debugfs的一些功能来查找。具体尝试如下:

     debugfs /dev/sde3

     stat .

     可以查看根目录的数据所在的block,根目录数据区block为数据区第一个block,(我这么认为,模糊的记忆,有待求证)

     输入ls -i 查看根目录下各个文件的inode编号。本来想通过inode编号反向索引到inode table区的,但没有成功。。。

     于是当然就想到了直接看mkfs的源码,看格式化到底默认配置各个区各占多少个block。

 

2:怎样运行自己的mkfs 

     在系统中输入格式化指令时:mkfs.ext2  mkfs.ext3 mkfs.ext4等,系统就直接调用了其默认的mke2fs指令。首先我们要搞清楚如下的指令是等价的。

      mke2fs -t ext4  = mkfs -t ext4 = mkfs.ext4

     所以我们的关键是让系统能够运行我们自己的mke2fs执行文件,而不是系统默认的。步骤如下:

step1:http://sourceforge.net/projects/e2fsprogs/这个链接文件下下载e2fsprogs源码包

step2:把下载到的e2fsprogs-1.42.11.tar.gz包在linux下解压缩:比如说我解压缩的路径如下

root@f303server:/mnt/sde1/mkfs/e2fsprogs-1.42.11# tar zxvf e2fsprogs-1.42.11.tar.gz 

step3:更改congifure文件的执行属性

   打开解压缩的文件,文件下有一个配置文件congifure。将其改成可执行文件的属性  chmod +x congifure

   congifure 文件是配置文件,运行它能够根据你系统情况生成对应的makefile文件,从而为make做准备。

step4:运行configure文件

./configure  configure完成后,系统会生成makefile文件

step5: 编译

make  make完之后就生成可执行文件了

step6: 使用编译好的mke2fs

可执行文件mke2fs在misc目录下

cd misc/

ls

我们可以看到绿色的可执行文件标示:

 

有了它,我们就可以愉快的运行自己的mke2fs了。不过要记得在这里加上路径哦,在:/mnt/sde1/mkfs/e2fsprogs-1.42.11/e2fsprogs-1.42.11/misc路径下,如果直接输入mke2fs,则系统调用的是内核安装默认的。若想要运行我们编译的版本,需要做的是加上当前路径./mke2fs。

请看如下截图,我故意输入错误的mke2fs的指令,让其有Usage提示信息。以便于观察,我在自己的mke2fs版本的上的Usage提示信息加入了TSS,方便打印观察

 

 

上图可以看到,黑色标记部分证明了运行的是我编译的mke2fs文件。

到此为止我们就可以在/mnt/sde1/mkfs/e2fsprogs-1.42.11/e2fsprogs-1.42.11/misc路径下输入路径化的./mke2fs -t ext4 /dev/ram0 来用自己编译的mke2fs了。由于可以再mke2fs中间加入辅助打印信息,因此我们就可以方便的看到super block,GDT(块组描述符), inode bitmap , data bitmap,inode table以及数据区的具体位置了。这样用hexdump指令观察disk上的数据就更加有目标性了。为后续观察提供很大的便利。。给自己点个赞!

 

3.该过程的经历

上述6个步骤我哗啦啦地就总结完了,如果跟着做也哗啦啦很快做完了。可是其实我摸索的过程也挺崎岖的。。。

主要是自己还是too young,too simple,然后被一篇博客误导了。制作嵌入式文件系统工具mkfs.ext2 mkfs.ext2 mkfs.ext2。其实也不叫误导,人家题目都写清楚了是“嵌入式”的,而我确值看了后半句。。o(╯□╰)o~~他应该是在linux上编译e2fsprogs-1.42.11里面的文件,然后再在手机上运行,编译的机器和编译后可执行代码的设备机器不是同一个,所以需要用到交叉编译工具。以前我们嵌入式的课弄过交叉编译这玩意儿,可是没什么印象。我居然很逗地以为我也要交叉编译,按照那个步骤做。。然后一直在整那个交叉编译工具。。疯了~~~

 

附录:

1.默认格式化为ext2

root@f303server:/mnt/sde1/mkfs/e2fsprogs-1.42.11/e2fsprogs-1.42.11/misc# mkfs /dev/sde2
mke2fs 1.42.11 (09-Jul-2014)
/dev/sde2 contains a ext3 file system
created on Fri Aug  1 16:35:03 2014
Proceed anyway? (y,n) y
Creating filesystem with 1310720 4k blocks and 327680 inodes
Filesystem UUID: dfcd8416-8bdf-486f-8c33-10d2584a4e6f
Superblock backups stored on blocks: 
32768, 98304, 163840, 229376, 294912, 819200, 884736
 
Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done 
 
root@f303server:/mnt/sde1/mkfs/e2fsprogs-1.42.11/e2fsprogs-1.42.11/misc# mkfs -t ext3 /dev/sde2
mke2fs 1.42.11 (09-Jul-2014)
/dev/sde2 contains a ext2 file system (提示,该磁盘有了ext2文件系统,所以从该处推出上述格式化时默认版本为ext2)
created on Fri Aug  1 17:04:15 2014
Proceed anyway? (y,n) n

2.查看mkfs版本

root@f303server:/mnt/sde1/mkfs/e2fsprogs-1.42.11/e2fsprogs-1.42.11/misc# ./mke2fs -V 
mke2fs 1.42.11 (09-Jul-2014)
Using EXT2FS Library version 1.42.11
root@f303server:/mnt/sde1/mkfs/e2fsprogs-1.42.11/e2fsprogs-1.42.11/misc# mke2fs -V 
mke2fs 1.42.11 (09-Jul-2014)
Using EXT2FS Library version 1.42.11
 
看来刚刚下载的版本和系统自带的版本是同一个版本。
 
7
18
2014
0

文件系统--重命名的实质

在minix系统中输入如下指令

mv /tmp/test/a.txt /tmp/test/ttt/b.txt

文件系统具体的操作时什么?

step1 :找到/tmp/test所在目录项对应的数据块,得到a.txt文件的inode number,假设是0x18,并把inode number设为0,这样就把a.txt删除了

step2 :通过路径名得到/tmp/test/ttt目录所在的数据块,在其中添加一个新的目录项,并把该目录项的inode编号设置为Ox18,其他目录项的设置保持不变。这样就在/tmp/test/ttt下新建了一个b.txt。

所以说文件本身没有任何移动,在重命名指令下改变的只是目录项。

 

具体如下。

1.在/tmp/test目录项所在block找到a.txt,置为0.

022f060 00 00 62 2e 74 78 7400 00 00 00 00 00 00 00 00 |..a.txt.........|  “a.txt”文件,其inode number 
0022f070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|  被设为0 
 
2. 通过路径名翻译成磁盘上的位置得到“/tmp/test/ttt/”目录文件中的目录项,在其中添加一个新的目录项
0022f860 18 00 63 2e 74 78 7400 00 00 00 00 00 00 00 00 |..b.txt.........|  “b.txt”文件,其inode number 
0022f870 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|  被设为0x18
 
橙色的内容62改成了63,其他内容没变,其实对应的是a.txt该名为b.txt,名字由a变成了b
Category: 文件系统 | Tags:

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com