第21章 其他文件系统
附录 D. OpenPGP 密钥
20.3.zpool 管理
ZFS 管理使用两个主要的实用程序。zpool 工具控制池的操作,允许添加、删除、替换和管理磁盘。zfs 工具允许创建、销毁和管理数据集,包括 文件系统

20.3.1. 创建和销毁存储池

创建一个 ZFS 存储池 (zpool) 是一个永久性的操作,因为池的结构在创建后不能改变。最重要的决定是把物理磁盘分成哪种类型的 vdevs。关于可能的选项的细节,请看 vdev 类型 的列表。在创建池之后,大多数 vdev 类型不允许向 vdev 添加磁盘。镜像和条纹是例外,前者允许向 vdev 添加新的磁盘,后者通过将一个新的磁盘附加到 vdev 而升级到镜像。尽管添加新的 vdev 会扩大池,但池的布局在池创建后不能改变。相反,备份数据,销毁池,然后重新创建。
创建一个简单的镜像池:
1
# zpool create mypool mirror /dev/ada1 /dev/ada2
2
# zpool status
3
pool: mypool
4
state: ONLINE
5
scan: none requested
6
config:
7
8
NAME STATE READ WRITE CKSUM
9
mypool ONLINE 0 0 0
10
mirror-0 ONLINE 0 0 0
11
ada1 ONLINE 0 0 0
12
ada2 ONLINE 0 0 0
13
14
errors: No known data errors
Copied!
要用一条命令创建一个以上的 vdev,请指定由 vdev 类型关键字分隔的磁盘组,在这个例子中是 mirror
1
# zpool create mypool mirror /dev/ada1 /dev/ada2 mirror /dev/ada3 /dev/ada4
2
# zpool status
3
pool: mypool
4
state: ONLINE
5
scan: none requested
6
config:
7
8
NAME STATE READ WRITE CKSUM
9
mypool ONLINE 0 0 0
10
mirror-0 ONLINE 0 0 0
11
ada1 ONLINE 0 0 0
12
ada2 ONLINE 0 0 0
13
mirror-1 ONLINE 0 0 0
14
ada3 ONLINE 0 0 0
15
ada4 ONLINE 0 0 0
16
17
errors: No known data errors
Copied!
池也可以使用分区而不是整个磁盘。把 ZFS 放在一个单独的分区里,允许同一磁盘有其他的分区用于其他目的。特别是,它允许添加启动所需的引导码和文件系统的分区。这允许从也是一个池的成员的磁盘上启动。当使用一个分区而不是整个磁盘时,ZFS 在 FreeBSD 上没有增加任何性能损失。使用分区还允许管理员对磁盘进行低配置,使用少于全部容量的磁盘。如果将来有一个与原来的名义大小相同的替换盘,实际的容量略小,那么较小的分区仍然适合,使用替换盘。
使用分区创建一个 RAID-Z2 池:
1
# zpool create mypool raidz2 /dev/ada0p3 /dev/ada1p3 /dev/ada2p3 /dev/ada3p3 /dev/ada4p3 /dev/ada5p3
2
# zpool status
3
pool: mypool
4
state: ONLINE
5
scan: none requested
6
config:
7
8
NAME STATE READ WRITE CKSUM
9
mypool ONLINE 0 0 0
10
raidz2-0 ONLINE 0 0 0
11
ada0p3 ONLINE 0 0 0
12
ada1p3 ONLINE 0 0 0
13
ada2p3 ONLINE 0 0 0
14
ada3p3 ONLINE 0 0 0
15
ada4p3 ONLINE 0 0 0
16
ada5p3 ONLINE 0 0 0
17
18
errors: No known data errors
Copied!
销毁一个不再需要的池,以重新使用磁盘。销毁一个池需要先缷载该池中的文件系统。如果有任何数据集正在使用,缷载操作就会失败,而不会销毁这个池。用 -f 强制销毁池。这可能会导致在这些数据集上有已打开文件的应用程序的未定义行为。

20.3.2. 添加和删除设备

