|
|
f1da6a |
#!/bin/bash
|
|
|
f1da6a |
#
|
|
|
f1da6a |
# weak-modules - determine which modules are kABI compatible with installed
|
|
|
f1da6a |
# kernels and set up the symlinks in /lib/*/weak-updates.
|
|
|
f1da6a |
#
|
|
|
f1da6a |
# Changelog:
|
|
|
f1da6a |
#
|
|
|
f1da6a |
# 2010/01/10 - Further updates for dracut use on Fedora/RHEL (jcm).
|
|
|
f1da6a |
# 2009/09/16 - Rebase and add a bunch of updates for dracut (jcm).
|
|
|
f1da6a |
|
|
|
f1da6a |
unset LANG LC_ALL LC_COLLATE
|
|
|
f1da6a |
|
|
|
f1da6a |
tmpdir=$(mktemp -td ${0##*/}.XXXXXX)
|
|
|
f1da6a |
trap "rm -rf $tmpdir" EXIT
|
|
|
f1da6a |
unset ${!changed_modules_*} ${!changed_initramfs_*}
|
|
|
f1da6a |
|
|
|
f1da6a |
initramfs_prefix="/boot" # can customize here
|
|
|
f1da6a |
dracut="/sbin/dracut"
|
|
|
f1da6a |
|
|
|
f1da6a |
if [ ! -x "$dracut" ]
|
|
|
f1da6a |
then
|
|
|
f1da6a |
echo "weak-modules: this tool requires a dracut-enabled kernel"
|
|
|
f1da6a |
exit 1
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
|
|
|
f1da6a |
# doit:
|
|
|
f1da6a |
# A wrapper used whenever we're going to perform a real operation.
|
|
|
f1da6a |
doit() {
|
|
|
f1da6a |
[ -n "$verbose" ] && echo "$@"
|
|
|
f1da6a |
[ -n "$dry_run" ] || "$@"
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
# rpmsort: The sort in coreutils can't sort the RPM list how we want it so we
|
|
|
f1da6a |
# instead transform the list into a form it will sort correctly, then sort.
|
|
|
f1da6a |
rpmsort() {
|
|
|
f1da6a |
local IFS=$' '
|
|
|
f1da6a |
REVERSE=""
|
|
|
f1da6a |
rpmlist=($(cat))
|
|
|
f1da6a |
|
|
|
f1da6a |
if [ "-r" == "$1" ];
|
|
|
f1da6a |
then
|
|
|
f1da6a |
REVERSE="-r"
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
|
|
|
f1da6a |
echo ${rpmlist[@]} | \
|
|
|
f1da6a |
sed -e 's/-/../g' | \
|
|
|
f1da6a |
sort ${REVERSE} -n -t"." -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 -k6,6 -k7,7 \
|
|
|
f1da6a |
-k8,8 -k9,9 -k10,10 | \
|
|
|
f1da6a |
sed -e 's/\.\./-/g'
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
# read_modules_list:
|
|
|
f1da6a |
# Read in a list of modules from standard input. Convert the filenames into
|
|
|
f1da6a |
# absolute paths and compute the kernel release for each module (either using
|
|
|
f1da6a |
# the modinfo section or through the absolute path.
|
|
|
f1da6a |
read_modules_list() {
|
|
|
f1da6a |
local IFS=$'\n'
|
|
|
f1da6a |
modules=($(cat))
|
|
|
f1da6a |
|
|
|
f1da6a |
for ((n = 0; n < ${#modules[@]}; n++)); do
|
|
|
f1da6a |
if [ ${modules[n]:0:1} != '/' ]; then
|
|
|
f1da6a |
modules[n]="$PWD/${modules[n]}"
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
if [ -f "${modules[n]}" ]; then
|
|
|
f1da6a |
module_krels[n]=$(krel_of_module ${modules[n]})
|
|
|
f1da6a |
else
|
|
|
f1da6a |
# Try to extract the kernel release from the path
|
|
|
1cb8b8 |
set -- "${modules[n]#*/lib/modules/}"
|
|
|
f1da6a |
module_krels[n]=${1%%/*}
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
done
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
6f41c8 |
pad() {
|
|
|
6f41c8 |
local len=$1
|
|
|
6f41c8 |
local padding=$2
|
|
|
6f41c8 |
|
|
|
6f41c8 |
echo "$(( $len + (($padding - ($len % $padding)) % $padding) ))"
|
|
|
6f41c8 |
}
|
|
|
6f41c8 |
|
|
|
6f41c8 |
cpio_len() {
|
|
|
6f41c8 |
local input=$1
|
|
|
6f41c8 |
local maxlen="$(( $(stat -c %s "$input") - 110))"
|
|
|
6f41c8 |
local len=0
|
|
|
6f41c8 |
local cpio_filename
|
|
|
6f41c8 |
local cpio_namesize
|
|
|
6f41c8 |
local cpio_filename
|
|
|
6f41c8 |
local cpio_headersize
|
|
|
6f41c8 |
|
|
|
6f41c8 |
while [ "$len" -lt "$maxlen" ]; do
|
|
|
6f41c8 |
cpio_filesize="0x$(dd if="$input" bs=1 skip="$(($len + 54))" count=8 2>/dev/null)"
|
|
|
6f41c8 |
cpio_namesize="0x$(dd if="$input" bs=1 skip="$(($len + 94))" count=8 2>/dev/null)"
|
|
|
6f41c8 |
cpio_filename="$(dd if="$input" bs=1 skip="$(($len + 110))" count="$(($cpio_namesize))" 2>/dev/null)"
|
|
|
6f41c8 |
|
|
|
6f41c8 |
# Pad the header size to a multiple of 4
|
|
|
6f41c8 |
cpio_headersize="$(pad "$((110 + $cpio_namesize))" 4)"
|
|
|
6f41c8 |
|
|
|
6f41c8 |
# Pad the file length to a multiple of 4
|
|
|
6f41c8 |
cpio_filesize="$(pad "$cpio_filesize" 4)"
|
|
|
6f41c8 |
|
|
|
6f41c8 |
len="$(($len + $cpio_headersize + $cpio_filesize))"
|
|
|
6f41c8 |
|
|
|
6f41c8 |
if [ "$cpio_filename" = "TRAILER!!!" ]; then
|
|
|
6f41c8 |
break
|
|
|
6f41c8 |
fi
|
|
|
6f41c8 |
done
|
|
|
6f41c8 |
|
|
|
6f41c8 |
# Pad the whole thing to a multiple of 512
|
|
|
6f41c8 |
echo "$(pad "$len" 512)"
|
|
|
6f41c8 |
}
|
|
|
6f41c8 |
|
|
|
6f41c8 |
decompress_initramfs() {
|
|
|
6f41c8 |
local input=$1
|
|
|
6f41c8 |
local output=$2
|
|
|
6f41c8 |
|
|
|
6f41c8 |
# First, check if this is compressed at all
|
|
|
6f41c8 |
if cpio -i -t < "$input" > /dev/null 2>/dev/null; then
|
|
|
6f41c8 |
# If this archive contains a file early_cpio, it's a trick. Strip off
|
|
|
6f41c8 |
# the early cpio archive and try again.
|
|
|
6f41c8 |
if cpio -i -t < "$input" 2>/dev/null | grep -q '^early_cpio$' ; then
|
|
|
6f41c8 |
dd if="$input" of="${tmpdir}/post_early_cpio.img" ibs=1 skip="$(cpio_len "$input")" 2>/dev/null
|
|
|
6f41c8 |
decompress_initramfs "${tmpdir}/post_early_cpio.img" "$output"
|
|
|
6f41c8 |
retval="$?"
|
|
|
6f41c8 |
rm -f "${tmpdir}/post_early_cpio.img"
|
|
|
6f41c8 |
return $retval
|
|
|
6f41c8 |
fi
|
|
|
6f41c8 |
|
|
|
6f41c8 |
cp "$input" "$output"
|
|
|
6f41c8 |
return 0
|
|
|
6f41c8 |
fi
|
|
|
6f41c8 |
|
|
|
6f41c8 |
# Try gzip
|
|
|
6f41c8 |
if gzip -cd < "$input" > "$output" 2>/dev/null ; then
|
|
|
6f41c8 |
return 0
|
|
|
6f41c8 |
fi
|
|
|
6f41c8 |
|
|
|
6f41c8 |
# Next try xz
|
|
|
6f41c8 |
if xz -cd < "$input" > "$output" 2>/dev/null ; then
|
|
|
6f41c8 |
return 0
|
|
|
6f41c8 |
fi
|
|
|
6f41c8 |
|
|
|
6f41c8 |
echo "Unable to decompress $input: Unknown format" >&2
|
|
|
6f41c8 |
return 1
|
|
|
6f41c8 |
}
|
|
|
6f41c8 |
|
|
|
f1da6a |
# read_old_initramfs:
|
|
|
f1da6a |
compare_initramfs_modules() {
|
|
|
f1da6a |
local old_initramfs=$1
|
|
|
f1da6a |
local new_initramfs=$2
|
|
|
f1da6a |
|
|
|
f1da6a |
rm -rf "$tmpdir/old_initramfs"
|
|
|
f1da6a |
rm -rf "$tmpdir/new_initramfs"
|
|
|
f1da6a |
mkdir "$tmpdir/old_initramfs"
|
|
|
f1da6a |
mkdir "$tmpdir/new_initramfs"
|
|
|
f1da6a |
|
|
|
6f41c8 |
decompress_initramfs "$old_initramfs" "$tmpdir/old_initramfs.img"
|
|
|
f1da6a |
pushd "$tmpdir/old_initramfs" >/dev/null
|
|
|
6f41c8 |
cpio -i < "$tmpdir/old_initramfs.img" 2>/dev/null
|
|
|
6f41c8 |
rm "$tmpdir/old_initramfs.img"
|
|
|
f1da6a |
n=0; for i in `find . -iname \*.ko|sort`; do
|
|
|
f1da6a |
old_initramfs_modules[n]="$i"
|
|
|
f1da6a |
n=$((n+1))
|
|
|
f1da6a |
done
|
|
|
f1da6a |
popd >/dev/null
|
|
|
f1da6a |
|
|
|
6f41c8 |
decompress_initramfs "$new_initramfs" "$tmpdir/new_initramfs.img"
|
|
|
f1da6a |
pushd "$tmpdir/new_initramfs" >/dev/null
|
|
|
6f41c8 |
cpio -i < "$tmpdir/new_initramfs.img" 2>/dev/null
|
|
|
6f41c8 |
rm "$tmpdir/new_initramfs.img"
|
|
|
f1da6a |
n=0; for i in `find . -iname \*.ko|sort`; do
|
|
|
f1da6a |
new_initramfs_modules[n]="$i"
|
|
|
f1da6a |
n=$((n+1))
|
|
|
f1da6a |
done
|
|
|
f1da6a |
popd >/dev/null
|
|
|
f1da6a |
|
|
|
f1da6a |
if [ "${#old_initramfs_modules[@]}" == "${#new_initramfs_modules[@]}" ];
|
|
|
f1da6a |
then
|
|
|
f1da6a |
for ((n = 0; n < ${#old_initramfs_modules[@]}; n++)); do
|
|
|
f1da6a |
old_md5=`md5sum $tmpdir/old_initramfs/${old_initramfs_modules[n]}|sed -nre 's:(^\ )* .*:\1:p'`
|
|
|
f1da6a |
new_md5=`md5sum $tmpdir/new_initramfs/${new_initramfs_modules[n]}|sed -nre 's:(^\ )* .*:\1:p'`
|
|
|
f1da6a |
if [ ! "$old_md5" == "$new_md5" ];
|
|
|
f1da6a |
then
|
|
|
f1da6a |
return 1
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
done
|
|
|
f1da6a |
else
|
|
|
f1da6a |
return 1
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
|
|
|
f1da6a |
return 0
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
# check_initramfs:
|
|
|
f1da6a |
# check and possibly also update the initramfs for changed kernels
|
|
|
f1da6a |
check_initramfs() {
|
|
|
f1da6a |
local kernel=$1
|
|
|
f1da6a |
|
|
|
f1da6a |
# If there is no initramfs already we will not make one here.
|
|
|
f1da6a |
if [ -e "$initramfs_prefix/initramfs-$kernel.img" ];
|
|
|
f1da6a |
then
|
|
|
f1da6a |
old_initramfs="$initramfs_prefix/initramfs-$kernel.img"
|
|
|
f1da6a |
tmp_initramfs="$initramfs_prefix/initramfs-$kernel.tmp"
|
|
|
f1da6a |
new_initramfs="$initramfs_prefix/initramfs-$kernel.img"
|
|
|
f1da6a |
|
|
|
f1da6a |
$dracut -f "$tmp_initramfs" "$kernel"
|
|
|
f1da6a |
|
|
|
f1da6a |
if ! $(compare_initramfs_modules "$old_initramfs" "$tmp_initramfs");
|
|
|
f1da6a |
then
|
|
|
f1da6a |
doit mv "$tmp_initramfs" "$new_initramfs"
|
|
|
f1da6a |
else
|
|
|
f1da6a |
rm -f "$tmp_initramfs"
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
# krel_of_module:
|
|
|
f1da6a |
# Compute the kernel release of a module.
|
|
|
f1da6a |
krel_of_module() {
|
|
|
f1da6a |
declare module=$1
|
|
|
f1da6a |
/sbin/modinfo -F vermagic "$module" | awk '{print $1}'
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
# module_is_compatible:
|
|
|
f1da6a |
# Determine if a module is compatible with a particular kernel release. Also
|
|
|
f1da6a |
# include any symbol deps that might be introduced by other external kmods.
|
|
|
f1da6a |
module_is_compatible() {
|
|
|
f1da6a |
declare module=$1 krel=$2 module_krel=$(krel_of_module "$module")
|
|
|
f1da6a |
|
|
|
f1da6a |
if [ ! -e "$tmpdir/all-symvers-$krel-$module_krel" ]; then
|
|
|
f1da6a |
# Symbols exported by the "new" kernel
|
|
|
f1da6a |
if [ ! -e $tmpdir/symvers-$krel ]; then
|
|
|
f1da6a |
if [ -e /boot/symvers-$krel.gz ]; then
|
|
|
f1da6a |
zcat /boot/symvers-$krel.gz \
|
|
|
f1da6a |
| sed -r -ne 's:^(0x[0]*[0-9a-f]{8}\t[0-9a-zA-Z_]+)\t.*:\1:p'
|
|
|
f1da6a |
fi > $tmpdir/symvers-$krel
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
|
|
|
f1da6a |
# Symbols that other add-on modules of the "old" kernel export
|
|
|
f1da6a |
# (and that this module may require)
|
|
|
f1da6a |
if [ ! -e "$tmpdir/extra-symvers-$module_krel" ]; then
|
|
|
f1da6a |
if [ -e /lib/modules/$module_krel/extra ] && \
|
|
|
f1da6a |
[ -n "`find /lib/modules/$module_krel/extra -type f`" ]; then
|
|
|
f1da6a |
find /lib/modules/$module_krel/extra -name '*.ko' \
|
|
|
f1da6a |
| xargs nm \
|
|
|
f1da6a |
| sed -nre 's:^[0]*([0-9a-f]{8}) A __crc_(.*):0x\1 \2:p'
|
|
|
f1da6a |
fi > $tmpdir/extra-symvers-$module_krel
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
|
|
|
f1da6a |
sort -u $tmpdir/symvers-$krel $tmpdir/extra-symvers-$module_krel \
|
|
|
f1da6a |
> "$tmpdir/all-symvers-$krel-$module_krel"
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
|
|
|
f1da6a |
# If the module does not have modversions enabled, $tmpdir/modvers
|
|
|
f1da6a |
# will be empty.
|
|
|
f1da6a |
/sbin/modprobe --dump-modversions "$module" \
|
|
|
f1da6a |
| sed -r -e 's:^(0x[0]*[0-9a-f]{8}\t.*):\1:' \
|
|
|
f1da6a |
| sort -u \
|
|
|
f1da6a |
> $tmpdir/modvers
|
|
|
f1da6a |
|
|
|
f1da6a |
# Only include lines of the second file in the output that don't
|
|
|
f1da6a |
# match lines in the first file. (The default separator is
|
|
|
f1da6a |
# <space>, so we are matching the whole line.)
|
|
|
f1da6a |
join -j 1 -v 2 $tmpdir/all-symvers-$krel-$module_krel \
|
|
|
f1da6a |
$tmpdir/modvers > $tmpdir/join
|
|
|
f1da6a |
|
|
|
f1da6a |
if [ ! -s $tmpdir/modvers ]; then
|
|
|
f1da6a |
echo "Warning: Module ${module##*/} from kernel $module_krel has no" \
|
|
|
f1da6a |
"modversions, so it cannot be reused for kernel $krel" >&2
|
|
|
f1da6a |
elif [ -s $tmpdir/join ]; then
|
|
|
f1da6a |
[ -n "$verbose" ] &&
|
|
|
f1da6a |
echo "Module ${module##*/} from kernel $module_krel is not compatible" \ "with kernel $krel in symbols:" $(sed -e 's:.* ::' $tmpdir/join)
|
|
|
f1da6a |
else
|
|
|
f1da6a |
[ -n "$verbose" ] &&
|
|
|
f1da6a |
echo "Module ${module##*/} from kernel $module_krel is compatible" \
|
|
|
f1da6a |
"with kernel $krel"
|
|
|
f1da6a |
return 0
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
return 1
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
usage() {
|
|
|
f1da6a |
echo "Usage: ${0##*/} [options] {--add-modules|--remove-modules}"
|
|
|
f1da6a |
echo "${0##*/} [options] {--add-kernel|--remove-kernel} {kernel-release}"
|
|
|
f1da6a |
cat <<'EOF'
|
|
|
f1da6a |
--add-modules
|
|
|
f1da6a |
Add a list of modules read from standard input. Create
|
|
|
f1da6a |
symlinks in compatible kernel's weak-updates/ directory.
|
|
|
f1da6a |
The list of modules is read from standard input.
|
|
|
f1da6a |
|
|
|
f1da6a |
--remove-modules
|
|
|
f1da6a |
Remove compatibility symlinks from weak-updates/ directories
|
|
|
f1da6a |
for a list of modules. The list of modules is read from
|
|
|
f1da6a |
standard input. Optionally specify --delete-modules to
|
|
|
f1da6a |
prevent weak-modules from attempting to locate any
|
|
|
f1da6a |
compatible modules to replace those being removed.
|
|
|
f1da6a |
|
|
|
f1da6a |
--add-kernel
|
|
|
f1da6a |
Add compatibility symlinks for all compatible modules to the
|
|
|
f1da6a |
specified or running kernel.
|
|
|
f1da6a |
|
|
|
f1da6a |
--remove-kernel
|
|
|
f1da6a |
Remove all compatibility symlinks for the specified or current
|
|
|
f1da6a |
kernel.
|
|
|
f1da6a |
|
|
|
f1da6a |
--no-initramfs
|
|
|
f1da6a |
Do not generate an initramfs.
|
|
|
f1da6a |
|
|
|
f1da6a |
--verbose
|
|
|
f1da6a |
Print the commands executed.
|
|
|
f1da6a |
|
|
|
f1da6a |
--dry-run
|
|
|
f1da6a |
Do not create/remove any files.
|
|
|
f1da6a |
EOF
|
|
|
f1da6a |
exit $1
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
# module_has_changed:
|
|
|
f1da6a |
# Mark if an actual change occured that we need to deal with later by calling
|
|
|
f1da6a |
# depmod or mkinitramfs against the affected kernel.
|
|
|
f1da6a |
module_has_changed() {
|
|
|
f1da6a |
|
|
|
f1da6a |
declare module=$1 krel=$2
|
|
|
f1da6a |
|
|
|
f1da6a |
module=${module%.ko}
|
|
|
f1da6a |
module=${module##*/}
|
|
|
f1da6a |
|
|
|
f1da6a |
eval "changed_modules_${krel//[^a-zA-Z0-9]/_}=$krel"
|
|
|
f1da6a |
eval "changed_initramfs_${krel//[^a-zA-Z0-9]/_}=$krel"
|
|
|
f1da6a |
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
# add_modules:
|
|
|
f1da6a |
# Read in a list of modules from stdinput and process them for compatibility
|
|
|
f1da6a |
# with installed kernels under /lib/modules.
|
|
|
f1da6a |
add_modules() {
|
|
|
f1da6a |
read_modules_list || exit 1
|
|
|
f1da6a |
if [ ${#modules[@]} -gt 0 ]; then
|
|
|
f1da6a |
for krel in $(ls /lib/modules/); do
|
|
|
f1da6a |
[ -e "/boot/symvers-$krel.gz" ] || continue
|
|
|
f1da6a |
for ((n = 0; n < ${#modules[@]}; n++)); do
|
|
|
f1da6a |
module="${modules[n]}"
|
|
|
f1da6a |
module_krel="${module_krels[n]}"
|
|
|
f1da6a |
case "$module" in
|
|
|
f1da6a |
/lib/modules/$krel/*)
|
|
|
f1da6a |
# Module was built against this kernel, update initramfs.
|
|
|
f1da6a |
module_has_changed $module $krel
|
|
|
f1da6a |
continue ;;
|
|
|
f1da6a |
esac
|
|
|
f1da6a |
|
|
|
f1da6a |
# Module my also serve as a weak-update built against another
|
|
|
f1da6a |
# kernel. We need to create symlinks for compatible kernels
|
|
|
f1da6a |
# under /lib/modules and rerun depmod/dracut for those.
|
|
|
f1da6a |
|
|
|
1cb8b8 |
subpath=`echo $module | sed -nre "s:(/usr)?/lib/modules/$module_krel/([^/]*)/(.*):\3:p"`
|
|
|
f1da6a |
weak_module="/lib/modules/$krel/weak-updates/${subpath#/}"
|
|
|
f1da6a |
if [ -r "$weak_module" ]; then
|
|
|
f1da6a |
weak_krel=$(krel_of_module "$weak_module")
|
|
|
f1da6a |
if [ "$weak_krel" != "$module_krel" ] &&
|
|
|
f1da6a |
[ "$(printf "%s\n" "$weak_krel" "$module_krel" \
|
|
|
f1da6a |
| rpmsort | (read input; echo "$input"; \
|
|
|
f1da6a |
while read input; do true; done))" = \
|
|
|
f1da6a |
"$module_krel" ]; then
|
|
|
f1da6a |
# Keep modules from more recent kernels.
|
|
|
f1da6a |
[ -n "$verbose" ] && echo \
|
|
|
f1da6a |
"Keeping module ${module##*/} from kernel $weak_krel for kernel $krel"
|
|
|
f1da6a |
continue
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
if module_is_compatible $module $krel; then
|
|
|
f1da6a |
doit mkdir -p $(dirname $weak_module)
|
|
|
f1da6a |
doit ln -sf $module $weak_module
|
|
|
f1da6a |
# Module was built against another kernel, update initramfs.
|
|
|
f1da6a |
module_has_changed $module $krel
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
done
|
|
|
f1da6a |
done
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
# remove_modules:
|
|
|
f1da6a |
# Read in a list of modules from stdinput and process them for removal.
|
|
|
f1da6a |
# Parameter is noreplace to delete modules, otherwise link compat.
|
|
|
f1da6a |
remove_modules() {
|
|
|
f1da6a |
delete_modules=${1:-replace}
|
|
|
f1da6a |
|
|
|
f1da6a |
read_modules_list || exit 1
|
|
|
f1da6a |
if [ ${#modules[@]} -gt 0 ]; then
|
|
|
f1da6a |
|
|
|
f1da6a |
# Hunt for all known users of this module in /lib/modules, remove them
|
|
|
f1da6a |
# and create symlinks to other compatible modules (downgrade) if
|
|
|
f1da6a |
# possible, update initramfs for each modified kernel too.
|
|
|
f1da6a |
|
|
|
f1da6a |
krels=($(ls /lib/modules/ | rpmsort -r))
|
|
|
f1da6a |
for krel in "${krels[@]}"; do
|
|
|
f1da6a |
[ -e "/boot/symvers-$krel.gz" ] || continue
|
|
|
f1da6a |
for ((n = 0; n < ${#modules[@]}; n++)); do
|
|
|
f1da6a |
module="${modules[n]}"
|
|
|
f1da6a |
module_krel="${module_krels[n]}"
|
|
|
f1da6a |
|
|
|
f1da6a |
# Module is going to be removed, update initramfs.
|
|
|
f1da6a |
module_has_changed $module $krel
|
|
|
f1da6a |
|
|
|
1cb8b8 |
subpath="${module#*/lib/modules/$module_krel/extra}"
|
|
|
f1da6a |
weak_module="/lib/modules/$krel/weak-updates/${subpath#/}"
|
|
|
f1da6a |
if [ "$module" == "`readlink $weak_module`" ]; then
|
|
|
f1da6a |
[ -n "$verbose" ] && echo \
|
|
|
f1da6a |
"Removing compatible module ${module##*/} from kernel $krel"
|
|
|
f1da6a |
doit rm -f "$weak_module"
|
|
|
f1da6a |
if [ "replace" == "$delete_modules" ]; then
|
|
|
f1da6a |
for krel2 in "${krels[@]}"; do
|
|
|
f1da6a |
if [ $krel2 != $krel ]; then
|
|
|
f1da6a |
module="/lib/modules/$krel2/extra/${subpath#/}"
|
|
|
f1da6a |
[ -e "$module" ] || continue
|
|
|
f1da6a |
if module_is_compatible "$module" "$krel"; then
|
|
|
f1da6a |
[ -n "$verbose" ] && echo \
|
|
|
f1da6a |
"Adding compatible module ${module##*/} from kernel $krel2 instead"
|
|
|
f1da6a |
doit ln -s "$module" "$weak_module"
|
|
|
f1da6a |
module_has_changed $module $krel
|
|
|
f1da6a |
break
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
done
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
doit rmdir --parents --ignore-fail-on-non-empty \
|
|
|
f1da6a |
"$(dirname "$weak_module")"
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
done
|
|
|
f1da6a |
done
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
add_kernel() {
|
|
|
f1da6a |
add_krel=${1:-$(uname -r)}
|
|
|
f1da6a |
if [ ! -e "/boot/symvers-$add_krel.gz" ]; then
|
|
|
f1da6a |
echo "Symvers dump file /boot/symvers-$add_krel.gz" \
|
|
|
f1da6a |
"not found" >&2
|
|
|
f1da6a |
exit 1
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
for krel in $(ls /lib/modules/ | rpmsort -r); do
|
|
|
f1da6a |
[ "$add_krel" = "$krel" ] && continue
|
|
|
f1da6a |
[ -d /lib/modules/$krel/extra ] || continue
|
|
|
f1da6a |
for module in $(find /lib/modules/$krel/extra -name '*.ko'); do
|
|
|
1cb8b8 |
subpath="${module#*/lib/modules/$krel/extra}"
|
|
|
f1da6a |
weak_module="/lib/modules/$add_krel/weak-updates/${subpath#/}"
|
|
|
f1da6a |
[ -e "$weak_module" ] && continue
|
|
|
f1da6a |
if module_is_compatible $module $add_krel; then
|
|
|
f1da6a |
module_has_changed $module $add_krel
|
|
|
f1da6a |
doit mkdir -p $(dirname $weak_module)
|
|
|
f1da6a |
doit ln -sf $module $weak_module
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
done
|
|
|
f1da6a |
done
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
remove_kernel() {
|
|
|
f1da6a |
remove_krel=${1:-$(uname -r)}
|
|
|
f1da6a |
weak_modules="/lib/modules/$remove_krel/weak-updates"
|
|
|
f1da6a |
module_has_changed $weak_modules $remove_krel
|
|
|
f1da6a |
doit rm -rf "$weak_modules"
|
|
|
f1da6a |
}
|
|
|
f1da6a |
|
|
|
f1da6a |
################################################################################
|
|
|
f1da6a |
################################## MAIN GUTS ###################################
|
|
|
f1da6a |
################################################################################
|
|
|
f1da6a |
|
|
|
f1da6a |
options=`getopt -o h --long help,add-modules,remove-modules \
|
|
|
f1da6a |
--long add-kernel,remove-kernel \
|
|
|
f1da6a |
--long dry-run,no-initramfs,verbose,delete-modules -- "$@"`
|
|
|
f1da6a |
|
|
|
f1da6a |
[ $? -eq 0 ] || usage 1
|
|
|
f1da6a |
|
|
|
f1da6a |
eval set -- "$options"
|
|
|
f1da6a |
|
|
|
f1da6a |
while :; do
|
|
|
f1da6a |
case "$1" in
|
|
|
f1da6a |
--add-modules)
|
|
|
f1da6a |
do_add_modules=1
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
--remove-modules)
|
|
|
f1da6a |
do_remove_modules=1
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
--add-kernel)
|
|
|
f1da6a |
do_add_kernel=1
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
--remove-kernel)
|
|
|
f1da6a |
do_remove_kernel=1
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
--dry-run)
|
|
|
f1da6a |
dry_run=1
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
--no-initramfs)
|
|
|
f1da6a |
no_initramfs=1
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
--verbose)
|
|
|
f1da6a |
verbose=1
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
--delete-modules)
|
|
|
f1da6a |
do_delete_modules=1
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
-h|--help)
|
|
|
f1da6a |
usage 0
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
--)
|
|
|
f1da6a |
shift
|
|
|
f1da6a |
break
|
|
|
f1da6a |
;;
|
|
|
f1da6a |
esac
|
|
|
f1da6a |
shift
|
|
|
f1da6a |
done
|
|
|
f1da6a |
|
|
|
f1da6a |
if [ -n "$do_add_modules" ]; then
|
|
|
f1da6a |
add_modules
|
|
|
f1da6a |
|
|
|
f1da6a |
elif [ -n "$do_remove_modules" ]; then
|
|
|
f1da6a |
if [ -n "$do_delete_modules" ]; then
|
|
|
f1da6a |
remove_modules "noreplace"
|
|
|
f1da6a |
else
|
|
|
f1da6a |
remove_modules
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
|
|
|
f1da6a |
elif [ -n "$do_add_kernel" ]; then
|
|
|
f1da6a |
kernel=${1:-$(uname -r)}
|
|
|
f1da6a |
add_kernel $kernel
|
|
|
f1da6a |
|
|
|
f1da6a |
elif [ -n "$do_remove_kernel" ]; then
|
|
|
f1da6a |
kernel=${1:-$(uname -r)}
|
|
|
f1da6a |
remove_kernel $kernel
|
|
|
f1da6a |
|
|
|
f1da6a |
exit 0
|
|
|
f1da6a |
else
|
|
|
f1da6a |
usage 1
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
|
|
|
f1da6a |
################################################################################
|
|
|
f1da6a |
###################### CLEANUP POST ADD/REMOVE MODULE/KERNEL ###################
|
|
|
f1da6a |
################################################################################
|
|
|
f1da6a |
|
|
|
f1da6a |
# run depmod and dracut as needed
|
|
|
f1da6a |
for krel in ${!changed_modules_*}; do
|
|
|
f1da6a |
krel=${!krel}
|
|
|
f1da6a |
|
|
|
f1da6a |
doit /sbin/depmod -ae -F /boot/System.map-$krel $krel
|
|
|
f1da6a |
done
|
|
|
f1da6a |
|
|
|
f1da6a |
for krel in ${!changed_initramfs_*}; do
|
|
|
f1da6a |
krel=${!krel}
|
|
|
f1da6a |
|
|
|
f1da6a |
if [ ! -n "$no_initramfs" ]; then
|
|
|
f1da6a |
check_initramfs $krel
|
|
|
f1da6a |
fi
|
|
|
f1da6a |
done
|