forked from pool/suse-module-tools
Accepting request 142369 from home:jengelh:dev
should have been part of 141930 OBS-URL: https://build.opensuse.org/request/show/142369 OBS-URL: https://build.opensuse.org/package/show/Base:System/suse-module-tools?expand=0&rev=1
This commit is contained in:
commit
d3ade7a35c
23
.gitattributes
vendored
Normal file
23
.gitattributes
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
## Default LFS
|
||||
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||
*.bsp filter=lfs diff=lfs merge=lfs -text
|
||||
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.gem filter=lfs diff=lfs merge=lfs -text
|
||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||
*.jar filter=lfs diff=lfs merge=lfs -text
|
||||
*.lz filter=lfs diff=lfs merge=lfs -text
|
||||
*.lzma filter=lfs diff=lfs merge=lfs -text
|
||||
*.obscpio filter=lfs diff=lfs merge=lfs -text
|
||||
*.oxt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.rpm filter=lfs diff=lfs merge=lfs -text
|
||||
*.tbz filter=lfs diff=lfs merge=lfs -text
|
||||
*.tbz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||
*.txz filter=lfs diff=lfs merge=lfs -text
|
||||
*.whl filter=lfs diff=lfs merge=lfs -text
|
||||
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.zst filter=lfs diff=lfs merge=lfs -text
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.osc
|
10
10-unsupported-modules.conf
Normal file
10
10-unsupported-modules.conf
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Every kernel module has a flag 'supported'. If this flag is not set loading
|
||||
# this module will taint your kernel. You will not get much help with a kernel
|
||||
# problem if your kernel is marked as tainted. In this case you firstly have
|
||||
# to avoid loading of unsupported modules.
|
||||
#
|
||||
# Setting allow_unsupported_modules 1 enables loading of unsupported modules
|
||||
# by modprobe, setting allow_unsupported_modules 0 disables it. This can
|
||||
# be overriden using the --allow-unsupported-modules commandline switch.
|
||||
allow_unsupported_modules 1
|
19
README.SUSE
Normal file
19
README.SUSE
Normal file
@ -0,0 +1,19 @@
|
||||
Please don't edit /etc/modprobe.conf. Place your settings into
|
||||
/etc/modprobe.conf.local instead.
|
||||
|
||||
|
||||
To avoid loading backup files of various tools and editors, modprobe skips
|
||||
files under /etc/modprobe.d/ that have the following prefixes
|
||||
|
||||
"."
|
||||
"~"
|
||||
|
||||
and the following suffixes
|
||||
|
||||
".rpmsave"
|
||||
".rpmorig"
|
||||
".rpmnew"
|
||||
".bak"
|
||||
".YaST2save"
|
||||
".-"
|
||||
"~"
|
17
depmod-00-system.conf
Normal file
17
depmod-00-system.conf
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# /etc/depmod.conf - configuration file for the depmod(8) command,
|
||||
# for its format see depmod.conf(5).
|
||||
#
|
||||
# Please don't edit this file, place your settings into the /etc/depmod.d
|
||||
# directory.
|
||||
|
||||
|
||||
# search order:
|
||||
# 1 updates/ (KMPs)
|
||||
# 2 extra/ (KMPs or manually compiled modules)
|
||||
# 3 weak-updates/ (KMPs built for older kernels)
|
||||
# 4 everything else
|
||||
search updates extra weak-updates built-in
|
||||
|
||||
# do not generate modules.*map files
|
||||
make_map_files no
|
314
driver-check.sh
Normal file
314
driver-check.sh
Normal file
@ -0,0 +1,314 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION="0.5"
|
||||
MAINTAINER="Michal Marek <mmarek@suse.cz>"
|
||||
USAGE="Usage: ${0##*/} [-o|--out output-file]"
|
||||
|
||||
errors=0
|
||||
warnings=0
|
||||
|
||||
trap 'rm -rf "$tmp"' EXIT
|
||||
tmp=$(mktemp -d)
|
||||
|
||||
rpm()
|
||||
{
|
||||
# rpm tends to send localized error messages to stdout :-(
|
||||
LC_ALL=C command rpm "$@"
|
||||
}
|
||||
|
||||
file_owner()
|
||||
{
|
||||
local f=$1
|
||||
|
||||
if (cd "$tmp/rpms"; grep -lFx "$f" *); then
|
||||
return
|
||||
fi
|
||||
rpm -qf "$f"
|
||||
}
|
||||
|
||||
_explain_called=()
|
||||
explain()
|
||||
{
|
||||
local caller=${BASH_LINENO[0]}
|
||||
|
||||
if test -n "${_explain_called[$caller]}"; then
|
||||
return
|
||||
fi
|
||||
_explain_called[$caller]=1
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
error()
|
||||
{
|
||||
echo "ERROR: $*"
|
||||
let errors++
|
||||
}
|
||||
|
||||
warning()
|
||||
{
|
||||
echo "warning: $*" >&2
|
||||
let warnings++
|
||||
}
|
||||
|
||||
check_system()
|
||||
{
|
||||
if test ! -x /usr/lib/module-init-tools/weak-modules2; then
|
||||
echo "This tool only works on SLE11 and later systems" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! zypper search >/dev/null; then
|
||||
echo "Cannot run zypper, please correct the above problem" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_rpm()
|
||||
{
|
||||
local rpm=$1 name=${1%-*-*}
|
||||
|
||||
# ignore changes to %config and %doc files and ignore changed mtimes
|
||||
if rpm -V "$rpm" | grep -Ev '^[^ ]{8,} [cd] |^\.{7}T\.* '; then
|
||||
error "$rpm was not installed correctly (see above)"
|
||||
fi
|
||||
# this is ugly. Apparently zypper insist on the progress messages and
|
||||
# the ascii table, so grep for the table row.
|
||||
if ! LC_ALL=C zypper -A search -t package -u -s --match-exact "$name" \
|
||||
| grep -qe ---; then
|
||||
error "$rpm: no update repositories found"
|
||||
fi
|
||||
}
|
||||
|
||||
check_kernel_package()
|
||||
{
|
||||
local kernel=$1
|
||||
|
||||
if ! rpm -q --qf '%{description}\n' "$kernel" | grep -q '^GIT '; then
|
||||
error "$kernel does not look like a SUSE kernel package (no commit id)"
|
||||
fi
|
||||
if ! rpm -q --qf '%{postin}\n' "$kernel" | grep -q 'weak-modules2'; then
|
||||
error "$kernel does not look like a SUSE kernel package (wrong %post script)"
|
||||
fi
|
||||
}
|
||||
|
||||
check_krel()
|
||||
{
|
||||
local krel=$1 system_map module_symvers msg res args bad=false
|
||||
local mit_version
|
||||
|
||||
system_map="/boot/System.map-$krel"
|
||||
module_symvers="/boot/symvers-$krel.gz"
|
||||
if ! test -e "$system_map"; then
|
||||
error "$system_map not found"
|
||||
bad=true
|
||||
fi
|
||||
if ! test -e "$module_symvers"; then
|
||||
error "$module_symvers not found"
|
||||
bad=true
|
||||
fi
|
||||
if $bad; then
|
||||
explain "Each kernel must install /boot/System.map-\$version and /boot/symvers-\$version.gz to be able to check module dependencies."
|
||||
return
|
||||
fi
|
||||
set -- $(/sbin/depmod --version | sed -rn 's/.* ([0-9]+)\.([0-9]+)(\..*)?/\1 \2/p')
|
||||
if test -n "$1" -a -n "$2"; then
|
||||
let "mit_version = $1 * 100 + $2"
|
||||
else
|
||||
warning "Cannot determine module-init-tools version, this is a bug in the script"
|
||||
mit_version=0
|
||||
fi
|
||||
# depmod -E was introduced in 3.10
|
||||
if test "$mit_version" -ge 310; then
|
||||
gzip -cd <"$module_symvers" >"$tmp/symvers"
|
||||
args=(-E "$tmp/symvers")
|
||||
else
|
||||
args=(-F "$system_map")
|
||||
fi
|
||||
msg=$(/sbin/depmod -n -e "${args[@]}" "$krel" 2>&1 >/dev/null)
|
||||
res=$?
|
||||
if test -n "$msg" -o "$res" -ne 0; then
|
||||
echo "$msg"
|
||||
error "depmod $krel returned errors (exit code $res)"
|
||||
explain "depmod must pass without errors otherwise KMP scripts will break"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
req_re='^(kernel\([^:]*:kernel[[:alnum:]_]*\)|ksym\([^:]*:(struct_module|module_layout)\)) = [0-9a-f]+'
|
||||
check_kmp()
|
||||
{
|
||||
local kmp=$1 prefix prev_krel krel path found_module=false
|
||||
|
||||
if ! rpm -q --qf '%{postin}\n' "$kmp" | grep -q 'weak-modules2'; then
|
||||
error "$kmp does not look like a SUSE kernel module package (wrong %post)"
|
||||
fi
|
||||
if ! rpm -q -R "$kmp" | grep -Eq "$req_re"; then
|
||||
error "$kmp does not have proper dependencies"
|
||||
fi
|
||||
exec 3< <(sed -rn 's:^(/lib/modules)?/([^/]*)/(.*\.ko)$:\1 \2 \3:p' \
|
||||
"$tmp/rpms/$kmp")
|
||||
while read prefix krel path <&3; do
|
||||
found_module=true
|
||||
if test "$prefix" != "/lib/modules"; then
|
||||
error "$kmp installs modules outside of /lib/modules"
|
||||
continue
|
||||
fi
|
||||
if test -z "$prev_krel"; then
|
||||
prev_krel=$krel
|
||||
elif test "$prev_krel" != "$krel"; then
|
||||
error "$kmp installs modules for multiple kernel versions"
|
||||
fi
|
||||
case "$path" in
|
||||
updates/* | extra/*)
|
||||
;;
|
||||
weak-updates/*)
|
||||
error "$kmp installs modules in weak-updates/ instead of updates/ or extra/"
|
||||
explain "The weak-modules directory is reserved for automatically generated symlinks"
|
||||
;;
|
||||
*)
|
||||
error "$kmp installs modules in an invalid directory"
|
||||
explain \
|
||||
"KMPs must install modules in the updates/ or extra/ subdirectories for the
|
||||
weak-modules2 script to work"
|
||||
;;
|
||||
esac
|
||||
|
||||
done
|
||||
if ! $found_module; then
|
||||
error "$kmp does not contain any modules"
|
||||
explain \
|
||||
"A KMP must contain it's modules in the rpm filelist, otherwise weak-modules2
|
||||
will not work"
|
||||
fi
|
||||
}
|
||||
|
||||
check_ko()
|
||||
{
|
||||
local ko=$1 kmp bad=false
|
||||
|
||||
case "$ko" in
|
||||
*/weak-updates/*)
|
||||
if test -L "$ko"; then
|
||||
return
|
||||
fi
|
||||
esac
|
||||
kmp=$(file_owner "$ko")
|
||||
case "$kmp" in
|
||||
kernel-* | *-kmp-*) ;;
|
||||
*not\ owned\ by\ any\ package)
|
||||
error "$ko is not owned by any package"
|
||||
bad=true
|
||||
;;
|
||||
*)
|
||||
error "$ko is not packaged as a KMP"
|
||||
bad=true
|
||||
;;
|
||||
esac
|
||||
if $bad; then
|
||||
explain \
|
||||
"External kernel modules must be packaged as KMPs, see
|
||||
http://developer.novell.com/wiki/index.php/Kernel_Module_Packages_Manuals"
|
||||
fi
|
||||
}
|
||||
|
||||
options=$(getopt -n "${0##*/}" -o o:h --long out:,help -- "$@")
|
||||
if test "$?" -ne 0; then
|
||||
echo "$USAGE" >&2
|
||||
exit 1
|
||||
fi
|
||||
eval set -- "$options"
|
||||
logfile="driver-check-report.txt"
|
||||
while :; do
|
||||
case "$1" in
|
||||
-o | --out)
|
||||
logfile="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
echo "${0##*/} $VERSION"
|
||||
echo "$USAGE"
|
||||
echo
|
||||
echo "Please report bugs and enhancement requests to $MAINTAINER"
|
||||
exit 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if test $# -gt 0; then
|
||||
echo "Unrecognized arguments: $*" >&2
|
||||
echo "$USAGE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
check_system
|
||||
|
||||
# set up redirection
|
||||
if test $logfile != "-"; then
|
||||
if test -e "$logfile"; then
|
||||
mv -f "$logfile" "$logfile~"
|
||||
fi
|
||||
if test -e /proc/self; then
|
||||
exec 99> >(cat >"$logfile")
|
||||
exec 1>&99
|
||||
exec 2> >(tee -a /proc/self/fd/99 >&2)
|
||||
else
|
||||
exec 1>"$logfile"
|
||||
exec 2>"$logfile"
|
||||
warning "/proc not mounted"
|
||||
fi
|
||||
fi
|
||||
echo "${0##*/} $VERSION started at $(date -R)" >&2
|
||||
|
||||
check_rpm $(rpm -q --qf '%{n}-%{v}-%{r}\n' module-init-tools)
|
||||
|
||||
mkdir -p "$tmp/rpms"
|
||||
found_kernel=false
|
||||
for rpm in $(rpm -qa --qf '%{n}-%{v}-%{r}\n' 'kernel-*' '*-kmp-*' | \
|
||||
/usr/lib/rpm/rpmsort); do
|
||||
case "$rpm" in
|
||||
kernel-source-* | kernel-syms-* | kernel-*-debug* | kernel-*-man-* | \
|
||||
kernel-*-devel-* | kernel-firmware-* | kernel-coverage-* | \
|
||||
kernel-docs-* | kernel-devel-*)
|
||||
continue
|
||||
esac
|
||||
# store the filelist to speed up file_owner()
|
||||
rpm -ql "$rpm" >"$tmp/rpms/$rpm"
|
||||
check_rpm "$rpm"
|
||||
case "$rpm" in
|
||||
kernel-*)
|
||||
check_kernel_package "$rpm"
|
||||
found_kernel=true
|
||||
;;
|
||||
*-kmp-*)
|
||||
check_kmp "$rpm"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if ! $found_kernel; then
|
||||
warning "no kernel package found"
|
||||
fi
|
||||
|
||||
for krel in /lib/modules/*/kernel; do
|
||||
krel=${krel%/kernel}
|
||||
krel=${krel##*/}
|
||||
check_krel "$krel"
|
||||
done
|
||||
|
||||
modules=($(find /lib/modules/ -name '*.ko'))
|
||||
for module in "${modules[@]}"; do
|
||||
check_ko "$module"
|
||||
done
|
||||
|
||||
echo "Found $errors error(s) and $warnings warning(s)" >&2
|
||||
if test "$logfile" != -; then
|
||||
echo "Report written to $logfile at $(date -R)" >&2
|
||||
else
|
||||
echo "Report finished at $(date -R)" >&2
|
||||
fi
|
||||
if test $errors -eq 0; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
3
modprobe.conf.tar.bz2
Normal file
3
modprobe.conf.tar.bz2
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1ac5daaf81b8c4c6c0aa83b9ffc89aedada1d1e8ff864166ecb52034a628b375
|
||||
size 2783
|
5
suse-module-tools.changes
Normal file
5
suse-module-tools.changes
Normal file
@ -0,0 +1,5 @@
|
||||
-------------------------------------------------------------------
|
||||
Wed Nov 14 18:31:35 UTC 2012 - jengelh@inai.de
|
||||
|
||||
- New package. Split SUSE-specific scripts from module-init-tools,
|
||||
so that we can actually get a system with kmod-compat running.
|
144
suse-module-tools.spec
Normal file
144
suse-module-tools.spec
Normal file
@ -0,0 +1,144 @@
|
||||
#
|
||||
# spec file for package suse-module-tools
|
||||
#
|
||||
# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
# upon. The license for this file, and modifications and additions to the
|
||||
# file, is the same license as for the pristine package itself (unless the
|
||||
# license for the pristine package is not an Open Source License, in which
|
||||
# case the license is the MIT License). An "Open Source License" is a
|
||||
# license that conforms to the Open Source Definition (Version 1.9)
|
||||
# published by the Open Source Initiative.
|
||||
|
||||
# Please submit bugfixes or comments via http://bugs.opensuse.org/
|
||||
#
|
||||
|
||||
|
||||
Name: suse-module-tools
|
||||
Version: 12.3
|
||||
Release: 0
|
||||
# for grepping /etc/SUSE-release
|
||||
PreReq: grep
|
||||
# nm and rpmsort (rpm) are required by the weak-modules script which is invoked
|
||||
# in post, it also requires getopt (coreutils) and sed
|
||||
PreReq: coreutils rpm
|
||||
# XXX: this should be nm OR eu-nm, the script works with both
|
||||
PreReq: /usr/bin/eu-nm /bin/sed
|
||||
Summary: Configuration for module loading and SUSE-specific utilities for KMPs
|
||||
License: GPL-2.0+
|
||||
Group: System/Base
|
||||
Source: README.SUSE
|
||||
Source2: modprobe.conf.tar.bz2
|
||||
Source3: depmod-00-system.conf
|
||||
Source4: 10-unsupported-modules.conf
|
||||
Source5: weak-modules
|
||||
Source6: weak-modules2
|
||||
Source7: driver-check.sh
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
BuildArch: noarch
|
||||
|
||||
%description
|
||||
This package contains helper scripts for KMP installation and
|
||||
uninstallation, as well as default configuration files for depmod and
|
||||
modprobe. These utilities are provided by kmod-compat or
|
||||
module-init-tools, whichever implementation you choose to install.
|
||||
|
||||
%prep
|
||||
%setup -Tcqa2
|
||||
|
||||
%build
|
||||
|
||||
%install
|
||||
b="%buildroot"
|
||||
mkdir -p "$b/%_docdir/module-init-tools"
|
||||
install -pm644 "%_sourcedir/README.SUSE" "$b/%_docdir/module-init-tools"
|
||||
#
|
||||
# now assemble the parts for modprobe.conf
|
||||
#
|
||||
cd modprobe.conf
|
||||
cp modprobe.conf.common 00-system.conf
|
||||
if [ -f "modprobe.conf.$RPM_ARCH" ]; then
|
||||
cat "modprobe.conf.$RPM_ARCH" >>00-system.conf
|
||||
fi
|
||||
install -d -m 755 "$b/etc/modprobe.d"
|
||||
install -pm644 "%_sourcedir/10-unsupported-modules.conf" \
|
||||
"$b/etc/modprobe.d/"
|
||||
install -pm644 00-system.conf "$b/etc/modprobe.d/"
|
||||
install -pm644 modprobe.conf.local "$b/etc/modprobe.d/99-local.conf"
|
||||
install -d -m 755 "$b/etc/depmod.d"
|
||||
install -pm 644 "%_sourcedir/depmod-00-system.conf" \
|
||||
"$b/etc/depmod.d/00-system.conf"
|
||||
|
||||
# "module-init-tools" name hardcoded in KMPs, mkinitrd, etc.
|
||||
install -d -m 755 "$b/usr/lib/module-init-tools"
|
||||
install -pm 755 %_sourcedir/weak-modules{,2} "$b/usr/lib/module-init-tools/"
|
||||
install -pm 755 %_sourcedir/driver-check.sh "$b/usr/lib/module-init-tools/"
|
||||
|
||||
%post
|
||||
test_allow_on_install()
|
||||
{
|
||||
# configure handling of unsupported modules
|
||||
# default is to allow them
|
||||
allow=1
|
||||
# if the obsolete LOAD_UNSUPPORTED_MODULES_AUTOMATICALLY variable is
|
||||
# set to no, don't allow (this was used in SLES 9 and 10)
|
||||
if test -e /etc/sysconfig/hardware/config; then
|
||||
. /etc/sysconfig/hardware/config
|
||||
if test "x$LOAD_UNSUPPORTED_MODULES_AUTOMATICALLY" = "xno"; then
|
||||
allow=0
|
||||
fi
|
||||
# obsolete
|
||||
rm /etc/sysconfig/hardware/config
|
||||
fi
|
||||
# don't change the setting during upgrade
|
||||
if test "$1" != 1; then
|
||||
return
|
||||
fi
|
||||
# on SLES, the default is not to allow unsupported modules
|
||||
if grep -qs "Enterprise Server" /etc/SuSE-release; then
|
||||
allow=0
|
||||
else
|
||||
return
|
||||
fi
|
||||
# unless the admin passed "oem-modules=1" to the kernel during install
|
||||
if grep -qs '\<oem-modules=1\>' /proc/cmdline; then
|
||||
allow=1
|
||||
return
|
||||
fi
|
||||
# or if the installer already loaded some unsupported modules
|
||||
# (see TAINT_NO_SUPPORT in /usr/src/linux/include/linux/kernel.h)
|
||||
tainted=$(cat /proc/sys/kernel/tainted 2>/dev/null || echo 0)
|
||||
if test $((tainted & (1<<30))) != 0; then
|
||||
allow=1
|
||||
return
|
||||
fi
|
||||
}
|
||||
# upgrade from old locations
|
||||
if test -e /etc/modprobe.d/unsupported-modules; then
|
||||
mv -f /etc/modprobe.d/unsupported-modules \
|
||||
/etc/modprobe.d/10-unsupported-modules.conf
|
||||
fi
|
||||
if test -e /etc/modprobe.conf.local; then
|
||||
mv -f /etc/modprobe.conf.local \
|
||||
/etc/modprobe.d/99-local.conf
|
||||
fi
|
||||
test_allow_on_install "$@"
|
||||
if test "$allow" = "0"; then
|
||||
sed -ri 's/^( *allow_unsupported_modules *) 1/\1 0/' \
|
||||
/etc/modprobe.d/10-unsupported-modules.conf
|
||||
fi
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%dir /etc/modprobe.d
|
||||
%config /etc/modprobe.d/00-system.conf
|
||||
%config(noreplace) /etc/modprobe.d/10-unsupported-modules.conf
|
||||
%config(noreplace) /etc/modprobe.d/99-local.conf
|
||||
%dir /etc/depmod.d
|
||||
%config /etc/depmod.d/00-system.conf
|
||||
%_docdir/module-init-tools
|
||||
/usr/lib/module-init-tools
|
||||
|
||||
%changelog
|
325
weak-modules
Normal file
325
weak-modules
Normal file
@ -0,0 +1,325 @@
|
||||
#! /bin/bash
|
||||
|
||||
# This script is only needed to uninstall old KMPs when updating
|
||||
# SLE10 to SLE11+. weak-modules2 is the script what should be used by new
|
||||
# packages
|
||||
|
||||
unset LANG LC_ALL LC_COLLATE
|
||||
|
||||
NM=
|
||||
if command -v nm >/dev/null; then
|
||||
NM=nm
|
||||
elif command -v eu-nm >/dev/null; then
|
||||
NM=eu-nm
|
||||
else
|
||||
echo "ERROR: nm not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if MODULE is compatible with kernel release KREL.
|
||||
module_is_compatible() {
|
||||
declare module=$1 krel=$2 module_krel=$(krel_of_module "$module")
|
||||
|
||||
if [ ! -e $tmpdir/all-symvers-$krel-$module_krel ]; then
|
||||
# Symbols exported by the "new" kernel
|
||||
if [ ! -e $tmpdir/symvers-$krel ]; then
|
||||
if [ -e /boot/symvers-$krel.gz ]; then
|
||||
zcat /boot/symvers-$krel.gz \
|
||||
| sed -r -ne 's:^0x0*([0-9a-f]+\t[0-9a-zA-Z_]+)\t.*:\1:p'
|
||||
fi > $tmpdir/symvers-$krel
|
||||
fi
|
||||
|
||||
# Symbols that other add-on modules of the "old" kernel export
|
||||
# (and that this module may require)
|
||||
if [ ! -e $tmpdir/extra-symvers-$module_krel ]; then
|
||||
if [ -e /lib/modules/$module_krel/updates ]; then
|
||||
find /lib/modules/$module_krel/updates -name '*.ko' \
|
||||
| xargs $NM -B \
|
||||
| sed -nre 's:^0*([0-9a-f]+) A __crc_(.*):\1 \2:p'
|
||||
fi > $tmpdir/extra-symvers-$module_krel
|
||||
fi
|
||||
|
||||
sort -u $tmpdir/symvers-$krel $tmpdir/extra-symvers-$module_krel \
|
||||
> $tmpdir/all-symvers-$krel-$module_krel
|
||||
fi
|
||||
|
||||
# If the module does not have modversions enabled, $tmpdir/modvers
|
||||
# will be empty.
|
||||
/sbin/modprobe --dump-modversions "$module" \
|
||||
| sed -r -e 's:^0x0*([0-9a-f]+\t.*):\1:' \
|
||||
| sort -u \
|
||||
> $tmpdir/modvers
|
||||
|
||||
# Only include lines of the second file in the output that don't
|
||||
# match lines in the first file. (The default separator is
|
||||
# <space>, so we are matching the whole line.)
|
||||
join -j 1 -v 2 $tmpdir/all-symvers-$krel-$module_krel \
|
||||
$tmpdir/modvers > $tmpdir/join
|
||||
|
||||
if [ ! -s $tmpdir/modvers ]; then
|
||||
echo "Warning: Module ${module##*/} from kernel $module_krel has no" \
|
||||
"modversions, so it cannot be reused for kernel $krel" >&2
|
||||
elif [ -s $tmpdir/join ]; then
|
||||
[ -n "$verbose" ] &&
|
||||
echo "Module ${module##*/} from kernel $module_krel is not compatible" \
|
||||
"with kernel $krel in symbols:" $(sed -e 's:.* ::' $tmpdir/join)
|
||||
elif [ "$krel" != "$module_krel" ]; then
|
||||
[ -n "$verbose" ] &&
|
||||
echo "Module ${module##*/} from kernel $module_krel is compatible" \
|
||||
"with kernel $krel"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Compute the kernel release of a module.
|
||||
krel_of_module() {
|
||||
declare module=$1
|
||||
set -- $(/sbin/modinfo -F vermagic "$module")
|
||||
echo "$1"
|
||||
}
|
||||
|
||||
# Read a list of modules from standard input, convert the filenames into
|
||||
# absolute names, and compute the kernel release of each module.
|
||||
read_modules_list() {
|
||||
local saved_IFS=$IFS
|
||||
IFS=$'\n'
|
||||
modules=($(cat))
|
||||
IFS=$saved_IFS
|
||||
|
||||
for ((n = 0; n < ${#modules[@]}; n++)); do
|
||||
if [ ${modules[n]:0:1} != / ]; then
|
||||
modules[n]=$PWD/${modules[n]}
|
||||
fi
|
||||
if [ -f "${modules[n]}" ]; then
|
||||
module_krels[n]=$(krel_of_module "${modules[n]}")
|
||||
else
|
||||
# Try to extract the kernel release from the path
|
||||
set -- "${modules[n]#/lib/modules/}"
|
||||
module_krels[n]=${1%%/*}
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
doit() {
|
||||
[ -n "$verbose" ] && echo "$@"
|
||||
[ -n "$dry_run" ] || "$@"
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: ${0##*/} [options] {--add-modules|--remove-modules}
|
||||
${0##*/} [options] {--add-kernel|--remove-kernel} {kernel-release}
|
||||
|
||||
--add-modules
|
||||
Add a list of modules read from standard input. Create
|
||||
symlinks in compatible kernel's weak-updates/ directory.
|
||||
The list of modules is read from standard input.
|
||||
|
||||
--remove-modules
|
||||
Remove compatibility symlinks from weak-updates/ directories
|
||||
for a list of modules. The list of modules is read from
|
||||
standard input.
|
||||
|
||||
--add-kernel
|
||||
Add compatibility symlinks for all compatible modules to the
|
||||
specified or running kernel.
|
||||
|
||||
--remove-kernel
|
||||
Remove all compatibility symlinks for the specified or current
|
||||
kernel.
|
||||
|
||||
--verbose
|
||||
Print the commands executed.
|
||||
|
||||
-dry-run
|
||||
Do not create/remove any files.
|
||||
EOF
|
||||
exit $1
|
||||
}
|
||||
|
||||
[ -e /etc/sysconfig/kernel ] && source /etc/sysconfig/kernel
|
||||
|
||||
unset ${!changed_modules_*} ${!changed_initrd_*}
|
||||
|
||||
module_has_changed() {
|
||||
declare module=$1 krel=$2
|
||||
|
||||
module=${module%.ko}
|
||||
module=${module##*/}
|
||||
|
||||
eval "changed_modules_${krel//[^a-zA-Z0-9]/_}=$krel"
|
||||
case " $INITRD_MODULES " in
|
||||
*" $module "*)
|
||||
eval "changed_initrd_${krel//[^a-zA-Z0-9]/_}=$krel"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
options=`getopt -o h --long help,add-modules,remove-modules \
|
||||
--long add-kernel,remove-kernel,dry-run,verbose -- "$@"`
|
||||
|
||||
[ $? -eq 0 ] || usage 1
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
--add-modules)
|
||||
add_modules=1
|
||||
;;
|
||||
--remove-modules)
|
||||
remove_modules=1
|
||||
;;
|
||||
--add-kernel)
|
||||
add_kernel=1
|
||||
;;
|
||||
--remove-kernel)
|
||||
remove_kernel=1
|
||||
;;
|
||||
--dry-run)
|
||||
dry_run=1
|
||||
;;
|
||||
--verbose)
|
||||
verbose=1
|
||||
;;
|
||||
-h|--help)
|
||||
usage 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "$add_modules$remove_modules$add_kernel$remove_kernel" != 1 ]; then
|
||||
usage 1
|
||||
fi
|
||||
if [ -n "$add_kernel" -o -n "$remove_kernel" ]; then
|
||||
[ $# -gt 1 ] && usage 1
|
||||
else
|
||||
[ $# -ne 0 ] && usage 1
|
||||
fi
|
||||
|
||||
tmpdir=$(mktemp -td ${0##*/}.XXXXXX)
|
||||
trap "rm -rf $tmpdir" EXIT
|
||||
|
||||
if [ -n "$add_modules" ]; then
|
||||
read_modules_list || exit 1
|
||||
if [ ${#modules[@]} -gt 0 ]; then
|
||||
for krel in $(ls /lib/modules/); do
|
||||
[ -e /boot/symvers-$krel.gz ] || continue
|
||||
for ((n = 0; n < ${#modules[@]}; n++)); do
|
||||
module=${modules[n]}
|
||||
module_krel=${module_krels[n]}
|
||||
case "$module" in
|
||||
/lib/modules/$krel/*)
|
||||
continue ;;
|
||||
esac
|
||||
subpath=${module#/lib/modules/$module_krel/updates}
|
||||
weak_module=/lib/modules/$krel/weak-updates/${subpath#/}
|
||||
if [ -r "$weak_module" ]; then
|
||||
weak_krel=$(krel_of_module "$weak_module")
|
||||
if [ "$weak_krel" != "$module_krel" ] &&
|
||||
[ "$(printf "%s\n" "$weak_krel" "$module_krel" \
|
||||
| /usr/lib/rpm/rpmsort | head -n 1)" = \
|
||||
"$module_krel" ]; then
|
||||
# Keep modules from more recent kernels.
|
||||
[ -n "$verbose" ] && echo \
|
||||
"Keeping module ${module##*/} from kernel $weak_krel for kernel $krel"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
if module_is_compatible $module $krel; then
|
||||
doit mkdir -p $(dirname $weak_module)
|
||||
doit ln -sf $module $weak_module
|
||||
module_has_changed $module $krel
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
elif [ -n "$remove_modules" ]; then
|
||||
read_modules_list || exit 1
|
||||
if [ ${#modules[@]} -gt 0 ]; then
|
||||
krels=($(ls /lib/modules/ | /usr/lib/rpm/rpmsort -r))
|
||||
for krel in "${krels[@]}"; do
|
||||
[ -e /boot/symvers-$krel.gz ] || continue
|
||||
for ((n = 0; n < ${#modules[@]}; n++)); do
|
||||
module=${modules[n]}
|
||||
[ -e "$module" ] && continue
|
||||
module_krel=${module_krels[n]}
|
||||
subpath=${module#/lib/modules/$module_krel/updates}
|
||||
weak_module=/lib/modules/$krel/weak-updates/${subpath#/}
|
||||
if [ "$(readlink "$weak_module")" = "$module" ]; then
|
||||
[ -n "$verbose" ] && echo \
|
||||
"Removing compatible module ${subpath#/} from kernel $krel"
|
||||
doit rm -f "$weak_module"
|
||||
for krel2 in "${krels[@]}"; do
|
||||
[ -e /boot/symvers-$krel2.gz ] || continue
|
||||
module=/lib/modules/$krel2/updates/${subpath#/}
|
||||
[ -e "$module" ] || continue
|
||||
if module_is_compatible "$module" "$krel2"; then
|
||||
[ -n "$verbose" ] && echo \
|
||||
"Adding compatible module ${module##*/} from kernel $krel2 instead"
|
||||
doit ln -s "$module" "$weak_module"
|
||||
break
|
||||
fi
|
||||
done
|
||||
doit rmdir --parents --ignore-fail-on-non-empty \
|
||||
"$(dirname "$weak_module")"
|
||||
module_has_changed $module $krel
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
elif [ -n "$add_kernel" ]; then
|
||||
add_krel=${1:-$(uname -r)}
|
||||
if [ ! -e /boot/symvers-$add_krel.gz ]; then
|
||||
echo "Symvers dump file /boot/symvers-$add_krel.gz" \
|
||||
"not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
for krel in $(ls /lib/modules/ | /usr/lib/rpm/rpmsort -r); do
|
||||
[ "$add_krel" = "$krel" ] && continue
|
||||
[ -d /lib/modules/$krel/updates ] || continue
|
||||
for module in $(find /lib/modules/$krel/updates -name '*.ko'); do
|
||||
subpath=${module#/lib/modules/$krel/updates}
|
||||
weak_module=/lib/modules/$add_krel/weak-updates/${subpath#/}
|
||||
[ -e "$weak_module" ] && continue
|
||||
if module_is_compatible $module $add_krel; then
|
||||
doit mkdir -p $(dirname $weak_module)
|
||||
doit ln -sf $module $weak_module
|
||||
fi
|
||||
done
|
||||
done
|
||||
elif [ -n "$remove_kernel" ]; then
|
||||
remove_krel=${1:-$(uname -r)}
|
||||
weak_modules=/lib/modules/$remove_krel/weak-updates
|
||||
doit rm -rf "$weak_modules"
|
||||
fi
|
||||
|
||||
for krel in ${!changed_modules_*}; do
|
||||
krel=${!krel}
|
||||
[ -e /boot/System.map-$krel ] || continue
|
||||
/sbin/depmod -ae -F /boot/System.map-$krel $krel
|
||||
done
|
||||
|
||||
for krel in ${!changed_initrd_*}; do
|
||||
krel=${!krel}
|
||||
[ -e /boot/System.map-$krel ] || continue
|
||||
|
||||
image=
|
||||
for x in vmlinuz image vmlinux linux bzImage uImage; do
|
||||
if [ -f /boot/$x-$krel ]; then
|
||||
image=$x
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -n "$image" ]; then
|
||||
/sbin/mkinitrd -k /boot/$image-$krel -i /boot/initrd-$krel
|
||||
fi
|
||||
done
|
||||
|
||||
# vim:shiftwidth=4 softtabstop=4
|
684
weak-modules2
Normal file
684
weak-modules2
Normal file
@ -0,0 +1,684 @@
|
||||
#! /bin/bash
|
||||
|
||||
##############################################################################
|
||||
# How it works:
|
||||
# * Kernels install modules below /lib/modules/$krel/kernel/.
|
||||
# * KMPs install modules below /lib/modules/$krel/updates/ or .../extra/.
|
||||
# * Symbolic links to modules of compatible KMPs are created under
|
||||
# /lib/modules/$krel/weak-updates/{updates,extra}/... (the original path
|
||||
# below /lib/modules/$other_krel is used).
|
||||
# * Depmod searches the directories in this order: updates/, extra/,
|
||||
# weak-updates/, kernel/ (see /etd/depmod.conf or
|
||||
# /etc/depmod.d/00-system.conf for details).
|
||||
# * Compatibility of a kernel with a KMP is defined as: The KMP is built
|
||||
# for the same flavor as the kernel and after adding the KMP modules to
|
||||
# the kernel, depmod -e -E Module.symvers reports no errors about
|
||||
# missing symbols or different symbol checksums. See the
|
||||
# has_unresolved_symbols() function for details.
|
||||
#
|
||||
# * At KMP install time (function add_kmp()), we create symbolic links
|
||||
# for all kernels that this KMP is compatible with. We skip kernels that
|
||||
# already contain symbolic links to a newer KMP of the same name,
|
||||
# contain the KMP itself or another version in updates/ or extra/ or
|
||||
# have overlapping module names with other KMPs in the respective
|
||||
# kernel (this should not happen).
|
||||
# * At kernel install time (functions add_kernel()), we create symbolic
|
||||
# links for each compatible KMP, unless the KMP or a different one with
|
||||
# overlapping module names is present in updates/ or extra/ (KMP build
|
||||
# against $krel can be installed before a kernel with that version).
|
||||
# When multiple KMPs of the same name are compatbile, we chose the one
|
||||
# with the highest version number. This is repeated when subsequent
|
||||
# subpackages (main or -extra) of that kernel are installed.
|
||||
# * At KMP removal time (function remove_kmp()), the modules and their
|
||||
# symlinks are removed and, where possible, replaced by symlinks to the
|
||||
# newest of the remaining compatible version of that KMP.
|
||||
# * [NOT IMPLEMENTED] When a kernel subpackage is removed, symlinks to
|
||||
# KMPs that become incompatible are removed as well. This is not
|
||||
# implemented, because removing the main subpackage and only keeping
|
||||
# the -base package AND having KMPs installed is not an expected
|
||||
# scenario, and implementing this would only slow down kernel updates.
|
||||
# * When the kernel is removed (function remove_kernel()), it's
|
||||
# weak-updates directory is also removed.
|
||||
#
|
||||
# naming conventions used in this script:
|
||||
# $kmp: name-version-release of a kmp, e.g kqemu-kmp-default-1.3.0pre11_2.6.25.16_0.1-7.1
|
||||
# $kmpshort: name of a kmp, e.g kqemu-kmp-default
|
||||
# $basename: portion of $kmp up to the "-kmp-" part, e.g kqemu
|
||||
# $flavor: flavor of a kmp or kernel, e.g default
|
||||
# $krel: kernel version, as in /lib/modules/$krel
|
||||
# $module: full path to a module below updates/
|
||||
# $symlink: full path to a module symlink below weak-updates/
|
||||
#
|
||||
# files in $tmpdir:
|
||||
# krel-$kmp: kernel version for which $kmp was built
|
||||
# modules-$kmp: list of modules in $kmp (full paths)
|
||||
# basenames-$kmp: list of basenames of modules in $kmp
|
||||
# kmps: list of kmps, newest first
|
||||
#
|
||||
|
||||
log() {
|
||||
[ -n "$opt_verbose" ] && echo "$@" >&2
|
||||
}
|
||||
|
||||
doit() {
|
||||
if [ -n "$doit" ]; then
|
||||
# override
|
||||
"$@"
|
||||
return
|
||||
fi
|
||||
log "$@"
|
||||
if [ -z "$opt_dry_run" ]; then
|
||||
"$@"
|
||||
else
|
||||
:
|
||||
fi
|
||||
}
|
||||
|
||||
filter_basenames() {
|
||||
sed -rn 's:/?lib/modules/.*/([^/]*\.ko)$:\1:p'
|
||||
}
|
||||
|
||||
# Name of the symlink that makes a module available to a given kernel
|
||||
symlink_to_module() {
|
||||
local module=$1 krel=$2
|
||||
|
||||
echo /lib/modules/$krel/weak-updates/${module#/lib/modules/*/}
|
||||
}
|
||||
|
||||
# Is a kmp already present in or linked to from this kernel?
|
||||
kmp_is_present() {
|
||||
local kmp=$1 krel=$2
|
||||
|
||||
if [ $krel = "$(cat $tmpdir/krel-$kmp)" ]; then
|
||||
return 0
|
||||
fi
|
||||
local module symlink
|
||||
while read module; do
|
||||
symlink=$(symlink_to_module $module $krel)
|
||||
[ $module -ef $symlink -o $module = "$(readlink $symlink)" ] || return 1
|
||||
done < $tmpdir/modules-$kmp
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Add the modules of a kmp to /lib/modules/$krel
|
||||
add_kmp_modules() {
|
||||
local kmp=$1 krel=$2 basedir=$3
|
||||
|
||||
[ -n "$kmp" ] || return 0
|
||||
|
||||
local module symlink
|
||||
while read module; do
|
||||
symlink=$(symlink_to_module $module $krel)
|
||||
doit mkdir -p ${opt_debug:+-v} $basedir${symlink%/*} || exit 1
|
||||
doit ln -sf ${opt_debug:+-v} $module $basedir$symlink || exit 1
|
||||
done < $tmpdir/modules-$kmp
|
||||
}
|
||||
|
||||
# Remove the modules of a kmp from /lib/modules/$krel
|
||||
remove_kmp_modules() {
|
||||
local kmp=$1 krel=$2 basedir=$3
|
||||
|
||||
[ -n "$kmp" ] || return 0
|
||||
|
||||
local module symlink
|
||||
while read module; do
|
||||
symlink=$(symlink_to_module $module $krel)
|
||||
doit rm -f ${opt_debug:+-v} $basedir$symlink
|
||||
done < $tmpdir/modules-$kmp
|
||||
}
|
||||
|
||||
# Create a temporary working copy of /lib/modules/$1
|
||||
create_temporary_modules_dir() {
|
||||
local modules_dir=/lib/modules/$1 basedir=$2
|
||||
local opt_v=${opt_debug:+-v}
|
||||
|
||||
mkdir -p $opt_v $basedir$modules_dir/weak-updates
|
||||
ln -s $opt_v $modules_dir/kernel $basedir$modules_dir/kernel
|
||||
|
||||
eval "$(find $modules_dir -path "$modules_dir/modules.*" -prune \
|
||||
-o -path "$modules_dir/kernel" -prune \
|
||||
-o -type d -printf "mkdir -p $opt_v $basedir%p\n" \
|
||||
-o -printf "ln -s $opt_v %p $basedir%p\n"
|
||||
)"
|
||||
}
|
||||
|
||||
# Check for unresolved symbols
|
||||
has_unresolved_symbols() {
|
||||
local krel=$1 basedir=$2 output status args sym_errors
|
||||
|
||||
if [ ! -e $tmpdir/symvers-$krel -a -e /boot/symvers-$krel.gz ]; then
|
||||
zcat /boot/symvers-$krel.gz > $tmpdir/symvers-$krel
|
||||
fi
|
||||
if [ -e $tmpdir/symvers-$krel ]; then
|
||||
args=(-E $tmpdir/symvers-$krel)
|
||||
else
|
||||
echo "warning: $tmpdir/symvers-$krel not available" >&2
|
||||
args=(-F /boot/System.map-$krel)
|
||||
fi
|
||||
output="$(/sbin/depmod -b "$basedir" -ae "${args[@]}" $krel 2>&1)"
|
||||
status=$?
|
||||
if [ $status -ne 0 ]; then
|
||||
echo "$output" >&2
|
||||
echo "depmod exited with error $status" >&2
|
||||
return 0
|
||||
fi
|
||||
sym_errors=$(echo "$output" | \
|
||||
grep -E ' (needs unknown|disagrees about version of) symbol ')
|
||||
if [ -n "$sym_errors" ]; then
|
||||
[ -z "$opt_debug" ] || echo "$sym_errors" >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# KMPs can only be added if none of the module basenames overlap
|
||||
basenames_are_unique() {
|
||||
local kmp=$1 krel=$2 basedir=$3 dir
|
||||
|
||||
for dir in $basedir/lib/modules/$krel/{weak-updates,updates,extra}/; do
|
||||
if [ ! -d "$dir" ]; then
|
||||
continue
|
||||
fi
|
||||
if [ -n "$(comm -1 -2 $tmpdir/basenames-$kmp \
|
||||
<(find "$dir" -not -type d -printf '%f\n' | sort -u))" ]; then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# Can a kmp be replaced by a different version of the same kmp in a kernel?
|
||||
# Set the old kmp to "" when no kmp is to be removed.
|
||||
can_replace_kmp() {
|
||||
local old_kmp=$1 new_kmp=$2 krel=$3
|
||||
|
||||
local basedir=$tmpdir/$krel
|
||||
local weak_updates=/lib/modules/$krel/weak-updates/
|
||||
|
||||
[ -d "$basedir" ] || \
|
||||
create_temporary_modules_dir "$krel" "$basedir"
|
||||
|
||||
# force doit() to execute the commands (in $tmpdir)
|
||||
doit=1 remove_kmp_modules "$old_kmp" "$krel" "$basedir"
|
||||
if ! basenames_are_unique "$new_kmp" "$krel" "$basedir"; then
|
||||
doit=1 add_kmp_modules "$old_kmp" "$krel" "$basedir"
|
||||
return 1
|
||||
fi
|
||||
doit=1 add_kmp_modules "$new_kmp" "$krel" "$basedir"
|
||||
if has_unresolved_symbols "$krel" "$basedir"; then
|
||||
doit=1 remove_kmp_modules "$new_kmp" "$krel" "$basedir"
|
||||
doit=1 add_kmp_modules "$old_kmp" "$krel" "$basedir"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Figure out which modules a kmp contains
|
||||
check_kmp() {
|
||||
local kmp=$1
|
||||
|
||||
# Make sure all modules are for the same kernel
|
||||
set -- $(sed -re 's:^/lib/modules/([^/]+)/.*:\1:' \
|
||||
$tmpdir/modules-$kmp \
|
||||
| sort -u)
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Error: package $kmp seems to contain modules for multiple" \
|
||||
"kernel versions" >&2
|
||||
return 1
|
||||
fi
|
||||
echo $1 > $tmpdir/krel-$kmp
|
||||
|
||||
# Make sure none of the modules are in kernel/ or weak-updates/
|
||||
if grep -qE -e '^/lib/modules/[^/]+/(kernel|weak-updates)/' \
|
||||
$tmpdir/modules-$kmp; then
|
||||
echo "Error: package $kmp must not install modules into " \
|
||||
"kernel/ or weak-updates/" >&2
|
||||
return 1
|
||||
fi
|
||||
sed -e 's:.*/::' $tmpdir/modules-$kmp \
|
||||
| sort -u > $tmpdir/basenames-$kmp
|
||||
}
|
||||
|
||||
# Figure out which kmps there are, and which modules they contain
|
||||
# set basename to '*' to find all kmps of a given flavor
|
||||
find_kmps() {
|
||||
local basename=$1 flavor=$2
|
||||
local kmp
|
||||
|
||||
for kmp in $(rpm -qa --qf '%{n}-%{v}-%{r}\n' --nodigest --nosignature "$basename-kmp-$flavor"); do
|
||||
rpm -ql --nodigest --nosignature "$kmp" \
|
||||
| grep -Ee '^/lib/modules/[^/]+/.+\.ko$' \
|
||||
> $tmpdir/modules-$kmp
|
||||
if [ $? != 0 ]; then
|
||||
echo "WARNING: $kmp does not contain any kernel modules" >&2
|
||||
rm -f $tmpdir/modules-$kmp
|
||||
continue
|
||||
fi
|
||||
|
||||
check_kmp $kmp || return 1
|
||||
done
|
||||
|
||||
printf "%s\n" $tmpdir/basenames-* \
|
||||
| sed -re "s:$tmpdir/basenames-::" \
|
||||
| /usr/lib/rpm/rpmsort -r \
|
||||
> $tmpdir/kmps
|
||||
}
|
||||
|
||||
previous_version_of_kmp() {
|
||||
local new_kmp=$1 krel=$2
|
||||
local module symlink old_kmp
|
||||
|
||||
while read module; do
|
||||
symlink=$(symlink_to_module $module $krel)
|
||||
[ -e "$symlink" ] || continue
|
||||
[ -L "$symlink" ] || return
|
||||
|
||||
old_kmp=$(grep -l "$(readlink "$symlink")" $tmpdir/modules-* | sed 's:.*/modules-::' ) || return
|
||||
# The package %NAME must be the same
|
||||
[ "${old_kmp%-*-*}" == "${new_kmp%-*-*}" ] || return
|
||||
# The other kmp must be older
|
||||
while read kmp; do
|
||||
[ "$kmp" == "$old_kmp" ] && return
|
||||
[ "$kmp" == "$new_kmp" ] && break
|
||||
done <$tmpdir/kmps
|
||||
done < $tmpdir/modules-$new_kmp
|
||||
echo "$old_kmp"
|
||||
}
|
||||
|
||||
# test if mkinitrd is needed for $krel. This should be decided by initrd itself
|
||||
# actually
|
||||
# stdin - list of changed modules ("_kernel_" for the whole kernel)
|
||||
needs_mkinitrd() {
|
||||
local krel=$1
|
||||
local changed_basenames=($(sort -u))
|
||||
|
||||
# Don't generate an initrd for kdump here. It's done automatically with mkdumprd when
|
||||
# /etc/init.d/boot.kdump is called to load the kdump kernel. See mkdumprd(8) why
|
||||
# it is done this way.
|
||||
if [[ "$krel" == *kdump* ]] ; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! [ -f /etc/fstab -a ! -e /.buildenv -a -x /sbin/mkinitrd ] ; then
|
||||
echo "Please run mkinitrd as soon as your system is complete." >&2
|
||||
return 1
|
||||
fi
|
||||
# KMPs can force mkinitrd run with %kernel_module_package -b that sets
|
||||
# this variable
|
||||
if test -n "$KMP_NEEDS_MKINITRD" && \
|
||||
! test "$KMP_NEEDS_MKINITRD" -eq 0 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
if [ "$changed_basenames" = "_kernel_" ]; then
|
||||
return 0
|
||||
fi
|
||||
if [ ! -e /boot/initrd-$krel ]; then
|
||||
return 0
|
||||
fi
|
||||
local initrd_basenames=($( (gzip -cd /boot/initrd-$krel | cpio -t --quiet | filter_basenames; INITRD_MODULES=; . /etc/sysconfig/kernel &>/dev/null; printf '%s.ko\n' $INITRD_MODULES) | sort -u))
|
||||
local i=($(join <(printf '%s\n' "${changed_basenames[@]}") \
|
||||
<(printf '%s\n' "${initrd_basenames[@]}") ))
|
||||
log "changed initrd modules for kernel $krel: ${i[@]-none}"
|
||||
if [ ${#i[@]} -gt 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# run depmod and mkinitrd for kernel version $krel
|
||||
# stdin - list of changed modules ("_kernel_" for a whole kernel)
|
||||
run_depmod_and_mkinitrd() {
|
||||
local krel=$1
|
||||
local status=0
|
||||
|
||||
if [ -d /lib/modules/$krel -a -f /boot/System.map-$krel ] ; then
|
||||
doit /sbin/depmod -F /boot/System.map-$krel -ae $krel || return 1
|
||||
fi
|
||||
if needs_mkinitrd $krel; then
|
||||
local image
|
||||
for x in vmlinuz image vmlinux linux bzImage uImage; do
|
||||
if [ -f /boot/$x-$krel ]; then
|
||||
image=$x
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -n "$image" ]; then
|
||||
doit /sbin/mkinitrd -k /boot/$image-$krel -i /boot/initrd-$krel
|
||||
status=$?
|
||||
# mkinitrd fails with status 10 if any required kernel modules
|
||||
# missing. We expect those modules to be added later (by one of
|
||||
# the other kernel-$flavor packages).
|
||||
if [ $status -eq 10 ]; then
|
||||
log "mkinitrd failed with status 10 (module missing), proceeding"
|
||||
status=0
|
||||
fi
|
||||
else
|
||||
echo "WARNING: kernel image for $krel not found!" >&2
|
||||
fi
|
||||
fi
|
||||
return $status
|
||||
}
|
||||
|
||||
kernel_changed() {
|
||||
local krel=$1 flavor=${1##*-}
|
||||
|
||||
if [ ! -f /boot/System.map-$krel ]; then
|
||||
# this kernel does not exist anymore
|
||||
return 0
|
||||
fi
|
||||
if [ ! -d /lib/modules/$krel ]; then
|
||||
# a kernel without modules - run mkinitrd nevertheless (to mount the
|
||||
# root fs, etc).
|
||||
echo "_kernel_" | run_depmod_and_mkinitrd "$krel"
|
||||
return
|
||||
fi
|
||||
|
||||
find_kmps '*' $flavor || return 1
|
||||
local kmps=( $(cat $tmpdir/kmps) )
|
||||
|
||||
while :; do
|
||||
[ ${#kmps[@]} -gt 0 ] || break
|
||||
local added='' skipped='' n kmp
|
||||
for ((n=0; n<${#kmps[@]}; n++)); do
|
||||
kmp=${kmps[n]}
|
||||
[ -n "$kmp" ] || continue
|
||||
|
||||
if kmp_is_present $kmp $krel; then
|
||||
log "Package $kmp does not need to be added to kernel $krel"
|
||||
kmps[n]=''
|
||||
continue
|
||||
fi
|
||||
local old_kmp=$(previous_version_of_kmp $kmp $krel)
|
||||
if can_replace_kmp "$old_kmp" $kmp $krel; then
|
||||
remove_kmp_modules "$old_kmp" "$krel"
|
||||
add_kmp_modules "$kmp" "$krel"
|
||||
if [ -z "$old_kmp" ]; then
|
||||
log "Package $kmp added to kernel $krel"
|
||||
else
|
||||
log "Package $old_kmp replaced by package $kmp in kernel $krel"
|
||||
fi
|
||||
added=1
|
||||
kmps[n]=''
|
||||
continue
|
||||
fi
|
||||
skipped=1
|
||||
done
|
||||
[ -n "$added" -a -n "$skipped" ] || break
|
||||
done
|
||||
echo "_kernel_" | run_depmod_and_mkinitrd "$krel"
|
||||
}
|
||||
|
||||
add_kernel() {
|
||||
local krel=$1
|
||||
|
||||
kernel_changed $krel
|
||||
}
|
||||
|
||||
remove_kernel() {
|
||||
local krel=$1
|
||||
|
||||
local dir=/lib/modules/$krel
|
||||
if [ -d $dir/weak-updates ]; then
|
||||
rm -rf $dir/weak-updates
|
||||
fi
|
||||
# If there are no KMPs left, remove the empty directory
|
||||
rmdir $dir 2>/dev/null
|
||||
}
|
||||
|
||||
add_kernel_modules() {
|
||||
local krel=$1
|
||||
cat >/dev/null
|
||||
|
||||
kernel_changed $krel
|
||||
}
|
||||
|
||||
remove_kernel_modules() {
|
||||
local krel=$1
|
||||
cat >/dev/null
|
||||
|
||||
# FIXME: remove KMP symlinks that no longer work
|
||||
kernel_changed $krel
|
||||
}
|
||||
|
||||
add_kmp() {
|
||||
local kmp=$1 kmpshort=${1%-*-*}
|
||||
local basename=${kmpshort%-kmp-*} flavor=${kmpshort##*-}
|
||||
|
||||
# Find the kmp to be added as well as any previous versions
|
||||
find_kmps "$basename" "$flavor" || return 1
|
||||
|
||||
local dir krel status
|
||||
for dir in /lib/modules/*; do
|
||||
krel=${dir#/lib/modules/}
|
||||
case "$krel" in
|
||||
*-$flavor)
|
||||
;;
|
||||
*)
|
||||
continue
|
||||
esac
|
||||
[ -d $dir -a -f /boot/System.map-$krel ] || continue
|
||||
if opt_debug=1 has_unresolved_symbols "$krel" "/"; then
|
||||
echo "Warning: /lib/modules/$krel is inconsistent" >&2
|
||||
echo "Warning: weak-updates symlinks might not be created" >&2
|
||||
fi
|
||||
|
||||
if kmp_is_present $kmp $krel; then
|
||||
log "Package $kmp does not need to be added to kernel $krel"
|
||||
run_depmod_and_mkinitrd "$krel" <$tmpdir/basenames-$kmp || \
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
local old_kmp=$(previous_version_of_kmp $kmp $krel)
|
||||
if can_replace_kmp "$old_kmp" $kmp $krel; then
|
||||
remove_kmp_modules "$old_kmp" "$krel"
|
||||
add_kmp_modules "$kmp" "$krel"
|
||||
if [ -z "$old_kmp" ]; then
|
||||
log "Package $kmp added to kernel $krel"
|
||||
run_depmod_and_mkinitrd "$krel" <$tmpdir/basenames-$kmp || \
|
||||
status=1
|
||||
else
|
||||
log "Package $old_kmp replaced by package $kmp in kernel $krel"
|
||||
cat $tmpdir/basenames-{$old_kmp,$kmp} \
|
||||
| run_depmod_and_mkinitrd "$krel" || status=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
return $status
|
||||
}
|
||||
|
||||
remove_kmp() {
|
||||
local kmp=$1 kmpshort=${1%-*-*}
|
||||
local basename=${kmpshort%-kmp-*} flavor=${kmpshort##*-}
|
||||
|
||||
# Find any previous versions of the same kmp
|
||||
find_kmps "$basename" "$flavor" || return 1
|
||||
|
||||
# Read the list of module names from standard input
|
||||
# (This kmp may already have been removed!)
|
||||
cat > $tmpdir/modules-$kmp
|
||||
check_kmp "$kmp" || return 1
|
||||
|
||||
local dir krel status
|
||||
for dir in /lib/modules/*; do
|
||||
krel=${dir#/lib/modules/}
|
||||
case "$krel" in
|
||||
*-$flavor)
|
||||
;;
|
||||
*)
|
||||
continue
|
||||
esac
|
||||
[ -d $dir -a -f /boot/System.map-$krel ] || continue
|
||||
if opt_debug=1 has_unresolved_symbols "$krel" "/"; then
|
||||
echo "Warning: /lib/modules/$krel is inconsistent" >&2
|
||||
echo "Warning: weak-updates symlinks might not be created" >&2
|
||||
fi
|
||||
if kmp_is_present $kmp $krel; then
|
||||
if [ $krel != "$(cat $tmpdir/krel-$kmp)" ]; then
|
||||
remove_kmp_modules "$kmp" "$krel"
|
||||
fi
|
||||
|
||||
local other_kmp
|
||||
while read other_kmp; do
|
||||
[ "$kmp" != "$other_kmp" ] || continue
|
||||
|
||||
if can_replace_kmp "" "$other_kmp" "$krel"; then
|
||||
add_kmp_modules "$other_kmp" "$krel"
|
||||
break
|
||||
fi
|
||||
done < $tmpdir/kmps
|
||||
if [ -n "$other_kmp" ]; then
|
||||
log "Package $kmp replaced by package $other_kmp in kernel $krel"
|
||||
cat $tmpdir/basenames-{$kmp,$other_kmp} \
|
||||
| run_depmod_and_mkinitrd "$krel" || status=1
|
||||
else
|
||||
log "Package $kmp removed from kernel $krel"
|
||||
run_depmod_and_mkinitrd "$krel" <$tmpdir/basenames-$kmp || \
|
||||
status=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
return $status
|
||||
}
|
||||
|
||||
help() {
|
||||
cat <<EOF
|
||||
${0##*/} --add-kmp kmp-name-version-release
|
||||
To be called in %post of kernel module packages. Creates
|
||||
symlinks in compatible kernel's weak-updates/ directory and runs
|
||||
mkinitrd if needed.
|
||||
|
||||
${0##*/} --remove-kmp kmp-name < module-list
|
||||
To be called in %postun of kernel module packages. Removes
|
||||
weak-updates/ symlinks for this KMP. As the KMP doesn't exist in
|
||||
the RPM database at this point, the list of modules has to be
|
||||
passed on standard input. Runs mkinitrd if needed.
|
||||
|
||||
${0##*/} --add-kernel kernel-release
|
||||
To be called in %post of the kernel base package. Adds
|
||||
compatibility symlinks for all compatible KMPs and runs mkinitrd
|
||||
if needed.
|
||||
|
||||
${0##*/} --remove-kernel kernel-release
|
||||
To be called in %postun of the kernel base package. Removes all
|
||||
compatibility symlinks.
|
||||
|
||||
${0##*/} --add-kernel-modules kernel-release < module-list
|
||||
To be called in %post of kernel subpackages that only contain
|
||||
modules (i.e. not kernel-*-base). Adds newly available
|
||||
compatibity symlinks and runs mkinitrd if needed.
|
||||
|
||||
${0##*/} --remove-kernel-modules kernel-release < module-list
|
||||
To be called in %postun of kernel subpackages that only contain
|
||||
modules (i.e. not kernel-*-base). Removes no longer working
|
||||
compatibity symlinks and runs mkinitrd if needed.
|
||||
|
||||
${0##*/} --verbose ...
|
||||
Print commands as they are executed and other information.
|
||||
|
||||
${0##*/} --dry-run ...
|
||||
Do not perform any changes to the system. Useful together with
|
||||
--verbose for debugging.
|
||||
EOF
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Usage:"
|
||||
help | sed -n 's/^[^[:blank:]]/ &/p'
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
|
||||
save_argv=("$@")
|
||||
options=`getopt -o vh --long add-kernel,remove-kernel,add-kmp,remove-kmp \
|
||||
--long add-kernel-modules,remove-kernel-modules \
|
||||
--long usage,help,verbose,dry-run,debug -- "$@"`
|
||||
if [ $? -ne 0 ]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
eval set -- "$options"
|
||||
mode=
|
||||
while :; do
|
||||
case "$1" in
|
||||
--add-kernel | --remove-kernel | --add-kernel-modules | \
|
||||
--remove-kernel-modules | --add-kmp | --remove-kmp )
|
||||
mode="$1"
|
||||
;;
|
||||
-v | --verbose)
|
||||
opt_verbose=1
|
||||
;;
|
||||
--dry-run)
|
||||
opt_dry_run=1
|
||||
;;
|
||||
--debug)
|
||||
opt_debug=1
|
||||
;;
|
||||
--usage)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-h | --help)
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
err=
|
||||
case "$mode" in
|
||||
"")
|
||||
err="Please specify one of the --add-* or --remove-* options"
|
||||
;;
|
||||
--add-kernel | --remove-kernel)
|
||||
if [ $# -gt 1 ]; then
|
||||
err="Too many arguments to $mode"
|
||||
fi
|
||||
[ $# -eq 1 ] || set -- $(uname -r)
|
||||
;;
|
||||
*)
|
||||
if [ $# -ne 1 ]; then
|
||||
err="Option $mode requires exactly one argument"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if [ -n "$err" ]; then
|
||||
echo "ERROR: $err" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#unset LANG LC_ALL LC_COLLATE
|
||||
|
||||
tmpdir=$(mktemp -d /var/tmp/${0##*/}.XXXXXX)
|
||||
trap "rm -rf $tmpdir" EXIT
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
case $mode in
|
||||
--add-kernel)
|
||||
add_kernel "$1"
|
||||
;;
|
||||
--remove-kernel)
|
||||
remove_kernel "$1"
|
||||
;;
|
||||
--add-kernel-modules)
|
||||
add_kernel_modules "$1"
|
||||
;;
|
||||
--remove-kernel-modules)
|
||||
remove_kernel_modules "$1"
|
||||
;;
|
||||
--add-kmp)
|
||||
add_kmp "$1"
|
||||
;;
|
||||
--remove-kmp)
|
||||
remove_kmp "$1"
|
||||
esac
|
||||
|
||||
# vim:shiftwidth=4 softtabstop=4
|
Loading…
Reference in New Issue
Block a user