有两种方法可以将磁盘添加到 zpool 中:用 zpool attach 将磁盘附加到现有的 vdev 上,或者用 zpool add 将 vdev 添加到池中。有些 vdev 类型 允许在创建后向 vdev 添加磁盘。
用单个磁盘创建的池缺乏冗余性。它可以检测到损坏,但不能修复,因为没有其他的数据副本。副本 属性可能能够从一个小的故障中恢复,如坏扇区,但不能提供与镜像或 RAID-Z 相同的保护水平。从一个由单个磁盘 vdev 组成的池开始,使用 zpool attach 向 vdev 添加一个新磁盘,创建一个镜像。也可以使用 zpool attach 向镜像组添加新的磁盘,增加冗余度和读取性能。当对用于池的磁盘进行分区时,将第一个磁盘的布局复制到第二个磁盘上。使用 gpart backupgpart restore 来使这个过程更容易。
通过连接 ada1p3 将单磁盘(stripe)vdev ada0p3 升级为镜像:
1
# zpool status
2
pool: mypool
3
state: ONLINE
4
scan: none requested
5
config:
6
7
NAME STATE READ WRITE CKSUM
8
mypool ONLINE 0 0 0
9
ada0p3 ONLINE 0 0 0
10
11
errors: No known data errors
12
# zpool attach mypool ada0p3 ada1p3
13
Make sure to wait until resilvering finishes before rebooting.
14
15
If you boot from pool 'mypool', you may need to update boot code on newly attached disk _ada1p3_.
16
17
Assuming you use GPT partitioning and _da0_ is your new boot disk you may use the following command:
18
19
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0
20
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1
21
bootcode written to ada1
22
# zpool status
23
pool: mypool
24
state: ONLINE
25
status: One or more devices is currently being resilvered. The pool will
26
continue to function, possibly in a degraded state.
27
action: Wait for the resilver to complete.
28
scan: resilver in progress since Fri May 30 08:19:19 2014
29
527M scanned out of 781M at 47.9M/s, 0h0m to go
30
527M resilvered, 67.53% done
31
config:
32
33
NAME STATE READ WRITE CKSUM
34
mypool ONLINE 0 0 0
35
mirror-0 ONLINE 0 0 0
36
ada0p3 ONLINE 0 0 0
37
ada1p3 ONLINE 0 0 0 (resilvering)
38
39
errors: No known data errors
40
# zpool status
41
pool: mypool
42
state: ONLINE
43
scan: resilvered 781M in 0h0m with 0 errors on Fri May 30 08:15:58 2014
44
config:
45
46
NAME STATE READ WRITE CKSUM
47
mypool ONLINE 0 0 0
48
mirror-0 ONLINE 0 0 0
49
ada0p3 ONLINE 0 0 0
50
ada1p3 ONLINE 0 0 0
51
52
errors: No known data errors
Copied!
当向现有的 vdev 添加磁盘不是一种选择,如 RAID-Z,另一种方法是向池中添加另一个 vdev。增加 vdevs 可以通过在 vdevs 上分配写操作而提供更高的性能。每个 vdev 都提供自己的冗余。混合 vdev 类型如镜像和 RAID-Z 是可能的,但不鼓励这样做。在一个包含镜像或 RAID-Z vdevs 的池中添加一个非冗余的 vdev,会给整个池的数据带来风险。分散写入意味着非冗余磁盘的故障将导致写入池中的每个块的一部分丢失。
ZFS 在每一个 vdevs 上进行数据条带化。例如,对于两个镜像 vdevs,这实际上是一个 RAID 10,它在两组镜像上进行条带化写入。ZFS 分配空间,使每个 vdev 在同一时间达到 100% 满载。拥有不同数量的可用空间的 vdev 将降低性能,因为更多的数据写入到未满的 vdev 上。
当把新设备连接到启动池时,记得要更新启动代码。
在现有的镜像上附加第二个镜像组(ada2p3ada3p3):
1
# zpool status
2
pool: mypool
3
state: ONLINE
4
scan: resilvered 781M in 0h0m with 0 errors on Fri May 30 08:19:35 2014
5
config:
6
7
NAME STATE READ WRITE CKSUM
8
mypool ONLINE 0 0 0
9
mirror-0 ONLINE 0 0 0
10
ada0p3 ONLINE 0 0 0
11
ada1p3 ONLINE 0 0 0
12
13
errors: No known data errors
14
# zpool add mypool mirror ada2p3 ada3p3
15
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada2
16
bootcode written to ada2
17
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada3
18
bootcode written to ada3
19
# zpool status
20
pool: mypool
21
state: ONLINE
22
scan: scrub repaired 0 in 0h0m with 0 errors on Fri May 30 08:29:51 2014
23
config:
24
25
NAME STATE READ WRITE CKSUM
26
mypool ONLINE 0 0 0
27
mirror-0 ONLINE 0 0 0
28
ada0p3 ONLINE 0 0 0
29
ada1p3 ONLINE 0 0 0
30
mirror-1 ONLINE 0 0 0
31
ada2p3 ONLINE 0 0 0
32
ada3p3 ONLINE 0 0 0
33
34
errors: No known data errors
Copied!
如果有足够的剩余冗余,从池中移除 vdevs 是不可能的,而从镜像中移除磁盘是代价高昂的。如果在一个镜像组中只保留一个磁盘,该组就不再是一个镜像,而成为一个条带,如果剩余的磁盘发生故障,整个池就会有风险。
如需从三路镜像组中删除一个磁盘:
1
# zpool status
2
pool: mypool
3
state: ONLINE
4
scan: scrub repaired 0 in 0h0m with 0 errors on Fri May 30 08:29:51 2014
5
config:
6
7
NAME STATE READ WRITE CKSUM
8
mypool ONLINE 0 0 0
9
mirror-0 ONLINE 0 0 0
10
ada0p3 ONLINE 0 0 0
11
ada1p3 ONLINE 0 0 0
12
ada2p3 ONLINE 0 0 0
13
14
errors: No known data errors
15
# zpool detach mypool ada2p3
16
# zpool status
17
pool: mypool
18
state: ONLINE
19
scan: scrub repaired 0 in 0h0m with 0 errors on Fri May 30 08:29:51 2014
20
config:
21
22
NAME STATE READ WRITE CKSUM
23
mypool ONLINE 0 0 0
24
mirror-0 ONLINE 0 0 0
25
ada0p3 ONLINE 0 0 0
26
ada1p3 ONLINE 0 0 0
27
28
errors: No known data errors
Copied!

