mirror of
				https://git.proxmox.com/git/mirror_zfs
				synced 2025-11-04 12:35:20 +00:00 
			
		
		
		
	modprobe -r only works for depmodded modules, but this also means we have to re-iterate legacy modules, and in the right order Reviewed-by: Brian Atkinson <batkinson@lanl.gov> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz> Closes #13356
		
			
				
	
	
		
			246 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/bin/sh
 | 
						|
#
 | 
						|
# A simple script to load/unload the ZFS module stack.
 | 
						|
#
 | 
						|
 | 
						|
BASE_DIR=${0%/*}
 | 
						|
SCRIPT_COMMON=common.sh
 | 
						|
if [ -f "${BASE_DIR}/${SCRIPT_COMMON}" ]; then
 | 
						|
	. "${BASE_DIR}/${SCRIPT_COMMON}"
 | 
						|
else
 | 
						|
	echo "Missing helper script ${SCRIPT_COMMON}" && exit 1
 | 
						|
fi
 | 
						|
 | 
						|
VERBOSE="no"
 | 
						|
UNLOAD="no"
 | 
						|
LOAD="yes"
 | 
						|
STACK_TRACER="no"
 | 
						|
 | 
						|
ZED_PIDFILE=${ZED_PIDFILE:-/var/run/zed.pid}
 | 
						|
LDMOD=${LDMOD:-/sbin/modprobe}
 | 
						|
DELMOD=${DELMOD:-/sbin/rmmod}
 | 
						|
 | 
						|
KMOD_ZLIB_DEFLATE=${KMOD_ZLIB_DEFLATE:-zlib_deflate}
 | 
						|
KMOD_ZLIB_INFLATE=${KMOD_ZLIB_INFLATE:-zlib_inflate}
 | 
						|
KMOD_SPL=${KMOD_SPL:-spl}
 | 
						|
KMOD_ZFS=${KMOD_ZFS:-zfs}
 | 
						|
KMOD_FREEBSD=${KMOD_FREEBSD:-openzfs}
 | 
						|
 | 
						|
 | 
						|
usage() {
 | 
						|
	cat << EOF
 | 
						|
USAGE:
 | 
						|
$0 [hvudS]
 | 
						|
 | 
						|
DESCRIPTION:
 | 
						|
	Load/unload the ZFS module stack.
 | 
						|
 | 
						|
OPTIONS:
 | 
						|
	-h	Show this message
 | 
						|
	-v	Verbose
 | 
						|
	-r	Reload modules
 | 
						|
	-u	Unload modules
 | 
						|
	-S	Enable kernel stack tracer
 | 
						|
EOF
 | 
						|
	exit 1
 | 
						|
}
 | 
						|
 | 
						|
while getopts 'hvruS' OPTION; do
 | 
						|
	case $OPTION in
 | 
						|
	v)
 | 
						|
		VERBOSE="yes"
 | 
						|
		;;
 | 
						|
	r)
 | 
						|
		UNLOAD="yes"
 | 
						|
		LOAD="yes"
 | 
						|
		;;
 | 
						|
	u)
 | 
						|
		UNLOAD="yes"
 | 
						|
		LOAD="no"
 | 
						|
		;;
 | 
						|
	S)
 | 
						|
		STACK_TRACER="yes"
 | 
						|
		;;
 | 
						|
	*)
 | 
						|
		usage
 | 
						|
		;;
 | 
						|
	esac
 | 
						|
done
 | 
						|
shift $(( OPTIND - 1 ))
 | 
						|
[ $# -eq 0 ] || usage
 | 
						|
 | 
						|
kill_zed() {
 | 
						|
	if [ -f "$ZED_PIDFILE" ]; then
 | 
						|
		read -r PID <"$ZED_PIDFILE"
 | 
						|
		kill "$PID"
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
check_modules_linux() {
 | 
						|
	LOADED_MODULES=""
 | 
						|
	MISSING_MODULES=""
 | 
						|
 | 
						|
	for KMOD in $KMOD_SPL $KMOD_ZFS; do
 | 
						|
		NAME="${KMOD##*/}"
 | 
						|
		NAME="${NAME%.ko}"
 | 
						|
 | 
						|
		if lsmod | grep -E -q "^${NAME}"; then
 | 
						|
			LOADED_MODULES="$LOADED_MODULES\t$NAME\n"
 | 
						|
		fi
 | 
						|
 | 
						|
		if ! modinfo "$KMOD" >/dev/null 2>&1; then
 | 
						|
			MISSING_MODULES="$MISSING_MODULES\t${KMOD}\n"
 | 
						|
		fi
 | 
						|
	done
 | 
						|
 | 
						|
	if [ -n "$LOADED_MODULES" ]; then
 | 
						|
		printf "Unload the kernel modules by running '%s -u':\n" "$0"
 | 
						|
		printf "%b" "$LOADED_MODULES"
 | 
						|
		exit 1
 | 
						|
	fi
 | 
						|
 | 
						|
	if [ -n "$MISSING_MODULES" ]; then
 | 
						|
		printf "The following kernel modules can not be found:\n"
 | 
						|
		printf "%b" "$MISSING_MODULES"
 | 
						|
		exit 1
 | 
						|
	fi
 | 
						|
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
load_module_linux() {
 | 
						|
	KMOD=$1
 | 
						|
 | 
						|
	FILE=$(modinfo "$KMOD" 2>&1 | awk 'NR == 1 && /zlib/ && /not found/ {print "(builtin)"; exit}  /^filename:/ {print $2}')
 | 
						|
	[ "$FILE" = "(builtin)" ] && return
 | 
						|
 | 
						|
	if [ "$VERBOSE" = "yes" ]; then
 | 
						|
		VERSION=$(modinfo "$KMOD" | awk '/^version:/ {print $2}')
 | 
						|
		echo "Loading: $FILE ($VERSION)"
 | 
						|
	fi
 | 
						|
 | 
						|
	if ! $LDMOD "$KMOD" >/dev/null 2>&1; then
 | 
						|
		echo "Failed to load $KMOD"
 | 
						|
		return 1
 | 
						|
	fi
 | 
						|
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
load_modules_freebsd() {
 | 
						|
	kldload "$KMOD_FREEBSD" || return 1
 | 
						|
 | 
						|
	if [ "$VERBOSE" = "yes" ]; then
 | 
						|
		echo "Successfully loaded ZFS module stack"
 | 
						|
	fi
 | 
						|
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
load_modules_linux() {
 | 
						|
	mkdir -p /etc/zfs
 | 
						|
 | 
						|
	for KMOD in "$KMOD_ZLIB_DEFLATE" "$KMOD_ZLIB_INFLATE" $KMOD_SPL $KMOD_ZFS; do
 | 
						|
		load_module_linux "$KMOD" || return 1
 | 
						|
	done
 | 
						|
 | 
						|
	if [ "$VERBOSE" = "yes" ]; then
 | 
						|
		echo "Successfully loaded ZFS module stack"
 | 
						|
	fi
 | 
						|
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
unload_modules_freebsd() {
 | 
						|
	kldunload "$KMOD_FREEBSD" || echo "Failed to unload $KMOD_FREEBSD"
 | 
						|
 | 
						|
	if [ "$VERBOSE" = "yes" ]; then
 | 
						|
		echo "Successfully unloaded ZFS module stack"
 | 
						|
	fi
 | 
						|
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
unload_modules_linux() {
 | 
						|
	legacy_kmods="icp zzstd zlua zcommon zunicode znvpair zavl"
 | 
						|
	for KMOD in "$KMOD_ZFS" $legacy_kmods "$KMOD_SPL"; do
 | 
						|
		NAME="${KMOD##*/}"
 | 
						|
		NAME="${NAME%.ko}"
 | 
						|
		! [ -d "/sys/module/$NAME" ] || $DELMOD "$NAME" || return
 | 
						|
	done
 | 
						|
 | 
						|
	if [ "$VERBOSE" = "yes" ]; then
 | 
						|
		echo "Successfully unloaded ZFS module stack"
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
stack_clear_linux() {
 | 
						|
	STACK_MAX_SIZE=/sys/kernel/debug/tracing/stack_max_size
 | 
						|
	STACK_TRACER_ENABLED=/proc/sys/kernel/stack_tracer_enabled
 | 
						|
 | 
						|
	if [ "$STACK_TRACER" = "yes" ] && [ -e "$STACK_MAX_SIZE" ]; then
 | 
						|
		echo 1 >"$STACK_TRACER_ENABLED"
 | 
						|
		echo 0 >"$STACK_MAX_SIZE"
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
stack_check_linux() {
 | 
						|
	STACK_MAX_SIZE=/sys/kernel/debug/tracing/stack_max_size
 | 
						|
	STACK_TRACE=/sys/kernel/debug/tracing/stack_trace
 | 
						|
	STACK_LIMIT=15362
 | 
						|
 | 
						|
	if [ -e "$STACK_MAX_SIZE" ]; then
 | 
						|
		read -r STACK_SIZE <"$STACK_MAX_SIZE"
 | 
						|
		if [ "$STACK_SIZE" -ge "$STACK_LIMIT" ]; then
 | 
						|
			echo
 | 
						|
			echo "Warning: max stack size $STACK_SIZE bytes"
 | 
						|
			cat "$STACK_TRACE"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
if [ "$(id -u)" != 0 ]; then
 | 
						|
	echo "Must run as root"
 | 
						|
	exit 1
 | 
						|
fi
 | 
						|
 | 
						|
UNAME=$(uname)
 | 
						|
 | 
						|
if [ "$UNLOAD" = "yes" ]; then
 | 
						|
	kill_zed
 | 
						|
	umount -t zfs -a
 | 
						|
	case $UNAME in
 | 
						|
		FreeBSD)
 | 
						|
		   unload_modules_freebsd
 | 
						|
		   ;;
 | 
						|
		Linux)
 | 
						|
		   stack_check_linux
 | 
						|
		   unload_modules_linux
 | 
						|
		   ;;
 | 
						|
		*)
 | 
						|
		   echo "unknown system: $UNAME" >&2
 | 
						|
		   exit 1
 | 
						|
		   ;;
 | 
						|
	esac
 | 
						|
fi
 | 
						|
if [ "$LOAD" = "yes" ]; then
 | 
						|
	case $UNAME in
 | 
						|
		FreeBSD)
 | 
						|
		   load_modules_freebsd
 | 
						|
		   ;;
 | 
						|
		Linux)
 | 
						|
		   stack_clear_linux
 | 
						|
		   check_modules_linux
 | 
						|
		   load_modules_linux
 | 
						|
		   udevadm trigger
 | 
						|
		   udevadm settle
 | 
						|
		   ;;
 | 
						|
		*)
 | 
						|
		   echo "unknown system: $UNAME" >&2
 | 
						|
		   exit 1
 | 
						|
		   ;;
 | 
						|
	esac
 | 
						|
fi
 | 
						|
 | 
						|
exit 0
 |