#!/bin/ksh -p # # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright (c) 2019 by Tim Chase. All rights reserved. # Copyright (c) 2019 Lawrence Livermore National Security, LLC. # Copyright 2019 Joyent, Inc. # . $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib # # Get the actual on disk disk for the provided file. # function get_size_mb { typeset rval=$(du -s "$1" | awk '{print $1}') rval=$((rval * 2048)) echo -n "$rval" } # # Use mdb to get the approximate number of trim IOs issued for the pool. # This really is just used to ensure that trim IO has occured and is a # temporary solution until illumos supports zpool iostat histograms. # function get_illumos_trim_io { typeset pool="${1-:$TESTPOOL}" typeset spa typeset vdevs typeset total_trim typeset v typeset trimmed typeset b # Get vdevs for the pool spa=$(mdb -ke '::spa' | awk -v pool=$pool '{if ($3 == pool) print $1}') vdevs=$(mdb -ke "$spa::spa -v" | awk '{ if ($4 == "DESCRIPTION") {st=1; next} if (st == 1) print $1 }') # Get trim counts for each vdev total_trim=0 for v in $vdevs do b=$(mdb -ke "$v::print vdev_t vdev_trim_bytes_done" | \ awk '{print $3}') trimmed=$(mdb -e "$b=E") trimmed=$((trimmed / 4096)) total_trim=$((total_trim + trimmed)) b=$(mdb -ke "$v::print vdev_t vdev_autotrim_bytes_done" | \ awk '{print $3}') trimmed=$(mdb -e "$b=E") trimmed=$((trimmed / 4096)) total_trim=$((total_trim + trimmed)) done echo -n "$total_trim" } # # Get the number of trim IOs issued for the pool (ind or agg). # function get_trim_io { typeset pool="${1-:$TESTPOOL}" typeset type="${2-:ind}" typeset rval # Sum the ind or agg columns of the trim request size histogram. case "$type" in "ind") rval=$(zpool iostat -pr $pool | awk \ '$1 ~ /[0-9].*/ { sum += $12 } END { print sum }') echo -n "$rval" ;; "agg") rval=$(zpool iostat -pr $pool | awk \ '$1 ~ /[0-9].*/ { sum += $13 } END { print sum }') echo -n "$rval" ;; *) log_fail "Type must be 'ind' or 'agg'" ;; esac } # # Verify that trim IOs were send to devices in the pool. # function verify_trim_io { typeset pool="${1:-$TESTPOOL}" typeset type="${2:-ind}" typeset min_trim_ios=${3:-100} typeset ios if is_linux; then ios=$(get_trim_io $pool $type) else ios=$(get_illumos_trim_io $pool $type) fi if [[ $ios -ge $min_trim_ios ]]; then log_note "Issued $ios $type trim IOs for pool $pool" else log_fail "Too few trim IOs issued $ios/$min_trim_ios" fi } # # Run N txgs which should be enough to trim the entire pool. # function wait_trim_io # pool type txgs { typeset pool="${1-:$TESTPOOL}" typeset type="${2-:ind}" typeset txgs=${3:-10} typeset timeout=120 typeset stop_time=$(( $(date +%s) + $timeout )) typeset -i i=0 while [[ $i -lt $txgs ]]; do if [ "$(date +%s)" -ge $stop_time ]; then log_fail "Exceeded trim time limit of ${timeout}s" return fi zpool sync -f ((i = i + 1)) done typeset ios=$(get_trim_io $pool $type) log_note "Waited for $txgs txgs, $ios $type TRIM IOs" } # # Verify that file vdevs against a target value. # function verify_vdevs # op size vdevs { typeset tgt_op=$1 typeset tgt_size=$2 shift 2 typeset vdevs=$@ for vdev in $vdevs; do typeset size=$(get_size_mb $vdev) if test $size $tgt_op $tgt_size; then log_note "Success $vdev is $size MB which is $tgt_op" \ "than $tgt_size MB" else log_fail "Failure $vdev is $size MB which is not" \ "$tgt_op than $tgt_size MB" fi done } # # Wait for up to 120 seconds for trimming of the listed vdevs to complete. # function wait_trim # pool vdevs { typeset stop_time=$(( $(date +%s) + 120 )) typeset pool="$1" shift typeset vdevs=$@ typeset complete while [[ $complete -eq 0 ]]; do complete=1 for vdev in $vdevs; do if [[ "$(trim_progress $pool $vdev)" -lt "100" ]]; then complete=0 break else log_must eval "trim_prog_line $pool $vdev | \ grep complete" fi done if [ "$(date +%s)" -ge $stop_time ]; then log_fail "Exceeded trim time limit of 120s" fi sleep 0.5 done log_note "Pool completed trim successfully." }