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