20.3.3. 检查池的状态

池的状态是很重要的。如果一个驱动器脱机或 ZFS 检测到一个读、写或校验错误,相应的错误计数会增加。status 输出显示池中每个设备的配置和状态,以及整个池的状态。还显示了要采取的操作和关于最后一次 scrub 的详细信息。
1
# zpool status
2
pool: mypool
3
state: ONLINE
4
scan: scrub repaired 0 in 2h25m with 0 errors on Sat Sep 14 04:25:50 2013
5
config:
6
7
NAME STATE READ WRITE CKSUM
8
mypool ONLINE 0 0 0
9
raidz2-0 ONLINE 0 0 0
10
ada0p3 ONLINE 0 0 0
11
ada1p3 ONLINE 0 0 0
12
ada2p3 ONLINE 0 0 0
13
ada3p3 ONLINE 0 0 0
14
ada4p3 ONLINE 0 0 0
15
ada5p3 ONLINE 0 0 0
16
17
errors: No known data errors
Copied!

20.3.4. 清除错误

当检测到一个错误时,ZFS 会增加读取、写入或校验的错误计数。用 zpool clear mypool 来清除错误信息并重置计数。清除错误状态对自动脚本很重要,这些脚本在池遇到错误的时候会提醒管理员。如果不清除旧的错误,脚本可能无法报告进一步的错误。

20.3.5. 替换一个正常工作的设备

用不同的磁盘替换一个磁盘可能是可取的。当替换一个工作磁盘时,该过程在替换期间保持旧磁盘在线。池永远不会进入 降级 状态,减少数据丢失的风险。运行 zpool replace 以将数据从旧磁盘复制到新磁盘。在操作完成后,ZFS 将旧磁盘从 vdev 上断开连接。如果新的磁盘比旧的磁盘大,可能有可能使用新的空间来扩大 zpool。请参阅 扩大池
替换池中一个正常工作的设备:
1
# zpool status
2
pool: mypool
3
state: ONLINE
4
scan: none requested
5
config:
6
7
NAME STATE READ WRITE CKSUM
8
mypool ONLINE 0 0 0
9
mirror-0 ONLINE 0 0 0
10
ada0p3 ONLINE 0 0 0
11
ada1p3 ONLINE 0 0 0
12
13
errors: No known data errors
14
# zpool replace mypool ada1p3 ada2p3
15
Make sure to wait until resilvering finishes before rebooting.
16
17
When booting from the pool 'zroot', update the boot code on the newly attached disk 'ada2p3'.
18
19
Assuming GPT partitioning is used and [.filename]#da0# is the new boot disk, use the following command:
20
21
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0
22
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada2
23
# zpool status
24
pool: mypool
25
state: ONLINE
26
status: One or more devices is currently being resilvered. The pool will
27
continue to function, possibly in a degraded state.
28
action: Wait for the resilver to complete.
29
scan: resilver in progress since Mon Jun 2 14:21:35 2014
30
604M scanned out of 781M at 46.5M/s, 0h0m to go
31
604M resilvered, 77.39% done
32
config:
33
34
NAME STATE READ WRITE CKSUM
35
mypool ONLINE 0 0 0
36
mirror-0 ONLINE 0 0 0
37
ada0p3 ONLINE 0 0 0
38
replacing-1 ONLINE 0 0 0
39
ada1p3 ONLINE 0 0 0
40
ada2p3 ONLINE 0 0 0 (resilvering)
41
42
errors: No known data errors
43
# zpool status
44
pool: mypool
45
state: ONLINE
46
scan: resilvered 781M in 0h0m with 0 errors on Mon Jun 2 14:21:52 2014
47
config:
48
49
NAME STATE READ WRITE CKSUM
50
mypool ONLINE 0 0 0
51
mirror-0 ONLINE 0 0 0
52
ada0p3 ONLINE 0 0 0
53
ada2p3 ONLINE 0 0 0
54
55
errors: No known data errors
Copied!

