3 # Takes a list of modules and unloads them and all dependent modules.
4 # If a module cannot be unloaded (e.g. it's in use), an error is
6 ###############################################################################
8 SCRIPT_NAME="$(basename "$0")"
11 [[ -n $DEBUG_RMMOD ]] && DEBUG='true'
15 echo "$SCRIPT_NAME -h|--help"
16 echo "$SCRIPT_NAME [-d|--debug-kernel] [modulesname...]"
18 echo -e "\t-h, --help\t\tDisplay this help message"
19 echo -e "\t-d, --debug-kernel\tDisplay lustre kernel debug messages"
20 echo -e "\tmodulesname\t\tList of lustre modules to unload. By default"
21 echo -e "\t\t\t\tldiskfs and libcfs (and their dependencies) are"
22 echo -e "\t\t\t\tselected."
25 # Print kernel debug message for lustre modules
28 $LCTL mark "$SCRIPT_NAME : Stop debug"
29 if [[ $DEBUG_RMMOD == "-" ]]; then
30 debug_file="" # dump to stdout
32 debug_file=$DEBUG_RMMOD
34 $LCTL debug_kernel $debug_file
38 # Unload all modules dependent on $1 (exclude removal of $1)
39 unload_dep_modules_exclusive() {
42 local DEPS="$(lsmod | awk '($1 == "'$MODULE'") { print $4 }')"
43 for SUBMOD in $(echo $DEPS | tr ',' ' '); do
44 unload_dep_modules_inclusive $SUBMOD || return 1
49 # Unload all modules dependent on $1 (include removal of $1)
50 unload_dep_modules_inclusive() {
53 # if $MODULE not loaded, return 0
54 lsmod | egrep -q "^\<$MODULE\>" || return 0
55 unload_dep_modules_exclusive $MODULE || return 1
58 if [ "$MODULE" = 'libcfs' ]; then
61 $LCTL mark "$SCRIPT_NAME : Unload $MODULE"
64 rmmod $MODULE || return 1
69 while [ $# -gt 0 ]; do
76 if lsmod | egrep -q '^libcfs'; then
79 echo "Debug unavailable: libcfs is not loaded" >&2
83 echo "Error invalid option" >&2
94 # To maintain backwards compatibility, ldiskfs and libcfs must be
95 # unloaded if no parameters are given, or if only the ldiskfs parameter
96 # is given. It's ugly, but is needed to emulate the prior functionality
97 if [ "${#modules[@]}" -eq 0 ] || [ "${modules[*]}" = "ldiskfs" ]; then
99 modules=('lnet_selftest' 'ldiskfs' 'libcfs')
104 if [ -f /sys/kernel/debug/kmemleak ] ; then
105 cat /proc/modules >/tmp/kmemleak-modules-list.txt
106 echo scan > /sys/kernel/debug/kmemleak
107 cat /sys/kernel/debug/kmemleak > /tmp/kmemleak-before-unload.txt
108 test -s /tmp/kmemleak-before-unload.txt && logger -t leak-pre -f /tmp/kmemleak-before-unload.txt
109 rm /tmp/kmemleak-before-unload.txt
110 # Clear everything here so that only new leaks show up
111 # after module unload
112 echo clear > /sys/kernel/debug/kmemleak
117 echo "Lustre debug parameters:" >&2
118 $LCTL get_param debug >&2
119 $LCTL get_param debug_mb >&2
121 $LCTL mark "$SCRIPT_NAME : Start debug"
125 unload_dep_modules_inclusive 'ptlrpc' || exit 1
126 # LNet may have an internal ref which can prevent LND modules from
127 # unloading. Try to drop it before unloading modules.
128 # NB: we squelch stderr because lnetctl/lctl may complain about
129 # LNet being "busy", but this is normal. We're making a best effort
131 # Prefer lnetctl if it is present
132 if [ -n "$(which lnetctl 2>/dev/null)" ]; then
133 lnetctl lnet unconfigure 2>/dev/null
134 elif [ -n "$(which lctl 2>/dev/null)" ]; then
135 lctl net down 2>/dev/null | grep -v "LNET ready to unload"
139 for mod in ${modules[*]}; do
140 unload_dep_modules_inclusive $mod || exit 1
147 if [ -f /sys/kernel/debug/kmemleak ] ; then
148 echo scan > /sys/kernel/debug/kmemleak
149 cat /sys/kernel/debug/kmemleak > /tmp/kmemleak-after-unload.txt
150 test -s /tmp/kmemleak-after-unload.txt && logger -t leak-mods -f /tmp/kmemleak-modules-list.txt && logger -t leak-post -f /tmp/kmemleak-after-unload.txt
151 rm -f /tmp/kmemleak-after-unload.txt /tmp/kmemleak-modules-list.txt