linux操作系统故障处理-ext4文件系统超级块损坏修复

Posted 我的征途是星辰大海

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux操作系统故障处理-ext4文件系统超级块损坏修复相关的知识,希望对你有一定的参考价值。

背景

      前天外面出差大数据测试环境平台有7台服务器挂了,同事重启好了五台服务器,但是还有两台服务器启动不起来,第二天回来后我和同事再次去机房检查,发现两台服务器都显示superblock的报错,经过一番处理后两台服务器都正常进系统了,现决定重现superblock故障并将此类问题故障处理思路写下来方便后面新同事参考。

硬盘的结构

硬盘的物理结构侧视图和俯视图,这两张图传递出来的比较重要的信息如下:

磁盘划分为磁头(Head),柱面(Cylinder),扇区(Sector)

磁头:每个磁片正反两面各有一个磁头,磁头固定在可移动的机械臂上,用于读写数据

磁道:当硬盘盘片旋转时,磁头若保持在一个位置上,则磁头会在盘片表面划出一个圆形轨迹,这些圆形轨迹就叫做磁道,磁道由外向内从0开始编号。

柱面:磁片中半径相同的同心磁道(Track)构成柱面。在实际应用中经常用到的磁盘分区就是用它作为范围划分的(重要)。

扇区:每个磁道上的一个弧段被成为一个扇区,它是硬盘的最小组成单元,一般扇区的大小是512字节。

了解了这几个概念就能算出一个分区的大小

硬盘容量:磁头数*柱面数*扇区数*512

磁盘sda的容量是: 255 * 2610 * 63 * 512 = 21467980800 ,算出的容量跟系统显示的基本一致。

[root@server1 ~]# fdisk -l

Disk /dev/sda: 21.5 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000205e3

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          26      204800   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2              26        2611    20765696   8e  Linux LVM

Disk /dev/sdb: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

ext4文件系统

由于Linux系统是多用户多的。从ext2开始,将磁盘分区格式化后是将文件属性和文件内容分开存储的,分别由inode和block来负责。

inode


    用于存储文件的各属性,包括:



     - 所有者信息:文件的owner,group;



     - 权限信息:read、write和excite;



     -时间信息:建立或改变时间(ctime)、最后读取时间(atime)、最后修改时间(mtime);



     - 标志信息:一些flags;



     - 内容信息:type,size,以及相应的block的位置信息。



    注意:不记录文件名或目录名,文件名或目录名记录在文件所在目录对应的block里。

   inode的大小一般是12Bytes,也可能是256 Bytes.


block


     用于存储文件的内容,它的大小一般是1K,2K,4K,一般在磁盘格式化的时候就默认了。


因为现在的磁盘都比较大,对其进行格式化后inode和block的个数将会非常大,为了便于管理,ext4文件系统在格式化的时候基本上是区分为多个区块群组(block group),这个跟军队里层级划分很像哦.
ext4文件系统格式化后的划分是下面这样的。


ext2文件系统示意图

Boot Sector 是用于引导分区上的操作系统的,这个一般用在双系统上,这里就直接忽略了。

Block Group 为了便于管理,文件系统格式化的时候划分为了多个区块群组,它里面保存了以下内容:

超级块(Superblock):

  Superblock 是记录整个 filesystem 相关信息的地方.为了系统的健壮性,最初每个块组都有超级块和组描述符表的一个拷贝,但是当文件系统很大时,这样浪费了很多块(尤其是组描述符表占用的块多),后来采用了一种稀疏的方式来存储这些拷贝,只有块组号是3, 5 ,7的幂的块组(譬如说1,3,5,7,9,25,49…)才备份这个拷贝。通常情况下,只有主拷贝(第0块块组)的超级块信息被文件系统使用,其它拷贝只有在主拷贝被破坏的情况下才使用,他记录的信息主要有:

block 与 inode 的总量;

  • 未使用与已使用的 inode / block 数量;
  • block 与 inode 的大小 (block 为 1, 2, 4K,inode 为 128 ,256bytes);
  • filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘 (fsck) 的时间等文件系统的相关信息;
  • 一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0 ,若未被挂载,则 valid bit 为 1 。
  • 档案系统描述(Filesystem Description):

        这个区段可以描述每个 block group 的开始与结束的 block 号码,以及说明每个区段 (superblock, bitmap, inodemap, data block) 分别介于哪一个 block 号码之间.

    区块位图(block bitmap)

        区块对应表用于描述该块组所管理的块的分配状态。如果某个块对应的位未置位,那么代表该块未分配,可以用于存储数据;否则,代表该块已经用于存储数据或者该块不能够使用(譬如该块物理上不存在)。由于区块位图仅占一个块,因此这也就决定了块组的大小。

    Inode位图(Inode bitmap)

        Inode位图用于描述该块组所管理的inode的分配状态。我们知道inode是用于描述文件的元数据,每个inode对应文件系统中唯一的一个号,如果inode位图中相应位置位,那么代表该inode已经分配出去;否则可以使用。由于其仅占用一个块,因此这也限制了一个块组中所能够使用的最大inode数量。

    Inode table(Inode表)

        Inode表用于存储inode信息。它占用一个或多个块(为了有效的利用空间,多个inode存储在一个块中),其大小取决于文件系统创建时的参数,由于inode位图的限制,决定了其最大所占用的空间。

    Data block(数据块)

        数据块存放真正的文件数据


    模拟文件系统故障和故障处理解决

    模拟superblock超级块故障

    现在回过头来观察自己的文件系统,每个区段与superblock的信息都可以使用dumpe2fs这个命令来查询

    [root@server1 ~]# dumpe2fs /dev/sdb|more
    dumpe2fs 1.41.12 (17-May-2010)
    Filesystem volume name:   <none>           ---------->>  文件系统的名称
    Last mounted on:          <not available>           -------------------------------->> 分区挂载,当前没有挂载,所以显示不可用
    Filesystem UUID:          c6421bf7-8497-45c0-86b0-dfac1b21989a
    Filesystem magic number:  0xEF53
    Filesystem revision #:    1 (dynamic)
    Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent flex_bg sparse_super large_file huge_file
     uninit_bg dir_nlink extra_isize              ----------->>  文件系统的一些特性
    Filesystem flags:         signed_directory_hash 
    Default mount options:    (none)
    Filesystem state:         clean                ----------->>  文件系统当前是好的(clean)
    Errors behavior:          Continue
    Filesystem OS type:       Linux
    Inode count:              655360               -------->> Inode 总的个数
    Block count:              2621440           --------->>  Block 总的个数
    Reserved block count:     131072
    Free blocks:              2541777     --------->>  空闲的block个数
    Free inodes:              655349  ----------->>  空闲的inode个数
    First block:              0                 ------------->>第一个block的编号
    Block size:               4096            --------------->> block的大小,这里是4K
    Fragment size:            4096
    Reserved GDT blocks:      639
    Blocks per group:         32768            ------------------->>  每个块组block的个数
    Fragments per group:      32768
    Inodes per group:         8192             ------------>>  每个块组inode的个数
    Inode blocks per group:   512          
    Flex block group size:    16
    Filesystem created:       Sat Nov 11 13:23:30 2017
    Last mount time:          n/a
    Last write time:          Sat Nov 11 13:23:32 2017
    Mount count:              0
    Maximum mount count:      33
    Last checked:             Sat Nov 11 13:23:30 2017
    Check interval:           15552000 (6 months)
    Next check after:         Thu May 10 13:23:30 2018
    Lifetime writes:          291 MB
    Reserved blocks uid:      0 (user root)
    Reserved blocks gid:      0 (group root)
    First inode:              11
    Inode size:              256    ------------>>  inode的大小
    Required extra isize:     28
    Desired extra isize:      28
    Journal inode:            8
    Default directory hash:   half_md4
    Directory Hash Seed:      2fd3813e-6245-4a62-bc28-34c1534c919d
    Journal backup:           inode blocks
    Journal features:         (none)
    日志大小:             128M
    Journal length:           32768
    Journal sequence:         0x00000001
    Journal start:            0
    
    
    Group 0: (Blocks 0-32767) [ITABLE_ZEROED]
      校验和 0xee7f,8181个未使用的inode
      主 superblock at 0, Group descriptors at 1-1               -------------->> 主superblock的位置在编号为0的block中
      保留的GDT块位于 2-640
      Block bitmap at 641 (+641), Inode bitmap at 657 (+657)
      Inode表位于 673-1184 (+673)
      23897 free blocks, 8181 free inodes, 2 directories, 8181个未使用的inodes
      可用块数: 8871-32767
      可用inode数: 12-8192
    Group 1: (Blocks 32768-65535) [INODE_UNINIT, ITABLE_ZEROED]
      校验和 0x1ae3,8192个未使用的inode
      备份 superblock at 32768, Group descriptors at 32769-32769   ------------->>  备份superblock的位置在编号为 32768 的block中
      保留的GDT块位于 32770-33408
      Block bitmap at 642 (+4294935170), Inode bitmap at 658 (+4294935186)
      Inode表位于 1185-1696 (+4294935713)
      32127 free blocks, 8192 free inodes, 0 directories, 8192个未使用的inodes
      可用块数: 33409-65535
      可用inode数: 8193-16384
    Group 2: (Blocks 65536-98303) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
      校验和 0x8b39,8192个未使用的inode
      Block bitmap at 643 (+4294902403), Inode bitmap at 659 (+4294902419)
      Inode表位于 1697-2208 (+4294903457)
      32768 free blocks, 8192 free inodes, 0 directories, 8192个未使用的inodes
      可用块数: 65536-98303
      可用inode数: 16385-24576
    Group 3: (Blocks 98304-131071) [INODE_UNINIT, ITABLE_ZEROED]
      校验和 0x6c3d,8192个未使用的inode
      备份 superblock at 98304, Group descriptors at 98305-98305
      保留的GDT块位于 98306-98944
      Block bitmap at 644 (+4294869636), Inode bitmap at 660 (+4294869652)
      Inode表位于 2209-2720 (+4294871201)
      32127 free blocks, 8192 free inodes, 0 directories, 8192个未使用的inodes
      可用块数: 98945-131071
      可用inode数: 24577-32768

    说到这里心里大概有谱了,原来superblock在文件系统上是有备份的,那我们模拟下主superblock出问题,看如何恢复

    这里直接利用dd命令将sdb磁盘第一个block的内容抹除

    [root@server1 ~]# dd if=/dev/zero of=/dev/sdb bs=1 count=4096
    记录了4096+0 的读入
    记录了4096+0 的写出
    4096字节(4.1 kB)已复制,0.019493 秒,210 kB/秒
    [root@server1 ~]# dumpe2fs /dev/sdb
    dumpe2fs 1.41.12 (17-May-2010)
    dumpe2fs: Bad magic number in super-block 当尝试打开 /dev/sdb 时
    找不到有效的文件系统超级块.
    [root@server1 ~]# tune2fs -l /dev/sdb
    tune2fs 1.41.12 (17-May-2010)
    tune2fs: Bad magic number in super-block 当尝试打开 /dev/sdb 时
    找不到有效的文件系统超级块.
    [root@server1 ~]#

    这时候我们根本无法从dumpe2fs和tune2fs看到Backup superblock的位置,都找不到superblock备份的位置该怎么恢复主superblock呢

    注意下面的命令都是针对ext类文件系统的,其它文件系统不适用

    首先要找到superblock备份的几个位置,这需要利用mke2fs这个命令

    mke2fs:create an ext2/ext3/ext4 filesystem

    利用mke2fs这个命令 mke2fs  -n  设备名,为了不引起歧义,所以这里直接复制了原文解释。

    -n     Causes mke2fs to not actually create a filesystem, but display what it would do if it were to create
                   a filesystem.  This can be used to determine the location of the backup superblocks for a particular
                   filesystem,  so  long  as  the mke2fs parameters that were passed when the filesystem was originally
                   created are used again.  (With the -n option added, of course!)

    简单来说就是接了-n 参数 ,mke2fs 不是真的在设备上创建文件系统,它只是模拟这个过程并显示给你看。让你明白它究竟做了那些事。

    [root@server1 ~]# mke2fs -n /dev/sdb
    mke2fs 1.41.12 (17-May-2010)
    /dev/sdb is entire device, not just one partition!
    无论如何也要继续? (y,n) y
    文件系统标签=
    操作系统:Linux
    块大小=4096 (log=2)
    分块大小=4096 (log=2)
    Stride=0 blocks, Stripe width=0 blocks
    655360 inodes, 2621440 blocks
    131072 blocks (5.00%) reserved for the super user
    第一个数据块=0
    Maximum filesystem blocks=2684354560
    80 block groups
    32768 blocks per group, 32768 fragments per group
    8192 inodes per group
    Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632  --------------->>>  超级块的备份位置就在这里
    
    [root@server1 ~]#

    利用上面的命令就可以找到超级块的备份位置了。然后我们就可以再利用系统提供的另一个磁盘命令e2fsck命令进行恢复,它有一个-b选项,由于我的操作系统是ext4格式的,也可以用fsck.ext4 -b 32768 /dev/sdb,效果一样。

    恢复的命令格式:  e2fsck –b superblock   device

    -b superblock
                   Instead of using the normal superblock, use an alternative superblock specified by superblock.  This
                   option is normally used when the primary superblock has been corrupted.  The location of the  backup
                   superblock is dependent on the filesystem’s blocksize.  For filesystems with 1k blocksizes, a backup
                   superblock can be found at block 8193; for filesystems with 2k blocksizes, at block 16384;  and  for
                   4k blocksizes, at block 32768.

                  Additional  backup  superblocks can be determined by using the mke2fs program using the -n option to
                   print out where the superblocks were created.   The -b option to mke2fs, which  specifies  blocksize
                   of the filesystem must be specified in order for the superblock locations that are printed out to be
                   accurate.

                  If an alternative superblock is specified and the filesystem is not opened  read-only,  e2fsck  will
                   make  sure  that  the  primary superblock is updated appropriately upon completion of the filesystem
                   check.

    [root@server1 ~]# e2fsck -b 32768 /dev/sdb
    e2fsck 1.41.12 (17-May-2010)
    /dev/sdb was not cleanly unmounted, 强制检查.
    第一步: 检查inode,块,和大小
    第二步: 检查目录结构
    第3步: 检查目录连接性
    Pass 4: Checking reference counts
    第5步: 检查簇概要信息
    
    /dev/sdb: ***** 文件系统已修改 *****
    /dev/sdb: 11/655360 files (0.0% non-contiguous), 79663/2621440 blocks
    [root@server1 ~]# dumpe2fs /dev/sdb|more
    dumpe2fs 1.41.12 (17-May-2010)
    Filesystem volume name:   <none>
    Last mounted on:          <not available>
    Filesystem UUID:          c6421bf7-8497-45c0-86b0-dfac1b21989a
    Filesystem magic number:  0xEF53
    Filesystem revision #:    1 (dynamic)
    Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent flex_bg sparse_super large_file huge_file
     uninit_bg dir_nlink extra_isize
    Filesystem flags:         signed_directory_hash 
    Default mount options:    (none)
    Filesystem state:         clean
    Errors behavior:          Continue
    Filesystem OS type:       Linux
    Inode count:              655360
    Block count:              2621440
    Reserved block count:     131072
    Free blocks:              2541777
    Free inodes:              655349
    First block:              0
    Block size:               4096
    Fragment size:            4096
    Reserved GDT blocks:      639
    Blocks per group:         32768
    Fragments per group:      32768
    Inodes per group:         8192
    Inode blocks per group:   512
    Flex block group size:    16
    Filesystem created:       Sat Nov 11 13:23:30 2017
    Last mount time:          n/a
    Last write time:          Sat Nov 11 16:57:39 2017
    Mount count:              0
    Maximum mount count:      33
    Last checked:             Sat Nov 11 16:57:39 2017

    现在主超级块已经恢复了,系统可以正常使用。

    模拟组描述错误故障和解决故障

    那如果档案系统描述(GDT)损坏了怎么办,这里也可以试验下:

    这里块组1的组描述符是在第二个块的,直接利用dd覆盖第二个块,可以看到现在磁盘已经无法进行挂载了。并且系统提示组块0有错误。

    [root@server1 /]# dd if=/dev/zero of=/dev/sdb bs=1 count=4096 seek=4096
    记录了4096+0 的读入
    记录了4096+0 的写出
    4096字节(4.1 kB)已复制,0.0795117 秒,51.5 kB/秒
    [root@server1 /]# mount /dev/sdb /data/
    mount: wrong fs type, bad option, bad superblock on /dev/sdb,
           missing codepage or helper program, or other error
           In some cases useful info is found in syslog - try
           dmesg | tail  or so
    [root@server1 /]# dmesg |tail -5
    EXT4-fs (sdb): mounted filesystem with ordered data mode. Opts: 
    EXT4-fs (sdb): ext4_check_descriptors: Checksum for group 0 failed (43116!=0)
    EXT4-fs (sdb): group descriptors corrupted!
    EXT4-fs (sdb): ext4_check_descriptors: Checksum for group 0 failed (43116!=0)
    EXT4-fs (sdb): group descriptors corrupted!
    [root@server1 /]#

    组描述错误可以直接利用fsck –y  device设备名来进行修复,修复好后就能正常挂载 。

    [root@server1 /]# fsck -y /dev/sdb
    fsck from util-linux-ng 2.17.2
    e2fsck 1.41.12 (17-May-2010)
    fsck.ext4: Group descriptors look bad... trying backup blocks...
    /dev/sdb was not cleanly unmounted, 强制检查.
    第一步: 检查inode,块,和大小
    第二步: 检查目录结构
    第3步: 检查目录连接性
    Pass 4: Checking reference counts
    第5步: 检查簇概要信息
    Free 块s count wrong for 簇 #48 (24544, counted=24543).
    处理? 是
    
    Free 块s count wrong (2541777, counted=2541776).
    处理? 是
    
    Free inodes count wrong for 簇 #48 (8192, counted=8191).
    处理? 是
    
    Directories count wrong for 簇 #48 (0, counted=1).
    处理? 是
    
    Free inodes count wrong (655349, counted=655348).
    处理?/dev/sdb: ***** 文件系统已修改 *****
    /dev/sdb: 12/655360 files (0.0% non-contiguous), 79664/2621440 blocks
    [root@server1 /]# mount /dev/sdb /data/
    [root@server1 /]# df -lh
    Filesystem                          Size  Used Avail Use% Mounted on
    /dev/mapper/VolGroup-LogVol01_root  9.9G  4.3G  5.1G  46% /
    tmpfs                               491M   32K  491M   1% /dev/shm
    /dev/sda1                           194M   35M  150M  19% /boot
    /dev/mapper/VolGroup-LogVol02_home  7.7G  149M  7.2G   2% /home
    /dev/sdb                            9.9G  151M  9.2G   2% /data
    [root@server1 /]#

    以上是关于linux操作系统故障处理-ext4文件系统超级块损坏修复的主要内容,如果未能解决你的问题,请参考以下文章

    linux_ext4恢复超级块.txt

    Ext4文件系统fsck后损坏修复方法-linux数据恢复案例

    系统篇: ext4 文件系统

    Linux.ext4文件系统.inode和extent

    服务器数据恢复Linux系统,EXT4文件系统下虚拟机误删除的数据恢复案例

    Linux Ext4文件系统的基本结构