tcler's blog --- 其实我是一个程序员
Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious.

ext2/3/4 magic相同,怎么区分是哪个类型呢?

大家都知道,文件系统类型是靠磁盘上superblock区块里的magic number不同来区分的, 但是,今天同事遇到相关问题,引出这个问题: ext2/3/4 使用的magic numner都一样,怎么判断分区类型到底是哪一个呢?

google 到一些工具可以判断,但是,具体他们根据什么判断的呢? 多年不看文件系统了,但是还有一点印象:

1.找磁盘superblock结构定义,hexdump -C -n 128 -s 1024 查看验证
2.找到 ext4 的超级块定义代码,对比ext3/2,有 incompatible feature 的字样, 就是它了:
//ext2/3/4 magic相同,区分靠 feature;
//不兼容 feature 信息对应的偏移地址 /*60*/ (代码如下)
        __le16  s_magic;                /* Magic signature */            /*38*/        <<<---magic
        __le16  s_state;                /* File system state */
        __le16  s_errors;               /* Behaviour when detecting errors */
        __le16  s_minor_rev_level;      /* minor revision level */
/*40*/  __le32  s_lastcheck;            /* time of last check */
        __le32  s_checkinterval;        /* max. time between checks */
        __le32  s_creator_os;           /* OS */
        __le32  s_rev_level;            /* Revision level */
/*50*/  __le16  s_def_resuid;           /* Default uid for reserved blocks */
        __le16  s_def_resgid;           /* Default gid for reserved blocks */
        /*
         * These fields are for EXT4_DYNAMIC_REV superblocks only.
         *
         * Note: the difference between the compatible feature set and
         * the incompatible feature set is that if there is a bit set
         * in the incompatible feature set that the kernel doesn't
         * know about, it should refuse to mount the filesystem.
         *
         * e2fsck's requirements are more strict; if it doesn't know
         * about a feature in either the compatible or incompatible
         * feature set, it must abort and not try to meddle with
         * things it doesn't understand...
         */
        __le32  s_first_ino;            /* First non-reserved inode */
        __le16  s_inode_size;           /* size of inode structure */
        __le16  s_block_group_nr;       /* block group # of this superblock */
        __le32  s_feature_compat;       /* compatible feature set */
/*60*/  __le32  s_feature_incompat;     /* incompatible feature set */         <<<--- ext2/3/4 magic相同,区分主要是feature,
        __le32  s_feature_ro_compat;    /* readonly-compatible feature set */
/*68*/  __u8    s_uuid[16];             /* 128-bit uuid for volume */

进一步看代码ext4 superblock初始化代码,会发现s_feature_incompat赋值里面 有EXT4FEATURE_INCOMPAT_EXTENTS等多个ext4独有的特性, 所以使用magic+s_feature*判断应该是可以的

验证: hexdump -C 查看超级块 feature 相关信息比较ext 4/3/2: ext4 ext3比较s_feature_incompat不同, ext3 ext2比较s_feature_compat 不同:

    [root@dhcp12-241 rdma.sunrpc]# hexdump -C -s 1024 ext4.image -n $((0x68))
    00000400 10 f4 01 00 00 d0 07 00 00 64 00 00 d6 67 07 00 |.........d...g..|
    00000410 05 f4 01 00 01 00 00 00 00 00 00 00 00 00 00 00 |................|
    00000420 00 20 00 00 00 20 00 00 f0 07 00 00 00 00 00 00 |. ... ..........|
    00000430 00 1e 4a 54 00 00 ff ff 53 ef 01 00 01 00 00 00 |..JT....S.......|
    00000440 00 1e 4a 54 00 00 00 00 00 00 00 00 01 00 00 00 |..JT............|
    00000450 00 00 00 00 0b 00 00 00 80 00 00 00 3c 00 00 00 |............<...|
    00000460 42 02 00 00 79 00 00 00 |B...y...|  ^^                       ^^
    00000468                          ^^^^^
    [root@dhcp12-241 rdma.sunrpc]# hexdump -C -s 1024 ext3.image -n $((0x68))
    00000400 10 f4 01 00 00 d0 07 00 00 64 00 00 b5 67 07 00 |.........d...g..|
    00000410 05 f4 01 00 01 00 00 00 00 00 00 00 00 00 00 00 |................|
    00000420 00 20 00 00 00 20 00 00 f0 07 00 00 00 00 00 00 |. ... ..........|
    00000430 72 13 4a 54 00 00 ff ff 53 ef 01 00 01 00 00 00 |r.JT....S.......|
    00000440 72 13 4a 54 00 00 00 00 00 00 00 00 01 00 00 00 |r.JT............|
    00000450 00 00 00 00 0b 00 00 00 80 00 00 00 3c 00 00 00 |............<...|
    00000460 02 00 00 00 01 00 00 00 |........|  ^^                       ^^
    00000468
    [root@dhcp12-241 rdma.sunrpc]# hexdump -C -s 1024 ext2.image -n $((0x68))
    00000400 10 f4 01 00 00 d0 07 00 00 64 00 00 d6 87 07 00 |.........d......|
    00000410 05 f4 01 00 01 00 00 00 00 00 00 00 00 00 00 00 |................|
    00000420 00 20 00 00 00 20 00 00 f0 07 00 00 00 00 00 00 |. ... ..........|
    00000430 61 13 4a 54 00 00 ff ff 53 ef 01 00 01 00 00 00 |a.JT....S.......|
    00000440 61 13 4a 54 00 00 00 00 00 00 00 00 01 00 00 00 |a.JT............|
    00000450 00 00 00 00 0b 00 00 00 80 00 00 00 38 00 00 00 |............8...|
    00000460 02 00 00 00 01 00 00 00 |........|  ^^                       ^^
    00000468

