Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move kernel_prerm.d logic into dkms #469

Merged
merged 12 commits into from
Dec 19, 2024
Merged
21 changes: 0 additions & 21 deletions debian_kernel_postinst.d.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,6 @@
# We're passed the version of the kernel being installed
inst_kern=$1

uname_s=$(uname -s)

_get_kernel_dir() {
KVER=$1
DIR="@MODDIR@/$KVER/build"
echo "$DIR"
}

_check_kernel_dir() {
DIR=$(_get_kernel_dir "$1")
test -e "$DIR/include"
}

header_pkg="linux-headers-$inst_kern"
kernel="Linux"

if [ -x @LIBDIR@/dkms_autoinstaller ]; then
exec @LIBDIR@/dkms_autoinstaller start "$inst_kern"
fi

if ! _check_kernel_dir "$inst_kern" ; then
echo "dkms: WARNING: $kernel headers are missing, which may explain the above failures." >&2
echo " please install the $header_pkg package to fix this." >&2
fi
18 changes: 1 addition & 17 deletions debian_kernel_prerm.d.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,7 @@
inst_kern=$1

if command -v dkms > /dev/null; then
dkms status -k "$inst_kern" 2>/dev/null | while IFS=",:/ " read -r name vers _ arch status; do
[ "$status" = "installed" ] || [ "$status" = "built" ] || continue
echo "dkms: removing: $name/$vers ($inst_kern) ($arch)" >&2
# Compromise on using 'unbuild' to remove the module when a
# kernel is being removed. The 'remove' command is too
# destructive. The 'uninstall' command leaves built files
# around that have no other trigger to 'unbuild' them.
# (Triggering 'unbuild' on kernel header removal would not be
# a good idea because that would also cause the module to be
# uninstalled for the kernel, even though only the headers are
# being removed.)
dkms unbuild -m "$name" -v "$vers" -k "$inst_kern" -a "$arch"
done
dkms kernel_prerm -k "$inst_kern"
fi

rmdir --ignore-fail-on-non-empty \
"@MODDIR@/$inst_kern/updates/dkms" \
"@MODDIR@/$inst_kern/updates" 2>/dev/null

exit 0
114 changes: 98 additions & 16 deletions dkms.in
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
# 11: autoinstall: One or more modules failed to install during autoinstall.
# 12: setup_kernels_arches(): Could not determine architecture.
# 13: build: Aborting build of module ... for kernel ... due to missing BUILD_DEPENDS: ...
# 14: kernel_prerm: dkms kernel_prerm for kernel ... failed for module(s) ...
# 77: skipped due to BUILD_EXCLUSIVE
# 101: install: pre_install failed, aborting install.

