Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | # SPDX-License-Identifier: GPL-2.0-only |
| 3 | # Copyright (C) 2024 Linaro Ltd. |
| 4 | |
| 5 | # shellcheck disable=SC1091 |
| 6 | . ../../lib/sh-test-lib |
| 7 | OUTPUT="$(pwd)/output" |
| 8 | RESULT_FILE="${OUTPUT}/result.txt" |
| 9 | export RESULT_FILE |
| 10 | |
| 11 | MODULES_LIST="" |
| 12 | MODULES_SUBDIRS="" |
| 13 | MODULE_MODPROBE_NUMBER="1" |
Anders Roxell | 8aa8dbf | 2024-07-11 14:42:19 +0200 | [diff] [blame] | 14 | SKIPLIST="" |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 15 | SHARD_NUMBER=1 |
| 16 | SHARD_INDEX=1 |
Anders Roxell | 261c1ee | 2025-07-02 09:17:39 +0200 | [diff] [blame] | 17 | MEMORY_TOLERANCE=512 |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 18 | |
| 19 | usage() { |
| 20 | echo "Usage: $0 [-d <subdir of the modules directory> ] |
| 21 | [-l <space separated module list> ] |
| 22 | [-c <Number of load/unload of a module> ] |
| 23 | [-i <sharding bucket to run> ] |
| 24 | [-n <number of shard buckets to create> ] |
Anders Roxell | 8aa8dbf | 2024-07-11 14:42:19 +0200 | [diff] [blame] | 25 | [-s <skiplist modules to skip> ] |
Anders Roxell | 261c1ee | 2025-07-02 09:17:39 +0200 | [diff] [blame] | 26 | [-t <memory tolerance in KB for leak detection> ] |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 27 | [-h ]" 1>&2 |
| 28 | exit 0 |
| 29 | } |
| 30 | |
Anders Roxell | 261c1ee | 2025-07-02 09:17:39 +0200 | [diff] [blame] | 31 | while getopts "c:d:i:l:n:s:t:h" o; do |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 32 | case "$o" in |
| 33 | d) MODULES_SUBDIRS="${OPTARG}" ;; |
| 34 | l) MODULES_LIST="${OPTARG}" ;; |
| 35 | c) MODULE_MODPROBE_NUMBER="${OPTARG}" ;; |
| 36 | i) SHARD_INDEX="${OPTARG}" ;; |
| 37 | n) SHARD_NUMBER="${OPTARG}" ;; |
Anders Roxell | 8aa8dbf | 2024-07-11 14:42:19 +0200 | [diff] [blame] | 38 | s) SKIPLIST="${OPTARG}" ;; |
Anders Roxell | 261c1ee | 2025-07-02 09:17:39 +0200 | [diff] [blame] | 39 | t) MEMORY_TOLERANCE="${OPTARG}" ;; |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 40 | h|*) usage ;; |
| 41 | esac |
| 42 | done |
| 43 | |
Anders Roxell | cb19cb9 | 2025-06-06 00:25:27 +0200 | [diff] [blame] | 44 | get_mem_usage_kb() { |
| 45 | grep -i "MemAvailable:" /proc/meminfo | awk '{ print $2 }' |
| 46 | } |
| 47 | |
Anders Roxell | b856256 | 2025-07-02 09:06:40 +0200 | [diff] [blame] | 48 | check_module_memory_leaks_cumulative() { |
Anders Roxell | 9d498ad | 2025-07-02 09:07:09 +0200 | [diff] [blame^] | 49 | local module=$1 |
| 50 | local mem_start=$2 |
| 51 | local mem_end=$3 |
Anders Roxell | cb19cb9 | 2025-06-06 00:25:27 +0200 | [diff] [blame] | 52 | local diff_kb |
Anders Roxell | 9d498ad | 2025-07-02 09:07:09 +0200 | [diff] [blame^] | 53 | diff_kb=$((mem_start - mem_end)) |
| 54 | echo "memcheck cumulative: start ${mem_start}, end ${mem_end}, diff ${diff_kb}" |
Anders Roxell | 261c1ee | 2025-07-02 09:17:39 +0200 | [diff] [blame] | 55 | if [ "$diff_kb" -lt "-${MEMORY_TOLERANCE}" ]; then |
Anders Roxell | cb19cb9 | 2025-06-06 00:25:27 +0200 | [diff] [blame] | 56 | report_fail "memcheck_${module}" |
| 57 | else |
| 58 | report_pass "memcheck_${module}" |
| 59 | fi |
| 60 | } |
| 61 | |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 62 | get_modules_list() { |
| 63 | if [ -z "${MODULES_LIST}" ]; then |
Anders Roxell | 25fd951 | 2025-04-28 13:50:31 +0200 | [diff] [blame] | 64 | if [ -n "${MODULES_SUBDIRS}" ]; then |
| 65 | subdir=$(echo "${MODULES_SUBDIRS}" | tr ' ' '|') |
| 66 | grep -E "kernel/(${subdir})" /lib/modules/"$(uname -r)"/modules.order > /tmp/find_modules.txt |
| 67 | else |
| 68 | # No subdir given, default to all modules |
| 69 | cat /lib/modules/"$(uname -r)"/modules.order > /tmp/find_modules.txt |
| 70 | fi |
| 71 | |
| 72 | if [ -n "${SKIPLIST}" ]; then |
| 73 | skiplist=$(echo "${SKIPLIST}" | tr ' ' '|') |
| 74 | grep -E -v "(${skiplist})" /tmp/find_modules.txt > /tmp/modules_to_run.txt |
| 75 | else |
| 76 | cp /tmp/find_modules.txt /tmp/modules_to_run.txt |
| 77 | fi |
| 78 | |
Anders Roxell | 8aa8dbf | 2024-07-11 14:42:19 +0200 | [diff] [blame] | 79 | split --verbose --numeric-suffixes=1 -n l/"${SHARD_INDEX}"/"${SHARD_NUMBER}" /tmp/modules_to_run.txt > /tmp/shardfile |
Anders Roxell | bde4f2e | 2024-07-09 19:29:06 +0200 | [diff] [blame] | 80 | echo "============== Tests to run ===============" |
| 81 | cat /tmp/shardfile |
| 82 | echo "===========End Tests to run ===============" |
| 83 | if [ -s /tmp/shardfile ]; then |
| 84 | report_pass "shardfile" |
| 85 | else |
| 86 | report_fail "shardfile" |
| 87 | fi |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 88 | while IFS= read -r line |
| 89 | do |
| 90 | module_basename=$(basename "${line}") |
| 91 | module_name=${module_basename%.*} |
| 92 | MODULES_LIST="${MODULES_LIST} ${module_name}" |
| 93 | done < /tmp/shardfile |
| 94 | fi |
| 95 | } |
| 96 | |
| 97 | report() { |
| 98 | local _modprop_flag="${1}" |
| 99 | local _module="${2}" |
| 100 | local _text="${3}" |
| 101 | local _num="${4}" |
| 102 | echo |
| 103 | echo "${_text} module: ${_module}" |
| 104 | if ! modprobe "${_module}" "${_modprop_flag}"; then |
| 105 | report_fail "${_text}_module_${_num}_${_module}" |
| 106 | else |
| 107 | report_pass "${_text}_module_${_num}_${_module}" |
| 108 | fi |
| 109 | } |
| 110 | |
Anders Roxell | a7b173b | 2025-04-28 12:24:19 +0200 | [diff] [blame] | 111 | scan_dmesg_for_errors() { |
| 112 | echo "=== Scanning dmesg for errors ===" |
| 113 | dmesg -l 0,1,2,3,4,5 | grep -Ei "BUG:|WARNING:|Oops:|Call Trace:" && report_fail "dmesg_error_scan" || report_pass "dmesg_error_scan" |
| 114 | } |
| 115 | |
Anders Roxell | e6199bd | 2025-04-28 12:25:03 +0200 | [diff] [blame] | 116 | check_module_unloaded() { |
| 117 | local _module="$1" |
| 118 | if lsmod | grep "^${_module} " > /dev/null; then |
| 119 | echo "Module ${_module} still loaded after removal!" |
| 120 | report_fail "module_stuck_${_module}" |
| 121 | else |
| 122 | report_pass "module_unloaded_${_module}" |
| 123 | fi |
| 124 | } |
| 125 | |
Anders Roxell | ad114aa | 2025-04-28 12:25:26 +0200 | [diff] [blame] | 126 | kmemleak_scan() { |
| 127 | if [ -e /sys/kernel/debug/kmemleak ]; then |
| 128 | echo "Triggering kmemleak scan..." |
| 129 | echo scan > /sys/kernel/debug/kmemleak |
| 130 | sleep 5 |
| 131 | if grep -q . /sys/kernel/debug/kmemleak; then |
| 132 | echo "Potential memory leaks detected:" |
| 133 | cat /sys/kernel/debug/kmemleak |
| 134 | report_fail "kmemleak_detected" |
| 135 | else |
| 136 | report_pass "kmemleak_no_leaks" |
| 137 | fi |
| 138 | else |
| 139 | echo "kmemleak not available, skipping scan." |
| 140 | fi |
| 141 | } |
| 142 | |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 143 | run () { |
| 144 | for module in ${MODULES_LIST}; do |
| 145 | # don't insert/remove modules that is already inserted. |
| 146 | if ! lsmod | grep "^${module}"; then |
| 147 | for num in $(seq "${MODULE_MODPROBE_NUMBER}"); do |
| 148 | dmesg -C |
Anders Roxell | cb19cb9 | 2025-06-06 00:25:27 +0200 | [diff] [blame] | 149 | mem_before=$(get_mem_usage_kb) |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 150 | report "" "${module}" "insert" "${num}" |
| 151 | echo |
| 152 | echo "modinfo ${module}" |
| 153 | modinfo "${module}" |
Anders Roxell | a7b173b | 2025-04-28 12:24:19 +0200 | [diff] [blame] | 154 | scan_dmesg_for_errors |
| 155 | |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 156 | report "--remove" "${module}" "remove" "${num}" |
Anders Roxell | a7b173b | 2025-04-28 12:24:19 +0200 | [diff] [blame] | 157 | scan_dmesg_for_errors |
Anders Roxell | e6199bd | 2025-04-28 12:25:03 +0200 | [diff] [blame] | 158 | |
| 159 | check_module_unloaded "${module}" |
Anders Roxell | cb19cb9 | 2025-06-06 00:25:27 +0200 | [diff] [blame] | 160 | mem_after=$(get_mem_usage_kb) |
Anders Roxell | b856256 | 2025-07-02 09:06:40 +0200 | [diff] [blame] | 161 | check_module_memory_leaks_cumulative "$mem_before" "$mem_after" "$module" |
Anders Roxell | e3f51b8 | 2024-07-04 12:30:01 +0200 | [diff] [blame] | 162 | done |
| 163 | fi |
| 164 | done |
| 165 | } |
| 166 | |
| 167 | # Test run. |
| 168 | ! check_root && error_msg "This script must be run as root" |
| 169 | create_out_dir "${OUTPUT}" |
| 170 | info_msg "Output directory: ${OUTPUT}" |
| 171 | info_msg "About to run load/unload kernel modules ..." |
| 172 | get_modules_list |
| 173 | run |
Anders Roxell | ad114aa | 2025-04-28 12:25:26 +0200 | [diff] [blame] | 174 | kmemleak_scan |