手动改一个ext3的的superblock /5c~60*/位置的值,再用file查看是否文件系统类型发生变化 将ext4.image superblock的 s_feature_incompat 值覆盖到ext3.image, 再 file ext3.image 查看 类型就变成ext4了!

    [root@dhcp12-241 rdma.sunrpc]# dd if=ext4.image skip=$((1024+0x60))c bs=8 count=1 iflag=skip_bytes of=ext3.image seek=$((1024+0x60))c oflag=seek_bytes
    1+0 records in
    1+0 records out
    8 bytes (8 B) copied, 0.000174478 s, 45.9 kB/s
    [root@dhcp12-241 rdma.sunrpc]# file ext3.image
    ext3.image: Linux rev 1.0 ext4 filesystem data (extents) (huge files)
    [root@dhcp12-241 rdma.sunrpc]# file *.image
    ext2.image: Linux rev 1.0 ext2 filesystem data, UUID=b63e742f-e5cc-4610-a702-f36d563e782c
    ext3.image: Linux rev 1.0 ext3 filesystem data, UUID=d986c054-9cc1-4b38-bfed-09caa75ee142
    ext4.image: Linux rev 1.0 ext4 filesystem data, UUID=f1fe77bf-ed5a-4c87-93fd-3921462b7a54 (extents) (huge files)
    [root@dhcp12-241 rdma.sunrpc]# blkid ext3.image
    ext3.image: UUID="d986c054-9cc1-4b38-bfed-09caa75ee142" SEC_TYPE="ext2" TYPE="ext3"
    [root@dhcp12-241 rdma.sunrpc]# dd if=ext4.image skip=$((1024+0x60))c bs=8 count=1 iflag=skip_bytes of=ext3.image seek=$((1024+0x60))c oflag=seek_bytes conv=notrunc
    1+0 records in
    1+0 records out
    8 bytes (8 B) copied, 9.2809e-05 s, 86.2 kB/s
    [root@dhcp12-241 rdma.sunrpc]# file *.image
    ext2.image: Linux rev 1.0 ext2 filesystem data, UUID=b63e742f-e5cc-4610-a702-f36d563e782c
    ext3.image: Linux rev 1.0 ext4 filesystem data, UUID=d986c054-9cc1-4b38-bfed-09caa75ee142 (extents) (huge files)
    ext4.image: Linux rev 1.0 ext4 filesystem data, UUID=f1fe77bf-ed5a-4c87-93fd-3921462b7a54 (extents) (huge files)
    [root@dhcp12-241 rdma.sunrpc]# blkid ext3.image
    ext3.image: UUID="d986c054-9cc1-4b38-bfed-09caa75ee142" TYPE="ext4"
    [root@dhcp12-241 rdma.sunrpc]#

ext2 变 ext3 同理,就不演示了,,

dd 注意事项:

 1. 修改文件记得加 conv=notrunc 不然文件会被截断;
 2. skip seek 默认单位是 block, 如果是字节需要加 iflag=skip_bytes oflag=seek_bytes

Update: 2019-02-19 从 backup superblock 恢复

 [student@workstation ~]$ hexdump -C -s 1024 ext4.img -n $((0x68))
00000400  00 00 01 00 00 00 04 00  33 33 00 00 65 cd 03 00  |........33..e...|
00000410  f5 ff 00 00 00 00 00 00  02 00 00 00 02 00 00 00  |................|
00000420  00 80 00 00 00 80 00 00  00 20 00 00 eb 94 6b 5c  |......... ....k\|
00000430  f6 94 6b 5c 02 00 ff ff  53 ef 01 00 01 00 00 00  |..k\....S.......|
00000440  5c 8b 6b 5c 00 00 00 00  00 00 00 00 01 00 00 00  |\.k\............|
00000450  00 00 00 00 0b 00 00 00  00 01 00 00 3c 00 00 00  |............<...|
00000460  c2 02 00 00 7b 00 00 00                           |....{...|
00000468
[student@workstation ~]$ dd if=/dev/zero of=ext4.img seek=1024 oflag=seek_bytes  bs=256 count=1 conv=notrunc
1+0 records in
1+0 records out
256 bytes (256 B) copied, 9.8364e-05 s, 2.6 MB/s
[student@workstation ~]$ hexdump -C -s 1024 ext4.img -n $((0x68))
00000400  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000460  00 00 00 00 00 00 00 00                           |........|
00000468
[student@workstation ~]$ sudo mount -t ext4  -oloop ext4.img /mnt/
mount: wrong fs type, bad option, bad superblock on /dev/loop0,
       missing codepage or helper program, or other error

       In some cases useful info is found in syslog - try
       dmesg | tail or so.
[student@workstation ~]$ dd if=ext4.img skip=$((32768*4096)) iflag=skip_bytes of=ext4.img  seek=1024 oflag=seek_bytes bs=256 count=1  conv=notrunc 
1+0 records in
1+0 records out
256 bytes (256 B) copied, 8.3631e-05 s, 3.1 MB/s
[student@workstation ~]$ sudo mount -t ext4  -oloop ext4.img /mnt/