当 ATA 停止响应时,md RAID 中的设备发生故障

当 ATA 停止响应时,md RAID 中的设备发生故障

我曾创造五个 1TB HDD 分区/dev/sda1,,,,和)在/dev/sdb1/dev/sdc1/dev/sde1/dev/sdf1RAID 6在 Ubuntu 14.04 LTS Trusty Tahr 上/dev/md0使用数组调用。mdadm

命令 sudomdadm --detail /dev/md0用于显示所有驱动器主动同步

然后,为了进行测试,我通过在阵列中仍然处于活动状态/dev/sdb时运行以下命令来模拟长 I/O 阻塞:/dev/sdb1

hdparm --user-master u --security-set-pass deltik /dev/sdb
hdparm --user-master u --security-erase-enhanced deltik /dev/sdb

警告

请勿对您关心的数据进行此尝试!
由于这次 ATA 操作,我最终损坏了 455681 个 inode。我承认我的疏忽。

ATA 的安全擦除命令预计运行188分钟,至少在这么长的时间内阻止所有其他命令。

我原本期望md像删除合适的 RAID 控制器一样删除无响应的驱动器,但令我惊讶的是,它/dev/md0也被阻塞了。

mdadm --detail /dev/md0查询被阻塞的设备,所以它会冻结并且不会输出。

/proc/mdstat这是我无法使用时的布局mdadm --detail /dev/md0

root@node51 [~]# cat /proc/mdstat 
Personalities : [raid6] [raid5] [raid4] [linear] [multipath] [raid0] [raid1] [raid10] 
md0 : active raid6 sdf1[5] sda1[0] sdb1[4] sdc1[2] sde1[1]
      2929887744 blocks super 1.2 level 6, 512k chunk, algorithm 2 [5/5] [UUUUU]

unused devices: <none>

我尝试mdadm /dev/md0 -f /dev/sdb1强制失败/dev/sdb1,但也被阻止了:

root@node51 [~]# ps aux | awk '{if($8~"D"||$8=="STAT"){print $0}}' 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      3334  1.2  0.0  42564  1800 ?        D    03:21   3:37 parted -l
root      4957  0.0  0.0  13272   900 ?        D    06:19   0:00 mdadm /dev/md0 -f /dev/sdb1
root      5706  0.0  0.0  13388  1028 ?        D    06:19   0:00 mdadm --detail /dev/md0
root      7541  0.5  0.0      0     0 ?        D    Jul19   6:12 [kworker/u16:2]
root     22420  0.0  0.0  11480   808 ?        D    07:48   0:00 lsblk
root     22796  0.0  0.0   4424   360 pts/13   D+   05:51   0:00 hdparm --user-master u --security-erase-enhanced deltik /dev/sdb
root     23312  0.0  0.0   4292   360 ?        D    05:51   0:00 hdparm -I /dev/sdb
root     23594  0.1  0.0      0     0 ?        D    06:11   0:07 [kworker/u16:1]
root     25205  0.0  0.0  17980   556 ?        D    05:52   0:00 ls --color=auto
root     26008  0.0  0.0  13388  1032 pts/23   D+   06:32   0:00 mdadm --detail /dev/md0
dtkms    29271  0.0  0.2  58336 10412 ?        DN   05:55   0:00 python /usr/share/backintime/common/backintime.py --backup-job
root     32303  0.0  0.0      0     0 ?        D    06:16   0:00 [kworker/u16:0]

更新(2015 年 7 月 21 日):在我等待了整整 188 分钟以清除 I/O 阻塞之后,当我看到md它被完全清除,/dev/sdb就像它完好无损一样时,惊讶变成了恐惧。

我认为这md至少会看到奇偶校验不匹配,然后就会下降/dev/sdb1

我惊慌失措地mdadm /dev/md0 -f /dev/sdb1再次奔跑,由于 I/O 阻塞已解除,命令很快就完成了。

当输入/输出错误出现时,文件系统就已经损坏了。仍然感到恐慌,我偷懒卸载了 RAID 阵列中的数据分区,因为reboot -nf我认为情况不会变得更糟了。

经过一番苦心经营e2fsck的分区后,455681 个 inode 终于被纳入其中lost+found

从那时起,我重新组装了阵列,并且阵列本身现在看起来很好:

root@node51 [~]# mdadm --detail /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Mon Feb 16 14:34:26 2015
     Raid Level : raid6
     Array Size : 2929887744 (2794.16 GiB 3000.21 GB)
  Used Dev Size : 976629248 (931.39 GiB 1000.07 GB)
   Raid Devices : 5
  Total Devices : 5
    Persistence : Superblock is persistent

    Update Time : Tue Jul 21 00:00:30 2015
          State : active 
 Active Devices : 5
Working Devices : 5
 Failed Devices : 0
  Spare Devices : 0

         Layout : left-symmetric
     Chunk Size : 512K

           Name : box51:0
           UUID : 6b8a654d:59deede9:c66bd472:0ceffc61
         Events : 643541

    Number   Major   Minor   RaidDevice State
       0       8        1        0      active sync   /dev/sda1
       1       8       97        1      active sync   /dev/sdg1
       2       8       33        2      active sync   /dev/sdc1
       6       8       17        3      active sync   /dev/sdb1
       5       8      113        4      active sync   /dev/sdh1

