如何修复/修复Linux中的Badblocks

时间:2020-03-05 15:27:20  来源:igfitidea点击:

存储设备中的Badblocks是由于某种原因不可读取的设备的部分。
如果我们能够达到该块的确切位置,可以恢复这些包块。

智能技术内置于许多存储设备(例如许多ATA-3,稍后ATA,IDE和SCSI-3硬盘)监视硬盘驱动器的可靠性,并可以预测驱动器故障。
智能代表自我监控,分析和报告技术。

本教程描述了SmartMontools在运行Linux的硬盘上检测和报告某些Badblocks时可以采取的操作。

关于SmartMontools.

SmartMontools包提供了两个实用程序:Smartrd和Smartctl。

SmartD是DEAMON每30分钟调查ATA和SCSI设备(可以更改此值)并使用SYSLOG接口记录智能错误和更改智能属性。

SmartCTL执行智能任务,可用于在其他任务中打印智能自检和错误日志,例如支持来自SCSI磁带驱动器的磁带信息。
当我们通过本文时,此命令的使用将很清楚。
本文通过对不同类型的文件系统进行磁盘失败的一些示例进行。

smartctl命令

SmartCTL命令在逻辑块地址LBA = 0x016561E9处报告BADBLOCK,其中十进制数系统是23421417.

root]# smartctl -l selftest /dev/hda
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Extended offline Completed: read failure 90% 217 0x016561e9

LBA以零开始以512字节为单位计数扇区。
"smartctl -a"命令中的"current_pending_sector"属性的值确认了坏扇区。

root]# smartctl -A /dev/hda
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail Always - 0
196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 0
197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 1
198 Offline_Uncorrectable 0x0008 100 100 000 Old_age Offline - 1

修复坏块

步骤1:

找到坏块所在的分区。
FDISK命令可用于查看硬盘分区的扇区。

root]# fdisk -lu /dev/hda
Disk /dev/hda: 123.5 GB, 123522416640 bytes
255 heads, 63 sectors/track, 15017 cylinders, total 241254720 sectors
Units = sectors of 1 * 512 = 512 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 63 4209029 2104483+ 83 Linux
/dev/hda2 4209030 5269319 530145 82 Linux swap
/dev/hda3 5269320 238227884 116479282+ 83 Linux
/dev/hda4 238227885 241248104 1510110 83 Linux

其中我们可以看到LBA 23421417位于第三分区中,例如:/dev/hda3.
扇区的偏移值是23421417 5269320 =分区/dev/hda3中的扇区18152097扇区。

现在我们需要检查分区的文件系统的类型。
这可以从/etc/fstab文件检查。

root]# grep hda3 /etc/fstab
/dev/hda3 /data ext2 defaults 1 2

第2步:

现在我们需要使用tune2fs命令找到文件系统的块大小

root]# tune2fs -l /dev/hda3 | grep Block
Block count: 29119820
Block size: 4096

这将块大小报告为4096字节。

第3步:

找到包含此问题LBA的文件系统块。
我们使用以下公式:

b =(int)((l-s)* 512/b)

其中:

B =文件系统块号B =文件系统块大小以字节为单位L = LBA的坏扇区S = FDISK -LU和(int)所示的分区的起始扇区表示整数部分。

对于我们的示例,L = 23421417,S = 5269320和B = 4096.

B =(int)18152097 * 512/4096 =(int)2269012.125

所以B = 2269012.

第四步:

使用debugfs定位存储在此块中的inode,因此将存储在该位置的文件。

root]# debugfs
debugfs 1.32 (09-Nov-2002)
debugfs: open /dev/hda3
debugfs: testb 2269012
Block 2269012 not in use

其中在这种情况下,块不使用。
所以可以跳过这一步的其余部分,我们可以直接跳转到下一步。
否则,如果块正在使用中,如以下输出所报告:

debugfs: testb 2269012
Block 2269012 marked in use
debugfs: icheck 2269012
Block Inode number
2269012 41032
debugfs: ncheck 41032
Inode Pathname
41032 /S1/R/H/714197568-714203359/H-R-714202192-16.gwf

在这种情况下,问题文件是:/data/s1/r/h/714197568-714203359/h-r-714202192-16.gwf

在ext3文件系统的情况下,此块可以是Junice本身的一部分。

inode将非常小,debugfs无法报告任何文件名。

debugfs: testb 2269012
Block 2269012 marked in use
debugfs: icheck 2269012
Block Inode number
2269012 8
debugfs: ncheck 8
Inode Pathname
debugfs:

在这种情况下,我们可以删除"使用tune2fs命令的日志:

tune2fs -O ^has_journal /dev/hda3

现在,我们重复第4步,如果没有报道问题,我们可以重建期刊:

tune2fs -j /dev/hda3

第5步:

此步骤将通过在其上写入零点来破坏该块上的数据。
坏块将被恢复,但文件的数据将丢失。
如果我们确定,我们可以继续执行以下步骤:

root]# dd if=/dev/zero of=/dev/hda3 bs=4096 count=1 seek=2269012
root]# sync

现在我们可以再次检查"smartctl -a"输出以验证一切恢复正常。

root]# smartctl -A /dev/hda
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail Always - 1
196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 1
197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 0
198 Offline_Uncorrectable 0x0008 100 100 000 Old_age Offline - 1

其中我们可以看到"current_pending_sector"的值为零。

ext2/ext3上的智能错误

To: ballen
Subject: SMART error (selftest) detected on host: medusa-slave166.medusa.phys.uwm.edu
This email was generated by the smartd daemon running on host:
medusa-slave166.medusa.phys.uwm.edu in the domain: master001-nis
The following warning/error was logged by the smartd daemon:
Device: /dev/hda, Self-Test Log error count increased from 0 to 1

来自SmartD的此电子邮件显示了故障的第一个迹象。
正如前面的示例中谈到的那样,我们运行"SmartCtl -A/dev/hda"以确认问题:

Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Extended offline Completed: read failure 80% 682 0x021d9f44

报告的LBA是0x021D9F44(基部16)= 35495748(基部10)

ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail Always - 0
196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 0
197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 3
198 Offline_Uncorrectable 0x0008 100 100 000 Old_age Offline - 3

其中3个扇区是不可读的。
使用以下Bash脚本,我们可以检查该区域周围的扇区。

[root]# export i=35495730
[root]# while [ $i -lt 35495800 ]
> do echo $i
> dd if=/dev/hda of=/dev/null bs=512 count=1 skip=$i
> let i+=1
> done

35495734 1 + 0记录在1 + 0记录中备注35495735 DD:读取`/dev/hda':输入/输出错误0 + 0记录0 + 0记录出来

35495751 DD:读取`/dev/hda':输入/输出错误0 + 0记录0 + 0记录35495752 1 + 0记录在1 + 0记录出来

这表明17个扇区35495735-35495751是不可读的。

包含此区域的文件系统块是:

L = 35495735至35495751 S = 5269320 B = 4096所以B = 3778301至3778303

要识别这些位置的文件,我们运行debugfs:

[root]# debugfs
debugfs 1.32 (09-Nov-2002)
debugfs: open /dev/hda3
debugfs: icheck 3778301
Block Inode number
3778301 45192
debugfs: icheck 3778302
Block Inode number
3778302 45192
debugfs: icheck 3778303
Block Inode number
3778303 45192
debugfs: ncheck 45192
Inode Pathname
45192 /S1/R/H/714979488-714985279/H-R-714979984-16.gwf
debugfs: quit

我们可以使用MD5SUM来确认我们的文件:

[root]# md5sum /data/S1/R/H/714979488-714985279/H-R-714979984-16.gwf
md5sum: /data/S1/R/H/714979488-714985279/H-R-714979984-16.gwf: Input/output error

因此,我们强制磁盘重新分配坏块:

[root]# dd if=/dev/zero of=/dev/hda3 bs=4096 count=3 seek=3778301
[root]# sync

或者

[root]# dd if=/dev/zero of=/dev/hda bs=512 count=17 seek=35495735
[root]# sync

