$ zpool status ztest
pool: ztest
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
ztest ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/tt1 ONLINE 0 0 0
gpt/tt2 ONLINE 0 0 0
errors: No known data errors
$ zpool list -v ztest
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
ztest 3.75G 3.62G 128M - - 72% 96% 1.00x ONLINE -
mirror-0 3.75G 3.62G 128M - - 72% 96.7% - ONLINE
gpt/tt1 - - - - - - - - ONLINE
gpt/tt2 - - - - - - - - ONLINE
$ zfs list ztest
NAME USED AVAIL REFER MOUNTPOINT
ztest 420K 3.62G 96K /ztest
$ df /ztest/
Filesystem 512-blocks Used Avail Capacity Mounted on
ztest 7601576 192 7601384 0% /ztest
写入伪数据
那么就像上次实验一样,使用 dd 命令用零数据填满文件系统。
$ dd if=/dev/zero of=/ztest/dummy bs=1m
dd: /ztest/dummy: No space left on device
3711+0 records in
3710+1 records out
3891134464 bytes transferred in 151.249101 secs (25726662 bytes/sec)
$ df -h /ztest/
Filesystem Size Used Avail Capacity Mounted on
ztest 3.6G 3.6G 0B 100% /ztest
$ zfs list -o space ztest
NAME AVAIL USED USEDSNAP USEDDS USEDREFRESERV USEDCHILD
ztest 0B 3.63G 0B 3.62G 0B 672K
$ ls -l /ztest/dummy
-rw-r--r-- 1 root wheel 3891134464 Dec 22 17:43 /ztest/dummy
$ zpool export ztest
$ ls -l /boot/kernel/kernel
-r-xr-xr-x 2 root wheel 29343392 Nov 4 10:27 /boot/kernel/kernel
$ dd if=/boot/kernel/kernel of=/dev/gpt/tt1 oseek=1000000
dd: /dev/gpt/tt1: Invalid argument
57311+1 records in
57311+0 records out
29343232 bytes transferred in 21.647581 secs (1355497 bytes/sec)
$
读取被破坏的数据部分
为了确认是否发生错误,仅使用 da1 这一侧进行导入。因为是 USB 接口的 HDD,把 da2 实体移除是最简单的方法。
$ zpool import
pool: ztest
id: 6304409293823647838
state: DEGRADED
status: One or more devices are missing from the system.
action: The pool can be imported despite missing or damaged devices. The
fault tolerance of the pool may be compromised if imported.
see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
config:
ztest DEGRADED
mirror-0 DEGRADED
gpt/tt1 ONLINE
gpt/tt2 UNAVAIL cannot open
如上所示,无法访问 da2 侧的 gpt/tt2。就这样将 ztest 导入。
$ zpool import ztest
$ zpool status ztest
pool: ztest
state: DEGRADED
status: One or more devices could not be opened. Sufficient replicas exist for
the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
config:
NAME STATE READ WRITE CKSUM
ztest DEGRADED 0 0 0
mirror-0 DEGRADED 0 0 0
gpt/tt1 ONLINE 0 0 0
13953643250226400519 UNAVAIL 0 0 0 was /dev/gpt/tt2
errors: No known data errors
$ df /ztest
Filesystem 512-blocks Used Avail Capacity Mounted on
ztest 7601264 7601024 240 100% /ztest
$ ls /ztest
dummy
虽然只有一侧的驱动器,但 /ztest/dummy 确实存在。那么现在尝试实际读取它的内容。为了确认数据内容,这里使用 hd 命令进行读取。
$ zpool import
pool: ztest
id: 6304409293823647838
state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:
ztest ONLINE
mirror-0 ONLINE
gpt/tt1 ONLINE
gpt/tt2 ONLINE
可以看到,gpt/tt2 一侧的状态已经是 ONLINE。那么就将 ztest 导入。
$ zpool import ztest
$ zpool status ztest
pool: ztest
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
ztest ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/tt1 ONLINE 0 0 0
gpt/tt2 ONLINE 0 0 0
errors: No known data errors
$
$ zpool status ztest
pool: ztest
state: ONLINE
scan: resilvered 432K in 00:00:01 with 0 errors on Fri Dec 23 11:14:23 2022
config:
NAME STATE READ WRITE CKSUM
ztest ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/tt1 ONLINE 0 0 0
gpt/tt2 ONLINE 0 0 0
errors: No known data errors
$
通过 scrub 检查磁盘一致性
ZFS 理论上应该存在无法读取的损坏块,因此执行了 scrub 操作来进行一致性检查。
$ zpool scrub ztest
$ zpool status ztest
pool: ztest
state: ONLINE
scan: scrub in progress since Fri Dec 23 11:18:02 2022
3.62G scanned at 530M/s, 378M issued at 54.0M/s, 3.62G total
0B repaired, 10.18% done, 00:01:01 to go
config:
NAME STATE READ WRITE CKSUM
ztest ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/tt1 ONLINE 0 0 0
gpt/tt2 ONLINE 0 0 0
errors: No known data errors
经过一段时间后,确认 scrub 完成后的状态如下:
$ zpool status ztest
pool: ztest
state: ONLINE
status: One or more devices has experienced an unrecoverable error. An
attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace'.
see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-9P
scan: scrub repaired 15.8M in 00:01:06 with 0 errors on Fri Dec 23 11:19:08 2022
config:
NAME STATE READ WRITE CKSUM
ztest ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/tt1 ONLINE 0 0 130
gpt/tt2 ONLINE 0 0 0
errors: No known data errors
$ zpool create -O atime=off ztest mirror gpt/tt1 gpt/tt2
$ dd if=/dev/zero of=/ztest/dummy bs=1m
dd: /ztest/dummy: No space left on device
3711+0 records in
3710+1 records out
3891134464 bytes transferred in 153.170356 secs (25403966 bytes/sec)
$ zpool export ztest
$ dd if=/boot/kernel/kernel of=/dev/gpt/tt1 oseek=1000000
dd: /dev/gpt/tt1: Invalid argument
57311+1 records in
57311+0 records out
29343232 bytes transferred in 21.643263 secs (1355767 bytes/sec)
$ zpool import ztest
$ zpool scrub ztest
$ zpool status ztest
pool: ztest
state: ONLINE
status: One or more devices has experienced an unrecoverable error. An
attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace'.
see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-9P
scan: scrub repaired 27.9M in 00:01:06 with 0 errors on Mon Dec 26 10:55:49 2022
config:
NAME STATE READ WRITE CKSUM
ztest ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/tt1 ONLINE 0 0 227
gpt/tt2 ONLINE 0 0 0
errors: No known data errors
$ zpool export ztest
已经成功导出,因此现在物理上移除 da2 一侧,只使用 da1 一侧进行导入并尝试读取数据。
$ zpool import
pool: ztest
id: 11275383091719095959
state: DEGRADED
status: One or more devices are missing from the system.
action: The pool can be imported despite missing or damaged devices. The
fault tolerance of the pool may be compromised if imported.
see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
config:
ztest DEGRADED
mirror-0 DEGRADED
gpt/tt1 ONLINE
gpt/tt2 UNAVAIL cannot open
$ zpool import ztest
$ hd /ztest/dummy
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
e7ee0000
$ zpool export ztest
成功读取了损坏侧 da1 上的所有数据,完全没有问题。也就是说,通过 scrub 操作,数据被写回并得到了修复。而且实际在导入之后通过 status 确认,CKSUM 的值也确实是 0(可惜没来得及截图……)。
接下来,再次为已经导出的 ztest 连接上 da2,并尝试导入。
$ zpool import ztest
$ zpool status ztest
pool: ztest
state: ONLINE
scan: scrub repaired 27.9M in 00:01:06 with 0 errors on Mon Dec 26 10:55:49 2022
config:
NAME STATE READ WRITE CKSUM
ztest ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/tt1 ONLINE 0 0 0
gpt/tt2 ONLINE 0 0 0
errors: No known data errors
$