不幸的是,当硬盘驱动器(通常是虚拟驱动器)速度缓慢时,Linux 会在超时后中止对该驱动器的请求,这可能会导致数据损坏。
上次发生这种情况时,我的存储上运行了 2 个虚拟机(Linux 和 FreeBSD),这些虚拟机存在连接问题并冻结了一个多小时。存储本身很好,没有错误,修复连接后,虚拟机(显然也被冻结了)似乎再次工作了。
然而,Linux 虚拟机决定中止请求,导致系统无法使用(大多数目录上的 ls 被卡住,因此在没有选项的情况下挂载,许多其他事情不再起作用);需要重新启动。这些是错误(dmesg):
...
[86707.916728] Write(10): 2a 00 02 4c 9e 38 00 03 c0 00
[86707.916732] mptscsih: ioc0: task abort: SUCCESS (rv=2002) (sc=ffff880036865500)
[86707.916734] mptscsih: ioc0: attempting task abort! (sc=ffff880036866100)
[86707.916735] sd 2:0:0:0: [sda] CDB:
[86707.916736] Write(10): 2a 00 02 4c a1 f8 00 03 c0 00
[86707.916739] mptscsih: ioc0: task abort: SUCCESS (rv=2002) (sc=ffff880036866100)
[86707.916741] mptscsih: ioc0: attempting task abort! (sc=ffff880036865c80)
[86707.916742] sd 2:0:0:0: [sda] CDB:
[86707.916743] Write(10): 2a 00 02 4c a5 b8 00 03 c0 00
[86707.916746] mptscsih: ioc0: task abort: SUCCESS (rv=2002) (sc=ffff880036865c80)
[86707.916748] mptscsih: ioc0: attempting task abort! (sc=ffff880036864300)
[86707.916749] sd 2:0:0:0: [sda] CDB:
[86707.916750] Write(10): 2a 00 02 4c a9 78 00 02 b0 00
[86707.916753] mptscsih: ioc0: task abort: SUCCESS (rv=2002) (sc=ffff880036864300)
有趣的是,FreeBSD 虚拟机没有记录任何错误并且工作正常。显然,只有 FreeBSD 能按预期工作,不会中止任何事情(尽管我认为我在 FreeBSD 系统上看到过类似的内核消息)。
我不知道为什么内核在超时后杀死挂起的写入请求。在某些情况下这可能是有意义的,但在我的情况下肯定没有——这实际上是一个不必要的风险(如果没有超时,Linux 虚拟机在连接恢复后会正常继续,一切都会再次工作)。
如何禁用冻结硬盘的 Linux 内核超时 (vm)?
编辑:
Linux 虚拟机只有 1 个硬盘驱动器 (/dev/sda),它看起来应该像一个常规(SCSI 类型)物理驱动器。
lspci 列出了此控制器:“SCSI 存储控制器 [0100]:LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI [1000:0030] (rev 01)”。
这是另一个例子(不同的虚拟机,相同的主机,也是Linux)(在这种情况下,存储没有消失,但主机负载很重):
[1179039.664031] ata2: lost interrupt (Status 0x18)
[1179039.727188] ata2: drained 8 bytes to clear DRQ
[1179039.727272] ata2.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
[1179039.740720] sr 1:0:0:0: CDB:
[1179039.740759] Get event status notification: 4a 01 00 00 10 00 00 00 08 00
[1179039.740768] ata2.00: cmd a0/00:00:00:08:00/00:00:00:00:00/a0 tag 0 pio 16392 in
res 40/00:02:00:08:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
[1179039.740770] ata2.00: status: { DRDY }
[1179039.748067] ata2: soft resetting link
[1179039.937757] ata2.00: configured for UDMA/33
[1179039.943435] ata2: EH complete
编辑:
这就是 Debian/kBSD(FreeBSD 内核)系统上的超时错误(相同主机、相同情况、不同虚拟机):
mpt0: request 0xffffff80007305d0:62955 timed out for ccb 0xfffffe000a3bb800 (req->ccb 0xfffffe000a3bb800)
mpt0: request 0xffffff800072fa90:62956 timed out for ccb 0xfffffe000a3d1000 (req->ccb 0xfffffe000a3d1000)
mpt0: request 0xffffff8000726070:62962 timed out for ccb 0xfffffe000a428000 (req->ccb 0xfffffe000a428000)
mpt0: attempting to abort req 0xffffff80007305d0:62955 function 0
mpt0: completing timedout/aborted req 0xffffff8000726070:62962
mpt0: completing timedout/aborted req 0xffffff80007305d0:62955
mpt0: completing timedout/aborted req 0xffffff800072fa90:62956
mpt0: abort of req 0xffffff80007305d0:0 completed
mpt0: request 0xffffff8000726190:64136 timed out for ccb 0xfffffe000a3d1800 (req->ccb 0xfffffe000a3d1800)
mpt0: attempting to abort req 0xffffff8000726190:64136 function 0
mpt0: completing timedout/aborted req 0xffffff8000726190:64136
mpt0: abort of req 0xffffff8000726190:0 completed
mpt0: request 0xffffff8000721990:50970 timed out for ccb 0xfffffe00024bf800 (req->ccb 0xfffffe00024bf800)
mpt0: attempting to abort req 0xffffff8000721990:50970 function 0
mpt0: completing timedout/aborted req 0xffffff8000721990:50970
mpt0: abort of req 0xffffff8000721990:0 completed
mpt0: request 0xffffff80007279c0:61393 timed out for ccb 0xfffffe000a3cf000 (req->ccb 0xfffffe000a3cf000)
mpt0: request 0xffffff8000732550:61395 timed out for ccb 0xfffffe000a428000 (req->ccb 0xfffffe000a428000)
mpt0: attempting to abort req 0xffffff80007279c0:61393 function 0
mpt0: completing timedout/aborted req 0xffffff80007279c0:61393
mpt0: completing timedout/aborted req 0xffffff8000732550:61395
mpt0: abort of req 0xffffff80007279c0:0 completed
答案1
我发现了一个超时,在大多数系统上默认的超时时间是 30 秒。我不完全确定这是相关的超时,但我在一些虚拟机上增加了它,使系统承受很大的负载,并且到目前为止我在虚拟机中没有任何硬盘超时。
另外,一些评论对我在虚拟机中配置的硬盘表示困惑,因此我已将该信息添加到问题中。而且我有多个 Linux 虚拟机同时运行,因此错误不会只出现在一台虚拟机中。
超时设置(例如,在 中/etc/rc.local
):
Linux:
TIMEOUT=86400
for f in /sys/block/sd?/device/timeout; do
echo $TIMEOUT >"$f"
done
如果此模式 ( sd?
) 与您的硬件不匹配,请搜索超时并手动检查它们:
find /sys/ -name timeout
Debian/kBSD (GNU/kFreeBSD 9.0-2-amd64):
sysctl kern.cam.da.default_timeout=86400
(我显着增加了超时而不是禁用它;如果这被证明是罪魁祸首,则可能会设置更合适的值。)
再说一次,我还没有确认这正是我的虚拟机遇到的超时(或者这就是仅有的超时),但考虑到我已经将系统置于高负载(用于触发硬盘超时的负载类型)并且尚未发生硬盘超时(尽管网络超时已经像以前一样),看起来这确实可能至少成为解决方案的一部分。