1#!/bin/sh 2# 3# A simple script to load/unload the ZFS module stack. 4# 5 6BASE_DIR=$(dirname "$0") 7SCRIPT_COMMON=common.sh 8if [ -f "${BASE_DIR}/${SCRIPT_COMMON}" ]; then 9 . "${BASE_DIR}/${SCRIPT_COMMON}" 10else 11 echo "Missing helper script ${SCRIPT_COMMON}" && exit 1 12fi 13 14PROG=zfs.sh 15VERBOSE="no" 16UNLOAD="no" 17LOAD="yes" 18STACK_TRACER="no" 19 20ZED_PIDFILE=${ZED_PIDFILE:-/var/run/zed.pid} 21LDMOD=${LDMOD:-/sbin/modprobe} 22 23KMOD_ZLIB_DEFLATE=${KMOD_ZLIB_DEFLATE:-zlib_deflate} 24KMOD_ZLIB_INFLATE=${KMOD_ZLIB_INFLATE:-zlib_inflate} 25KMOD_SPL=${KMOD_SPL:-spl} 26KMOD_ZAVL=${KMOD_ZAVL:-zavl} 27KMOD_ZNVPAIR=${KMOD_ZNVPAIR:-znvpair} 28KMOD_ZUNICODE=${KMOD_ZUNICODE:-zunicode} 29KMOD_ZCOMMON=${KMOD_ZCOMMON:-zcommon} 30KMOD_ZLUA=${KMOD_ZLUA:-zlua} 31KMOD_ICP=${KMOD_ICP:-icp} 32KMOD_ZFS=${KMOD_ZFS:-zfs} 33KMOD_FREEBSD=${KMOD_FREEBSD:-openzfs} 34KMOD_ZZSTD=${KMOD_ZZSTD:-zzstd} 35 36 37usage() { 38cat << EOF 39USAGE: 40$0 [hvudS] [module-options] 41 42DESCRIPTION: 43 Load/unload the ZFS module stack. 44 45OPTIONS: 46 -h Show this message 47 -v Verbose 48 -r Reload modules 49 -u Unload modules 50 -S Enable kernel stack tracer 51EOF 52} 53 54while getopts 'hvruS' OPTION; do 55 case $OPTION in 56 h) 57 usage 58 exit 1 59 ;; 60 v) 61 VERBOSE="yes" 62 ;; 63 r) 64 UNLOAD="yes" 65 LOAD="yes" 66 ;; 67 u) 68 UNLOAD="yes" 69 LOAD="no" 70 ;; 71 S) 72 STACK_TRACER="yes" 73 ;; 74 ?) 75 usage 76 exit 77 ;; 78 esac 79done 80 81kill_zed() { 82 if [ -f "$ZED_PIDFILE" ]; then 83 PID=$(cat "$ZED_PIDFILE") 84 kill "$PID" 85 fi 86} 87 88check_modules_linux() { 89 LOADED_MODULES="" 90 MISSING_MODULES="" 91 92 for KMOD in $KMOD_SPL $KMOD_ZAVL $KMOD_ZNVPAIR $KMOD_ZUNICODE $KMOD_ZCOMMON \ 93 $KMOD_ZLUA $KMOD_ZZSTD $KMOD_ICP $KMOD_ZFS; do 94 NAME=$(basename "$KMOD" .ko) 95 96 if lsmod | grep -E -q "^${NAME}"; then 97 LOADED_MODULES="$LOADED_MODULES\t$NAME\n" 98 fi 99 100 if ! modinfo "$KMOD" >/dev/null 2>&1; then 101 MISSING_MODULES="$MISSING_MODULES\t${KMOD}\n" 102 fi 103 done 104 105 if [ -n "$LOADED_MODULES" ]; then 106 printf "Unload the kernel modules by running '%s -u':\n" "$PROG" 107 printf "%b" "$LOADED_MODULES" 108 exit 1 109 fi 110 111 if [ -n "$MISSING_MODULES" ]; then 112 printf "The following kernel modules can not be found:\n" 113 printf "%b" "$MISSING_MODULES" 114 exit 1 115 fi 116 117 return 0 118} 119 120load_module_linux() { 121 KMOD=$1 122 123 FILE=$(modinfo "$KMOD" | awk '/^filename:/ {print $2}') 124 VERSION=$(modinfo "$KMOD" | awk '/^version:/ {print $2}') 125 126 if [ "$VERBOSE" = "yes" ]; then 127 echo "Loading: $FILE ($VERSION)" 128 fi 129 130 if ! $LDMOD "$KMOD" >/dev/null 2>&1; then 131 echo "Failed to load $KMOD" 132 return 1 133 fi 134 135 return 0 136} 137 138load_modules_freebsd() { 139 kldload "$KMOD_FREEBSD" || return 1 140 141 if [ "$VERBOSE" = "yes" ]; then 142 echo "Successfully loaded ZFS module stack" 143 fi 144 145 return 0 146} 147 148load_modules_linux() { 149 mkdir -p /etc/zfs 150 151 if modinfo "$KMOD_ZLIB_DEFLATE" >/dev/null 2>&1; then 152 modprobe "$KMOD_ZLIB_DEFLATE" >/dev/null 2>&1 153 fi 154 155 if modinfo "$KMOD_ZLIB_INFLATE">/dev/null 2>&1; then 156 modprobe "$KMOD_ZLIB_INFLATE" >/dev/null 2>&1 157 fi 158 159 for KMOD in $KMOD_SPL $KMOD_ZAVL $KMOD_ZNVPAIR \ 160 $KMOD_ZUNICODE $KMOD_ZCOMMON $KMOD_ZLUA $KMOD_ZZSTD \ 161 $KMOD_ICP $KMOD_ZFS; do 162 load_module_linux "$KMOD" || return 1 163 done 164 165 if [ "$VERBOSE" = "yes" ]; then 166 echo "Successfully loaded ZFS module stack" 167 fi 168 169 return 0 170} 171 172unload_module_linux() { 173 KMOD=$1 174 175 NAME=$(basename "$KMOD" .ko) 176 FILE=$(modinfo "$KMOD" | awk '/^filename:/ {print $2}') 177 VERSION=$(modinfo "$KMOD" | awk '/^version:/ {print $2}') 178 179 if [ "$VERBOSE" = "yes" ]; then 180 echo "Unloading: $KMOD ($VERSION)" 181 fi 182 183 rmmod "$NAME" || echo "Failed to unload $NAME" 184 185 return 0 186} 187 188unload_modules_freebsd() { 189 kldunload "$KMOD_FREEBSD" || echo "Failed to unload $KMOD_FREEBSD" 190 191 if [ "$VERBOSE" = "yes" ]; then 192 echo "Successfully unloaded ZFS module stack" 193 fi 194 195 return 0 196} 197 198unload_modules_linux() { 199 for KMOD in $KMOD_ZFS $KMOD_ICP $KMOD_ZZSTD $KMOD_ZLUA $KMOD_ZCOMMON \ 200 $KMOD_ZUNICODE $KMOD_ZNVPAIR $KMOD_ZAVL $KMOD_SPL; do 201 NAME=$(basename "$KMOD" .ko) 202 USE_COUNT=$(lsmod | grep -E "^${NAME} " | awk '{print $3}') 203 204 if [ "$USE_COUNT" = "0" ] ; then 205 unload_module_linux "$KMOD" || return 1 206 elif [ "$USE_COUNT" != "" ] ; then 207 echo "Module ${NAME} is still in use!" 208 return 1 209 fi 210 done 211 212 if modinfo "$KMOD_ZLIB_DEFLATE" >/dev/null 2>&1; then 213 modprobe -r "$KMOD_ZLIB_DEFLATE" >/dev/null 2>&1 214 fi 215 216 if modinfo "$KMOD_ZLIB_INFLATE">/dev/null 2>&1; then 217 modprobe -r "$KMOD_ZLIB_INFLATE" >/dev/null 2>&1 218 fi 219 220 if [ "$VERBOSE" = "yes" ]; then 221 echo "Successfully unloaded ZFS module stack" 222 fi 223 224 return 0 225} 226 227stack_clear_linux() { 228 STACK_MAX_SIZE=/sys/kernel/debug/tracing/stack_max_size 229 STACK_TRACER_ENABLED=/proc/sys/kernel/stack_tracer_enabled 230 231 if [ "$STACK_TRACER" = "yes" ] && [ -e "$STACK_MAX_SIZE" ]; then 232 echo 1 >"$STACK_TRACER_ENABLED" 233 echo 0 >"$STACK_MAX_SIZE" 234 fi 235} 236 237stack_check_linux() { 238 STACK_MAX_SIZE=/sys/kernel/debug/tracing/stack_max_size 239 STACK_TRACE=/sys/kernel/debug/tracing/stack_trace 240 STACK_LIMIT=15362 241 242 if [ -e "$STACK_MAX_SIZE" ]; then 243 STACK_SIZE=$(cat "$STACK_MAX_SIZE") 244 245 if [ "$STACK_SIZE" -ge "$STACK_LIMIT" ]; then 246 echo 247 echo "Warning: max stack size $STACK_SIZE bytes" 248 cat "$STACK_TRACE" 249 fi 250 fi 251} 252 253if [ "$(id -u)" != 0 ]; then 254 echo "Must run as root" 255 exit 1 256fi 257 258UNAME=$(uname -s) 259 260if [ "$UNLOAD" = "yes" ]; then 261 kill_zed 262 umount -t zfs -a 263 case $UNAME in 264 FreeBSD) 265 unload_modules_freebsd 266 ;; 267 Linux) 268 stack_check_linux 269 unload_modules_linux 270 ;; 271 esac 272fi 273if [ "$LOAD" = "yes" ]; then 274 case $UNAME in 275 FreeBSD) 276 load_modules_freebsd 277 ;; 278 Linux) 279 stack_clear_linux 280 check_modules_linux 281 load_modules_linux "$@" 282 udevadm trigger 283 udevadm settle 284 ;; 285 esac 286fi 287 288exit 0 289