💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、豆包、星火、月之暗面及文生图、文生视频 广告
# :-: e2fsprogs工具介绍 | 适用范围 | 适用版本 | 人员 | 发布时间 | 文档版本 |备注 | | --- | --- | --- | --- | --- |--- | | 服务器操作系统 | | 王国武 |2022.3.22| V1.0|发布| | 服务器操作系统 | | 张志勇 |2022.3.22| V1.1|模板调整| ### 经测试,该方案有效可行 ***** ## 简介: 介绍e2fsprogs中一些工具的用途和用法。并给出一些简单的使用实例。 ## 正文: e2fsprogs提供了一些针对EXT2/EXT3/EXT4文件系统的实用工具,用来创建、检查、修改、修复上述文件系统。 接下来简单介绍其中几个常用工具的使用方法。 1. tune2fs tune2fs工具的作用是查看和调整文件系统的参数。 首先来看怎样使用tune2fs查看文件系统的整体情况。 -l选项提供了查看文件系统整体情况的功能,它列出了文件系统超级块中的内容。它提供了这样一些信息: Filesystem volume name,即文件系统标签,用作简述该文件系统的用途或其存储的数据。可以使用e2label或tune2fs –L修改。 Last mounted on,文件系统上一次挂载点路径,此项一般为空,较少使用,可以通过tune2fs –M设定。 Filesystem UUID,一个一般由乱数产生的识别码,可以用来识别文件系统。可以使用tune2fs –U修改:clear,清除文件系统UUID;random生成随机的UUID;time,基于时间生成UUID。 Filesystem magic number,用来识别文件系统为EXT2/EXT3/EXT4的签名,EXT系列文件系统必定为0xEF53。 Filesystem revision #,文件系统版本编号,现在支持:0,原始格式,Linux 1.2之前只支持此种格式;1(dynamic),支持动态inode大小,是默认值。 Filesystem features,文件系统已经开启的功能。通过查看mke2fs配置文件/etc/mke2fs.conf文件,可以得知,有基础功能(base_features)如下: sparse_super,只有少数块组有超级块,而不是每个块组都有超级块,节省空间。格式化文件系统时若使用了这个功能,则只会在0或者3,5,7幂次号块中备份超级块。 filetype,目录项可以记录文件类型 resize_inode,保留一定的空间,以保证块组描述符表在进行扩展时有空间可以使用。 dir_index,使用哈希B树来加快在大目录中的查找速度。 ext_attr,支持extended attribute。 并且针对不同的文件系统还有不同的功能,例如EXT3文件系统还有如下功能: has_journal,有日志,表示当前文件系统具有日志功能。 EXT4文件系统除了有has_journal功能以外,还有以下功能: extent,文件系统使用extent树作为文件数据的索引方式,而不是使用直接间接索引。 huge_file,扩展inode大小至256,即扩大inode索引的地址空间,使文件系统支持大于2T大小单个文件。 flex_bg,灵活块组的功能,提供更多更大的逻辑块组。 uninit_bg,创建文件系统时不会初始化所有的块组。 dir_nlink,允许单个目录下能够包含超过65000个子目录。 extra_isize,inode额外的大小,使inode以包含更多信息,例如纳秒级的时间戳。 在这些功能中,dir_index、dir_nlink、filetype、flex_bg、has_journal、large_file、resize_inode、sparse_super、uninit_bg这些功能能够通过tune2fs -O进行设置,其中设置或取消sparse_super,uninit_bg,filetype和resize_inode功能后需要再执行e2fsck。设置了dir_index功能之后要使用e2fsck -D来讲现存的目录由线性结构转化为哈希B树结构。另外,只有EXT4文件系统支持uninit_bg功能和flex_bg功能。 Filesystem flags,文件系统标志,有如下值可以使用:1 (signed_directory_hash),表示目录结构使用signed hash;2 (unsigned_directory_hash)表示目录结构使用unsigned hash;4,表示测试开发代码。 Default mount options,表示默认挂载选项。默认挂载选项可以通过tune2fs -o设置或清除。 Filesystem state,表明文件系统状态。在没有使用日志的文件系统上,使用文件系统状态来确定文件系统是否被正常卸载,其值可以为: clean – 表示文件系统已经成功被卸载; not-clean – 表示文件系统挂载成读写模式后,任未被卸载; erroneous – 表示文件系统被发现有问题。 Errors behavior,文件系统发生问题时内核代码的处理方案,可以通过tune2fs -e进行设置,其值可以为: Continue – 继续正常运行; remount-ro – 重新挂载成只读模式; panic – 系统当掉。 Filesystem OS type,创建该文件系统的操作系统类型。 Inode count,该文件系统中inode的总数,也就是整个文件系统文件数上限。 Block count,文件系统总的块数。 Reserved block count,保留给系统管理员使用的块数。可以通过tune2fs –r进行设置。同样,也可以通过tune2fs –m分配一定比例总块数的块作为保留块。 Free blocks,未使用的块数。 Free inodes,未使用的inode总数。 First block,superblock或第一个块组开始的块编号。由于文件系统最开始要保留1024大小的区域不使用,对于块大小为1024的文件系统,0号块是不能使用的,块组开始于1号块;而对于块大小为2048或4096的文件系统,应该是从0号块组开始。 Block size,块大小。 Fragment size,由于EXT2/EXT3/EXT4文件系统不支持fragment,所以这个值一般和块大小相同。 Reserved GDT blocks,保留块组描述符块数,在创建文件系统时,mkfs会紧接着在块组描述符表之后、块位图之前分配一定数量的块保留下来,以供文件系统扩展时使用(加大块组描述符大小或者增加块组描述符数目)。 Blocks per group,每个块组的块数 Fragments per group,每个块组的fragments数。 Inodes per group,每个块组的inode数。 Inode blocks per group,每个块组中inode表所占块组数。 Flex block group size,一个灵活块组中块组的数目。 Filesystem created,文件系统创建时间。 Last mount time,最后挂载时间,上一次挂载此文件系统的时间。 Last write time,最后修改时间,上一次改动此文件系统的时间。 Mount count,距离上一次完整的文件系统检查后文件系统被挂载的次数,让fsck决定是否进行另一次完整文件系统检查。可以通过tune2fs –C设置。 Maximum mount count,文件系统进行另一次完整检查可被挂载次数,若挂载次数(Mount count)大于此值,则会进行以此完整的文件系统检查。该值可通过tune2fs -c 进行设置,若该值为0或者-1,则不会根据挂载次数来决定是否进行完整的文件系统检查。 Last checked,最后检查时间,上一次文件系统完整检查的时间。可以通过tune2fs –T进行设置。 Check interval,检查间距,文件系统应该进行另一次完整检查的最大时间距。可以通过tune2fs –i进行设置。若该值为0,则关闭该项功能。 Lifetime writes,文件系统创建至今总共的写入量。 Reserved blocks uid,保留块用户id。可以通过tune2fs –u进行设置。 Reserved blocks gid,保留块组id。可以通过tune2fs –g进行设置。 First inode,第一个可以用作正常存放文件的inode编号,一般情况下为11。在EXT文件系统中,前几个inode号都有其他的用处。0,不存在,没有0号inode;1,list of defective blocks,有错误的块的列表;2,文件系统根目录;3,用户配额;4,组配额;5,启动装载器;6,undelete directory;7,保留块组描述符inode,记录保留GDT位置;8,日志;9,the “exclude” inode,for snapshots;10,replica inode,供非上游版本功能使用。 Inode size,索引节点的大小。关于索引节点及其相关数值,有以下关系:inode_size = inode_blocks_per_group * block_size / inodes_per_group Required extra isize,inode需要的额外大小。这一部分表示inode需要的额外大小,通常情况下,inode大小可以为128字节,但在EXT4中,由于加入了一些新功能,inode需要额外的大小,一般情况下需要28个字节,那么现在一个inode大小也就是128 + 28 = 156字节,由于对齐的需要,一个inode的大小为256。这28个字节如下,__le16 iextra_isize,记录inode_real_size – 128,一般情况下为28;__le16 i_checksum_hi,inode节点checksum的高16位;__le32 i_ctime_extra,inode最后改变时间的额外部分,提高时间精度;__le32 i_mtime_extra,最后数据修改时间的额外部分,提高时间精度;__le32 i_atime_extra,最后访问时间的额外部分,提高时间精度;__le32 i_crtime,文件创建时间,精度为秒;__le32 i_crtime_extra,文件创建时间的额外部分,提高时间精度;__le32 i_version_hi,版本号的高32位。 Desired extra isize,inode期望的额外大小。 Journal inode,日志所用inode号,一般为8。 Default directory hash,目录哈希B树结构所用的哈希算法。 Directory Hash Seed,目录哈希B数结构所用哈希算法的种子。 Journal backup,不清楚。 除了-l选项以及之前介绍的调整文件系统参数的选项外,还有一点常用的参数: -j,给文件系统增加日志功能。 -J,日志选项。size和device只能二者选其一。 size = journal-size,在文件系统上创建一个大小为journal-size的日志。 device = external-journal,为文件系统附加一个external-journal上的文件块设备。该外部日志必须已经通过mke2fs –O journal_dev external-journal创建。 以上是tune2fs常用的一些选项及其解释。 2. dumpe2fs tune2fs基本上是对文件系统超级块的解析与调整。再来看一个,能够进一步提供整个文件系统信息的命令,它的主要目标是看每个块组的情况——dumpe2fs。 首先还是来看一看它提供哪些常用的选项: -b,打印出文件系统中保留为bad的数据块。 -o superblock=superblock,使用superblock为文件系统超级块进行解析,这在一个被严重破坏的文件系统上有用,因为默认的超级块很有可能已经被破坏了。 -o blocksize=blocksize,使用blocksize作为文件系统的大小,默认情况下不需要指定,同样的,也是在一个被严重破坏的文件系统上有用,因为可能已经无法正常解析出块大小了。 -h,只显示超级块的信息,这个就和tune2fs –l的效果一样,将超级块的内容解析出来。另外它还会显示一些日志相关信息,包括日志特性,日志大小,日志长度,日志序列号,日志起始等。 -i,使用e2image创建的的image文件显示文件系统相关信息。这个首先需要使用e2image创建相关的image文件,此处暂时不表。 -x,将块组信息以16进制形式显示。 了解了这些选项之后,我们来看一看dumpe2fs是怎么显示块组信息的。 ![](https://img.kancloud.cn/61/c0/61c0c26c0744e8ac907425a71025704a_554x474.png) 由上图可以看到,它给出了块组的一些信息: 块组编号和块的范围。 块组状态: INODE_UNINIT,块组索引节点表/索引节点位图未初始化; BLOCK_UNINIT,块组块位图未初始化; ITABLE_ZEROED,磁盘上索引节点表初始化为0。 块组校验和。 主/备份超级块位置。 主/备份块组描述符位置。 保留GDT块位置。 块组块位图位置和相对于块组起始块偏移量。 块组索引节点位图位置和相对于块组起始块偏移量。 块组索引节点表位置和相对于块组起始块偏移量。 剩余块数,剩余索引节点数目录数量。 所有可用数据块编号。 所有可用索引节点编号。 在一个块组中没有块被使用时,块组会有BLOCK_UNINIT标志;当块组中没有inode被使用时,块组就会有INODE_UNINIT标志。 可以看到,在上图某些块组中,块位图,inode位图和inode表相对于对应块组起始块的偏移量是一个很大的数字,显然不正确,这是由于:该文件系统为EXT4文件系统,并且使用了flex_bg功能,通过tune2fs –l或者dumpe2fs查看到Flex block group size项的值为16,那么每16个块组就组成一个flexible block group;这16个块组中每个块组的块位图,inode位图和inode表都放在了这个flex block group的第一个块组里;除了第一个块组,之后每个块组的位图等都——在第一个块组内——不在对应的块组里,那么在某些块组计算相应偏移量时,位图块号 – 块组起始块 得到的结果是一个负数,在u32情况下就溢出了,导致相应的显示结果为一个很大的正整数。例如,我们看1号块组的块位图,它的物理块号为1026,1号块组的起始块号为32768,那么得到的偏移量为1026 – 32768 = -31742,那么它在u32的情况下,对应的正整数应该为它对0x100000000取模,-31742 mod 4294967296 = 4294935554,就是我们看到的偏移量。 我们可以使用通过dumpe2fs工具查看超级块和块组描述符都在文件系统的什么位置。 #dumpe2fs device | grep superblock 可以看到结果如图: ![](https://img.kancloud.cn/c5/a6/c5a6e58801ca184e079e84c775a2d108_554x305.png) 这样就列出了主/备份超级块和块组描述符所在的位置。并且通过位置可以计算出它在哪个块组。通过tune2fs –l或者dumpe2fs可以得到Blocks per group项的值32768,得到First block项的值0,那么表明n号块组块组的块编号区间为[n*32768, (n+1)*32768-1],n=0,1,2…,例如对于位于2654208号的备份超级块,它的块组号为2654208 / 32768 = 81。 以上就是对dumpe2fs工具的一些简单的介绍和使用。 dumpe2fs对块组这一层级有了一定的描述,接下来介绍一个可以针对文件本身及其元数据进行查看和修改的工具debugfs。 debugfs是一个交互式的文件系统调试器程序,它能被用来检查和改变EXT2/EXT3/EXT4文件系统的状态。作为一个可交互式的程序,它有命令本身的选项,也有一些子命令及子命令选项。首先来看一看命令选项: -w,文件系统以可读写模式打开,否则以只读模式打开。Debugfs工具中的一些子命令需要可写权限,在使用那些子命令时,文件系统必须以可读写模式打开。 -c,文件系统以catastrophic模式打开,这是文件系统是只读的。在catastrophic模式下,索引节点和块位图没有在初始化时读入。这种模式在文件系统遭到严重破坏时有用。 -i,使用e2image创建的的image文件显示文件系统相关信息。由于image文件中只包含超级块,块组描述符,块位图,索引节点位图和索引节点表,所以debugfs一些子命令不能正常使用。这个首先需要使用e2image创建相关的image文件,此处暂时不表。 -d data_source_device,和-i参数一起使用,指定使用data_source_device作为image文件中缺失块的来源。这些块包括文件数据,目录,间接块。 -b blocksize,指定文件系统的块大小。 -s superblock,选择指定块作为文件系统的超级块。使用该参数时,必须同时使用-b参数。 -f cmd_file,debugfs还能从文件中读取并执行命令。执行完命令之后就退出了。 -R request,debugfs将执行一条单独的命令request,然后退出。request就是一条debugfs的子命令。 在debugfs中,许多子命令使用一个filespec参数来指定一个inode(或文件)。filespec参数可以通过两种方式指定。第一种方式:用一对尖括号将inode号括起来,例如<11>。第二种方式:使用文件的路径名。 3. debugfs 接下来介绍debugfs的一些子命令。 首先是一组与超级块和块组相关的调试命令。 stats,显示超级块和块组相关信息。-h选项表示只显示超级块信息。这个命令同dumpe2fs命令显示的内容类似。 ssv <field> <value>,设置超级块值,可用的field可以通过ssv -l列出来。各个field的具体含义可以参考之前tune2fs -l中一些对应项的说明。更为详细的说明可以参考EXT4文件系统wiki页相关内容。 set_bg <bg_number> <field> <value>,设置块组信息,块组相关的field可以通过set_bg -l列出来。块组中各个field的含义可以参考之前dumpe2fs显示内容的说明,亦可以参考EXT4文件系统wiki页中更为详细的说明。 supported_feature,显示该版本e2fsprogs支持的文件系统功能。 features,显示当前文件系统已经开启的功能。同时也可以通过该命令设置功能,features <feature>;清除某项功能,features -<feature>。 在debugfs命令打开的文件系统中,有一些命令提供了在被打开文件系统中进行目录操作的子命令。 pwd,显示当前工作目录和根目录。 cd,更改当前工作目录。 chroot <file>,更改根“/”目录。 现有操作如下: # debugfs /dev/vda2 debugfs 1.41.12 (17-May-2010) debugfs: pwd [pwd] INODE: 2 PATH: / [root] INODE: 2 PATH: / debugfs: chroot root debugfs: pwd [pwd] INODE: 2 PATH: / [root] INODE: 81921 PATH: /root debugfs: cd / debugfs: pwd [pwd] INODE: 81921 PATH: /root [root] INODE: 81921 PATH: /root debugfs: 可以看到,通过debugfs进入文件系统时,初始的当前工作目录和根目录都是“/”目录。使用chroot将root变为根目录之后,pwd显示的根目录就为root目录了。之后再通过cd /进入根目录,可以看到由于现在根目录为root,所以当前工作目录也到了root目录。 ls,类似于系统中的ls命令,用来查看目录下有哪些文件和目录。它有几种参数。-l显示较为详细的信息,-p以/分隔个显示项,-d能够显示出已删除文件。 debugfs: ls 1081345 (12) . 2 (12) .. 1246499 (4072) rh debugfs: ls -l 1081345 40755 (2) 0 0 4096 5-Dec-2013 07:33 . 2 40555 (2) 0 0 4096 5-Dec-2013 04:06 .. 1246499 40755 (2) 0 0 4096 12-Nov-2012 22:18 rh debugfs: ls -p /1081345/040755/0/0/.// /2/040555/0/0/..// /1246499/040755/0/0/rh// debugfs: ls -d 1081345 (12) . 2 (12) .. 1246499 (4072) rh <1083786> (4060) abc debugfs: 不加选项时,显示的是inode号,目录项大小,目录项名字。 -l,显示的是inode号,文件类型和文件权限(开头数字2表示字符设备,4表示目录,6表示块设备,10表示普通文件,12表示符号链接),所有者uid,组gid,文件大小(字节),日期,最后创建时间,文件名。 -p显示的是inode号,文件类型和文件权限,所有者uid,组gid,文件名。 目录相关的子命令还有mkdir和rmdir,用于创建和删除目录。rmdir只能用来删除空目录。 接下来是一些与inode相关的子命令 stat filespec,显示filespec对应inode结构的内容 debugfs: stat /usr/bin/firefox Inode: 276272 Type: regular Mode: 0755 Flags: 0x80000 Generation: 1328750058 Version: 0x00000000:00000001 User: 0 Group: 0 Size: 7781 File ACL: 0 Directory ACL: 0 Links: 1 Blockcount: 16 Fragment: Address: 0 Number: 0 Size: 0 ctime: 0x5192f348:d4cc5240 -- Wed May 15 10:30:32 2013 atime: 0x529eea1d:a602c2e4 -- Wed Dec 4 16:38:53 2013 mtime: 0x4f275760:00000000 -- Tue Jan 31 10:52:16 2012 crtime: 0x5192f348:d4152c14 -- Wed May 15 10:30:32 2013 Size of extra inode fields: 28 Extended attributes stored in inode body: selinux = "system_u:object_r:bin_t:s0\000" (27) EXTENTS: (0-1): 1264330-1264331 这显示了文件对应inode结构的内容。其中有一些很重要的内容,例如文件的Mode,User,Group,Size,Links,各种日期以及文件所在物理块信息等。 modify_inode,mi,修改inode结构的值。 set_inode_field,设置inode结构的某些项。-l参数可以列出这些可以修改的项。 clri,清除inode结构的内容。 find_free_inode,ffi,找到目录结构中下一个空闲的inode号。 例如test目录的inode号为395571。 debugfs: find_free_inode 393217 Free inode found: 403111 那么在目录test中,下一个可用的inode号为403111。 testi,查看一个inode是否被使用。 freei,清除某个inode的正在使用状态。 seti,设置某个inode的正在使用状态。 接着之前的例子: debugfs: find_free_inode 393217 Free inode found: 403111 debugfs: testi <403111> Inode 403111 is not in use debugfs: seti <403111> debugfs: testi <403111> Inode 403111 is marked in use debugfs: freei <403111> debugfs: testi <403111> Inode 403111 is not in use debugfs: 我们可以看到,freei和seti可以改变inode的使用状态。 以上是关于inode的一些子命令。 关于文件系统的块,debugfs也有一些可以使用的子命令。 find_free_block,从某一个块开始,找到指定个数的可使用块。 testb,检查一个块是否被使用。 freeb,清除某个块的正在使用状态。 setb,设置某个块的正在使用状态。 debugfs: find_free_block 10 32768 Free blocks found: 33793 33805 33806 33807 33808 33809 33810 33811 33812 33813 debugfs: testb 33793 Block 33793 not in use debugfs: setb 33793 debugfs: testb 33793 Block 33793 marked in use debugfs: freeb 33793 debugfs: testb 33793 Block 33793 not in use debugfs: 上述过程是从第32768号块开始,寻找前10个没有被使用的块,针对第一个没有被使用的块执行setb和freeb操作,并查看其使用情况。 以上是debugfs中与块相关的子命令。 如果想获取文件系统中某个文件的内容,则可以通过以下几个子命令完成。这都只需要debugfs以只读方式打开文件系统,不会对文件系统进行修改。 cat,将文件系统中一个文件的内容输出到标准输出。 dump,将文件系统中一个文件的内容输出到本地文件。-p选项会设置文件本身的用户,组合,权限。 rdump,递归地将文件系统中一个目录输出到本地文件系统。 debugfs还提供了一个日志相关的子命令,可以用来查看日志相关的信息。 不加任何参数时,logdump子命令显示日志各个块的信息,包括revoke表,描述块,提交块,以及这些块对应的事务序列号等。 ![](https://img.kancloud.cn/60/83/6083adbbe9ce432f908bc0271f109bb2_554x335.png) logdump子命令加上-a选项之后,就会将每一个revoke表和每个事务中记录的信息显示出来。 ![](https://img.kancloud.cn/db/fb/dbfbd26eaf2874041337e0ca7ab6f88c_554x734.png) 如上图所示,这个就记录了一个revoke表,一个序列号为466215的事务。这个事务有一个描述块,一个提交块,若干个数据块。数据块对应的文件系统块号和日志块号都显示了出来。 如果我们关心一个inode相关的日志,也可以加-i选项接一个inode号,这样与这个inode相关的日志就能显示出来。 inode号相关的日志信息包括,inode所在块组号,inode所在块号,inode在块内的偏移,inode所在块在日志中的事务号,对应的日志块,以及inode的详细信息。但是在EXT4上,inode的信息为空,EXT3上会显示inode的信息。 如果没有真正找到该inode相关的日志,就不会显示inode信息。但是我们仍然能够知道日志中哪些内容是和这个inode有关的。logdump子命令还提供了一个-b选项,可以查看文件系统中某一个块在日志中的记录。 ![](https://img.kancloud.cn/db/ed/dbedbae81dd39dcb9811a0f3180d647b_554x290.png) 在使用了-b选项时,在加上-c选项,就能把文件系统这个块在日志中记录的内容显示出来。 这是debugfs与日志有关的子命令。 debugfs中还有能够对文件系统结构理解有所帮助的子命令。 首先是文件的extent树结构。 dump_extents,显示出一个文件的extent树,包括index节点和叶子节点。-n选项就只显示内部节点,-l选项就只显示叶子节点,默认都显示。 debugfs: dump_extents <403050> Level Entries Logical Physical Length Flags 0/ 1 1/ 1 0 - 44895 8921830 44896 1/ 1 1/ 2 0 - 32767 2756608 - 2789375 32768 1/ 1 2/ 2 32768 - 44895 2789376 - 2801503 12128 debugfs: dump_extents -n <403050> Level Entries Logical Physical Length Flags 0/ 1 1/ 1 0 - 44895 8921830 44896 debugfs: dump_extents -l <403050> Level Entries Logical Physical Length Flags 1/ 1 1/ 2 0 - 32767 2756608 - 2789375 32768 1/ 1 2/ 2 32768 - 44895 2789376 - 2801503 12128 我们可以看到,对于inode号为403050的文件,它的extent树有两个level,level 0为内部节点,level 1为叶子节点。 level 0的内部节点表示文件的0~44895号块,这个index节点所在物理位置为8921830号块。level 1有两个叶子节点,每一个都表示一段逻辑块到物理块的映射。 接下来是文件系统中哈希树结构的目录,使用哈希树结构目录的具体触发条件没有搞清楚。 htree_dump,显示一个哈希树结构目录的结构。以/usr/bin目录为例。 首先可以看到该目录树结构根节点(dx_root数据结构)的信息: Root node dump: Reserved zero: 0 Hash Version: 1 Info length: 8 Indirect levels: 0 Flags: 0 Number of entries (count): 16 Number of entries (limit): 508 Entry #0: Hash 0x00000000, block 1 Entry #1: Hash 0x10ac880e, block 11 Entry #2: Hash 0x21b5cde6, block 5 Entry #3: Hash 0x35eaccf4, block 9 Entry #4: Hash 0x4a472cc6, block 3 Entry #5: Hash 0x590819de, block 10 Entry #6: Hash 0x697f1422, block 7 Entry #7: Hash 0x787af150, block 15 Entry #8: Hash 0x8699b1b0, block 2 Entry #9: Hash 0x969a75ba, block 13 Entry #10: Hash 0xa73eec0a, block 6 Entry #11: Hash 0xb683d704, block 14 Entry #12: Hash 0xc5e21056, block 4 Entry #13: Hash 0xd46f1200, block 12 Entry #14: Hash 0xe401cc86, block 8 Entry #15: Hash 0xf1e04a24, block 16 Reserved zero,默认情况下就应该为0;Hash Virsion,0为Legacy,1为Half MD4,2为Tea,3为unsigned Legacy,4为unsigned Half MD4,5为unsigned Tea,此处是Half MD4;Info length表示的是指向树中下一级节点的数据结构(dx_entry)大小,默认为8,4个字节表示哈希值,4个字节表示该块在目录文件中的块编号;Indirect levels,如果是0,则表示树形结构中下一级节点就是普通的线性结构目录,否则是一个内部节点,内部节点将指向下一级节点(叶子节点,即线性目录结构);Flags,未使用;可用的dx_entry数,为16;dx_entry结构中最大dx_entry限制数508;每个dx_entry的哈希值及其对应在目录文件中的块编号。 限制数508的来源,dx_root数据结构首地址与块大小对齐,它占据一个页dx_entry为该结构最后的成员,而dx_entry之前的成员占据了0x28,即40个字节大小,块大小4096 – 40 = 4056,每个dx_entry的大小为8,则4056 / 8 = 507,另外在dx_root结构里会标明hash=0的目录块的物理地址,所以此处为507 + 1 = 508。 htree_dump命令然后显示的是每个线性结构目录的内容,例如: Entry #0: Hash 0x00000000, block 1 266131 0x0c4eea88-0ccb2352 (16) iconv 264222 0x0866892a-72773295 (16) igawk 264631 0x0c1416c0-448e626b (20) rgb2ycbcr 271991 0x05fccc22-6691ea89 (12) top 264925 0x0b68363a-5a969f83 (16) pod2man 265195 0x012826f6-769bfefd (20) lesspipe.sh 对于entry 0,它的哈希值为0x00000000,块编号为1。对于该块中的每一个文件,例如 266131 0x0c4eea88-0ccb2352 (16) iconv 有文件的inode号,计算出来的哈希值,该文件目录项在目录中所占大小,文件名。 对于一个文件名的哈希值,可以通过debugfs中的子命令dx_hash计算。 dx_hash,有选项-h指定哈希算法,-s选项指定哈希种子,计算一个文件名的哈希值。文件系统选择的哈希算法和哈希种子可以通过tune2fs –l查找到,例如: # tune2fs -l /dev/sda3 | grep -i hash Filesystem flags: signed_directory_hash Default directory hash: half_md4 Directory Hash Seed: 86b59363-a73c-4b7a-8f66-1a1f6751310e 可知算法为half_md4,种子为86b59363-a73c-4b7a-8f66-1a1f6751310e。 通过dx_hash计算iconv文件的哈希值,可以用: debugfs: dx_hash -h half_md4 -s 86b59363-a73c-4b7a-8f66-1a1f6751310e iconv Hash of iconv is 0xc4eea88 (minor 0xccb2352) 可以看到,这同之前用htree_dump看到的文件名iconv的哈希值就有了对应。 0x0c4eea88-0ccb2352,对应为0xc4eea88 (minor 0xccb2352)。 以上是debugfs对文件系统数据结构的一些查看情况。 debugfs还有一些子命令,也有自己的用处。 icheck,通过一个块号查找这是哪个inode所有的数据块。若不属于任何inode,则显示未找到。 ncheck,通过一个inode号查找其对应的文件路径。若inode没有对应的文件路径,则不显示。 那么我们现在如果知道一个块号,就可以查看它是属于哪个文件,例如 debugfs: icheck 47742981 Block Inode number 47742981 11927561 debugfs: ncheck 11927561 Inode Pathname 11927561 /root/anaconda-ks.cfg 使用icheck找到了块47742981属于inode 11927561,通过inode 11927561找到了文件/root/anaconda-ks.cfg。 bmap,计算一个文件一个逻辑块对应的物理块号。例如: bmap: Usage: bmap <file> logical_blk debugfs: bmap <11> 0 9250 这样就找到了11号inode对应文件0号逻辑块的物理块位置。 imap,计算一个inode节点的物理位置。这样可以更加快速地取出该inode以查看,例如: debugfs: imap <403050> Inode 403050 is part of block group 49 located at block 1573510, offset 0x0900 这样就快速得到了403050号inode所在物理位置。 expand_dir,扩展一个目录的大小。这个命令实际上是为一个目录预先多分配一个块,因此这个目录在使用时能够多些块来容纳更多的目录项,以减少使用时新的块分配。在一个没有剩余空间的文件系统进行fsck时,恢复的文件会放到lost+found目录下,如果lost+found目录之前扩展的空间足够,则不需要再进行新的块分配。expand_dir子命令需要在可读写模式下使用,使用前后对比: debugfs: stat /lost+found Inode: 11 Type: directory Mode: 0700 Flags: 0x0 Generation: 0 Version: 0x00000000:00000019 User: 0 Group: 0 Size: 24576 File ACL: 0 Directory ACL: 0 Links: 2 Blockcount: 48 Fragment: Address: 0 Number: 0 Size: 0 ctime: 0x52a1211b:bff177b4 -- Fri Dec 6 08:58:03 2013 atime: 0x52a1211d:90fd6a40 -- Fri Dec 6 08:58:05 2013 mtime: 0x52a1211b:bff177b4 -- Fri Dec 6 08:58:03 2013 crtime: 0x5192f0a3:00000000 -- Wed May 15 10:19:15 2013 Size of extra inode fields: 28 Extended attributes stored in inode body: selinux = "system_u:object_r:lost_found_t:s0\000" (34) BLOCKS: (0-3):9250-9253, (4):9266, (5):9268 TOTAL: 6 debugfs: expand_dir /lost+found debugfs: stat /lost+found Inode: 11 Type: directory Mode: 0700 Flags: 0x0 Generation: 0 Version: 0x00000000:00000019 User: 0 Group: 0 Size: 28672 File ACL: 0 Directory ACL: 0 Links: 2 Blockcount: 56 Fragment: Address: 0 Number: 0 Size: 0 ctime: 0x52a1211b:bff177b4 -- Fri Dec 6 08:58:03 2013 atime: 0x52a1211d:90fd6a40 -- Fri Dec 6 08:58:05 2013 mtime: 0x52a1211b:bff177b4 -- Fri Dec 6 08:58:03 2013 crtime: 0x5192f0a3:00000000 -- Wed May 15 10:19:15 2013 Size of extra inode fields: 28 Extended attributes stored in inode body: selinux = "system_u:object_r:lost_found_t:s0\000" (34) BLOCKS: (0-3):9250-9253, (4):9266, (5):9268, (6):9376 TOTAL: 7 可以看到,在执行了expand_dir之后,目录的数据块多了一块,可以供更多的目录项使用。 以上是对debugfs工具的简单介绍。