20.3.6. 处理故障设备

当池中的一个磁盘发生故障时,该磁盘所属的 vdev 会进入 降级 状态。数据仍然可用,但性能下降,因为 ZFS 从可用的冗余中计算缺失的数据。为了将 vdev 恢复到完全功能的状态,替换故障的物理设备。然后 ZFS 被指示开始 resilver 操作。ZFS 从可用的冗余中重新计算故障设备上的数据,并将其写入替换设备中。完成后,vdev 返回到在线状态。
如果 vdev 没有任何冗余,或者如果设备已经故障,并且没有足够的冗余来补偿,池就会进入 故障 状态。除非有足够的设备可以重新连接,否则这个池就无法运行,需要从备份中进行数据恢复。
当替换一个故障磁盘时,故障磁盘的名称将变为新磁盘的 GUID。如果替换的设备具有相同的设备名称,则不需要为 zpool replace 提供新的设备名称参数。
使用 zpool replace 替换一个故障磁盘:
1
# zpool status
2
pool: mypool
3
state: DEGRADED
4
status: One or more devices could not be opened. Sufficient replicas exist for
5
the pool to continue functioning in a degraded state.
6
action: Attach the missing device and online it using 'zpool online'.
7
see: http://illumos.org/msg/ZFS-8000-2Q
8
scan: none requested
9
config:
10
11
NAME STATE READ WRITE CKSUM
12
mypool DEGRADED 0 0 0
13
mirror-0 DEGRADED 0 0 0
14
ada0p3 ONLINE 0 0 0
15
316502962686821739 UNAVAIL 0 0 0 was /dev/ada1p3
16
17
errors: No known data errors
18
# zpool replace mypool 316502962686821739 ada2p3
19
# zpool status
20
pool: mypool
21
state: DEGRADED
22
status: One or more devices is currently being resilvered. The pool will
23
continue to function, possibly in a degraded state.
24
action: Wait for the resilver to complete.
25
scan: resilver in progress since Mon Jun 2 14:52:21 2014
26
641M scanned out of 781M at 49.3M/s, 0h0m to go
27
640M resilvered, 82.04% done
28
config:
29
30
NAME STATE READ WRITE CKSUM
31
mypool DEGRADED 0 0 0
32
mirror-0 DEGRADED 0 0 0
33
ada0p3 ONLINE 0 0 0
34
replacing-1 UNAVAIL 0 0 0
35
15732067398082357289 UNAVAIL 0 0 0 was /dev/ada1p3/old
36
ada2p3 ONLINE 0 0 0 (resilvering)
37
38
errors: No known data errors
39
# zpool status
40
pool: mypool
41
state: ONLINE
42
scan: resilvered 781M in 0h0m with 0 errors on Mon Jun 2 14:52:38 2014
43
config:
44
45
NAME STATE READ WRITE CKSUM
46
mypool ONLINE 0 0 0
47
mirror-0 ONLINE 0 0 0
48
ada0p3 ONLINE 0 0 0
49
ada2p3 ONLINE 0 0 0
50
51
errors: No known data errors
Copied!

20.3.7. 刷新池

定期刷新 (scrub) 池,最好是每月一次以上。刷新操作是磁盘密集型的,在运行中会降低性能。在调度 scrub 时要避开高需求期,或者使用 vfs.zfs.scrub_delay 来调整 scrub 的相对优先级,以免拖累其他工作负载。
1
# zpool scrub mypool
2
# zpool status
3
pool: mypool
4
state: ONLINE
5
scan: scrub in progress since Wed Feb 19 20:52:54 2014
6
116G scanned out of 8.60T at 649M/s, 3h48m to go
7
0 repaired, 1.32% done
8
config:
9
10
NAME STATE READ WRITE CKSUM
11
mypool ONLINE 0 0 0
12
raidz2-0 ONLINE 0 0 0
13
ada0p3 ONLINE 0 0 0
14
ada1p3 ONLINE 0 0 0
15
ada2p3 ONLINE 0 0 0
16
ada3p3 ONLINE 0 0 0
17
ada4p3 ONLINE 0 0 0
18
ada5p3 ONLINE 0 0 0
19
20
errors: No known data errors
Copied!
如果需要,可以运行 zpool scrub -s mypool 以取消刷新操作。

