ZFS排错和池恢复(part 2)

解决ZFS存储池中的数据问题

数据问题的示例包括: 在某些情况下,这些错误是暂时的,例如控制器出现问题时出现随机I/O错误。
在其他情况下,损坏是永久性的,例如磁盘损坏。
即使如此,损坏是否永久并不一定表明错误可能再次发生。例如,如果您意外地覆盖了磁盘的一部分,则不会发生任何类型的硬件故障,并且不需要更换设备。
识别设备的确切问题不是一项容易的任务,在后面的章节中会详细介绍。

解决ZFS空间问题

如果您不确定ZFS如何报告文件系统和池空间记帐,请查看以下部分。
ZFS文件系统空间报告
zpool listzfs list命令在确定可用池和文件系统空间方面优于以前的dfdu命令。
传统命令无法区分池空间和文件系统空间,也无法说明子文件系统或快照所占的空间。

例如,下面的池(rpool)分配了5.46GB空间和68.5GB的空余。
$ zpool list rpool
NAME   SIZE  ALLOC   FREE  CAP  DEDUP  HEALTH  ALTROOT
rpool   74G  5.46G  68.5G   7%  1.00x  ONLINE  -			
如果通过查看各个文件系统的USED列将池空间核算与文件系统空间核算进行比较,则可以看到ALLOC中报告的池空间计入了文件系统的已使用总量。
例如:
$ zfs list -r rpool
NAME                      USED  AVAIL  REFER  MOUNTPOINT
rpool                    5.41G  67.4G  74.5K  /rpool
rpool/ROOT               3.37G  67.4G    31K  legacy
rpool/ROOT/solaris       3.37G  67.4G  3.07G  /
rpool/ROOT/solaris/var    302M  67.4G   214M  /var
rpool/dump               1.01G  67.5G  1000M  -
rpool/export             97.5K  67.4G    32K  /rpool/export
rpool/export/home        65.5K  67.4G    32K  /rpool/export/home
rpool/export/home/admin  33.5K  67.4G  33.5K  /rpool/export/home/admin
rpool/swap               1.03G  67.5G  1.00G  -			
top
ZFS存储池空间报告
zpool list命令输出结果中SIZE值通常指的是物理磁盘空间量,但根据池的冗余级别而有所不同。参见以下例子。
zfs list命令列出文件系统可用的空间,即磁盘空间减去zfs池冗余元素的开销(如果有)。
以下ZFS数据集配置由zfs list命令作为已分配空间进行跟踪,但在zpool list输出中不作为已分配空间进行跟踪: 以下项目描述了使用不同的池配置、ZFS卷和ZFS保留如何影响已消耗和可用的磁盘空间。根据配置,应使用下面列出的步骤耿总监视池空间。 top

检查ZFS文件系统完整性

ZFS不存在与fsck命令等效的实用程序。该实用程序传统上有两个用途:文件系统修复和文件系统验证。
文件系统修复
对于传统的文件系统,写入数据的方式本质上容易受到意外故障的影响,从而导致文件系统不一致。
因为传统的文件系统不是事务性的,所以可能存在未引用的块、错误的链接计数或其他不一致的文件系统结构。
日志记录的添加确实解决了其中一些问题,但当日志无法回滚时,可能会带来其他问题。
如果ZFS中的硬件或软件配置不一致,则ZFS中的数据池应以不一致的方式存在。

fsck实用程序修复特定于UFS文件系统的已知问题。
大多数ZFS存储池问题通常与硬件故障或电源故障有关。使用冗余池可以避免许多问题。
如果您的池由于硬件故障或断电而损坏,请参阅修复ZFS存储池范围的损坏。

如果您的池不是冗余的,则文件系统损坏可能导致部分或全部数据无法访问的风险始终存在。
文件系统验证
除了执行文件系统修复外,fsck实用程序还验证磁盘上的数据是否没有问题。
传统上,此任务需要卸载文件系统并运行fsck实用程序,在此过程中可能会将系统转换为单用户模式。这种情况导致的停机时间与所检查的文件系统的大小成正比。

ZFS不需要显式实用程序来执行必要的检查,而是提供了一种机制来执行所有不一致性的例行检查。
这种被称为擦洗(scrubbing)的功能通常用于内存和其他系统中,作为一种在错误导致硬件或软件故障之前检测和防止错误的方法。
top
控制ZFS数据清理
每当ZFS遇到错误时,无论是通过清理还是在按需访问文件时,都会在内部记录该错误,以便可以快速查看池中的所有已知错误。
显式ZFS数据清理
检查数据完整性的最简单方法是启动池内所有数据的显式清理。
此操作将遍历池中的所有数据一次,并验证是否可以读取所有块。
尽管任何I/O的优先级仍低于正常操作的优先级,但清理仍以设备允许的速度进行。
此操作可能会对性能产生负面影响,尽管池的数据在清理过程中应该保持可用性,并且几乎具有同样的响应能力。
要启动显式清理,请使用zpool scrub命令。例如:
$ zpool scrub system1
实用zpool status命令可以显示当前擦洗操作的状态。例如:
$ zpool status -v system1
pool: system1
state: ONLINE
scan: scrub in progress since Mon Jun  7 12:07:52 2010
201M scanned out of 222M at 9.55M/s, 0h0m to go
0 repaired, 90.44% done
config:

NAME          STATE     READ WRITE CKSUM
system1       ONLINE       0     0     0
   mirror-0   ONLINE       0     0     0
      c1t0d0  ONLINE       0     0     0
      c1t1d0  ONLINE       0     0     0

errors: No known data errors				
每个池同时只能有一个活动的擦洗操作。
可以实用-s选项停止正在进行的擦洗操作:
$ zpool scrub -s system1
在大多数情况下,为确保数据完整性而进行的擦洗操作应持续完成。如果系统性能受到擦洗操作的影响,请自行决定停止擦洗操作。
执行例行擦洗可确保系统上所有磁盘的连续I/O。例行擦洗具有防止电源管理将空闲磁盘置于低功耗模式的副作用。
如果系统通常一直在执行I/O,或者如果功耗不是问题,则可以安全地忽略此问题。
如果系统在很大程度上是空闲的,并且您想节省磁盘的功率,则应该考虑使用cron计划的明确擦洗而不是后台擦洗。这仍然会执行完整的数据擦洗,尽管在擦洗完成之前,它只会生成大量的I/O,此时磁盘可以正常进行电源管理。
缺点(除了增加的I/O)是,在很长一段时间内根本不会进行擦洗,这可能会增加这些期间的数据损坏风险。
计划数据清理
随着时间的推移,可能会出现数据不一致的情况。定期擦洗数据有助于发现这些不一致并尽早解决它们。因此,定期擦洗可确保数据可用性。
在此版本中,添加了自动擦洗作为预防性维护工具。自动或计划的数据清理现在是日常操作的一部分。
默认情况下,此功能在安装时启用。两个ZFS属性与计划清理关联:(以下两个属性FreeBSD中没有)
可以在计划的时间之外手动启动擦洗操作。如果此时计划的擦洗正在进行,则手动的操作将失败。
就像手动清理一样,您可以取消正在进行的计划清理。
在这种情况下,将计划在间隔指定的下一个时段运行清理操作,并从取消清理的开始时间开始计算。
要取消正在进行的清理操作,请使用以下命令:
$ zpool scrub -s
仅当没有其他清理或重定大小器操作正在进行时,计划的清理才会运行。
启动resilver操作时,正在进行的计划清理将立即取消,并将在resliver完成后重新启动。
ZFS数据清理和重定大小
更换设备时,将启动重定大小操作,以将数据从完好副本移动到新设备。此操作是磁盘清理的一种形式。
因此,在池中的给定时间只能发生一个这样的操作。如果正在进行清理操作,则重定位操作将暂停当前清理,并在重定位完成后重新启动。
top
修复损坏的ZFS数据
当一个或多个设备错误(指示一个或多个丢失或损坏的设备)影响顶级虚拟设备时,会发生数据损坏。
例如,镜像的一半可能会遇到数千个设备错误,而不会导致数据损坏。
如果镜像的另一侧在完全相同的位置遇到错误,则会导致数据损坏。

数据损坏总是永久性的,在修复期间需要特别考虑。即使底层设备被修复或更换,原始数据也将永远丢失。
通常,此场景需要从备份中恢复数据。数据错误会在遇到时记录下来,并且可以通过下一节中解释的例行池清理来控制这些错误。
删除损坏的块后,下一次清理过程将识别损坏不再存在,并从系统中删除任何错误跟踪。

ZFS使用校验和、冗余和自愈数据将数据损坏的风险降至最低。
尽管如此,如果池不是冗余的,如果池降级时发生损坏,或者一系列不太可能的事件合谋损坏一段数据的多个副本,则可能会发生数据损坏。
无论来源如何,结果都是一样的:数据已损坏,因此不再可访问。
所采取的操作取决于被破坏的数据类型及其相对值。两种基本类型的数据可能会损坏: 数据在正常操作期间以及通过清洗进行验证。

以下各节介绍如何识别数据损坏的类型以及如何修复数据(如果可能)。
识别数据损坏的类型
默认情况下,zpool status命令仅显示发生了损坏,而不显示此损坏发生的位置。例如:
	$ zpool status system1
pool: system1
state: ONLINE
status: One or more devices has experienced an error resulting in data
corruption.  Applications may be affected.
action: Restore the file in question if possible. Otherwise restore the
entire pool from backup.
see: http://support.oracle.com/msg/ZFS-8000-8A
config:

NAME                           STATE     READ WRITE CKSUM
   system1                     ONLINE       4     0     0
      c0t5000C500335E106Bd0    ONLINE       0     0     0
      c0t5000C500335FC3E7d0    ONLINE       4     0     0


