xref: /illumos-gate/usr/src/test/zfs-tests/tests/functional/trim/trim.kshlib (revision 5328fc53d11d7151861fa272e4fb0248b8f0e145)
1#!/bin/ksh -p
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11#
12
13#
14# Copyright (c) 2019 by Tim Chase. All rights reserved.
15# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
16# Copyright 2019 Joyent, Inc.
17#
18
19. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
20
21#
22# Get the actual on disk disk for the provided file.
23#
24function get_size_mb
25{
26	typeset rval=$(du -s "$1" | awk '{print $1}')
27	rval=$((rval * 2048))
28	echo -n "$rval"
29}
30
31#
32# Use mdb to get the approximate number of trim IOs issued for the pool.
33# This really is just used to ensure that trim IO has occured and is a
34# temporary solution until illumos supports zpool iostat histograms.
35#
36function get_illumos_trim_io
37{
38	typeset pool="${1-:$TESTPOOL}"
39	typeset spa
40	typeset vdevs
41	typeset total_trim
42	typeset v
43	typeset trimmed
44	typeset b
45
46	# Get vdevs for the pool
47	spa=$(mdb -ke '::spa' | awk -v pool=$pool '{if ($3 == pool) print $1}')
48	vdevs=$(mdb -ke "$spa::spa -v" | awk '{
49		if ($4 == "DESCRIPTION") {st=1; next}
50		if (st == 1) print $1
51	}')
52
53	# Get trim counts for each vdev
54	total_trim=0
55	for v in $vdevs
56	do
57		b=$(mdb -ke "$v::print vdev_t vdev_trim_bytes_done" | \
58		    awk '{print $3}')
59		trimmed=$(mdb -e "$b=E")
60		trimmed=$((trimmed / 4096))
61		total_trim=$((total_trim + trimmed))
62
63		b=$(mdb -ke "$v::print vdev_t vdev_autotrim_bytes_done" | \
64		    awk '{print $3}')
65		trimmed=$(mdb -e "$b=E")
66		trimmed=$((trimmed / 4096))
67		total_trim=$((total_trim + trimmed))
68	done
69	echo -n "$total_trim"
70}
71
72#
73# Get the number of trim IOs issued for the pool (ind or agg).
74#
75function get_trim_io
76{
77	typeset pool="${1-:$TESTPOOL}"
78	typeset type="${2-:ind}"
79	typeset rval
80
81	# Sum the ind or agg columns of the trim request size histogram.
82	case "$type" in
83	"ind")
84		rval=$(zpool iostat -pr $pool | awk \
85		    '$1 ~ /[0-9].*/ { sum += $12 } END { print sum }')
86		echo -n "$rval"
87		;;
88	"agg")
89		rval=$(zpool iostat -pr $pool | awk \
90		    '$1 ~ /[0-9].*/ { sum += $13 } END { print sum }')
91		echo -n "$rval"
92		;;
93	*)
94		log_fail "Type must be 'ind' or 'agg'"
95		;;
96	esac
97}
98
99#
100# Verify that trim IOs were send to devices in the pool.
101#
102function verify_trim_io
103{
104	typeset pool="${1:-$TESTPOOL}"
105	typeset type="${2:-ind}"
106	typeset min_trim_ios=${3:-100}
107	typeset ios
108
109	if is_linux; then
110		ios=$(get_trim_io $pool $type)
111	else
112		ios=$(get_illumos_trim_io $pool $type)
113	fi
114
115	if [[ $ios -ge $min_trim_ios ]]; then
116		log_note "Issued $ios $type trim IOs for pool $pool"
117	else
118		log_fail "Too few trim IOs issued $ios/$min_trim_ios"
119	fi
120}
121
122#
123# Run N txgs which should be enough to trim the entire pool.
124#
125function wait_trim_io # pool type txgs
126{
127	typeset pool="${1-:$TESTPOOL}"
128	typeset type="${2-:ind}"
129	typeset txgs=${3:-10}
130	typeset timeout=120
131	typeset stop_time=$(( $(date +%s) + $timeout ))
132
133	typeset -i i=0
134	while [[ $i -lt $txgs ]]; do
135		if [ "$(date +%s)" -ge $stop_time ]; then
136			log_fail "Exceeded trim time limit of ${timeout}s"
137			return
138		fi
139
140		zpool sync -f
141		((i = i + 1))
142	done
143
144	typeset ios=$(get_trim_io $pool $type)
145	log_note "Waited for $txgs txgs, $ios $type TRIM IOs"
146}
147
148#
149# Verify that file vdevs against a target value.
150#
151function verify_vdevs # op size vdevs
152{
153	typeset tgt_op=$1
154	typeset tgt_size=$2
155	shift 2
156	typeset vdevs=$@
157
158	for vdev in $vdevs; do
159		typeset size=$(get_size_mb $vdev)
160		if test $size $tgt_op $tgt_size; then
161			log_note "Success $vdev is $size MB which is $tgt_op" \
162			    "than $tgt_size MB"
163		else
164			log_fail "Failure $vdev is $size MB which is not" \
165			    "$tgt_op than $tgt_size MB"
166		fi
167	done
168}
169
170#
171# Wait for up to 120 seconds for trimming of the listed vdevs to complete.
172#
173function wait_trim # pool vdevs
174{
175	typeset stop_time=$(( $(date +%s) + 120 ))
176	typeset pool="$1"
177	shift
178	typeset vdevs=$@
179	typeset complete
180
181	while [[ $complete -eq 0 ]]; do
182		complete=1
183
184		for vdev in $vdevs; do
185			if [[ "$(trim_progress $pool $vdev)" -lt "100" ]]; then
186				complete=0
187				break
188			else
189				log_must eval "trim_prog_line $pool $vdev | \
190				    grep complete"
191			fi
192		done
193
194		if [ "$(date +%s)" -ge $stop_time ]; then
195			log_fail "Exceeded trim time limit of 120s"
196		fi
197
198		sleep 0.5
199	done
200
201	log_note "Pool completed trim successfully."
202}
203