diff --git a/dkms/PKGBUILD b/dkms/PKGBUILD index 9da47becbf..c0799fa863 100644 --- a/dkms/PKGBUILD +++ b/dkms/PKGBUILD @@ -3,13 +3,13 @@ # Contributor: Balwinder S "bsd" Dheeman (bdheeman AT gmail.com) pkgname=dkms -pkgver=2.8.6 -pkgrel=2 +pkgver=3.0.3 +pkgrel=1 pkgdesc='Dynamic Kernel Modules System' arch=('any') url='https://github.com/dell/dkms' license=('GPL2') -depends=('bash' 'kmod' 'gcc' 'make' 'patch') +depends=('coreutils' 'bash' 'gawk' 'sed' 'kmod' 'gcc' 'make' 'patch') makedepends=('git') optdepends=('linux-headers: build modules against the Arch kernel' 'linux-lts-headers: build modules against the LTS kernel' @@ -21,14 +21,12 @@ source=("git+https://github.com/dell/dkms.git#tag=v$pkgver" 'hook.install' 'hook.remove' 'hook.upgrade' - 'hook.sh' - '0001-Revert-Make-newly-installed-modules-available-immedi.patch') + 'hook.sh') sha256sums=('SKIP' - '047e0e46967e98fbf3ff8860a80f259c28693d5989373d5a5395714495b59844' - 'ae5483980db914d52bff981ed83356c85679dd7e6e8f73bdd94265f065014c73' - 'd61d94532789928085a8494ba039c59244cfb3bfd47deaf21bcbe54a2243dc45' - '55209947f6266dc7f29b82f3d2635a6b92f6e175d59571dca4d2fd435dffab4a' - '124b821b1b44ba365d915945825bcf32c1077655c3a98eb1644de56b6abfcd09') + 'acdc5b45cc018cea04ee1aec56fd8fc3a2de62cf7bc41acf53b3790872120998' + '326515cc7d00f93760beb844434ca7442caf7a9424614aa95a8f6d1ab79e15df' + '4f8dff7716e73a8bba885638f12e3cdc9e87daec1896f75e700b981527e43870' + 'c1b4a4e2e4e0e0e59ee0887403e79d60b209f3878dbbec6612573f13b90cce01') prepare() { cd dkms @@ -44,7 +42,7 @@ prepare() { # /usr move msg2 '/usr move patching' - for i in dkms{,_framework.conf,.bash-completion,.8,_common.postinst}; do + for i in dkms{.in,.8.in,_framework.conf,.bash-completion,_common.postinst} sign_helper.sh; do sed -ri 's,/lib/modules,/usr/lib/modules,g' "$i" done } @@ -59,15 +57,17 @@ package() { install -D -m 644 hook.upgrade "$pkgdir/usr/share/libalpm/hooks/70-dkms-upgrade.hook" install -D -m 644 hook.remove "$pkgdir/usr/share/libalpm/hooks/71-dkms-remove.hook" # hook helper - install -D -m 755 hook.sh "$pkgdir/usr/lib/dkms/alpm-hook" + install -D -m 755 hook.sh "$pkgdir/usr/share/libalpm/scripts/dkms" # upstream installer cd dkms - # we don't need kconf files, so we install them outside $pkgdir + # we don't need kconf files and libdir is only for debian stuff, so + # we install them outside of $pkgdir make \ DESTDIR="$pkgdir" \ SBIN="$pkgdir/usr/bin" \ BASHDIR="$pkgdir/usr/share/bash-completion/completions" \ - KCONF="$srcdir"/kconf \ + KCONF="$srcdir"/trash \ + LIBDIR="$srcdir"/trash \ install } diff --git a/dkms/hook.install b/dkms/hook.install index 84b482751e..ac08b83e96 100644 --- a/dkms/hook.install +++ b/dkms/hook.install @@ -10,5 +10,5 @@ Target = usr/lib/modules/*/modules.alias Description = Install DKMS modules Depends = dkms When = PostTransaction -Exec = /usr/lib/dkms/alpm-hook install +Exec = /usr/share/libalpm/scripts/dkms install NeedsTargets diff --git a/dkms/hook.remove b/dkms/hook.remove index 29be6bba04..c489c817b5 100644 --- a/dkms/hook.remove +++ b/dkms/hook.remove @@ -9,5 +9,5 @@ Target = usr/lib/modules/*/modules.alias Description = Remove DKMS modules Depends = dkms When = PreTransaction -Exec = /usr/lib/dkms/alpm-hook remove +Exec = /usr/share/libalpm/scripts/dkms remove NeedsTargets diff --git a/dkms/hook.sh b/dkms/hook.sh index d3f6678c51..6c685ee35d 100755 --- a/dkms/hook.sh +++ b/dkms/hook.sh @@ -1,7 +1,7 @@ #!/bin/bash # -# Copyright © 2018-2020, Sébastien Luttringer +# Copyright © 2018-2021, Sébastien Luttringer # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -22,7 +22,7 @@ run() { echo "==> $*" "$@" > /dev/null local ret=$? - (( $ret )) && echo "==> Warning, \`$*' returned $ret" + (( $ret )) && echo "==> WARNING: \`$*' exited $ret" return $ret } @@ -52,129 +52,168 @@ check_buildexclusive() { [[ "$3" =~ $BUILD_EXCLUSIVE_KERNEL ]] } -# handle actions on module addition/upgrade/removal -# $1: module name -# $2: module version -parse_module() { +# list all kernel versions +all_kver() { pushd "$install_tree" >/dev/null local path for path in */build/; do - local kver="${path%%/*}" - dkms_register "$1" "$2" "$kver" + echo "${path%%/*}" done popd >/dev/null } -# handle actions on kernel addition/upgrade/removal +# list all module name/version for a specific kernel version # $1: kernel version -parse_kernel() { +all_nv_from_kver() { local path for path in "$source_tree"/*-*/dkms.conf; do if [[ -f "$path" && "$path" =~ ^$source_tree/([^/]+)-([^/]+)/dkms\.conf$ ]]; then - dkms_register "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "$1" + echo "${BASH_REMATCH[1]}/${BASH_REMATCH[2]}" fi done } -# register a dkms module to install/remove -# this function suppress echo call for a module -# $1: module name, $2: module version, $3: kernel version -dkms_register() { - DKMS_MODULES["$1/$2/$3"]='' +# list of modules/version for installed/built kernel version +# $1: kernel version +built_nv_from_kver() { + local line + dkms status -k "$1" | while read -r line; do + if [[ "$line" =~ ^([^/]+/[^,]+)", $1, "[^:]+": "(built|installed) ]]; then + echo "${BASH_REMATCH[1]}" + fi + done +} + +# list installed or built kernel version for a specific module version +# $1 : module name/module version +built_kver_from_nv() { + local line + dkms status "$1" | while read -r line; do + if [[ "$line" =~ ^"$1, "([^,]+)", "[^:]+": "(built|installed) ]]; then + echo "${BASH_REMATCH[1]}" + fi + done } # install registered modules dkms_install() { - local nvk mod mver kver - local -i retry=1 - local -A dmods=() + # list of modules to build for a specific kernel + local -A tobuild=() + # add new/updated modules for all kernels to the build list + local nv kver + for nv in "${!DKMS_MODULES[@]}"; do + for kver in $(all_kver); do + tobuild["$nv/$kver"]='' + done + done + # add modules for new/updated kernels to the build list + for kver in "${!KERNEL_VERSIONS[@]}"; do + for nv in $(all_nv_from_kver "$kver"); do + tobuild["$nv/$kver"]='' + done + done + + # list of kver which requires depmod refresh + local -A depmods=() + + # let's build and install + local nvk mod mver + local -i retry=1 while (( $retry > 0 )); do retry=0 - for nvk in "${!DKMS_MODULES[@]}"; do - [[ "$nvk" =~ ([^/]+)/([^/]+)/(.+) ]] + for nvk in "${!tobuild[@]}"; do + [[ "$nvk" =~ ([^/]+)/([^/]+)/(.+) ]] || continue mod="${BASH_REMATCH[1]}" mver="${BASH_REMATCH[2]}" kver="${BASH_REMATCH[3]}" # do not build excluded modules if ! check_buildexclusive "$mod" "$mver" "$kver"; then - unset DKMS_MODULES[$nvk] + unset tobuild[$nvk] continue # skip modules with missing kernel headers elif [[ ! -d "$install_tree/$kver/build/include" ]]; then - DKMS_MODULES[$nvk]='Missing kernel headers' + ERROR_MESSAGES+=("Missing $kver kernel headers for module $mod/$mver.") + unset tobuild[$nvk] continue # skip modules with missing kernel package elif [[ ! -d "$install_tree/$kver/kernel" ]]; then - DKMS_MODULES[$nvk]='Missing kernel modules tree' + ERROR_MESSAGES+=("Missing $kver kernel modules tree for module $mod/$mver.") + unset tobuild[$nvk] continue # postpone modules with missing dependencies elif ! check_dependency "$mod" "$mver" "$kver"; then - DKMS_MODULES[$nvk]='Missing dependency' continue fi # give it a try dkms - run dkms install --no-depmod -m "$mod" -v "$mver" -k "$kver" - dmods[$kver]='' - unset DKMS_MODULES[$nvk] + run dkms install --no-depmod "$mod/$mver" -k "$kver" + if (( $? == 0 )); then + # register kernel version for later depmod + depmods[$kver]='' + fi + unset tobuild[$nvk] # maybe this module was a dep of another, so we retry retry=1 done done # run depmod later for performance improvments if (( $DKMS_DEPMOD )); then - for kver in "${!dmods[@]}"; do + for kver in "${!depmods[@]}"; do run depmod "$kver" done fi + # add errors messages for missing dependencies modules + for nvk in "${!tobuild[@]}"; do + [[ "$nvk" =~ ([^/]+/[^/]+)/(.+) ]] || continue + nv="${BASH_REMATCH[1]}" + kver="${BASH_REMATCH[2]}" + ERROR_MESSAGES+=("Missing dependencies to install module $nv for kernel $kver.") + done } -# remove registered modules when built/installed -# run depmod later for performance improvments +# remove registered modules +# run depmod once per kernel for performance improvments dkms_remove() { - local nvk mod mver kver state - local -A dmods=() - for nvk in "${!DKMS_MODULES[@]}"; do - [[ "$nvk" =~ ([^/]+)/([^/]+)/(.+) ]] - mod="${BASH_REMATCH[1]}" - mver="${BASH_REMATCH[2]}" - kver="${BASH_REMATCH[3]}" - # do not remove excluded modules (n.b. display not found errors) - if ! check_buildexclusive "$mod" "$mver" "$kver"; then - unset DKMS_MODULES[$nvk] - continue - fi - state=$(dkms status -m "$mod" -v "$mver" -k "$kver") - if [[ "$state" =~ "$mod/$mver, $kver, "[^:]+": "(added|built|installed) ]]; then - dmods[$kver]='' - run dkms remove --no-depmod -m "$mod" -v "$mver" -k "$kver" + local nv kver + local -A depmods=() + # remove full modules first + for nv in "${!DKMS_MODULES[@]}"; do + # try to remove modules one by one to keep the depmod optimization + for kver in $(built_kver_from_nv "$nv"); do + run dkms remove --no-depmod "$nv" -k "$kver" if (( $? == 0 )); then - unset DKMS_MODULES[$nvk] + # register kernel version for later depmod + depmods[$kver]='' else - DKMS_MODULES[$nvk]='dkms remove failed' + ERROR_MESSAGES+=("Failed to remove module $nv for kernel $kver.") fi - else - DKMS_MODULES[$nvk]='Not found in dkms status output' + done + # ensure module removal (even if only added) + if [[ $(dkms status "$nv") ]]; then + run dkms remove "$nv" + (( $? == 0 )) || ERROR_MESSAGES+=("Failed to remove module $nv.") fi done + # remove modules for a specific kernel version + for kver in "${!KERNEL_VERSIONS[@]}"; do + for nv in $(built_nv_from_kver "$kver"); do + run dkms remove --no-depmod "$nv" -k "$kver" + if (( $? == 0 )); then + # register kernel version for later depmod + depmods[$kver]='' + else + ERROR_MESSAGES+=("Failed to remove module $nv for kernel $kver.") + fi + done + done # run depmod later for performance improvments if (( $DKMS_DEPMOD )); then - for kver in "${!dmods[@]}"; do + for kver in "${!depmods[@]}"; do run depmod "$kver" done fi } -# show information about failed modules -show_errors() { - local nvk mod kver - for nvk in "${!DKMS_MODULES[@]}"; do - mod=${nvk%/*} - kver=${nvk##*/} - echo "==> Unable to $DKMS_ACTION module $mod for kernel $kver: ${DKMS_MODULES[$nvk]}." - done -} - # display hook usage and exit $1 (default 1) usage() { cat << EOF >&2 @@ -191,7 +230,7 @@ main() { # prevent each dkms call from failing with authorization errors if (( EUID )); then echo 'You must be root to use this hook' >&2 - exit 1 + return 1 fi # parse command line options @@ -206,10 +245,9 @@ main() { shift $((OPTIND - 1)) (( $# != 1 )) && usage - # register DKMS action + # parse command action to early exit case "$1" in - install|remove) - declare -r DKMS_ACTION="$1";; + install|remove) declare -r DKMS_ACTION="$1";; *) usage;; esac @@ -223,27 +261,41 @@ main() { local path for path in "$source_tree" "$install_tree"; do if [[ ! -d "$path" ]]; then - echo "==> Missing mandatory directory: $path. Exiting!" + echo "==> Missing mandatory directory: $path. Exiting!" >&2 return 1 fi done - # storage for DKMS modules to install/remove - # we use associate arrays to prevent duplicate + # global storage for changed DKMS modules + # we use associate arrays to prevent duplication + # the key is // declare -A DKMS_MODULES - # parse stdin paths to guess what do do + # global storage for changed linux kernels + # we use associate arrays to prevent duplication + declare -A KERNEL_VERSIONS + + # global storage for error messages + declare -a ERROR_MESSAGES + + # parse stdin paths to guess what we should install/remove while read -r path; do if [[ "/$path" =~ ^$source_tree/([^/]+)-([^/]+)/dkms\.conf$ ]]; then - parse_module "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" + # we match file updates on dkms modules sources + DKMS_MODULES["${BASH_REMATCH[1]}/${BASH_REMATCH[2]}"]='' elif [[ "/$path" =~ ^$install_tree/([^/]+)/ ]]; then - parse_kernel "${BASH_REMATCH[1]}" + # we match file updates on kernels install/removal + KERNEL_VERSIONS["${BASH_REMATCH[1]}"]='' fi done dkms_$DKMS_ACTION - show_errors + # display errors at the end, to maximize readers + local msg + for msg in "${ERROR_MESSAGES[@]}"; do + echo "==> ERROR: $msg" >&2 + done return 0 } diff --git a/dkms/hook.upgrade b/dkms/hook.upgrade index 8d1bc42ba1..46d4d42c04 100644 --- a/dkms/hook.upgrade +++ b/dkms/hook.upgrade @@ -9,5 +9,5 @@ Target = usr/lib/modules/*/modules.alias Description = Remove upgraded DKMS modules Depends = dkms When = PreTransaction -Exec = /usr/lib/dkms/alpm-hook -D remove +Exec = /usr/share/libalpm/scripts/dkms -D remove NeedsTargets