#!/bin/sh
#
# This script tries to do insmod & rmmod for each kernel module
# multiple times. Script can help to detect buggy initialization and
# cleanup code. After running, man should check kernel log messages.
#
# Side effects:
# - during running some important modules can be unloaded temporarily
#   (see BLACKLIST_MODULES)
# - possible crash or malfunction of machine
#
# Written by Pavol Gono
# Free to use and modify


# Number of insmod-s and rmmod-s for each module
NUM_LOADINGS=10

# Path where your modules reside (path will be searched recursively)
MODULES_PATH="/lib/modules/$(uname -r)"

# Modules which shall not be tested, separated by spaces
# (use only underscores '_' in module names)
BLACKLIST_MODULES="arptable_filter atkbd pktgen rfcomm rpcsec_gss_krb5 sctp sdhci xt_NFQUEUE"

# Modules which shall remain loaded after test
LOADED_MODULES="$(lsmod | awk 'NR > 1 {print $1}')"


find "$MODULES_PATH" -type f -name '*.ko' -printf "%f\n" | tr - _ | \
while read MODULE_FILE ; do
   MODULE_NAME="${MODULE_FILE%.ko}"
   BLACKLISTED=0
   for I in $BLACKLIST_MODULES ; do
      if [ $I = "$MODULE_NAME" ] ; then
         BLACKLISTED=1
         break
      fi
   done
   if [ $BLACKLISTED = 1 ] ; then
      continue
   fi
   echo -n "Testing module $MODULE_NAME "
   I=1
   while [ $I -le "$NUM_LOADINGS" ] ; do
      modprobe "$MODULE_NAME" >/dev/null 2>&1
      if [ $? = 0 ] ; then
         echo -n .
      else
         echo -n I
      fi
      rmmod "$MODULE_NAME" >/dev/null 2>&1
      if [ $? = 0 ] ; then
         echo -n .
      else
         echo -n R
      fi
      I=$(($I + 1))
   done
   TO_BE_LOADED=0
   for I in $LOADED_MODULES ; do
      if [ $I = "$MODULE_NAME" ] ; then
         TO_BE_LOADED=1
         break
      fi
   done
   if [ $TO_BE_LOADED = 1 ] ; then
      modprobe "$MODULE_NAME" >/dev/null 2>&1
   fi
   echo
done

# Trying to unload all modules which haven't been loaded
echo -n "Unloading needless modules "
for i in 1 2 3 4 ; do
   lsmod | awk 'NR > 1 {print $1}' | \
   while read MODULE_NAME ; do
      TO_BE_UNLOADED=1
      for I in $LOADED_MODULES ; do
         if [ $I = "$MODULE_NAME" ] ; then
            TO_BE_UNLOADED=0
            break
         fi
      done
      if [ $TO_BE_UNLOADED = 1 ] ; then
         modprobe -r "$MODULE_NAME" >/dev/null 2>&1
         if [ $? = 0 ] ; then
            echo -n .
         fi
      fi
   done
done
echo

# Some missing cleanups in module code could generate oops
echo "Testing /sys searchability"
find /sys >/dev/null 2>&1
echo "Testing /proc searchability"
find /proc >/dev/null 2>&1

echo "done"
