Debug and usage output
This commit is contained in:
parent
beb6320df8
commit
45a7b4d491
244
cachestats.sh
244
cachestats.sh
@ -5,50 +5,63 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# Copyright 2023 Forza <forza@tnonline.net>
|
||||
|
||||
device_name="$1"
|
||||
|
||||
# Declare an associative array to store key-value pairs
|
||||
declare -A data
|
||||
declare -i sizess
|
||||
# cacheatats usage
|
||||
usage() {
|
||||
echo "Usage: $(basename "${0}") [DEVICE_NAME or PATH] [DEVICE_NAME or PATH] ..."
|
||||
echo " -h, --help Display this help message"
|
||||
}
|
||||
|
||||
# Check for help option or no arguments
|
||||
if [ "$#" -eq 0 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [ "${1:0:1}" == "-" ]; then
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Declare used variables
|
||||
declare -A data # associative array
|
||||
declare -a dmstatus # indexed array
|
||||
declare -i sizess # integer variable
|
||||
declare status_output
|
||||
declare -a dmstatus
|
||||
declare device_name_or_path
|
||||
declare device_name
|
||||
|
||||
# Function to convert bytes to IEC units
|
||||
to_iec() {
|
||||
local bytes kib mib gib tib
|
||||
local -i bytes kib mib gib tib # integers
|
||||
bytes=$1
|
||||
kib=$(( (bytes + 512) / 1024 ))
|
||||
mib=$(( (kib + 512) / 1024 ))
|
||||
gib=$(( (mib + 512) / 1024 ))
|
||||
tib=$(( (gib + 512) / 1024 ))
|
||||
mib=$(( (kib + 512) / 1024 ))
|
||||
gib=$(( (mib + 512) / 1024 ))
|
||||
tib=$(( (gib + 512) / 1024 ))
|
||||
if [ $tib -gt 0 ]; then
|
||||
echo "${tib} TiB"
|
||||
echo "$tib TiB"
|
||||
elif [ $gib -gt 0 ]; then
|
||||
echo "${gib} GiB"
|
||||
echo "$gib GiB"
|
||||
elif [ $mib -gt 0 ]; then
|
||||
echo "${mib} MiB"
|
||||
echo "$mib MiB"
|
||||
elif [ $kib -gt 0 ]; then
|
||||
echo "${kib} KiB"
|
||||
echo "$kib KiB"
|
||||
else
|
||||
echo "${bytes} bytes"
|
||||
echo "$bytes bytes"
|
||||
fi
|
||||
}
|
||||
debug_output(){
|
||||
# DEBUG info
|
||||
|
||||
# Get the status output using dmsetup
|
||||
status_output=$(dmsetup status "$device_name" 2>/dev/null)
|
||||
|
||||
# Check if the device exists and has valid output
|
||||
if [ -n "$status_output" ]; then
|
||||
sizess=$(blockdev --getss "/dev/mapper/${device_name}")
|
||||
|
||||
# Parse the status information into the associative array
|
||||
IFS='/: ' read -r -a dmstatus <<< "$status_output"
|
||||
|
||||
## Ouput `dmsetup status` raw data:
|
||||
# for ((i = 0; i < ${#dmstatus[@]}; i += 1)); do
|
||||
# echo \# $i: ${dmstatus["$i"]}
|
||||
# done
|
||||
|
||||
# Field order of `dmsetup status <cachedev>`:
|
||||
# https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/cache.html
|
||||
#
|
||||
@ -59,77 +72,112 @@ if [ -n "$status_output" ]; then
|
||||
# <#core args> <core args>* <policy name> <#policy args> <policy args>*
|
||||
# <cache metadata mode>
|
||||
|
||||
data["name"]="$device_name"
|
||||
data["origin_start"]=$(( ${dmstatus[0]} * $sizess )) # in sectors
|
||||
data["origin_length"]=$(( ${dmstatus[1]} * $sizess )) # in sectors
|
||||
data["table_type"]="${dmstatus[2]}"
|
||||
data["metadata_block_size"]=$(( ${dmstatus[3]} * $sizess )) # in sectors
|
||||
data["used_metadata_blocks"]="${dmstatus[4]}"
|
||||
data["total_metadata_blocks"]="${dmstatus[5]}"
|
||||
data["cache_block_size"]=$(( ${dmstatus[6]} * $sizess )) # in sectors
|
||||
data["used_cache_blocks"]="${dmstatus[7]}"
|
||||
data["total_cache_blocks"]="${dmstatus[8]}"
|
||||
data["read_hits"]="${dmstatus[9]}"
|
||||
data["read_misses"]="${dmstatus[10]}"
|
||||
data["write_hits"]="${dmstatus[11]}"
|
||||
data["write_misses"]="${dmstatus[12]}"
|
||||
data["demotions"]="${dmstatus[13]}"
|
||||
data["promotions"]="${dmstatus[14]}"
|
||||
data["dirty_cache"]=$(( ${dmstatus[15]} * ${data[cache_block_size]} ))
|
||||
if [ "${dmstatus[16]}" = 2 ]; then
|
||||
data["cache_type"]="${dmstatus[17]}"
|
||||
data["discard_passdown"]="${dmstatus[18]}"
|
||||
data["migration_threshold"]=$(( ${dmstatus[21]} * $sizess ))
|
||||
data["cache_policy"]="${dmstatus[22]}"
|
||||
data["smq_count"]="${dmstatus[23]}"
|
||||
data["cache_rw"]="${dmstatus[24]}"
|
||||
data["status"]="${dmstatus[25]//-/OK}"
|
||||
else
|
||||
data["cache_type"]="${dmstatus[17]}"
|
||||
data["discard_passdown"]="true"
|
||||
data["migration_threshold"]=$(( ${dmstatus[20]} * $sizess ))
|
||||
data["cache_policy"]="${dmstatus[21]}"
|
||||
data["smq_count"]="${dmstatus[22]}"
|
||||
data["cache_rw"]="${dmstatus[23]}"
|
||||
data["status"]="${dmstatus[24]//-/OK}"
|
||||
# Loop through throuh all fields to list and print their values
|
||||
if (( DEBUG > 0 )) ; then
|
||||
printf "\nDEBUG INFO\n"
|
||||
printf "========\n"
|
||||
printf "dmstatus index: value\n"
|
||||
## Ouput `dmsetup status` raw data:
|
||||
for ((i = 0; i < ${#dmstatus[@]}; i += 1)); do
|
||||
echo "# $i: ${dmstatus[$i]}"
|
||||
done
|
||||
printf "\nidentified values:\n"
|
||||
printf "========\n"
|
||||
for field in "${!data[@]}"; do
|
||||
value="${data[$field]}"
|
||||
if [ -n "$value" ]; then
|
||||
echo "$field : $value"
|
||||
else
|
||||
echo "Field '$field' not found."
|
||||
fi
|
||||
done | sort
|
||||
printf "========\n"
|
||||
fi
|
||||
}
|
||||
|
||||
# Loop through throuh all fields to list and print their values
|
||||
# for field in "${!data[@]}"; do
|
||||
# value="${data[$field]}"
|
||||
# if [ -n "$value" ]; then
|
||||
# echo "$field : $value"
|
||||
# else
|
||||
# echo "Field '$field' not found."
|
||||
# fi
|
||||
# done |sort
|
||||
# Loop through all devices and print their info
|
||||
for device_name_or_path in "${@}"; do
|
||||
|
||||
# Output defined fields
|
||||
printf "DEVICE\n"
|
||||
printf "========\n"
|
||||
printf "%-*s%s\n" "26" "Device-mapper name: " "/dev/mapper/${data[name]}"
|
||||
printf "%-*s%s\n" "26" "Origin size: " "$(to_iec $(( ${data[origin_length]} - ${data[origin_start]} )) )"
|
||||
printf "%-*s%s\n" "26" "Discards: " "${data[discard_passdown]}"
|
||||
# Strip path part from device name
|
||||
device_name=$(basename "${device_name_or_path}")
|
||||
|
||||
printf "\n"
|
||||
printf "CACHE\n"
|
||||
printf "========\n"
|
||||
printf "%-*s%s\n" "26" "Size / Usage: " "$(to_iec $((${data[total_cache_blocks]} * ${data[cache_block_size]}))) / $(to_iec $(( ${data[used_cache_blocks]} * ${data[cache_block_size]} ))) ($(( 100 * ${data[used_cache_blocks]} / ${data[total_cache_blocks]} )) %)"
|
||||
printf "%-*s%s\n" "26" "Read Hit Rate: " "${data[read_hits]} / $((${data[read_misses]} + ${data[read_hits]})) ($(( 100 * ${data[read_hits]} / (${data[read_hits]} + ${data[read_misses]}) )) %)"
|
||||
printf "%-*s%s\n" "26" "Write Hit Rate: " "${data[write_hits]} / $((${data[write_misses]} + ${data[write_hits]})) ($(( 100 * ${data[write_hits]} / (${data[write_hits]} + ${data[write_misses]}) )) %)"
|
||||
printf "%-*s%s\n" "26" "Dirty: " "$(to_iec ${data[dirty_cache]})"
|
||||
printf "%-*s%s\n" "26" "Block Size: " "$(to_iec ${data[cache_block_size]})"
|
||||
printf "%-*s%s\n" "26" "Promotions / Demotions: " "${data[promotions]} / ${data[demotions]}"
|
||||
printf "%-*s%s\n" "26" "Migration Threshold: " "$(to_iec ${data[migration_threshold]})"
|
||||
printf "%-*s%s\n" "26" "Read-Write mode: " "${data[cache_rw]}"
|
||||
printf "%-*s%s\n" "26" "Type: " "${data[cache_type]}"
|
||||
printf "%-*s%s\n" "26" "Policy: " "${data[cache_policy]}"
|
||||
printf "%-*s%s\n" "26" "Status: " "${data[status]}"
|
||||
# Get the status output using dmsetup
|
||||
status_output=$(dmsetup status "${device_name}" 2>/dev/null)
|
||||
|
||||
printf "\n"
|
||||
printf "METADATA\n"
|
||||
printf "========\n"
|
||||
printf "%-*s%s\n" "26" "Size / Usage: " "$(to_iec $(( ${data[total_metadata_blocks]} * ${data[metadata_block_size]} ))) / $(to_iec $(( ${data[used_metadata_blocks]} * ${data[metadata_block_size]} ))) ($(( 100 * ${data[used_metadata_blocks]} / ${data[total_metadata_blocks]} )) %)"
|
||||
else
|
||||
echo "Device not found or no valid status output."
|
||||
fi
|
||||
# Check if the device exists and has valid output
|
||||
if [ -n "$status_output" ]; then
|
||||
# Check device block size
|
||||
sizess=$(blockdev --getss "/dev/mapper/${device_name}")
|
||||
|
||||
# Parse the dmstatus information into the associative array
|
||||
IFS='/: ' read -r -a dmstatus <<< "${status_output}"
|
||||
|
||||
# Populate the data array
|
||||
data["name"]="$device_name"
|
||||
data["origin_start"]=$(( dmstatus[0] * sizess )) # in sectors
|
||||
data["origin_length"]=$(( dmstatus[1] * sizess )) # in sectors
|
||||
data["table_type"]="${dmstatus[2]}"
|
||||
data["metadata_block_size"]=$(( dmstatus[3] * sizess )) # in sectors
|
||||
data["used_metadata_blocks"]="${dmstatus[4]}"
|
||||
data["total_metadata_blocks"]="${dmstatus[5]}"
|
||||
data["cache_block_size"]=$(( dmstatus[6] * sizess )) # in sectors
|
||||
data["used_cache_blocks"]="${dmstatus[7]}"
|
||||
data["total_cache_blocks"]="${dmstatus[8]}"
|
||||
data["read_hits"]="${dmstatus[9]}"
|
||||
data["read_misses"]="${dmstatus[10]}"
|
||||
data["write_hits"]="${dmstatus[11]}"
|
||||
data["write_misses"]="${dmstatus[12]}"
|
||||
data["demotions"]="${dmstatus[13]}"
|
||||
data["promotions"]="${dmstatus[14]}"
|
||||
data["dirty_cache"]=$(( dmstatus[15] * data[cache_block_size] ))
|
||||
if [ "${dmstatus[16]}" = 2 ]; then
|
||||
data["cache_type"]="${dmstatus[17]}"
|
||||
data["discard_passdown"]="${dmstatus[18]}"
|
||||
data["migration_threshold"]=$(( dmstatus[21] * sizess ))
|
||||
data["cache_policy"]="${dmstatus[22]}"
|
||||
data["smq_count"]="${dmstatus[23]}"
|
||||
data["cache_rw"]="${dmstatus[24]}"
|
||||
data["status"]="${dmstatus[25]//-/OK}"
|
||||
else
|
||||
data["cache_type"]="${dmstatus[17]}"
|
||||
data["discard_passdown"]="true"
|
||||
data["migration_threshold"]=$(( dmstatus[20] * sizess ))
|
||||
data["cache_policy"]="${dmstatus[21]}"
|
||||
data["smq_count"]="${dmstatus[22]}"
|
||||
data["cache_rw"]="${dmstatus[23]}"
|
||||
data["status"]="${dmstatus[24]//-/OK}"
|
||||
fi
|
||||
|
||||
# Print debug information
|
||||
debug_output
|
||||
|
||||
# Print dm-cache data
|
||||
printf "\nDEVICE\n"
|
||||
printf "========\n"
|
||||
printf "%-*s%s\n" "26" "Device-mapper name: " "/dev/mapper/${data[name]}"
|
||||
printf "%-*s%s\n" "26" "Origin size: " "$(to_iec $(( data[origin_length] - data[origin_start] )) )"
|
||||
printf "%-*s%s\n" "26" "Discards: " "${data[discard_passdown]}"
|
||||
|
||||
printf "\n"
|
||||
printf "CACHE\n"
|
||||
printf "========\n"
|
||||
printf "%-*s%s\n" "26" "Size / Usage: " "$(to_iec $(( data[total_cache_blocks] * data[cache_block_size] ))) / $(to_iec $(( data[used_cache_blocks] * data[cache_block_size] ))) ($(( 100 * data[used_cache_blocks] / data[total_cache_blocks] )) %)"
|
||||
printf "%-*s%s\n" "26" "Read Hit Rate: " "${data[read_hits]} / $(( data[read_misses] + data[read_hits] )) ($(( 100 * data[read_hits] / (data[read_hits] + data[read_misses] ) )) %)"
|
||||
printf "%-*s%s\n" "26" "Write Hit Rate: " "${data[write_hits]} / $(( data[write_misses] + data[write_hits] )) ($(( 100 * data[write_hits] / ( data[write_hits] + data[write_misses] ) )) %)"
|
||||
printf "%-*s%s\n" "26" "Dirty: " "$(to_iec "${data[dirty_cache]}")"
|
||||
printf "%-*s%s\n" "26" "Block Size: " "$(to_iec "${data[cache_block_size]}")"
|
||||
printf "%-*s%s\n" "26" "Promotions / Demotions: " "${data[promotions]} / ${data[demotions]}"
|
||||
printf "%-*s%s\n" "26" "Migration Threshold: " "$(to_iec "${data[migration_threshold]}")"
|
||||
printf "%-*s%s\n" "26" "Read-Write mode: " "${data[cache_rw]}"
|
||||
printf "%-*s%s\n" "26" "Type: " "${data[cache_type]}"
|
||||
printf "%-*s%s\n" "26" "Policy: " "${data[cache_policy]}"
|
||||
printf "%-*s%s\n" "26" "Status: " "${data[status]}"
|
||||
|
||||
printf "\n"
|
||||
printf "METADATA\n"
|
||||
printf "========\n"
|
||||
printf "%-*s%s\n" "26" "Size / Usage: " "$(to_iec $(( data[total_metadata_blocks] * data[metadata_block_size] ))) / $(to_iec $(( data[used_metadata_blocks] * data[metadata_block_size] ))) ($(( 100 * data[used_metadata_blocks] / data[total_metadata_blocks] )) %)"
|
||||
else
|
||||
echo "Device not found or no valid status output."
|
||||
fi
|
||||
done
|
||||
|
Loading…
Reference in New Issue
Block a user