20.3.8. 自修复

与数据块一起存储的校验和使文件系统能够自我修复。这个功能将自动修复那些校验和与另一个属于存储池的设备上记录的校验和不一致的数据。例如,有两个磁盘的镜像配置,其中一个驱动器开始出现故障,无法再正常存储数据。当数据很长时间没有被访问时,这种情况就更严重了,就像长期的档案存储一样。传统的文件系统需要运行检查和修复数据的命令,如 fsck(8)。这些命令需要时间,而且在严重的情况下,管理员必须决定执行哪种修复操作。当 ZFS 检测到一个具有不匹配校验和的数据块时,它试图从镜像磁盘读取数据。如果该磁盘能够提供正确的数据,ZFS 将把它交给应用程序,并纠正磁盘上有错误校验和的数据。在正常的池操作中,这种情况无需系统管理员的任何互动。
下一个例子通过创建一个 /dev/ada0/dev/ada1 磁盘的镜像池来展示这种自修复行为:
1
# zpool create healer mirror /dev/ada0 /dev/ada1
2
# zpool status healer
3
pool: healer
4
state: ONLINE
5
scan: none requested
6
config:
7
8
NAME STATE READ WRITE CKSUM
9
healer ONLINE 0 0 0
10
mirror-0 ONLINE 0 0 0
11
ada0 ONLINE 0 0 0
12
ada1 ONLINE 0 0 0
13
14
errors: No known data errors
15
# zpool list
16
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
17
healer 960M 92.5K 960M - - 0% 0% 1.00x ONLINE -
Copied!
将一些重要的数据复制到池中,利用自修复功能防止数据错误,并创建一个池的校验和,以便以后进行比较:
1
# cp /some/important/data /healer
2
# zfs list
3
NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT
4
healer 960M 67.7M 892M 7% 1.00x ONLINE -
5
# sha1 /healer > checksum.txt
6
# cat checksum.txt
7
SHA1 (/healer) = 2753eff56d77d9a536ece6694bf0a82740344d1f
Copied!
通过向镜像中的一个磁盘的开头写入随机数据来模拟数据损坏。为了防止 ZFS 在检测到数据时进行修复,在损坏之前导出池,之后再导入。
警告
这是一个危险的操作,可能会破坏重要的数据,这里仅作示范。在存储池的正常操作中,不要尝试它。这个故意破坏的例子也不应该在任何不使用 ZFS 文件系统的磁盘或分区上运行。不要使用不在池中的任何其他磁盘设备名称。在运行该命令之前,请确保有适当的存储池备份,并对其进行测试!
1
# zpool export healer
2
# dd if=/dev/random of=/dev/ada1 bs=1m count=200
3
200+0 records in
4
200+0 records out
5
209715200 bytes transferred in 62.992162 secs (3329227 bytes/sec)
6
# zpool import healer
Copied!
池的状态显示,有一个设备出现错误。请注意,从池中读取数据的应用程序并没有收到任何不正确的数据。ZFS 从 ada0 设备提供具有正确校验和的数据。要找到有错误校验和的设备,寻找其 CKSUM 列包含一个非零值的设备。
1
# zpool status healer
2
pool: healer
3
state: ONLINE
4
status: One or more devices has experienced an unrecoverable error. An
5
attempt was made to correct the error. Applications are unaffected.
6
action: Determine if the device needs to be replaced, and clear the errors
7
using 'zpool clear' or replace the device with 'zpool replace'.
8
see: http://illumos.org/msg/ZFS-8000-4J
9
scan: none requested
10
config:
11
12
NAME STATE READ WRITE CKSUM
13
healer ONLINE 0 0 0
14
mirror-0 ONLINE 0 0 0
15
ada0 ONLINE 0 0 0
16
ada1 ONLINE 0 0 1
17
18
errors: No known data errors
Copied!
ZFS 检测到这个错误,并通过使用未受影响的 ada0 镜像盘中存在的冗余来处理它。与原始磁盘的校验和比较将揭示池是否再次一致:
1
# sha1 /healer >> checksum.txt
2
# cat checksum.txt
3
SHA1 (/healer) = 2753eff56d77d9a536ece6694bf0a82740344d1f
4
SHA1 (/healer) = 2753eff56d77d9a536ece6694bf0a82740344d1f
Copied!
在故意篡改之前和之后生成校验和,而池的数据仍然匹配。这表明当校验和不同时,ZFS能够自动检测并纠正任何错误。注意这是在池中存在足够的冗余的情况下才可能实现的。一个由单一设备组成的池没有自我修复的能力。这也是为什么校验和在 ZFS 中如此重要的原因;不要以任何理由禁用它们。ZFS 不需要 fsck(8) 或类似的文件系统一致性检查程序来检测和纠正这一点,并在有问题时保持池的可用性。现在需要一次刷新操作来覆盖 ada1 上的损坏的数据。
1
# zpool scrub healer
2
# zpool status healer
3
pool: healer
4
state: ONLINE
5
status: One or more devices has experienced an unrecoverable error. An
6
attempt was made to correct the error. Applications are unaffected.
7
action: Determine if the device needs to be replaced, and clear the errors
8
using 'zpool clear' or replace the device with 'zpool replace'.
9
see: http://illumos.org/msg/ZFS-8000-4J
10
scan: scrub in progress since Mon Dec 10 12:23:30 2012
11
10.4M scanned out of 67.0M at 267K/s, 0h3m to go
12
9.63M repaired, 15.56% done
13
config:
14
15
NAME STATE READ WRITE CKSUM
16
healer ONLINE 0 0 0
17
mirror-0 ONLINE 0 0 0
18
ada0 ONLINE 0 0 0
19
ada1 ONLINE 0 0 627 (repairing)
Copied!
刷新操作从 ada0 读取数据,并在 ada1 上重写任何有错误校验的数据,由 zpool status(repairing) 输出显示。操作完成后,池的状态变成:
1
# zpool status healer
2
pool: healer
3
state: ONLINE
4
status: One or more devices has experienced an unrecoverable error. An
5
attempt was made to correct the error. Applications are unaffected.
6
action: Determine if the device needs to be replaced, and clear the errors
7
using 'zpool clear' or replace the device with 'zpool replace'.
8
see: http://illumos.org/msg/ZFS-8000-4J
9
scan: scrub repaired 66.5M in 0h2m with 0 errors on Mon Dec 10 12:26:25 2012
10
config:
11
12
NAME STATE READ WRITE CKSUM
13
healer ONLINE 0 0 0
14
mirror-0 ONLINE 0 0 0
15
ada0 ONLINE 0 0 0
16
ada1 ONLINE 0 0 2.72K
17
18
errors: No known data errors
Copied!
在刷新操作完成后,所有数据会从 ada0 同步到 ada1,通过运行 zpool clear 清除 池状态中的错误信息。
1
# zpool clear healer
2
# zpool status healer
3
pool: healer
4
state: ONLINE
5
scan: scrub repaired 66.5M in 0h2m with 0 errors on Mon Dec 10 12:26:25 2012
6
config:
7
8
NAME STATE READ WRITE CKSUM
9
healer ONLINE 0 0 0
10
mirror-0 ONLINE 0 0 0
11
ada0 ONLINE 0 0 0
12
ada1 ONLINE 0 0 0
13
14
errors: No known data errors
Copied!
现在池已经恢复到完全工作的状态,所有的错误计数都是零。

