OK ,我们拿到了这些信息,但是,我怎么证明debugfs拿到的信息是对的呢。只有一个办法,我们钻到超级块里面,根据超级块数据结构,获得超级块每个字段的值,听起来很刺激吧,OK,Just DO IT。
- root@libin:/mnt/bean# dd if=/dev/loop0 bs=1k count=261 |od -tx1 -Ax > /tmp/dump_hex
- 记录了261
0 的读入 - 记录了261
0 的写出 - 267264字节(267 kB)已复制,0.0393023 秒,6.8 MB/秒
- root@libin:/mnt/bean# vi /tmp/dump_hex
我将整个loop设备前面的261K字节读入了/tmp/dump_hex中。其中第0块是启动块,按下不提。第一块就是说super block。很激动,我们终于可以和传说中的超级块赤裸相见了。
- 000400 10 f4 01 00 00 d0 07 00 00 64 00 00 d6 87 07 00
- 000410 05 f4 01 00 01 00 00 00 00 00 00 00 00 00 00 00
- 000420 00 20 00 00 00 20 00 00 f0 07 00 00 5f cb f7 4f
- 000430 5f cb f7 4f 01 00 1a 00 53 ef 00 00 01 00 00 00
- 000440 25 cb f7 4f 00 4e ed 00 00 00 00 00 01 00 00 00
- 000450 00 00 00 00 0b 00 00 00 80 00 00 00 38 00 00 00
- 000460 02 00 00 00 01 00 00 00 5a 65 4b 92 fe 63 43 eb
- 000470 b6 86 3e f3 6e 44 19 af 00 00 00 00 00 00 00 00
- 000480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- *
- 0004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
- 0004d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 0004e0 00 00 00 00 00 00 00 00 00 00 00 00 f9 6f 16 79
- 0004f0 b7 dc 4f 8a a1 a1 18 82 72 a7 d8 25 01 00 00 00
- 000500 00 00 00 00 00 00 00 00 25 cb f7 4f 00 00 00 00
- 000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- *
- 000560 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 000570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- *
- 000800 04 01 00 00 05 01 00 00 06 01 00 00 ef 1d e5 07
最左边一列是地址,16进制。000400=1K,换句话说,就是文件第1K个字节。000800 =2K,这就是我们朝思暮想的超级块啊。我很激动,所以把整个超级块都贴上了,幸好我不是靠字数来骗稿费的人,否则咱得被鄙视死。 再把ext2超级块的数据结构贴上,咱挨个字段比较比较,看看debugfs说的对不?
- struct ext2_super_block {
- __u32 s_inodes_count;
- __u32 s_blocks_count;
- __u32 s_r_blocks_count;
- __u32 s_free_blocks_count;
- __u32 s_free_inodes_count;
- __u32 s_first_data_block;
- __u32 s_log_block_size;
-
- ...
-
- }
第一个字段叫s_inodes_count, 占四个字节。OK,我们看,从1K开始前四个字节是10 f4 01 00。我们知道有little-endian和big-endian。ext2设计者为了支持文件系统的可移动,规定磁盘上一律是little-endian,数据读入内存中时,kernel来负责把格式转成cpu的本机格式。
OK,是little-endian咱就明白了,不就是0x0001f410嘛 。 0x0001f410=128016,看看debugfs给我们的数据,Inode count: 128016,一模一样。
再举个例子,比如,我们关心free_blocks_count,查看数据结构,free_blocks_count字段起始位置是超级块的第12字节。即00040c地址。看下的 d6 87 07 00。计算以下可以得到0x000787d6 = 493526,和debugfs 的Free blocks给出的一样。OK。看管关心什么字段,可以自己查看。通过和超级块赤裸想见,我们知道了ext2 super block的结构。
最后总结一句,不是所有的块组都有超级块,超级块只占1个block块,没错,当blocksize为4K的时候,这个块大多数空间是浪费的。不过还好,毕竟超级块个数有限,浪费不了多少。
下面讲述 块组描述符:
组描述符一共32个字节,大多数的教材都会给我们一组误解,就是每个块组,都要有组描述符。事实上并不是这样。我们知道,一个组描述符只占32字节,而大多数的教材都会告诉我们,一个块组里面的组描述符占k个块,一个组描述符是用不了这么多空间的。
真相只有一个,就是所有的组描述符以数组的形式存放在k个块中。也就是说,某个块组可能没有组描述符,而有组描述符的块组,k个block中存放了所有组块的组描述符。下面我来证实:
- struct ext2_group_desc
- {
- __u32 bg_block_bitmap; /* Blocks bitmap block */
- __u32 bg_inode_bitmap; /* Inodes bitmap block */
- __u32 bg_inode_table; /* Inodes table block */
- __u16 bg_free_blocks_count; /* Free blocks count */
- __u16 bg_free_inodes_count; /* Free inodes count */
- __u16 bg_used_dirs_count; /* Directories count */
- __u16 bg_flags;
- __u32 bg_exclude_bitmap_lo;/* Exclude bitmap for snapshots */
- __u16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap)LSB */
- __u16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap)LSB */
- __u16 bg_itable_unused; /* Unused inodes count */
- __u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/
- };
Group 0: (Blocks 1-8192)
主 superblock at 1, Group descriptors at 2-3
保留的GDT块位于 4-259
Block bitmap at 260 (+259), Inode bitmap at 261 (+260)
Inode表位于 262-515 (+261)
7663 free blocks, 2021 free inodes, 2 directories
可用块数: 530-8192
可用inode数: 12-2032
|