errors: 2 data errors, use '-v' for a list			
每个错误仅表示在给定的时间点发生错误。每个错误不一定仍然存在于系统上。
在正常情况下,情况就是这样。某些临时中断可能会导致数据损坏,在中断结束后会自动修复这些损坏。
池的完整清理保证检查池中的每个活动块,因此每次清理完成时都会重置错误日志。
如果确定错误不再存在,并且不想等待清理完成,请使用zpool online命令重置池中的所有错误。
如果数据损坏发生在池范围的元数据中,则输出略有不同。例如:
$ zpool status -v morpheus
pool: morpheus
id: 13289416187275223932
state: UNAVAIL
status: The pool metadata is corrupted.
action: The pool cannot be imported due to damaged devices or data.
see: http://support.oracle.com/msg/ZFS-8000-72
config:

morpheus  FAULTED   corrupted data
c1t10d0   ONLINE			
在池范围损坏的情况下,池将处于FAULTED状态,因为池无法提供所需的冗余级别。
top
修复损坏的文件或目录
如果文件或目录已损坏,系统可能仍能正常工作,具体取决于损坏的类型。
如果系统上不存在数据的良好副本,则任何损坏实际上都是不可恢复的。
如果数据有价值,则必须从备份中恢复受影响的数据。
即使如此,您也可以从这种损坏中恢复,而无需恢复整个池。

如果损坏在文件数据块内,则可以安全地删除该文件,从而清除系统中的错误。
使用zpool status –v命令显示具有持续错误的文件名列表。例如:
$ zpool status system1 -v
pool: system1
state: ONLINE
status: One or more devices has experienced an error resulting in data
corruption.  Applications may be affected.
action: Restore the file in question if possible. Otherwise restore the
entire pool from backup.
see: http://support.oracle.com/msg/ZFS-8000-8A
config:

NAME                           STATE     READ WRITE CKSUM
   system1                     ONLINE       4     0     0
      c0t5000C500335E106Bd0    ONLINE       0     0     0
      c0t5000C500335FC3E7d0    ONLINE       4     0     0

errors: Permanent errors have been detected in the following files:
/system1/file.1
/system1/file.2			
具有持续错误的文件名列表可能描述如下: 可以尝试通过在多次迭代中清除池并清除池错误来解决更轻微的数据损坏。如果第一次清理和清除迭代无法解决损坏的文件,请再次运行它们。例如:
$ zpool scrub system1
$ zpool clear system1
如果损坏发生在目录或文件元数据中,则唯一的选择是将文件移到其他位置。
可以安全地将任何文件或目录移动到不太方便的位置,从而可以将原始对象还原到原来的位置。

如果损坏的文件系统具有多个块引用(如快照)的损坏数据,则zpool status –v命令无法显示所有损坏的数据路径。
损坏数据的当前zpool status报告受元数据损坏量以及执行zpool status命令后是否重用了任何块的限制。
消除重复的数据块使报告所有损坏的数据变得更加复杂。

如果数据已损坏,并且zpool status –v命令确定快照数据受到影响,则考虑运行以下命令以确定其他损坏路径:
$ find mount-point -inum $inode -print
$ find mount-point/.zfs/snapshot -inum $inode -print		
第一个命令搜索指定文件系统及其所有快照中报告的损坏数据的索引节点号。
第二个命令搜索具有相同inode编号的快照。
top
修复ZFS存储池范围内的损坏
如果损坏位于池元数据中,并且该损坏阻止打开或导入池,则您可以使用以下选项: top

修复损坏的ZFS配置

ZFS在根文件系统中维护活动池及其配置的缓存。
如果此缓存文件已损坏或与存储在磁盘上的配置信息不同步,则无法再打开池。
ZFS试图避免这种情况,尽管考虑到底层存储的质量,任意损坏总是可能的。
这种情况通常会导致一个本来应该可用的池从系统中消失。这种情况还可以表现为缺少未知数量的顶级虚拟设备的部分配置。
在任何一种情况下,都可以通过导出池(如果池可见)并重新导入来恢复配置。
top

修复不可启动的系统

ZFS被设计为具有强壮性和稳定性,尽管存在错误。
即使如此,当访问池时,软件错误或某些意外问题可能会导致系统死机。
作为启动过程的一部分,必须打开每个池,这意味着此类故障将导致系统进入紧急重启循环。
要从这种情况中恢复,必须通知ZFS不要在启动时查找任何池。

ZFS在/etc/zfs/zpool.cache中维护可用池及其配置的内部缓存。此文件的位置和内容是私有的,可能会发生更改。
如果系统变得不可引导,则使用–m milestone=none引导选项引导至里程碑none
系统启动后,将根文件系统重新装载为可写,然后重命名/etc/zfs/zpool.cache文件或将其移动到其他位置。
这些操作会导致ZFS忘记系统上存在任何池,从而阻止其尝试访问导致问题的不健康池。
然后,可以通过发出svcadm milestone all命令进入正常系统状态。当从备用根目录引导以执行修复时,可以使用类似的过程。

系统启动后,可以尝试使用zpool import命令导入池。但是,这样做可能会导致启动期间发生的相同错误,因为该命令使用相同的机制访问池。
如果系统上存在多个池,请执行以下操作: top