20.3.9. 扩大池

每个 vdev 中最小的设备限制冗余池的可用大小。用一个更大的设备替换最小的设备。在完成 替换resilver 操作后,池就可以增长到使用新设备的容量。以一个 1TB 驱动器和一个 2TB 驱动器组成的镜像为例。可用的空间是 1TB。当用另一个 2TB 的驱动器替换 1TB 的驱动器时,resilver 程序会将现有数据复制到新的驱动器上。由于这两台设备现在都有 2TB 的容量,镜像的可用空间增长到 2TB。
通过在每个设备上使用 zpool online -e 开始扩展。在扩展所有设备后,额外的空间就成为池的可用空间。

20.3.10. 导入和导出池

在把池移到另一个系统之前,先导出池。ZFS 解除对所有数据集的挂载,将每个设备标记为已导出但仍被锁定,以防止被其他磁盘使用。这允许在其他机器、其他支持 ZFS 的操作系统、甚至不同的硬件架构上导入池(有一些注意事项,见 zpool(8))。当一个数据集有已打开的文件时,使用 zpool export -f 来强制导出池。使用这个方法时要注意。数据集被强制卸载,可能会导致在这些数据集上有已打开文件的应用程序出现意外行为。
导出一个不使用的池:
1
# zpool export mypool
Copied!
导入一个池会自动挂载数据集。zpool import -o 为这个特定的导入设置临时属性。zpool import altroot= 允许导入一个具有基本挂载点而不是文件系统根目录的池。如果这个池最后是在不同的系统上使用,并且没有被正确导出,请使用 zpool import -f 强制导入。 zpool import -a 会导入所有看起来没有被其他系统使用的池。
列出所有可供导入的池:
1
# zpool import
2
pool: mypool
3
id: 9930174748043525076
4
state: ONLINE
5
action: The pool can be imported using its name or numeric identifier.
6
config:
7
8
mypool ONLINE
9
ada2p3 ONLINE
Copied!
用另一个根目录导入池。
1
# zpool import -o altroot=/mnt mypool
2
# zfs list
3
zfs list
4
NAME USED AVAIL REFER MOUNTPOINT
5
mypool 110K 47.0G 31K /mnt/mypool
Copied!