现在我们可以检查错误块是否在"current_pending_sector"属性(smart_pending_sector"属性(smartctl -a命令)的值中创建问题:

ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail Always - 0
196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 0
197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 0
198 Offline_Uncorrectable 0x0008 100 100 000 Old_age Offline - 0

未分配的部门

在上面的示例中,当未分配给任何文件时,我们未考虑错误块。
当我们运行debugfs命令查找对应于特定块的文件时,这将是清楚的。
如果是这种情况,那么我们可以首先创建一个足够大的文件来填充剩余的文件系统(再次,DD命令是救援)。

dd if=/dev/zero of=/some/mount/point bs=4k

此命令将运行,直到文件系统上没有剩余空间。
现在我们可以通过其余的步骤进行。

Reiserfs上的坏块

在此示例中,使用的文件系统是ReisErfs。
因此,使用的一些命令将与上述情况不同。

智能错误日志表示BAD块地址为58656333.分区表指示该块在具有Reiserfs文件系统的分区中,从块地址54781650开始。

获取文件系统的块大小

# debugreiserfs /dev/hda3 | grep '^Blocksize'
Blocksize: 4096

获取块号码

# echo "(58656333-54781650)*512/4096" | bc -l
484335.37500000000000000000

有关该块的更多信息

# debugreiserfs -1 484335 /dev/hda3
debugreiserfs 3.6.19 (2003 http://www.namesys.com)
484335 is free in ondisk bitmap

问题已发生如硬件问题。

其中我们看到读取块失败。
但我们现在从这个输出中知道它是未使用的块。

此时,我们可以尝试编写坏块,看看驱动器是否倒退了坏块。
如果无法重新映射块,请使用ReiserFS Utils使用Badblock选项(-b)正确处理此块。

面包:无法读取块(484335):(输入/输出错误)。

中产响

至少我们有正确的坏块。

找到受影响的文件

tar -cO /mydir | cat >/dev/null

运行badblock-n以引发重新分配

# badblocks -b 4096 -p 3 -s -v -n /dev/hda3 `expr 484335 + 100` `expr 484335 - 100`

如果一切正常发生,Debugreiserfs -1 484335/dev/hda3报告没有错误。
除此以外:

使用dd命令在特定区域写入zeroes

# dd if=/dev/zero of=/dev/hda3 count=1 bs=4096 seek=484335
1+0 records in
1+0 records out
4096 bytes transferred in 0.007770 seconds (527153 bytes/sec)

坏块修复LVM.

此示例认为Badblock在LVM卷上:

报告错误,发现错误的块在LBA 37383668中,其中包含以下命令:

# smartctl -a /dev/hdb
...
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Short offline Completed: read failure 90% 66 37383668

sfdisk可以帮助找到坏块的物理分区:

# sfdisk -luS /dev/hdb

或者

# fdisk -ul /dev/hdb
Disk /dev/hdb: 9729 cylinders, 255 heads, 63 sectors/track
Units = sectors of 512 bytes, counting from 0
Device Boot Start End #sectors Id System
/dev/hdb1 63 996029 995967 82 Linux swap/Solaris
/dev/hdb2 * 996030 1188809 192780 83 Linux
/dev/hdb3 1188810 156296384 155107575 8e Linux LVM
/dev/hdb4 0 - 0 0 Empty

坏块位于/dev/hdb3分区中,它是基于LVM的分区。

该块的偏移是:(37383668 1188810)= 36194858

LVM使用的物理分区分为PE(物理范围)。
'pvdisplay'命令为lvm分区提供PE的大小:

part =/dev/hdb3; pvdisplay -c $part | awk-f:'{打印$8}'4096

要在LBA块大小(512字节或者0.5 kB)中获得其大小,我们将此数字乘以2:4096 * 2 =每个PE的8192块。

现在我们搜索了糟糕块居住的PE:物理分区的坏块号/尺寸(PE)

36194858/8192 = 4418.3176

现在我们需要找到与PE号4418对应的逻辑分区。

# lvdisplay --maps |egrep 'Physical|LV Name|Type'
LV Name /dev/WDC80Go/racine
Type linear
Physical volume /dev/hdb3
Physical extents 0 to 127
LV Name /dev/WDC80Go/usr
Type linear
Physical volume /dev/hdb3
Physical extents 128 to 1407
LV Name /dev/WDC80Go/var
Type linear
Physical volume /dev/hdb3
Physical extents 1408 to 1663
LV Name /dev/WDC80Go/tmp
Type linear
Physical volume /dev/hdb3
Physical extents 1664 to 1791
LV Name /dev/WDC80Go/home
Type linear
Physical volume /dev/hdb3
Physical extents 1792 to 3071
LV Name /dev/WDC80Go/ext1
Type linear
Physical volume /dev/hdb3
Physical extents 3072 to 10751
LV Name /dev/WDC80Go/ext2
Type linear
Physical volume /dev/hdb3
Physical extents 10752 to 18932

因此,PE 4418处于/dev/wdc80go/ext1逻辑分区。
文件系统逻辑块的大小/dev/wdc80go/ext1是

# dumpe2fs /dev/WDC80Go/ext1 | grep 'Block size'
dumpe2fs 1.37 (21-Mar-2005)
Block size: 4096

逻辑分区从PE 3072开始:

(PE的分区开始* sizeof(pe))+ parttion offset [pe_start] =(3072 * 8192)+ 384 = 25166208

有512个物理分区块,因此错误的块号是:

(36194858 25166208)/(尺寸(FS块)/512)= 11028650 /(4096/512)= 1378581.25

我们可以验证是否是具有DD命令的实际坏块:

dd if=/dev/WDC80Go/ext1 of=block1378581 bs=4096 count=1 skip=1378581

如果命令发出一些错误,则BAD块的计算是正确的。
否则,请重新检查计算以查找正确的块。
找到了正确的块后,用DD命令解析问题,如上所述中解释:

dd if=/dev/zero of=/dev/WDC80Go/ext1 count=1 bs=4096 seek=1378581