干净的 ext3 分区出现输入/输出错误 - 如何检查数据块有什么问题

干净的 ext3 分区出现输入/输出错误 - 如何检查数据块有什么问题

我在带有 HP Raid 控制器的 CentOS 5 服务器(内核版本 2.6.18-164.15.1.el5)上的 ext3 分区上的文件遇到问题:

hpacucli ctrl all show detail

Smart Array P410 in Slot 1
   Bus Interface: PCI
   ...

HP 工具没有报告任何问题。

这是正常的分区 ext3,块大小设置为 2k,并且没有问题 - fsck 输出:

fsck 1.39 (29-May-2006)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information

文件 inode 也可以:

File: `name.xxx'
Size: 3126962       Blocks: 6124       IO Block: 4096   regular file
Device: 6851h/26705d    Inode: 64579729    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2014-07-28 09:02:59.000000000 -0400
Modify: 2014-07-28 09:02:59.000000000 -0400
Change: 2014-07-28 09:02:59.000000000 -0400

我无法执行的操作之一是文件复制:

> cp /long_path/name.xxx .
 cp: reading `/long_path.name.xxx': Input/output error

为了查明问题出在哪里,我运行 dd 来复制文件:

> dd if=/long_path/name.xxx bs=2048 of=test
 dd: reading `/long_path/name.xxx': Input/output error
 222+0 records in
 222+0 records out
 454656 bytes (455 kB) copied, 0.042867 seconds, 10.6 MB/s

所以我猜测问题出在 223 文件块中。

Debugfs 应该有助于在磁盘上定位该块

debugfs  -R "stat name.xxx" /dev/sdf
debugfs 1.39 (29-May-2006)
Inode: 64579729   Type: regular    Mode:  0644   Flags: 0x0   Generation: 2900468317
User:     0   Group:     0   Size: 3126962
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 6124
Fragment:  Address: 0    Number: 0    Size: 0
ctime: 0x53d64a03 -- Mon Jul 28 09:02:59 2014
atime: 0x53d64a03 -- Mon Jul 28 09:02:59 2014
mtime: 0x53d64a03 -- Mon Jul 28 09:02:59 2014
BLOCKS:
(0):130402311, (1-4):130402844-130402847, (5-6):130484033-130484034, (7):130484036,
(8-10):130484049-130484051, (11):130484055, (IND):130761221, (12-13):130761222-130761223,   
(14):130763791, (15):130763942, (16):130765268, (17-23):130838937-130838943,  
(24-46):130853946-130853968, (47-48):130855126-130855127, (49):130855215, 
(50-53):130856428-130856431, (54-104):130856533-130856583, (105-341):130856748-130856984, 
...
[MORE BLOCKS]     
....
TOTAL: 1531

所以我猜测有问题的数据在块 130856866 中。

我如何才能获得有关该块的更多信息?我运行了 badblocks,并得到了一个坏块列表。我猜我必须将上面的块号乘以 2(文件系统块大小为 2K,而 badblocks 默认使用 1K)。此外,badblocks 检查的是磁盘,而不是分区,所以也许我应该添加一些偏移量(该磁盘上有一个分区,所以可能没有)。

> fdisk -l /dev/sdf

Disk /dev/sdf: 2000.3 GB, 2000365379584 bytes
255 heads, 63 sectors/track, 243197 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
       Device Boot      Start         End      Blocks   Id  System
/dev/cciss/c0d5p1   *       1      243197  1953479871   83  Linux

我也想过使用 smartd。我应该寻找什么?

Error counter log:
       Errors Corrected by           Total   Correction     Gigabytes    Total
           ECC          rereads/    errors   algorithm      processed    uncorrected
       fast | delayed   rewrites  corrected  invocations   [10^9 bytes]  errors
read:          0     1457         0  2887405961          0      65948.712          18
write:         0        0         0         0          0      15056.493           0
verify:        0        1         0  361901613          0       3591.720           0

Non-medium error count:      226

SMART Self-test log
Num  Test              Status                 segment  LifeTime  LBA_first_err [SK ASC ASQ]
   Description                              number   (hours)
# 1  Background long   Failed in segment -->       -   34479          16845361 [0x3 0x11 0x0]
# 2  Background short  Completed                   -      44                 - [-   -    -]
# 3  Background short  Completed                   -      39                 - [-   -    -]
# 4  Background long   Completed                   -       6                 - [-   -    -]

Long (extended) Self Test duration: 18500 seconds [308.3 minutes]

Background scan results log
Status: scan is active
  Accumulated power on time, hours:minutes 34541:56 [2072516 minutes]
  Number of background scans performed: 1139,  scan progress: 38.18%
  Number of background medium scans performed: 1139

 #  when        lba(hex)    [sk,asc,ascq]    reassign_status
 1 19215:06  0000000000014c61  [3,11,0]   Recovered via rewrite in-place
 2 19215:07  0000000000014c66  [3,11,0]   Recovered via rewrite in-place
 3 19413:28  0000000001010a31  [3,11,0]   Require Write or Reassign Blocks command
 4 19943:24  000000000001ea99  [3,11,0]   Recovered via rewrite in-place
 5 20152:23  00000000000232b8  [3,11,0]   Recovered via rewrite in-place
 6 31229:34  810000004087f984  [3,11,0]   Require Write or Reassign Blocks command
 7 33021:51  810000004087ba85  [3,11,0]   Require Write or Reassign Blocks command
 8 33021:51  000000004087ba9f  [3,11,0]   Require Write or Reassign Blocks command
 9 33021:52  000000004087bad6  [3,11,0]   Require Write or Reassign Blocks command
10 33029:43  000000004087baa5  [3,11,0]   Require Write or Reassign Blocks command
11 33055:27  000000004087bac3  [3,11,0]   Require Write or Reassign Blocks command
12 33244:40  810000004087f9d6  [3,11,0]   Require Write or Reassign Blocks command
13 33431:58  990000004087f105  [0,0,0]   Reassignment by disk failed
14 33480:17  00000000463d7713  [3,11,0]   Require Write or Reassign Blocks command
15 33480:19  00000000463d7723  [3,11,0]   Require Write or Reassign Blocks command
16 33480:20  00000000463d7725  [3,11,0]   Require Write or Reassign Blocks command
17 33480:28  81000000463d774e  [3,11,0]   Require Write or Reassign Blocks command
18 33686:17  8100000044e50edc  [3,11,0]   Require Write or Reassign Blocks command
19 34154:17  81000000432bef27  [3,11,0]   Require Write or Reassign Blocks command
20 34463:43  810000001f32decd  [3,11,0]   Require Write or Reassign Blocks command
21 34463:43  0000000030080000  [3,11,0]   Require Write or Reassign Blocks command

我应该如何将上述 smartctl 输出(或来自 smartd run 的任何其他输出)与我最初的问题结合起来。

这个问题难道不应该通过 HDD 软件来解决吗?

顺便说一句。我发现以下链接有助于理解“debugs -R”输出。也许关联对别人有用。

更新

经过进一步研究,我发现与有问题的 inode 相关的操作(如上面的 cp 命令)会在内核日志中触发以下行:

kernel: cciss: cmd ffff810037e00000 has CHECK CONDITION sense key = 0x3 

'sense key' 是一种 'status',是 SCSI 标准的一部分(此处列出以及更多描述这里)。

答案1

因此,为了解决这个问题,我做了以下事情。

取出你的区块编号,乘以四,再加一

(130856866 * 4) + 1 = 523427465

这表示报告产生 I/O 错误的扇区。块大小为 2k,扇区为 512 字节。额外的一个扇区表示分区的起始扇区偏移量。

为了与 SMART 关联,我们需要将现在的值转换为十六进制。

$ printf "0x%x\n" 523427465
0x1f32de89

现在,当您将其与 SMART 显示的内容进行关联时,就会出现一条可疑的接近线。

20 34463:43  810000001f32decd  [3,11,0]   Require Write or Reassign Blocks command

有多远?

$ bc -l
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
obase=16
ibase=16
1F32DECD-1F32DE89
44

计算结果显示距离仅在 34816 到 32768 字节之间,但是我们无法说出组成该块的四个扇区中哪个扇区已损坏。

如果我不得不猜测的话,我会说可能同一地址周围有大量的块会报告 I/O 错误(假设 raid 条带化的大小为 32k 或其他)。

此外,如果 RAID 从另一个磁盘获取块,则读取可能无法发现问题。无论如何,写入必须传播到 RAID1 设置中的所有磁盘,因此这可能会导致写入失败但读取成功。此外,如果我们假设 RAID 卡的块大小为 32k,我们还可以假设损坏的块加上 SMART 报告的块都是由该盘片上发生的任何事情造成的。它只是从好磁盘读取前 32k 和从坏磁盘读取接下来 32k 的 SMART 测试。

现代硬盘会保留“保留扇区”,以便用新扇区位置替换此类损坏的扇区。鉴于您现在收到此消息,以及Reassign by disk failed来自智能设备的消息,我认为磁盘已耗尽。

至于如何解决这个问题,那就比较棘手了。LBA 寻址是对底层真实磁盘的抽象。您需要确定是哪个磁盘导致了此问题,在 RAID 阵列中将其故障并替换它。

无论如何,您的磁盘有问题,您应该尽快更换它。

答案2

有很多事情需要处理...但有几件事引起了我的注意。

您的内核版本是:2.6.18-164.15.1.el5 - 表示您的内核修订版本处于 EL5.4 级别,或者大约 2010 年 3 月

我在 EL5 中一直遇到 ext3 文件系统稳定性和损坏问题。直到 2012 年中期,问题才得到完全解决。最糟糕的情况是,我与一家云基础设施公司合作,该公司从未更新过其基础版本的内核。因此,我开始在数千台 EL5 服务器上大规模看到这些问题。

您是否可以更新您的 OS/内核/e2fsprogs、fsck 并再试一次?

此外,如果内核是 2010 年左右的版本,则系统的 BIOS 和 Smart Array P410 固件可能已经非常过时。这是什么型号的服务器?


编辑:

cciss CHECK_CONDITION 错误就是明证。此时甚至不需要处理 SMART。运行HP 阵列诊断实用程序它会将错误信息提炼成报告。无论哪种方式,我真的希望这不是 RAID5 阵列。

您可以发布输出吗hpacucli ctrl all show config detail

答案3

实际失败的块可以从内核日志中读取,您可以在下面的某处读取/var/log(可能是/var/log/kernel.log),或者从命令的输出中读取dmesg

注意:您需要的不是磁盘扇区号,而是分区和文件系统特定的块号。从 2.4.x 开始的内核都在 dmesg 中显示这两个信息。

给 e2fsck 一个-L标志可以将这个块列表添加到文件系统的坏块列表中。因此正确的步骤如下:

首先,从 dmesg 检查坏块列表。

其次,将它们放入一个简单的文本文件中,

cat >badblockfile.txt
34252345
3452345
23452345

(Ctrl/D)

e2fsck -f -y -C0 /dev/diskname -L badblockfile.txt

如果您无法解释 dmesg,请将相关部分放在这里作为注释或问题的扩展。

扩大

您的文件系统有 2k 块,并从硬盘的第一个扇区(有 512 字节扇区)开始。因此,文件系统块(可以提供给 e2fsck)和磁盘块(在 dmesg 输出中)之间的公式非常简单:

filesystem_block=(serctor_no-1)/4

如果您的消息中没有文件系统级块,您也可以使用此公式。

替代提示

还有一个额外的提示:e2fsck 有一个标志-c。这会在检查之前调用该工具badblocks,并将新发现的坏块标记为坏块。根据我的经验,它确实不行,在大多数情况下它找不到所有的坏块。我代替你在一个周末(或至少一晚)无限循环地运行了这个:

while true; do e2fsck -f -y -C0 -c /dev/sdf;done

相关内容