有几次我突然断电,导致 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
。