Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Frederick888/8fdd100ec6233c062f84998a8d1704e3 to your computer and use it in GitHub Desktop.
Save Frederick888/8fdd100ec6233c062f84998a8d1704e3 to your computer and use it in GitHub Desktop.
Arch Linux `initcpio` hook that additionally unloads NVIDIA modules and exports ZFS pools
  1. Put the files below in place (replace _ with /)
  2. Add my-shutdown to /etc/mkinitcpio.conf's HOOKS, after zfs and before filesystems. For example, HOOKS=(base udev autodetect keyboard keymap modconf kms block zfs my-shutdown filesystems).
#!/usr/bin/ash
# SPDX-License-Identifier: GPL-2.0-only
run_cleanuphook() {
rm -rf /usr/lib/modules
cp -ax /. /run/initramfs
}
# vim: set ft=sh ts=4 sw=4 et:
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-only
build() {
add_binary cp
add_binary date
add_binary lsblk
add_binary findmnt
add_binary fuser
add_binary umount
add_file "/etc/initcpio/my-shutdown" "/shutdown" 755
add_runscript
}
help() {
cat <<HELPEOF
This hook copies the contents of the initramfs into /run/initramfs for reuse
on shutdown. This is needed when you have /usr mounted on a separate partition.
This version additionally unloads NVIDIA modules and exports ZFS pools.
HELPEOF
}
# vim: set ft=sh ts=4 sw=4 et:
#!/usr/bin/ash
# SPDX-License-Identifier: GPL-2.0-only
# teardown a single device by node name
# $1: device node name, e.g. md0, dm-2
stop_device() {
local devtype='' devname=''
# the device must still be active
[ -e "/sys/class/block/$1" ] || return 1
# this can sometimes fail on stopped md devices, when the
# sysfs node doesn't go away as quickly as i'd like it to.
devtype="$(lsblk -drno TYPE "/dev/$1" 2>/dev/null)" || return 1
case "$devtype" in
crypt)
# dmsetup could be used here, but we don't know that it
# exists.
read -r devname <"$1/dm/name"
cryptsetup remove "$devname"
;;
lvm | dm)
read -r devname <"$1/dm/name"
dmsetup --noudevsync remove "$devname"
;;
raid*)
# wait for arrays with external metadata to be marked as
# clean. unfortunately, there isn't a whole lot we can do
# if this fails, and the array may need a full rebuild on
# the next reboot.
IFS=: read -r metadata _ <"/sys/class/block/$1/md/metadata_version"
if [ "$metadata" = external ]; then
mdadm --wait-clean "/dev/$1"
fi
mdadm --stop "/dev/$1"
;;
dmraid)
read -r devname <"$1/dm/name"
dmraid -an "$devname"
;;
# silently ignore unstacked devices
esac
}
# recursively disassemble a device chain
# $1: device node name, e.g. md0, dm-2
disassemble() {
local holder=''
for holder in "$1"/holders/*; do
[ -e "$holder" ] && disassemble "${holder##*/}"
stop_device "$1"
done
}
copy_binary_from_host() {
local bin="$1"
# hardcode a sane PATH
for p in '/usr/sbin' '/usr/bin' '/sbin' '/bin'; do
if [ -e "/oldroot/$p/$bin" ]; then
cp "/oldroot/$p/$bin" "/usr/bin/$1"
return 0
fi
done
return 1
}
# XXX: Discourage libdevmapper from thinking that udev
# might be in a useful state. FS#30995.
rm -rf /run/udev
if [ "$1" = kexec ] && ! command -v kexec >/dev/null; then
copy_binary_from_host kexec
fi
# chdir, so that we can avoid a lot of path chopping
cd /sys/class/block || exit
date
printf '%s\n' "Unloading NVIDIA modules."
lsmod | grep nvidia
# printf 'SKIPPED!\n'
rmmod nvidia_drm nvidia_uvm nvidia_modeset nvidia
date
printf '%s\n' "Unmounting all devices."
umount --recursive /oldroot
date
printf '%s\n' "Exporting ZFS pools."
zpool export -a
debug_log() {
mkdir /debug
mount /dev/disk/by-uuid/e0919973-0f0d-4938-b23a-fdf243675a97 /debug
date | tee -a /debug/log.txt
mount 2>&1 | tee -a /debug/log.txt
fuser -vm "$1" 2>&1 | tee -a /debug/log.txt
umount /debug
}
if findmnt /oldroot/sys; then
debug_log /oldroot/sys
elif findmnt /oldroot; then
debug_log /oldroot
fi
date
printf '%s\n' 'Detaching loop devices.'
for loop in loop*/loop; do
[ -e "$loop" ] && losetup -d "${loop%/loop}"
done
date
printf '%s\n' "Disassembling stacked devices."
# iterate over devices with holders
for part in */holders/*; do
[ -e "$part" ] && disassemble "${part%%/*}"
done
case "$1" in
poweroff | shutdown | halt)
"$1" -f
;;
*)
type kexec >/dev/null && kexec -e
reboot -f
;;
esac
# vim: ft=sh ts=4 sw=4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment