Currently we take care to load only iTCO_wdt if this module was loaded in primary kernel. This new approach is capitalizing on recent changes proposed in the kernel which are following:
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=65... http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=90... http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=33...
Above kernel patches fixes/adds two major aspects: 1) It fixes parent of watchdog_device so that /sys/class/watchdog/watchdogn/device is populated. 2) Adds some sysfs device attributes so that we can read different watchdog status.
With the above support, now we can find out whether a watchdog is active or not. If it is active, we can also find out the driver/module responsible for that watchdog device.
Proposed patch uses above kernel support and then loads relevant wdt modules in kdump initramfs only for the active device.
Testing: It has been tested with kernel-4.5.0-0.rc1.git2.1.fc24 and fc23 user space.
- Added RuntimeWatchdogSec=40s in /etc/systemd/system.conf - Modified cmdline for crashkernel=256M - systemctl enable kdump - [temporarily changed /etc/kdump.conf to stop at dracut shell] - restart - echo c > /proc/sysrq-trigger
On dracut shell I can see kdump:/# cat /sys/class/watchdog/watchdog0/identity iTCO_wdt kdump:/# cat /sys/class/watchdog/watchdog0/state active
Tested also with correct /etc/kdump.conf and it was able to save the vmcore.
Assumption: Both watchdog and kdump daemon are managed by systemd.systemd starts watchdog daemon before kdump. If an user changes the watchdog status afterwards then he/she will have to execute `kdumpctrl restart`.
Limitations: This patch will be able to recognize an active wdt, only if its driver has been written in watchdog-core framework and registered with watchdog_class.
Signed-off-by: Pratyush Anand panand@redhat.com --- dracut-module-setup.sh | 19 +++++++++++++------ kdump-lib.sh | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 4cd7107c4a35..32032304476e 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -706,10 +706,17 @@ install() { }
installkernel() { - wdt=$(lsmod|cut -f1 -d' '|grep "wdt$") - if [ -n "$wdt" ]; then - [ "$wdt" = "iTCO_wdt" ] && instmods lpc_ich && - echo "rd.driver.pre=lpc_ich,iTCO_wdt " >> ${initdir}/etc/cmdline.d/00-wdt.conf - instmods $wdt - fi + wdtcmdline=$(get_wdt_cmdline) + + if [ "$?" = "0" ]; then + echo $wdtcmdline >> ${initdir}/etc/cmdline.d/00-wdt.conf + IFS='=,' read -ra modarr <<< "$wdtcmdline" + count='1' + while [ "$count" -lt ${#modarr[@]} ] + do + instmods ${modarr[$count]} + count=`expr $count + 1` + done + fi + return 0 } diff --git a/kdump-lib.sh b/kdump-lib.sh index 4d3420652b2f..f60909bca047 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -230,3 +230,42 @@ is_hostname() fi echo $1 | grep -q "[a-zA-Z]" } + +get_wdt_cmdline() +{ + local wdtcmdline="" + wdtcls=/sys/class/watchdog + cd $wdtcls + for dir in */; do + cd $dir + active=`[ -f state ] && cat state` + if [ "$active" = "active" ]; then + # device/modalias will return driver of this device + wdtdrv=`cat device/modalias` + # There can be more than one module represnted by same + # modalias. Currently load all of them. + # TODO: Need to find a way to avoid any unwanted module + # represented by modalias + wdtdrv=`modprobe -R $wdtdrv | tr "\n" "," | sed 's/.$//'` + wdtcmdline="rd.driver.pre=$wdtdrv" + # however in some cases, we also need to check that if + # there is a specific driver for the parent bus/device. + # In such cases we also need to enable driver for parent + # bus/device. + wdtppath="device/.."; + while [ -f "$wdtppath/modalias" ] + do + wdtpdrv=`cat $wdtppath/modalias` + wdtpdrv=`modprobe -R $wdtpdrv | tr "\n" "," | sed 's/.$//'` + wdtcmdline="$wdtcmdline,$wdtpdrv" + wdtppath="$wdtppath/.." + done + echo "$wdtcmdline" + return 0 + fi + cd .. + done + + echo "$wdtcmdline" + return 1 +}