对于我来说,这还是相当震惊的,因为md我预期的两道防线并没有出现:

  • 设备锁定时发生故障
  • 当设备返回的数据为垃圾时,设备会失败

问题

  1. md为什么无响应的驱动器/分区不会失败?
  2. 当驱动器被阻止时,我可以从阵列中删除驱动器/分区吗?
  3. 是否可以配置超时以便md自动使不响应 ATA 命令的驱动器失效?
  4. 为什么要md继续使用具有无效数据的设备?

答案1

德尔蒂克,您误解了 Linux 软件 RAID(md)的工作原理。

md由多个设备或分区构成虚拟块设备,并且不知道您正在向虚拟设备传输什么数据。
您希望它能够完成它没有被设计做的事情。


答案

md1. 为什么无响应的驱动器/分区不会失败?

这是因为md不知道

  • 驱动器正忙于处理其md自身请求的 I/O 或
  • 由于某些外部情况(如驱动器自身的错误恢复或 ATA 安全擦除),驱动器被阻止,

因此md将等待驱动器返回什么。驱动器最终没有返回任何读取或写入错误。如果存在读取错误,md则会自动从奇偶校验中修复它,如果存在写入错误,md则会导致设备故障(请参阅md手册页)。

由于没有读取错误也没有写入错误,因此md内核等待其响应后继续使用该设备。

2. 当驱动器被阻止时,我可以从阵列中删除驱动器/分区吗?

不可以。RAID/dev/md0设备已被阻止,除非清除阻止,否则无法修改。

您已将-f--fail标志传递给mdadm“管理”模式。
以下是其实际作用的演示:

这是该标志工作原理的源代码

case 'f': /* set faulty */
    /* FIXME check current member */
    if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
        (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
                rdev))) {
        if (errno == EBUSY)
            busy = 1;
        pr_err("set device faulty failed for %s:  %s\n",
            dv->devname, strerror(errno));
        if (sysfd >= 0)
            close(sysfd);
        goto abort;
    }
    if (sysfd >= 0)
        close(sysfd);
    sysfd = -1;
    count++;
    if (verbose >= 0)
        pr_err("set %s faulty in %s\n",
            dv->devname, devname);
    break;

请注意,调用write(sysfd, "faulty", 6). sysfd是文件中先前设置的变量:
sysfd = sysfs_open(fd2devnm(fd), dname, "block/dev");

sysfs_open()是一个函数这个文件

int sysfs_open(char *devnm, char *devname, char *attr)
{
    char fname[50];
    int fd;

    sprintf(fname, "/sys/block/%s/md/", devnm);
    if (devname) {
        strcat(fname, devname);
        strcat(fname, "/");
    }
    strcat(fname, attr);
    fd = open(fname, O_RDWR);
    if (fd < 0 && errno == EACCES)
        fd = open(fname, O_RDONLY);
    return fd;
}

如果你跟踪这些功能,你会发现它mdadm /dev/md0 -f /dev/sdb1本质上是这样做的:

echo "faulty" > /sys/block/md0/md/dev-sdb1/block/dev

/dev/md0由于被阻止,该请求将处于等待状态并且不会立即通过。

3. 是否可以配置超时以便md自动使不响应 ATA 命令的驱动器失效?

是的。事实上,默认情况下,超时时间为 30 秒

root@node51 [~]# cat /sys/block/sdb/device/timeout
30

您的假设存在问题,因为您的驱动器实际上正忙于运行 ATA 命令(持续 188 分钟),因此并没有超时。

有关详情,请参阅Linux 内核 SCSI 错误处理文档

4. 为什么要md继续使用含有无效数据的设备?

当 ATA 安全擦除完成时,驱动器未报告任何问题,例如中止命令,因此md没有理由怀疑存在问题。

此外,在您使用分区作为 RAID 设备而不是整个磁盘的情况下,内核的内存分区表并未被告知擦除驱动器上的分区已消失,因此md会继续访问,/dev/sdb1就像没有任何问题一样。

这是来自md手册页

清理和不匹配

由于存储设备随时可能出现坏块,因此定期读取阵列中所有设备上的所有块以尽早捕获此类坏块非常有价值。此过程称为擦洗

可以通过以下方式擦除 md 数组:查看或者维修到文件md/sync_action在里面系统文件系统设备的目录。

请求清除将导致 md 读取阵列中每个设备的每个块,并检查数据是否一致。对于 RAID1 和 RAID10,这意味着检查副本是否相同。对于 RAID4、RAID5、RAID6,这意味着检查奇偶校验块(或多个块)是否正确。

由此我们可以推断,通常不会在每次磁盘读取时检查奇偶校验。(此外,每次读取时都检查奇偶校验会增加完成读取所需的事务量,并运行奇偶校验与数据读取的比较,这将严重影响性能。)

在正常运行下,md只是假设它读取的数据是有效的,因此很容易受到静默数据损坏。就你的情况而言,由于你擦除了驱动器,所以整个驱动器上的数据都被悄无声息地损坏了。

您的文件系统没有意识到损坏。您在文件系统级别看到输入/输出错误,因为文件系统无法理解为什么它有坏数据。

为了避免静默数据损坏,首先,永远不要再做你做过的事.其次,考虑使用虚拟文件系统,一种专注于数据完整性并检测和纠正静默数据损坏的文件系统。

相关内容