1#!/bin/ksh -p 2# CDDL HEADER START 3# 4# The contents of this file are subject to the terms of the 5# Common Development and Distribution License (the "License"). 6# You may not use this file except in compliance with the License. 7# 8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9# or https://opensource.org/licenses/CDDL-1.0. 10# See the License for the specific language governing permissions 11# and limitations under the License. 12# 13# When distributing Covered Code, include this CDDL HEADER in each 14# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15# If applicable, add the following below this CDDL HEADER, with the 16# fields enclosed by brackets "[]" replaced with your own identifying 17# information: Portions Copyright [yyyy] [name of copyright owner] 18# 19# CDDL HEADER END 20# 21 22# 23# Copyright (c) 2018 by Lawrence Livermore National Security, LLC. 24# Copyright (c) 2020 by Delphix. All rights reserved. 25# 26 27# DESCRIPTION: 28# Verify that duplicate I/O ereport errors are not posted 29# 30# STRATEGY: 31# 1. Create a mirror pool 32# 2. Inject duplicate read/write IO errors and checksum errors 33# 3. Verify there are no duplicate events being posted 34# 35 36. $STF_SUITE/include/libtest.shlib 37 38verify_runnable "both" 39 40MOUNTDIR=$TEST_BASE_DIR/mount 41FILEPATH=$MOUNTDIR/badfile 42VDEV1=$TEST_BASE_DIR/vfile1 43VDEV2=$TEST_BASE_DIR/vfile2 44POOL=error_pool 45FILESIZE="10M" 46OLD_LEN_MAX=$(get_tunable ZEVENT_LEN_MAX) 47RETAIN_MAX=$(get_tunable ZEVENT_RETAIN_MAX) 48 49duplicates=false 50 51function cleanup 52{ 53 log_must set_tunable64 ZEVENT_LEN_MAX $OLD_LEN_MAX 54 55 log_must zinject -c all 56 if poolexists $POOL ; then 57 destroy_pool $POOL 58 fi 59 log_must rm -fd $VDEV1 $VDEV2 $MOUNTDIR 60} 61 62log_assert "Duplicate I/O ereport errors are not posted" 63log_note "zevent retain max setting: $RETAIN_MAX" 64 65log_onexit cleanup 66 67# Set our threshold high to avoid dropping events. 68set_tunable64 ZEVENT_LEN_MAX 20000 69 70log_must truncate -s $MINVDEVSIZE $VDEV1 $VDEV2 71log_must mkdir -p $MOUNTDIR 72 73# 74# $1: test type - corrupt (checksum error), io 75# $2: read, write 76function do_dup_test 77{ 78 ERR=$1 79 RW=$2 80 81 log_note "Testing $ERR $RW ereports" 82 log_must zpool create -f -m $MOUNTDIR -o failmode=continue $POOL mirror $VDEV1 $VDEV2 83 log_must zpool events -c 84 log_must zfs set compression=off $POOL 85 86 if [ "$RW" == "read" ] ; then 87 log_must mkfile $FILESIZE $FILEPATH 88 89 # unmount and mount filesystems to purge file from ARC 90 # to force reads to go through error inject handler 91 log_must zfs unmount $POOL 92 log_must zfs mount $POOL 93 94 # all reads from this file get an error 95 if [ "$ERR" == "corrupt" ] ; then 96 log_must zinject -a -t data -e checksum -T read $FILEPATH 97 else 98 log_must zinject -a -t data -e io -T read $FILEPATH 99 fi 100 101 # Read the file a few times to generate some 102 # duplicate errors of the same blocks 103 for _ in {1..15}; do 104 dd if=$FILEPATH of=/dev/null bs=128K 2>/dev/null 105 done 106 log_must zinject -c all 107 fi 108 109 log_must zinject -d $VDEV1 -e $ERR -T $RW -f 100 $POOL 110 111 if [ "$RW" == "write" ] ; then 112 log_must mkfile $FILESIZE $FILEPATH 113 sync_pool $POOL 114 fi 115 116 log_must zinject -c all 117 118 ereports="$(ereports | sort)" 119 actual=$(echo "$ereports" | wc -l) 120 unique=$(echo "$ereports" | uniq | wc -l) 121 log_note "$actual total $ERR $RW ereports where $unique were unique" 122 123 if [ $actual -gt $unique ] ; then 124 log_note "UNEXPECTED -- $((actual-unique)) duplicate $ERR $RW ereports" 125 echo "$ereports" 126 duplicates=true 127 fi 128 129 log_must zpool destroy $POOL 130} 131 132do_dup_test "corrupt" "read" 133do_dup_test "io" "read" 134do_dup_test "io" "write" 135 136if $duplicates; then 137 log_fail "FAILED -- Duplicate I/O ereport errors encountered" 138else 139 log_pass "Duplicate I/O ereport errors are not posted" 140fi 141