Expand Down Expand Up @@ -248,7 +249,8 @@ show_usage()
{
echo "Usage: $0 [action] [options]"
echo " [action] = { add | remove | build | unbuild | install | uninstall | match |"
echo " autoinstall | mktarball | ldtarball | status | generate_mok }"
echo " autoinstall | mktarball | ldtarball | status | generate_mok |"
echo " kernel_postinst | kernel_prerm }"
echo " [options] = [-m module] [-v module-version] [-k kernel-version] [-a arch]"
echo " [-c dkms.conf-location] [-q] [--force] [--force-version-override] [--all]"
echo " [--templatekernel=kernel] [--directive='cli-directive=cli-value']"
Expand Down Expand Up @@ -354,6 +356,7 @@ check_all_is_banned()
# A little test function for DKMS commands that only work on one kernel.
have_one_kernel() {
if (( ${#kernelver[@]} != 1 )); then
[[ $1 =~ kernel_(postinst|prerm) ]] && die 4 "The action $1 requires exactly one kernel version parameter on the command line."
die 4 "The action $1 does not support multiple kernel version parameters on the command line."
fi
check_all_is_banned $1
Expand Down Expand Up @@ -1517,7 +1520,7 @@ do_install()
exit 6
}

if [[ $modprobe_on_install ]]; then
if [[ $modprobe_on_install ]] && [[ $kernelver = "$(uname -r)" ]]; then
# Make the newly installed modules available immediately
find /sys/devices -name modalias -print0 | xargs -0 cat | sort -u | xargs modprobe -a -b -q
if [[ -f /lib/systemd/system/systemd-modules-load.service ]]; then
Expand Down Expand Up @@ -1568,9 +1571,7 @@ is_module_added() {
is_module_built() {
[[ $1 && $2 && $3 && $4 ]] || return 1
local d
local m
d="$dkms_tree/$1/$2/$3/$4"
m=''
[[ -d $d/module ]] || return 1
local default_conf
default_conf="$dkms_tree/$1/$2/source/dkms.conf"
Expand All @@ -1579,6 +1580,7 @@ is_module_built() {
real_conf="${conf:-${default_conf}}"
read_conf_or_die "$3" "$4" "$real_conf"
set_module_suffix "$3"
local m
for m in "${dest_module_name[@]}"; do
local t
t=$(compressed_or_uncompressed "$d/module" "$m")
Expand Down Expand Up @@ -1750,7 +1752,11 @@ do_uninstall()
run_build_script post_remove "$post_remove"

# Run depmod because we changed $install_tree
invoke_command "do_depmod $1" "Running depmod" '' background
if [[ ! $delayed_depmod ]]; then
invoke_command "do_depmod $1" "Running depmod" '' background
else
touch $dkms_tree/depmod-pending-$1-$2
fi

# Delete the original_module if nothing for this kernel is installed anymore
if [[ $was_active && -d $dkms_tree/$module/original_module/$1/$2 && ! -d $dkms_tree/$module/original_module/$1/$2/collisions ]]; then
Expand Down Expand Up @@ -1973,7 +1979,7 @@ module_status_built_extra() (
)

# Return a list of all the modules that are either built or installed.
# This and module_status do some juggling of $IFS to ensure that
# This and list_module_version_combos do some juggling of $IFS to ensure that
# we do not get word splitting where it would be inconvenient.
module_status_built() {
local ret
Expand Down Expand Up @@ -2002,32 +2008,44 @@ module_status_built() {
return $ret
}

# Return the status of all modules that have been added, built, or installed.
module_status() {
# Return a list of all module/version combos known to DKMS.
list_module_version_combos() {
local ret
local modv
local m
local v
local directory
local oifs
ret=1
oifs="$IFS"
IFS=''
for directory in "$dkms_tree/"${1:-*}/${2:-*}; do
IFS="$oifs"
[[ -d $directory ]] || continue
modv="${directory#$dkms_tree/}"
m="${modv%/*}"
v="${modv#*/}"
is_module_broken "$m" "$v" && { echo "broken $m/$v"; continue; }
is_module_added "$m" "$v" || continue
# skip <module>/kernel-<kver>-<karch> -> <modver>/<kver>/<karch> symlinks
[[ $modv != */kernel-*-* ]] || continue
echo "$modv"
ret=0
module_status_built "$m" "$v" "$3" "$4" || echo "added $m/$v"
IFS=''
done
IFS="$oifs"
return $ret
}

# Return the status of all modules that have been added, built, or installed.
module_status() {
local ret
local m
local v
ret=1
while IFS='/' read m v; do
is_module_broken "$m" "$v" && { echo "broken $m/$v"; continue; }
is_module_added "$m" "$v" || continue
ret=0
module_status_built "$m" "$v" "$3" "$4" || echo "added $m/$v"
done < <(list_module_version_combos "$1" "$2")
return $ret
}

# Print out the status in the format that people who call DKMS expect.
# Internal callers should use the module_status functions, as their output
# is easier to parse.
Expand Down Expand Up @@ -2459,6 +2477,11 @@ add_source_tree() {
# functionality, and makes it much easier to reinstall DKMS kernel modules
# by hand if dkms_autoinstaller is not used.
autoinstall() {
if [[ -f /etc/dkms/no-autoinstall ]]; then
echo "Automatic installation of modules has been disabled."
return
fi

local status
local mv
local mvka
Expand Down Expand Up @@ -2540,6 +2563,7 @@ autoinstall() {
for modv in "${to_install[@]}"; do
IFS=/ read m v <<< "$modv"
if [[ -z ${build_depends[$m]} ]]; then
echo "Autoinstall of module $m/$v for kernel $kernelver ($arch)"
(module="$m" module_version="$v" kernelver="$kernelver" arch="$arch" install_module)
status=$?
if (( status == 0 )); then
Expand Down Expand Up @@ -2591,6 +2615,57 @@ autoinstall() {
fi
}

# A wrapper for 'autoinstall', to be used in combination with 'kernel_prerm'.
kernel_postinst()
{
local m
local v
local failed

have_one_kernel kernel_postinst

autoinstall
}

# This is roughly the inverse action to 'autoinstall'. It is supposed to be
# called upon removal of a kernel to also remove all modules (including
# those with AUTOINSTALL="") that were built or installed for that kernel.
#
# Compromise on using 'unbuild' to remove the module when a kernel is being
# removed. The 'remove' command is too destructive. The 'uninstall' command
# leaves built files around that have no other trigger to 'unbuild' them.
# (Triggering 'unbuild' on kernel header removal would not be a good idea
# because that would also cause the module to be uninstalled for the kernel,
# even though only the headers are being removed.)
kernel_prerm()
{
local m
local v
local failed

have_one_kernel kernel_prerm

# run depmod only once after uninstalling all dkms modules
delayed_depmod=1

while IFS='/' read m v; do
is_module_built "$m" "$v" "$kernelver" "$arch" || continue
echo "dkms: removing module $m/$v for kernel $kernelver ($arch)" >&2
(module="$m" module_version="$v" unbuild_module) || failed="$failed $m/$v($?)"
done < <(list_module_version_combos)

if [[ -f $dkms_tree/depmod-pending-$kernelver-$arch ]]; then
rm -f $dkms_tree/depmod-pending-$kernelver-$arch
invoke_command "do_depmod $1" "Running depmod" '' background
fi
delayed_depmod=

# clean leftover empty directories
[[ ! -d $install_tree/$kernelver ]] || find "$install_tree/$kernelver" -type d -empty -delete

[[ -z $failed ]] || die 14 "dkms kernel_prerm for kernel $kernelver ($arch) failed for module(s)$failed."
}

#############################
#### ####
#### Program Starts Here ####
Expand Down Expand Up @@ -2666,8 +2741,9 @@ die_is_fatal="yes"
[ -x /sbin/weak-modules ] && weak_modules='/sbin/weak-modules'
[ -x /usr/lib/module-init-tools/weak-modules ] && weak_modules='/usr/lib/module-init-tools/weak-modules'
no_depmod=""
delayed_depmod=""

action_re='^(remove|(auto|un)?install|match|mktarball|(un)?build|add|status|ldtarball|generate_mok)$'
action_re='^(remove|(auto|un)?install|match|mktarball|(un)?build|add|status|ldtarball|generate_mok|kernel_(postinst|prerm))$'

# Parse command line arguments
while (($# > 0)); do
Expand Down Expand Up @@ -2847,6 +2923,9 @@ parallel_jobs=${parallel_jobs:-$(get_num_cpus)}
# Make sure we're not passing -j0 to make; treat -j0 as just "-j"
[[ "$parallel_jobs" = 0 ]] && parallel_jobs=""

# Require explicit --kernelver argument
[[ $action =~ kernel_(postinst|prerm) ]] && have_one_kernel "$action"

setup_kernels_arches "$action"
case "$action" in
remove | unbuild | uninstall)
Expand Down Expand Up @@ -2887,6 +2966,9 @@ generate_mok)
read_framework_conf $dkms_framework_signing_variables
prepare_mok
;;
kernel_postinst | kernel_prerm)
check_root && have_one_kernel "$action" && "$action"
;;
*)
error "Unknown action specified: \"$action\""
show_usage
Expand Down
4 changes: 1 addition & 3 deletions dkms_autoinstaller.in
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ case "$1" in
else
kernel=$(uname -r)
fi
if [ -f /etc/dkms/no-autoinstall ]; then
echo "Automatic installation of modules has been disabled."
elif ! _check_kernel_dir $kernel; then
if ! _check_kernel_dir $kernel; then
echo "Automatic installation of modules for kernel $kernel was skipped since the kernel headers for this kernel do not seem to be installed."
else
dkms autoinstall --kernelver $kernel
Expand Down
11 changes: 2 additions & 9 deletions redhat_kernel_install.d.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,9 @@ KERNEL_VERSION=$2

case "$COMMAND" in
add)
if [ -f /etc/dkms/no-autoinstall ]; then
echo "Automatic installation of modules has been disabled."
else
dkms autoinstall --kernelver $KERNEL_VERSION
fi
dkms kernel_postinst --kernelver $KERNEL_VERSION
;;
remove)
dkms status -k "$KERNEL_VERSION" 2>/dev/null | while IFS=",:/ " read -r name vers _ arch status; do
dkms unbuild -m "$name" -v "$vers" -k "$KERNEL_VERSION" -a "$arch"
done
find /usr/lib/modules/$KERNEL_VERSION -type d -empty -delete
dkms kernel_prerm --kernelver $KERNEL_VERSION
;;
esac
Loading