20.3.11. 升级存储池

在升级 FreeBSD 之后,或者从使用旧版本的系统中导入一个池,请手动将池升级到最新的 ZFS 版本,以支持更多的新功能。在升级之前,请考虑是否需要在旧系统上导入这个池。升级是一个单向的过程。升级较旧的池是可能的,但降级具有较新功能的池是不可能的。
升级一个 v28 池以支持 Feature Flags
1
# zpool status
2
pool: mypool
3
state: ONLINE
4
status: The pool is formatted using a legacy on-disk format. The pool can
5
still be used, but some features are unavailable.
6
action: Upgrade the pool using 'zpool upgrade'. Once this is done, the
7
pool will no longer be accessible on software that does not support feat
8
flags.
9
scan: none requested
10
config:
11
12
NAME STATE READ WRITE CKSUM
13
mypool ONLINE 0 0 0
14
mirror-0 ONLINE 0 0 0
15
ada0 ONLINE 0 0 0
16
ada1 ONLINE 0 0 0
17
18
errors: No known data errors
19
# zpool upgrade
20
This system supports ZFS pool feature flags.
21
22
The following pools are formatted with legacy version numbers and are upgraded to use feature flags.
23
After being upgraded, these pools will no longer be accessible by software that does not support feature flags.
24
25
VER POOL
26
--- ------------
27
28 mypool
28
29
Use 'zpool upgrade -v' for a list of available legacy versions.
30
Every feature flags pool has all supported features enabled.
31
# zpool upgrade mypool
32
This system supports ZFS pool feature flags.
33
34
Successfully upgraded 'mypool' from version 28 to feature flags.
35
Enabled the following features on 'mypool':
36
async_destroy
37
empty_bpobj
38
lz4_compress
39
multi_vdev_crash_dump
Copied!
zpool upgrade 完成之前,ZFS 的较新功能将无法使用。使用 zpool upgrade -v 查看升级提供哪些新功能,以及哪些功能已经被支持。
升级一个池以支持新的功能标志:
1
# zpool status
2
pool: mypool
3
state: ONLINE
4
status: Some supported features are not enabled on the pool. The pool can
5
still be used, but some features are unavailable.
6
action: Enable all features using 'zpool upgrade'. Once this is done,
7
the pool may no longer be accessible by software that does not support
8
the features. See zpool-features(7) for details.
9
scan: none requested
10
config:
11
12
NAME STATE READ WRITE CKSUM
13
mypool ONLINE 0 0 0
14
mirror-0 ONLINE 0 0 0
15
ada0 ONLINE 0 0 0
16
ada1 ONLINE 0 0 0
17
18
errors: No known data errors
19
# zpool upgrade
20
This system supports ZFS pool feature flags.
21
22
All pools are formatted using feature flags.
23
24
Some supported features are not enabled on the following pools. Once a
25
feature is enabled the pool may become incompatible with software
26
that does not support the feature. See zpool-features(7) for details.
27
28
POOL FEATURE
29
---------------
30
zstore
31
multi_vdev_crash_dump
32
spacemap_histogram
33
enabled_txg
34
hole_birth
35
extensible_dataset
36
bookmarks
37
filesystem_limits
38
# zpool upgrade mypool
39
This system supports ZFS pool feature flags.
40
41
Enabled the following features on 'mypool':
42
spacemap_histogram
43
enabled_txg
44
hole_birth
45
extensible_dataset
46
bookmarks
47
filesystem_limits
Copied!
警告: 在从池中启动的系统上更新启动代码,以支持新的池版本。在包含启动代码的分区上使用 gpart bootcode。根据系统启动的方式,有两种类型的引导码可用。GPT(最常见的选项)和 EFI(用于更现代的系统)。 对于使用 GPT 的传统启动,使用以下命令:
1
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1
Copied!
对于使用 EFI 启动的系统,执行以下命令:
1
# gpart bootcode -p /boot/boot1.efifat -i 1 ada1
Copied!
将启动代码应用于池中的所有可启动磁盘。参见 gpart(8) 了解更多信息。

20.3.12. 显示已记录的池历史

