断电后从 ZFS 错误中恢复的正确方法是什么?

断电后从 ZFS 错误中恢复的正确方法是什么?

有几次我突然断电,导致 ZFS 池无法使用,直到系统完全重启后才可使用。我打算买一个 UPS 以避免将来出现问题,但似乎应该有一种方法可以解决这种简单的问题,而无需完全关闭系统。

重现该问题非常容易:我的 ZFS 池由两个通过 USB 连接的硬盘运行。这是池正常运行时的状态:

$ sudo zpool status
pool: tank
state: ONLINE
  scan: scrub repaired 0 in 1h36m with 0 errors on Sun Dec 11 02:00:22 2016
config:

NAME                                                STATE     READ WRITE CKSUM
tank                                                ONLINE       0     0     0
  mirror-0                                          ONLINE       0     0     0
    usb-ST4000DM_000-1F2168_000000000000-0:0-part1  ONLINE       0     0     0
    usb-ST3000DM_001-1E6166_000000000000-0:1-part1  ONLINE       0     0     0

如果我关闭 USB 驱动器的电源而不先停止 ZFS,然后在几秒钟后再次打开电源,则会出现以下问题:如果我尝试在 ZFS 挂载点内执行 LS,它将无限期挂起,需要我关闭终端。(ls 进程将保持为僵尸状态)。如果通过 samba 连接到 nfs 服务器的任何计算机尝试访问共享目录,它们也会同样挂起。

现在状态如下:

$ sudo zpool status
  pool: tank
 state: UNAVAIL
status: One or more devices are faulted in response to IO failures.
action: Make sure the affected devices are connected, then run 'zpool clear'.
   see: http://zfsonlinux.org/msg/ZFS-8000-HC
  scan: scrub repaired 0 in 1h36m with 0 errors on Sun Dec 11 02:00:22 2016
config:

NAME                                                STATE     READ WRITE CKSUM
tank                                                UNAVAIL      0     0     0  insufficient replicas
  mirror-0                                          UNAVAIL      0     0     0  insufficient replicas
    usb-ST4000DM_000-1F2168_000000000000-0:0-part1  UNAVAIL      0     0     0
    usb-ST3000DM_001-1E6166_000000000000-0:1-part1  UNAVAIL      0     0     0

尽管 USB 驱动器已再次打开。

我已尝试以下命令来修复该问题。

$ sudo zpool clear tank
cannot clear errors for tank: I/O error

$ sudo zfs unmount tank
cannot open 'tank': pool I/O is currently suspended

# Note: Because other computers were trying to access the zfs share via     samba, there are zombie processes, which is why an export won't work.

$ sudo zpool export tank
umount: /tank: target is busy
    (In some cases useful info about processes that
     use the device is found by lsof(8) or fuser(1).)
cannot unmount '/tank': umount failed

$ sudo zpool export -f tank
umount: /tank: target is busy
    (In some cases useful info about processes that
     use the device is found by lsof(8) or fuser(1).)
cannot unmount '/tank': umount failed

# Tried this just for kicks, and got the expected result.
$ sudo zpool import -nfF tank
cannot import 'tank': a pool with that name already exists
use the form 'zpool import <pool | id> <newpool>' to give it a new name

我花了几个小时阅读了其他人的类似帖子,但似乎没有一个帖子能解决这个确切的问题。如果我重新启动运行 ZFS 的计算机,所有错误都会消失,死进程也会被清除,一切都会恢复正常。

但肯定有更干净的方法来解决这个问题。有什么建议吗?

编辑:我可能应该澄清一下。驱动器所连接的服务器是一台改装的笔记本电脑,因此它有一个内部电源。因此,在正常运行下,如果发生断电,USB 驱动器可能会断电,然后再次启动,而无需服务器/笔记本电脑重新启动。

答案1

我目前无法重现您的情况,但发生此类故障后,我首先会尝试访问zpool reopen池,并可能zpool online访问设备(如果需要)。例如,当您有

$ sudo zpool status
  pool: tank
 state: UNAVAIL
status: One or more devices are faulted in response to IO failures.
action: Make sure the affected devices are connected, then run 'zpool clear'.
   see: http://zfsonlinux.org/msg/ZFS-8000-HC
  scan: scrub repaired 0 in 1h36m with 0 errors on Sun Dec 11 02:00:22 2016
config:

NAME                                                STATE     READ WRITE CKSUM
tank                                                UNAVAIL      0     0     0  insufficient replicas
  mirror-0                                          UNAVAIL      0     0     0  insufficient replicas
    usb-ST4000DM_000-1F2168_000000000000-0:0-part1  UNAVAIL      0     0     0
    usb-ST3000DM_001-1E6166_000000000000-0:1-part1  UNAVAIL      0     0     0

你可以尝试

$ sudo zpool reopen tank

如果这还不能完全解释清楚

$ sudo zpool online tank 'usb-ST4000DM_000-1F2168_000000000000-0:0-part1'
$ sudo zpool online tank 'usb-ST3000DM_001-1E6166_000000000000-0:1-part1'

完全有可能,只需zpool reopen $POOL让池重新工作,因为它指示 ZFS 重新打开与池关联的所有设备。(手册页简要地描述了它重新打开与池关联的所有 vdev。我不知道它是否会触发 vdev 扫描,或者它是否会尝试以已知的名称重新打开。)只要仍然以相同的名称找到设备,那么应该就足够了,而且可能如果设备有其他名称,则足够了(如果执行了 vdev 扫描)。

之后您可能仍需要记录zpool clear任何 I/O 错误,但这取决于 ZFS 是否有时间记录它们。如果两个驱动器都坏了,那么 ZFS 可能没有时间将错误记录到驱动器中,因此zpool clear不需要记录。

另外,您还可以查看failmode池的属性(zpool get failmode tank)。听起来您的池目前有,failmode=wait但对于您的用例来说,failmode=continue可能更合适。请参阅man 8 zpool有关该属性的各种值的描述failmode

相关内容