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/resilver/resilver.cfg 24 25SYSEVENT=$STF_SUITE/tests/functional/resilver/sysevent 26 27# 28# DESCRIPTION: 29# Testing resilver completes when scan errors are encountered, but relevant 30# DTL's have not been lost. 31# 32# STRATEGY: 33# 1. Create a pool (1k recordsize) 34# 2. Create a 32m file (32k records) 35# 3. Inject an error halfway through the file 36# 4. Start a resilver, ensure the error is triggered and that the resilver 37# does not restart after finishing 38# 39# NB: use legacy scanning to ensure scan of specific block causes error 40# 41 42function cleanup 43{ 44 log_must zinject -c all 45 destroy_pool $TESTPOOL 46 rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE 47 log_must set_tunable32 zfs_scan_legacy $ORIG_SCAN_LEGACY 48 [[ -n "$EVTPID" ]] && kill "$EVTPID" 49 [[ -n "$EVTFILE" ]] && rm -f "$EVTFILE" 50} 51 52log_assert "Check for resilver restarts caused by scan errors" 53 54ORIG_SCAN_LEGACY=$(get_tunable zfs_scan_legacy) 55 56log_onexit cleanup 57 58# use legacy scan to ensure injected error will be triggered 59log_must set_tunable32 zfs_scan_legacy 1 60 61 # create the pool and a 32M file (32k blocks) 62log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[0]} $SPARE_VDEV_FILE 63log_must zpool create -f -O recordsize=1k $TESTPOOL ${VDEV_FILES[0]} 64log_must dd if=/dev/urandom of=/$TESTPOOL/file bs=1M count=32 > /dev/null 2>&1 65 66# determine objset/object 67objset=$(zdb -d $TESTPOOL/ | sed -ne 's/.*ID \([0-9]*\).*/\1/p') 68object=$(ls -i /$TESTPOOL/file | awk '{print $1}') 69 70# inject event to cause error during resilver 71log_must zinject -b `printf "%x:%x:0:3fff" $objset $object` $TESTPOOL 72 73 74EVTFILE=$(mktemp /tmp/resilver_events.XXXXXX) 75EVTPID=$($SYSEVENT -o $EVTFILE ESC_ZFS_resilver_start ESC_ZFS_resilver_finish) 76log_must test -n "$EVTPID" 77 78# start resilver 79log_must zpool attach $TESTPOOL ${VDEV_FILES[0]} $SPARE_VDEV_FILE 80 81log_note "waiting for read errors to start showing up" 82for iter in {0..59} 83do 84 zpool sync $TESTPOOL 85 err=$(zpool status $TESTPOOL | grep ${VDEV_FILES[0]} | awk '{print $3}') 86 (( $err > 0 )) && break 87 sleep 1 88done 89 90(( $err == 0 )) && log_fail "Unable to induce errors in resilver" 91 92log_note "waiting for resilver to finish" 93for iter in {0..59} 94do 95 finish=$(grep "ESC_ZFS_resilver_finish" $EVTFILE | wc -l) 96 (( $finish > 0 )) && break 97 sleep 1 98done 99 100(( $finish == 0 )) && log_fail "resilver took too long to finish" 101 102# wait a few syncs to ensure that zfs does not restart the resilver 103log_must zpool sync $TESTPOOL 104log_must zpool sync $TESTPOOL 105 106# check if resilver was restarted 107start=$(grep "ESC_ZFS_resilver_start" $EVTFILE | wc -l) 108(( $start != 1 )) && log_fail "resilver restarted unnecessarily" 109 110log_pass "Resilver did not restart unnecessarily from scan errors" 111