ZFS 记录改变池的命令,包括创建数据集、改变属性或替换磁盘。回顾池子的创建历史是很有用的,就像检查哪个用户在什么时候执行一个特定的动作一样。历史记录不保存在日志文件中,而是池本身的一部分。查看这个历史的命令被恰当地命名为 zpool history
1
# zpool history
2
History for 'tank':
3
2013-02-26.23:02:35 zpool create tank mirror /dev/ada0 /dev/ada1
4
2013-02-27.18:50:58 zfs set atime=off tank
5
2013-02-27.18:51:09 zfs set checksum=fletcher4 tank
6
2013-02-27.18:51:18 zfs create tank/backup
Copied!
输出显示以某种方式改变池的 zpoolzfs 命令,以及一个时间戳。像 zfs list 这样的命令不包括在内。当没有指定池的名称时,ZFS 显示所有池的历史。
当提供 -i-l 选项时,zpool history 可以显示更多信息。-i 显示用户发起的事件以及内部记录的 ZFS 事件。
1
# zpool history -i
2
History for 'tank':
3
2013-02-26.23:02:35 [internal pool create txg:5] pool spa 28; zfs spa 28; zpl 5;uts 9.1-RELEASE 901000 amd64
4
2013-02-27.18:50:53 [internal property set txg:50] atime=0 dataset = 21
5
2013-02-27.18:50:58 zfs set atime=off tank
6
2013-02-27.18:51:04 [internal property set txg:53] checksum=7 dataset = 21
7
2013-02-27.18:51:09 zfs set checksum=fletcher4 tank
8
2013-02-27.18:51:13 [internal create txg:55] dataset = 39
9
2013-02-27.18:51:18 zfs create tank/backup
Copied!
通过添加 -l 显示更多细节。以显示长格式的历史记录,包括发出命令的用户名称和发生变化的主机名等信息。
1
# zpool history -l
2
History for 'tank':
3
2013-02-26.23:02:35 zpool create tank mirror /dev/ada0 /dev/ada1 [user 0 (root) on :global]
4
2013-02-27.18:50:58 zfs set atime=off tank [user 0 (root) on myzfsbox:global]
5
2013-02-27.18:51:09 zfs set checksum=fletcher4 tank [user 0 (root) on myzfsbox:global]
6
2013-02-27.18:51:18 zfs create tank/backup [user 0 (root) on myzfsbox:global]
Copied!
输出显示,root 用户用磁盘 /dev/ada0/dev/ada1 创建了镜像池。主机名 myzfsbox 也显示在池创建后的命令中。当从一个系统导出池并导入另一个系统时,主机名的显示变得很重要。可以通过每条命令记录的主机名来区分其他系统上发出的命令。
将这两个选项合并到 zpool history 中,可以为任何给定的池提供最详细的信息。当追踪所执行的操作或需要更详细的输出进行调试时,池的历史记录提供宝贵的信息。

20.3.13. 性能监测

一个内置的监控系统可以实时显示池的 I/O 统计数据。它显示池上的自由空间和使用空间的数量,每秒执行的读写操作,以及使用的 I/O 带宽。默认情况下,ZFS 监控并显示系统中的所有池。提供一个池的名字来限制对该池的监控。一个基本的例子:
1
# zpool iostat
2
capacity operations bandwidth
3
pool alloc free read write read write
4
---------- ----- ----- ----- ----- ----- -----
5
data 288G 1.53T 2 11 11.3K 57.1K
Copied!
要连续看到 I/O 活动,可以指定一个数字作为最后一个参数,表示更新之间的间隔时间,单位是秒。每隔一段时间就会打印出下一个统计行。按 Ctrl+C 停止这种连续监测。在间隔时间之后,在命令行中给出第二个数字,以指定要显示的统计数字的总数。
-v 显示更详细的 I/O 统计数据。池中的每个设备都会出现一个统计行。这对于查看每个设备上执行的读写操作很有用,可以帮助确定是否有任何单个设备拖累池子。这个例子显示一个有两个设备的镜像池。
1
# zpool iostat -v
2
capacity operations bandwidth
3
pool alloc free read write read write
4
----------------------- ----- ----- ----- ----- ----- -----
5
data 288G 1.53T 2 12 9.23K 61.5K
6
mirror 288G 1.53T 2 12 9.23K 61.5K
7
ada1 - - 0 4 5.61K 61.7K
8
ada2 - - 1 4 5.04K 61.7K
9
----------------------- ----- ----- ----- ----- ----- -----
Copied!

20.3.14. 分割一个存储池

ZFS 可以将一个由一个或多个镜像 vdev 组成的池分割成两个池。除非另有规定,否则 ZFS 将分离每个镜像的最后一个成员,并创建一个包含相同数据的新池。请确保先用 -n 对该操作进行模拟运行。这将显示所请求的操作的细节,而不实际执行。这有助于确认该操作将完成用户的意图。