1#!/bin/ksh -p
2
3#
4# CDDL HEADER START
5#
6# This file and its contents are supplied under the terms of the
7# Common Development and Distribution License ("CDDL"), version 1.0.
8# You may only use this file in accordance with the terms of version
9# 1.0 of the CDDL.
10#
11# A full copy of the text of the CDDL should have accompanied this
12# source.  A copy of the CDDL is also available via the Internet at
13# http://www.illumos.org/license/CDDL.
14#
15# CDDL HEADER END
16#
17
18#
19# Copyright (c) 2020, Datto Inc. All rights reserved.
20#
21
22. $STF_SUITE/include/libtest.shlib
23. $STF_SUITE/tests/functional/replacement/replacement.cfg
24
25#
26# DESCRIPTION:
27# Testing resilver completes when scan errors are encountered, but relevant
28# DTL's have not been lost.
29#
30# STRATEGY:
31# 1. Create a pool (1k recordsize)
32# 2. Create a 32m file (32k records)
33# 3. Inject an error halfway through the file
34# 4. Start a resilver, ensure the error is triggered and that the resilver
35#    does not restart after finishing
36#
37# NB: use legacy scanning to ensure scan of specific block causes error
38#
39
40function cleanup
41{
42	log_must zinject -c all
43	destroy_pool $TESTPOOL1
44	rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE
45	log_must set_tunable32 SCAN_LEGACY $ORIG_SCAN_LEGACY
46}
47
48log_assert "Check for resilver restarts caused by scan errors"
49
50ORIG_SCAN_LEGACY=$(get_tunable SCAN_LEGACY)
51
52log_onexit cleanup
53
54# use legacy scan to ensure injected error will be triggered
55log_must set_tunable32 SCAN_LEGACY 1
56
57 # create the pool and a 32M file (32k blocks)
58log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[0]} $SPARE_VDEV_FILE
59log_must zpool create -f -O recordsize=1k $TESTPOOL1 ${VDEV_FILES[0]}
60log_must eval "dd if=/dev/urandom of=/$TESTPOOL1/file bs=1M count=32 2>/dev/null"
61
62# determine objset/object
63objset=$(zdb -d $TESTPOOL1/ | sed -ne 's/.*ID \([0-9]*\).*/\1/p')
64object=$(ls -i /$TESTPOOL1/file | awk '{print $1}')
65
66# inject event to cause error during resilver
67log_must zinject -b $(printf "%x:%x:0:3fff" $objset $object) $TESTPOOL1
68
69# clear events and start resilver
70log_must zpool events -c
71log_must zpool attach $TESTPOOL1 ${VDEV_FILES[0]} $SPARE_VDEV_FILE
72
73log_note "waiting for read errors to start showing up"
74for iter in {0..59}
75do
76	sync_pool $TESTPOOL1
77	err=$(zpool status $TESTPOOL1 | awk -v dev=${VDEV_FILES[0]} '$0 ~ dev {print $3}')
78	(( $err > 0 )) && break
79	sleep 1
80done
81
82(( $err == 0 )) && log_fail "Unable to induce errors in resilver"
83
84log_note "waiting for resilver to finish"
85for iter in {0..59}
86do
87	finish=$(zpool events | grep -cF "sysevent.fs.zfs.resilver_finish")
88	(( $finish > 0 )) && break
89	sleep 1
90done
91
92(( $finish == 0 )) && log_fail "resilver took too long to finish"
93
94# wait a few syncs to ensure that zfs does not restart the resilver
95sync_pool $TESTPOOL1
96sync_pool $TESTPOOL1
97
98# check if resilver was restarted
99start=$(zpool events | grep -cF "sysevent.fs.zfs.resilver_start")
100(( $start != 1 )) && log_fail "resilver restarted unnecessarily"
101
102log_pass "Resilver did not restart unnecessarily from scan errors"
103