[Bug 922201] New: rmmod confused by built-ins
by Red Hat Bugzilla
Product: Red Hat Enterprise Linux 7
https://bugzilla.redhat.com/show_bug.cgi?id=922201
Bug ID: 922201
Summary: rmmod confused by built-ins
Product: Red Hat Enterprise Linux 7
Version: 7.0
Component: kmod
Severity: medium
Priority: medium
Assignee: kay(a)redhat.com
Reporter: bmr(a)redhat.com
CC: gansalmon(a)Gmail.com, itamar(a)ispbrasil.com.br,
jonathan(a)jonmasters.org, kernel-maint(a)redhat.com,
kmod-maint(a)lists.fedoraproject.org,
madhu.chinakonda(a)gmail.com, msivak(a)redhat.com
Depends On: 922187
+++ This bug was initially created as a clone of Bug #922187 +++
Description of problem:
Attempting to rmmod something that's not actually built as a module now gives a
slightly confusing error:
# rmmod loop
libkmod: kmod_module_get_holders: could not open '/sys/module/loop/holders': No
such file or directory
Error: Module loop is in use
Previously rmmod from module-init-tools gave a still vague but better "not
found" message:
# rmmod ext2
ERROR: Module ext2 does not exist in /proc/modules
Version-Release number of selected component (if applicable):
kmod-*
How reproducible:
100%
Steps to Reproduce:
1. compile something that can be built as a module as a built-in
2. rmmod $thing
Actual results:
# rmmod loop
libkmod: kmod_module_get_holders: could not open '/sys/module/loop/holders': No
such file or directory
Error: Module loop is in use
Which isn't really true: it's not in use, it's simply built in to vmlinuz so
unloading makes no sense.
Expected results:
modprobe does the right thing:
# modprobe -r loop
FATAL: Module loop is builtin.
Additional info:
I know rmmod is the low-level tool and users should be using modprobe -r (or
just not messing with this in the first place.. :) but knowledge of modprobe to
load and rmmod to unload seems much more widespread among admins and the
current behaviour looks at first like a kernel bug (if you didn't realise that
there are paths directories missing in /sys/modules/$thing and the module name
isn't present in /proc/modules you might think some refcount was broken etc.).
--- Additional comment from Bryn M. Reeves on 2013-03-15 13:12:04 EDT ---
Error is slightly different from 0:12-1.fc18 but same basic problem:
# rmmod loop
rmmod: ERROR: could not open '/sys/module/loop/holders': No such file or
directory
rmmod: ERROR: Module loop is in use
--
You are receiving this mail because:
You are on the CC list for the bug.
Unsubscribe from this bug https://bugzilla.redhat.com/token.cgi?t=NR8Odg50eP&a=cc_unsubscribe
9 years, 10 months
[Bug 907581] New: [abrt] kmod-10-1.fc18: elf_get_mem: Process /usr/bin/kmod was killed by signal 6 (SIGABRT)
by Red Hat Bugzilla
Product: Fedora
https://bugzilla.redhat.com/show_bug.cgi?id=907581
Bug ID: 907581
Summary: [abrt] kmod-10-1.fc18: elf_get_mem: Process
/usr/bin/kmod was killed by signal 6 (SIGABRT)
Product: Fedora
Version: 18
Component: kmod
Severity: unspecified
Priority: unspecified
Reporter: bug-zilla(a)o2.pl
Version-Release number of selected component:
kmod-10-1.fc18
Additional info:
backtrace_rating: 4
cmdline: /sbin/depmod -a 3.7.4-204.fc18.x86_64
crash_function: elf_get_mem
executable: /usr/bin/kmod
kernel: 3.7.2-204.fc18.x86_64
remote_result: NOTFOUND
uid: 0
var_log_messages: Feb 4 19:30:56 localhost abrt[12775]: Saved core dump of pid
12774 (/usr/bin/kmod) to /var/spool/abrt/ccpp-2013-02-04-19:30:56-12774
(3887104 bytes)
Truncated backtrace:
Thread no. 1 (7 frames)
#4 elf_get_mem at libkmod/libkmod-elf.c:207
#5 elf_get_uint at libkmod/libkmod-elf.c:142
#6 kmod_elf_new at libkmod/libkmod-elf.c:315
#7 kmod_module_get_symbols at libkmod/libkmod-module.c:2458
#8 depmod_load_symbols at tools/depmod.c:1543
#9 depmod_load at tools/depmod.c:1733
#10 do_depmod at tools/depmod.c:2751
--
You are receiving this mail because:
You are on the CC list for the bug.
You are the assignee for the bug.
10 years, 2 months
[kmod/f19] Pull in weak-modules script for kABI
by Václav Pavlín
commit a819aa4451d4dc2d5445562705212aaa9c2135a8
Author: Václav Pavlín <vpavlin(a)redhat.com>
Date: Thu Mar 28 16:31:33 2013 +0100
Pull in weak-modules script for kABI
kmod.spec | 10 +-
weak-modules | 475 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 484 insertions(+), 1 deletions(-)
---
diff --git a/kmod.spec b/kmod.spec
index e88f8cc..1073f0d 100644
--- a/kmod.spec
+++ b/kmod.spec
@@ -1,12 +1,13 @@
Name: kmod
Version: 12
-Release: 3%{?dist}
+Release: 4%{?dist}
Summary: Linux kernel module management utilities
Group: System Environment/Kernel
License: GPLv2+
URL: http://git.kernel.org/?p=utils/kernel/kmod/kmod.git;a=summary
Source0: ftp://ftp.kernel.org/pub/linux/utils/kernel/kmod/%{name}-%{version}.tar.xz
+Source1: weak-modules
Exclusiveos: Linux
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
@@ -75,6 +76,9 @@ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/modprobe.d
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/depmod.d
mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/modprobe.d
+mkdir -p $RPM_BUILD_ROOT/sbin
+install -m 755 %{SOURCE1} $RPM_BUILD_ROOT%{_sbindir}/weak-modules
+
%post libs -p /sbin/ldconfig
%postun libs -p /sbin/ldconfig
@@ -91,6 +95,7 @@ mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/modprobe.d
%{_sbindir}/rmmod
%{_sbindir}/lsmod
%{_sbindir}/depmod
+%{_sbindir}/weak-modules
%attr(0644,root,root) %{_mandir}/man5/*.5*
%attr(0644,root,root) %{_mandir}/man8/*.8*
%doc NEWS README TODO COPYING
@@ -104,6 +109,9 @@ mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/modprobe.d
%{_libdir}/libkmod.so
%changelog
+* Thu Mar 20 2013 Weiping Pan <wpan(a)redhat.com> - 12-3
+- Pull in weak-modules for kABI from Jon Masters <jcm(a)redhat.com>
+
* Mon Mar 18 2013 Josh Boyer <jwboyer(a)redhat.com>
- Add patch to make rmmod understand built-in modules (rhbz 922187)
diff --git a/weak-modules b/weak-modules
new file mode 100644
index 0000000..05d1b0f
--- /dev/null
+++ b/weak-modules
@@ -0,0 +1,475 @@
+#!/bin/bash
+#
+# weak-modules - determine which modules are kABI compatible with installed
+# kernels and set up the symlinks in /lib/*/weak-updates.
+#
+# Changelog:
+#
+# 2010/01/10 - Further updates for dracut use on Fedora/RHEL (jcm).
+# 2009/09/16 - Rebase and add a bunch of updates for dracut (jcm).
+
+unset LANG LC_ALL LC_COLLATE
+
+tmpdir=$(mktemp -td ${0##*/}.XXXXXX)
+trap "rm -rf $tmpdir" EXIT
+unset ${!changed_modules_*} ${!changed_initramfs_*}
+
+initramfs_prefix="/boot" # can customize here
+dracut="/sbin/dracut"
+
+if [ ! -x "$dracut" ]
+then
+ echo "weak-modules: this tool requires a dracut-enabled kernel"
+ exit 1
+fi
+
+# doit:
+# A wrapper used whenever we're going to perform a real operation.
+doit() {
+ [ -n "$verbose" ] && echo "$@"
+ [ -n "$dry_run" ] || "$@"
+}
+
+# rpmsort: The sort in coreutils can't sort the RPM list how we want it so we
+# instead transform the list into a form it will sort correctly, then sort.
+rpmsort() {
+ local IFS=$' '
+ REVERSE=""
+ rpmlist=($(cat))
+
+ if [ "-r" == "$1" ];
+ then
+ REVERSE="-r"
+ fi
+
+ echo ${rpmlist[@]} | \
+ sed -e 's/-/../g' | \
+ sort ${REVERSE} -n -t"." -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 -k6,6 -k7,7 \
+ -k8,8 -k9,9 -k10,10 | \
+ sed -e 's/\.\./-/g'
+}
+
+# read_modules_list:
+# Read in a list of modules from standard input. Convert the filenames into
+# absolute paths and compute the kernel release for each module (either using
+# the modinfo section or through the absolute path.
+read_modules_list() {
+ local IFS=$'\n'
+ modules=($(cat))
+
+ 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
+}
+
+# read_old_initramfs:
+compare_initramfs_modules() {
+ local old_initramfs=$1
+ local new_initramfs=$2
+
+ rm -rf "$tmpdir/old_initramfs"
+ rm -rf "$tmpdir/new_initramfs"
+ mkdir "$tmpdir/old_initramfs"
+ mkdir "$tmpdir/new_initramfs"
+
+ pushd "$tmpdir/old_initramfs" >/dev/null
+ zcat "$old_initramfs" | cpio -i 2>/dev/null
+ n=0; for i in `find . -iname \*.ko|sort`; do
+ old_initramfs_modules[n]="$i"
+ n=$((n+1))
+ done
+ popd >/dev/null
+
+ pushd "$tmpdir/new_initramfs" >/dev/null
+ zcat "$new_initramfs" | cpio -i 2>/dev/null
+ n=0; for i in `find . -iname \*.ko|sort`; do
+ new_initramfs_modules[n]="$i"
+ n=$((n+1))
+ done
+ popd >/dev/null
+
+ if [ "${#old_initramfs_modules[@]}" == "${#new_initramfs_modules[@]}" ];
+ then
+ for ((n = 0; n < ${#old_initramfs_modules[@]}; n++)); do
+ old_md5=`md5sum $tmpdir/old_initramfs/${old_initramfs_modules[n]}|sed -nre 's:(^\ )* .*:\1:p'`
+ new_md5=`md5sum $tmpdir/new_initramfs/${new_initramfs_modules[n]}|sed -nre 's:(^\ )* .*:\1:p'`
+ if [ ! "$old_md5" == "$new_md5" ];
+ then
+ return 1
+ fi
+ done
+ else
+ return 1
+ fi
+
+ return 0
+}
+
+# check_initramfs:
+# check and possibly also update the initramfs for changed kernels
+check_initramfs() {
+ local kernel=$1
+
+ # If there is no initramfs already we will not make one here.
+ if [ -e "$initramfs_prefix/initramfs-$kernel.img" ];
+ then
+ old_initramfs="$initramfs_prefix/initramfs-$kernel.img"
+ tmp_initramfs="$initramfs_prefix/initramfs-$kernel.tmp"
+ new_initramfs="$initramfs_prefix/initramfs-$kernel.img"
+
+ $dracut -f "$tmp_initramfs" "$kernel"
+
+ if ! $(compare_initramfs_modules "$old_initramfs" "$tmp_initramfs");
+ then
+ doit mv "$tmp_initramfs" "$new_initramfs"
+ else
+ rm -f "$tmp_initramfs"
+ fi
+ fi
+}
+
+# krel_of_module:
+# Compute the kernel release of a module.
+krel_of_module() {
+ declare module=$1
+ /sbin/modinfo -F vermagic "$module" | awk '{print $1}'
+}
+
+# module_is_compatible:
+# Determine if a module is compatible with a particular kernel release. Also
+# include any symbol deps that might be introduced by other external kmods.
+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:^(0x[0]*[0-9a-f]{8}\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/extra ] && \
+ [ -n "`find /lib/modules/$module_krel/extra -type f`" ]; then
+ find /lib/modules/$module_krel/extra -name '*.ko' \
+ | xargs nm \
+ | sed -nre 's:^[0]*([0-9a-f]{8}) A __crc_(.*):0x\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:^(0x[0]*[0-9a-f]{8}\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)
+ else
+ [ -n "$verbose" ] &&
+ echo "Module ${module##*/} from kernel $module_krel is compatible" \
+ "with kernel $krel"
+ return 0
+ fi
+ return 1
+}
+
+usage() {
+ echo "Usage: ${0##*/} [options] {--add-modules|--remove-modules}"
+ echo "${0##*/} [options] {--add-kernel|--remove-kernel} {kernel-release}"
+ cat <<'EOF'
+--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. Optionally specify --delete-modules to
+ prevent weak-modules from attempting to locate any
+ compatible modules to replace those being removed.
+
+--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.
+
+--no-initramfs
+ Do not generate an initramfs.
+
+--verbose
+ Print the commands executed.
+
+--dry-run
+ Do not create/remove any files.
+EOF
+ exit $1
+}
+
+# module_has_changed:
+# Mark if an actual change occured that we need to deal with later by calling
+# depmod or mkinitramfs against the affected kernel.
+module_has_changed() {
+
+ declare module=$1 krel=$2
+
+ module=${module%.ko}
+ module=${module##*/}
+
+ eval "changed_modules_${krel//[^a-zA-Z0-9]/_}=$krel"
+ eval "changed_initramfs_${krel//[^a-zA-Z0-9]/_}=$krel"
+
+}
+
+# add_modules:
+# Read in a list of modules from stdinput and process them for compatibility
+# with installed kernels under /lib/modules.
+add_modules() {
+ 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/*)
+ # Module was built against this kernel, update initramfs.
+ module_has_changed $module $krel
+ continue ;;
+ esac
+
+ # Module my also serve as a weak-update built against another
+ # kernel. We need to create symlinks for compatible kernels
+ # under /lib/modules and rerun depmod/dracut for those.
+
+ subpath=`echo $module | sed -nre "s:/lib/modules/$module_krel/([^/]*)/(.*):\2:p"`
+ 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" \
+ | rpmsort | (read input; echo "$input"; \
+ while read input; do true; done))" = \
+ "$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 was built against another kernel, update initramfs.
+ module_has_changed $module $krel
+ fi
+ done
+ done
+ fi
+}
+
+# remove_modules:
+# Read in a list of modules from stdinput and process them for removal.
+# Parameter is noreplace to delete modules, otherwise link compat.
+remove_modules() {
+ delete_modules=${1:-replace}
+
+ read_modules_list || exit 1
+ if [ ${#modules[@]} -gt 0 ]; then
+
+ # Hunt for all known users of this module in /lib/modules, remove them
+ # and create symlinks to other compatible modules (downgrade) if
+ # possible, update initramfs for each modified kernel too.
+
+ krels=($(ls /lib/modules/ | rpmsort -r))
+ for krel in "${krels[@]}"; do
+ [ -e "/boot/symvers-$krel.gz" ] || continue
+ for ((n = 0; n < ${#modules[@]}; n++)); do
+ module="${modules[n]}"
+ module_krel="${module_krels[n]}"
+
+ # Module is going to be removed, update initramfs.
+ module_has_changed $module $krel
+
+ subpath="${module#/lib/modules/$module_krel/extra}"
+ weak_module="/lib/modules/$krel/weak-updates/${subpath#/}"
+ if [ "$module" == "`readlink $weak_module`" ]; then
+ [ -n "$verbose" ] && echo \
+"Removing compatible module ${module##*/} from kernel $krel"
+ doit rm -f "$weak_module"
+ if [ "replace" == "$delete_modules" ]; then
+ for krel2 in "${krels[@]}"; do
+ if [ $krel2 != $krel ]; then
+ module="/lib/modules/$krel2/extra/${subpath#/}"
+ [ -e "$module" ] || continue
+ if module_is_compatible "$module" "$krel"; then
+ [ -n "$verbose" ] && echo \
+"Adding compatible module ${module##*/} from kernel $krel2 instead"
+ doit ln -s "$module" "$weak_module"
+ module_has_changed $module $krel
+ break
+ fi
+ fi
+ done
+ fi
+ doit rmdir --parents --ignore-fail-on-non-empty \
+ "$(dirname "$weak_module")"
+ fi
+ done
+ done
+ fi
+}
+
+add_kernel() {
+ 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/ | rpmsort -r); do
+ [ "$add_krel" = "$krel" ] && continue
+ [ -d /lib/modules/$krel/extra ] || continue
+ for module in $(find /lib/modules/$krel/extra -name '*.ko'); do
+ subpath="${module#/lib/modules/$krel/extra}"
+ weak_module="/lib/modules/$add_krel/weak-updates/${subpath#/}"
+ [ -e "$weak_module" ] && continue
+ if module_is_compatible $module $add_krel; then
+ module_has_changed $module $add_krel
+ doit mkdir -p $(dirname $weak_module)
+ doit ln -sf $module $weak_module
+ fi
+ done
+ done
+}
+
+remove_kernel() {
+ remove_krel=${1:-$(uname -r)}
+ weak_modules="/lib/modules/$remove_krel/weak-updates"
+ module_has_changed $weak_modules $remove_krel
+ doit rm -rf "$weak_modules"
+}
+
+################################################################################
+################################## MAIN GUTS ###################################
+################################################################################
+
+options=`getopt -o h --long help,add-modules,remove-modules \
+ --long add-kernel,remove-kernel \
+ --long dry-run,no-initramfs,verbose,delete-modules -- "$@"`
+
+[ $? -eq 0 ] || usage 1
+
+eval set -- "$options"
+
+while :; do
+ case "$1" in
+ --add-modules)
+ do_add_modules=1
+ ;;
+ --remove-modules)
+ do_remove_modules=1
+ ;;
+ --add-kernel)
+ do_add_kernel=1
+ ;;
+ --remove-kernel)
+ do_remove_kernel=1
+ ;;
+ --dry-run)
+ dry_run=1
+ ;;
+ --no-initramfs)
+ no_initramfs=1
+ ;;
+ --verbose)
+ verbose=1
+ ;;
+ --delete-modules)
+ do_delete_modules=1
+ ;;
+ -h|--help)
+ usage 0
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+ shift
+done
+
+if [ -n "$do_add_modules" ]; then
+ add_modules
+
+elif [ -n "$do_remove_modules" ]; then
+ if [ -n "$do_delete_modules" ]; then
+ remove_modules "noreplace"
+ else
+ remove_modules
+ fi
+
+elif [ -n "$do_add_kernel" ]; then
+ kernel=${1:-$(uname -r)}
+ add_kernel $kernel
+
+elif [ -n "$do_remove_kernel" ]; then
+ kernel=${1:-$(uname -r)}
+ remove_kernel $kernel
+
+ exit 0
+else
+ usage 1
+fi
+
+################################################################################
+###################### CLEANUP POST ADD/REMOVE MODULE/KERNEL ###################
+################################################################################
+
+# run depmod and dracut as needed
+for krel in ${!changed_modules_*}; do
+ krel=${!krel}
+
+ doit /sbin/depmod -ae -F /boot/System.map-$krel $krel
+done
+
+for krel in ${!changed_initramfs_*}; do
+ krel=${!krel}
+
+ if [ ! -n "$no_initramfs" ]; then
+ check_initramfs $krel
+ fi
+done
11 years, 1 month
[kmod] Pull in weak-modules script for kABI
by Václav Pavlín
commit 59185aa6d2d00447ac33549cd5526a2ccbd23853
Author: Václav Pavlín <vpavlin(a)redhat.com>
Date: Thu Mar 28 16:31:33 2013 +0100
Pull in weak-modules script for kABI
kmod.spec | 10 +-
weak-modules | 475 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 484 insertions(+), 1 deletions(-)
---
diff --git a/kmod.spec b/kmod.spec
index e88f8cc..1073f0d 100644
--- a/kmod.spec
+++ b/kmod.spec
@@ -1,12 +1,13 @@
Name: kmod
Version: 12
-Release: 3%{?dist}
+Release: 4%{?dist}
Summary: Linux kernel module management utilities
Group: System Environment/Kernel
License: GPLv2+
URL: http://git.kernel.org/?p=utils/kernel/kmod/kmod.git;a=summary
Source0: ftp://ftp.kernel.org/pub/linux/utils/kernel/kmod/%{name}-%{version}.tar.xz
+Source1: weak-modules
Exclusiveos: Linux
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
@@ -75,6 +76,9 @@ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/modprobe.d
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/depmod.d
mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/modprobe.d
+mkdir -p $RPM_BUILD_ROOT/sbin
+install -m 755 %{SOURCE1} $RPM_BUILD_ROOT%{_sbindir}/weak-modules
+
%post libs -p /sbin/ldconfig
%postun libs -p /sbin/ldconfig
@@ -91,6 +95,7 @@ mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/modprobe.d
%{_sbindir}/rmmod
%{_sbindir}/lsmod
%{_sbindir}/depmod
+%{_sbindir}/weak-modules
%attr(0644,root,root) %{_mandir}/man5/*.5*
%attr(0644,root,root) %{_mandir}/man8/*.8*
%doc NEWS README TODO COPYING
@@ -104,6 +109,9 @@ mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/modprobe.d
%{_libdir}/libkmod.so
%changelog
+* Thu Mar 20 2013 Weiping Pan <wpan(a)redhat.com> - 12-3
+- Pull in weak-modules for kABI from Jon Masters <jcm(a)redhat.com>
+
* Mon Mar 18 2013 Josh Boyer <jwboyer(a)redhat.com>
- Add patch to make rmmod understand built-in modules (rhbz 922187)
diff --git a/weak-modules b/weak-modules
new file mode 100644
index 0000000..05d1b0f
--- /dev/null
+++ b/weak-modules
@@ -0,0 +1,475 @@
+#!/bin/bash
+#
+# weak-modules - determine which modules are kABI compatible with installed
+# kernels and set up the symlinks in /lib/*/weak-updates.
+#
+# Changelog:
+#
+# 2010/01/10 - Further updates for dracut use on Fedora/RHEL (jcm).
+# 2009/09/16 - Rebase and add a bunch of updates for dracut (jcm).
+
+unset LANG LC_ALL LC_COLLATE
+
+tmpdir=$(mktemp -td ${0##*/}.XXXXXX)
+trap "rm -rf $tmpdir" EXIT
+unset ${!changed_modules_*} ${!changed_initramfs_*}
+
+initramfs_prefix="/boot" # can customize here
+dracut="/sbin/dracut"
+
+if [ ! -x "$dracut" ]
+then
+ echo "weak-modules: this tool requires a dracut-enabled kernel"
+ exit 1
+fi
+
+# doit:
+# A wrapper used whenever we're going to perform a real operation.
+doit() {
+ [ -n "$verbose" ] && echo "$@"
+ [ -n "$dry_run" ] || "$@"
+}
+
+# rpmsort: The sort in coreutils can't sort the RPM list how we want it so we
+# instead transform the list into a form it will sort correctly, then sort.
+rpmsort() {
+ local IFS=$' '
+ REVERSE=""
+ rpmlist=($(cat))
+
+ if [ "-r" == "$1" ];
+ then
+ REVERSE="-r"
+ fi
+
+ echo ${rpmlist[@]} | \
+ sed -e 's/-/../g' | \
+ sort ${REVERSE} -n -t"." -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 -k6,6 -k7,7 \
+ -k8,8 -k9,9 -k10,10 | \
+ sed -e 's/\.\./-/g'
+}
+
+# read_modules_list:
+# Read in a list of modules from standard input. Convert the filenames into
+# absolute paths and compute the kernel release for each module (either using
+# the modinfo section or through the absolute path.
+read_modules_list() {
+ local IFS=$'\n'
+ modules=($(cat))
+
+ 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
+}
+
+# read_old_initramfs:
+compare_initramfs_modules() {
+ local old_initramfs=$1
+ local new_initramfs=$2
+
+ rm -rf "$tmpdir/old_initramfs"
+ rm -rf "$tmpdir/new_initramfs"
+ mkdir "$tmpdir/old_initramfs"
+ mkdir "$tmpdir/new_initramfs"
+
+ pushd "$tmpdir/old_initramfs" >/dev/null
+ zcat "$old_initramfs" | cpio -i 2>/dev/null
+ n=0; for i in `find . -iname \*.ko|sort`; do
+ old_initramfs_modules[n]="$i"
+ n=$((n+1))
+ done
+ popd >/dev/null
+
+ pushd "$tmpdir/new_initramfs" >/dev/null
+ zcat "$new_initramfs" | cpio -i 2>/dev/null
+ n=0; for i in `find . -iname \*.ko|sort`; do
+ new_initramfs_modules[n]="$i"
+ n=$((n+1))
+ done
+ popd >/dev/null
+
+ if [ "${#old_initramfs_modules[@]}" == "${#new_initramfs_modules[@]}" ];
+ then
+ for ((n = 0; n < ${#old_initramfs_modules[@]}; n++)); do
+ old_md5=`md5sum $tmpdir/old_initramfs/${old_initramfs_modules[n]}|sed -nre 's:(^\ )* .*:\1:p'`
+ new_md5=`md5sum $tmpdir/new_initramfs/${new_initramfs_modules[n]}|sed -nre 's:(^\ )* .*:\1:p'`
+ if [ ! "$old_md5" == "$new_md5" ];
+ then
+ return 1
+ fi
+ done
+ else
+ return 1
+ fi
+
+ return 0
+}
+
+# check_initramfs:
+# check and possibly also update the initramfs for changed kernels
+check_initramfs() {
+ local kernel=$1
+
+ # If there is no initramfs already we will not make one here.
+ if [ -e "$initramfs_prefix/initramfs-$kernel.img" ];
+ then
+ old_initramfs="$initramfs_prefix/initramfs-$kernel.img"
+ tmp_initramfs="$initramfs_prefix/initramfs-$kernel.tmp"
+ new_initramfs="$initramfs_prefix/initramfs-$kernel.img"
+
+ $dracut -f "$tmp_initramfs" "$kernel"
+
+ if ! $(compare_initramfs_modules "$old_initramfs" "$tmp_initramfs");
+ then
+ doit mv "$tmp_initramfs" "$new_initramfs"
+ else
+ rm -f "$tmp_initramfs"
+ fi
+ fi
+}
+
+# krel_of_module:
+# Compute the kernel release of a module.
+krel_of_module() {
+ declare module=$1
+ /sbin/modinfo -F vermagic "$module" | awk '{print $1}'
+}
+
+# module_is_compatible:
+# Determine if a module is compatible with a particular kernel release. Also
+# include any symbol deps that might be introduced by other external kmods.
+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:^(0x[0]*[0-9a-f]{8}\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/extra ] && \
+ [ -n "`find /lib/modules/$module_krel/extra -type f`" ]; then
+ find /lib/modules/$module_krel/extra -name '*.ko' \
+ | xargs nm \
+ | sed -nre 's:^[0]*([0-9a-f]{8}) A __crc_(.*):0x\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:^(0x[0]*[0-9a-f]{8}\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)
+ else
+ [ -n "$verbose" ] &&
+ echo "Module ${module##*/} from kernel $module_krel is compatible" \
+ "with kernel $krel"
+ return 0
+ fi
+ return 1
+}
+
+usage() {
+ echo "Usage: ${0##*/} [options] {--add-modules|--remove-modules}"
+ echo "${0##*/} [options] {--add-kernel|--remove-kernel} {kernel-release}"
+ cat <<'EOF'
+--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. Optionally specify --delete-modules to
+ prevent weak-modules from attempting to locate any
+ compatible modules to replace those being removed.
+
+--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.
+
+--no-initramfs
+ Do not generate an initramfs.
+
+--verbose
+ Print the commands executed.
+
+--dry-run
+ Do not create/remove any files.
+EOF
+ exit $1
+}
+
+# module_has_changed:
+# Mark if an actual change occured that we need to deal with later by calling
+# depmod or mkinitramfs against the affected kernel.
+module_has_changed() {
+
+ declare module=$1 krel=$2
+
+ module=${module%.ko}
+ module=${module##*/}
+
+ eval "changed_modules_${krel//[^a-zA-Z0-9]/_}=$krel"
+ eval "changed_initramfs_${krel//[^a-zA-Z0-9]/_}=$krel"
+
+}
+
+# add_modules:
+# Read in a list of modules from stdinput and process them for compatibility
+# with installed kernels under /lib/modules.
+add_modules() {
+ 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/*)
+ # Module was built against this kernel, update initramfs.
+ module_has_changed $module $krel
+ continue ;;
+ esac
+
+ # Module my also serve as a weak-update built against another
+ # kernel. We need to create symlinks for compatible kernels
+ # under /lib/modules and rerun depmod/dracut for those.
+
+ subpath=`echo $module | sed -nre "s:/lib/modules/$module_krel/([^/]*)/(.*):\2:p"`
+ 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" \
+ | rpmsort | (read input; echo "$input"; \
+ while read input; do true; done))" = \
+ "$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 was built against another kernel, update initramfs.
+ module_has_changed $module $krel
+ fi
+ done
+ done
+ fi
+}
+
+# remove_modules:
+# Read in a list of modules from stdinput and process them for removal.
+# Parameter is noreplace to delete modules, otherwise link compat.
+remove_modules() {
+ delete_modules=${1:-replace}
+
+ read_modules_list || exit 1
+ if [ ${#modules[@]} -gt 0 ]; then
+
+ # Hunt for all known users of this module in /lib/modules, remove them
+ # and create symlinks to other compatible modules (downgrade) if
+ # possible, update initramfs for each modified kernel too.
+
+ krels=($(ls /lib/modules/ | rpmsort -r))
+ for krel in "${krels[@]}"; do
+ [ -e "/boot/symvers-$krel.gz" ] || continue
+ for ((n = 0; n < ${#modules[@]}; n++)); do
+ module="${modules[n]}"
+ module_krel="${module_krels[n]}"
+
+ # Module is going to be removed, update initramfs.
+ module_has_changed $module $krel
+
+ subpath="${module#/lib/modules/$module_krel/extra}"
+ weak_module="/lib/modules/$krel/weak-updates/${subpath#/}"
+ if [ "$module" == "`readlink $weak_module`" ]; then
+ [ -n "$verbose" ] && echo \
+"Removing compatible module ${module##*/} from kernel $krel"
+ doit rm -f "$weak_module"
+ if [ "replace" == "$delete_modules" ]; then
+ for krel2 in "${krels[@]}"; do
+ if [ $krel2 != $krel ]; then
+ module="/lib/modules/$krel2/extra/${subpath#/}"
+ [ -e "$module" ] || continue
+ if module_is_compatible "$module" "$krel"; then
+ [ -n "$verbose" ] && echo \
+"Adding compatible module ${module##*/} from kernel $krel2 instead"
+ doit ln -s "$module" "$weak_module"
+ module_has_changed $module $krel
+ break
+ fi
+ fi
+ done
+ fi
+ doit rmdir --parents --ignore-fail-on-non-empty \
+ "$(dirname "$weak_module")"
+ fi
+ done
+ done
+ fi
+}
+
+add_kernel() {
+ 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/ | rpmsort -r); do
+ [ "$add_krel" = "$krel" ] && continue
+ [ -d /lib/modules/$krel/extra ] || continue
+ for module in $(find /lib/modules/$krel/extra -name '*.ko'); do
+ subpath="${module#/lib/modules/$krel/extra}"
+ weak_module="/lib/modules/$add_krel/weak-updates/${subpath#/}"
+ [ -e "$weak_module" ] && continue
+ if module_is_compatible $module $add_krel; then
+ module_has_changed $module $add_krel
+ doit mkdir -p $(dirname $weak_module)
+ doit ln -sf $module $weak_module
+ fi
+ done
+ done
+}
+
+remove_kernel() {
+ remove_krel=${1:-$(uname -r)}
+ weak_modules="/lib/modules/$remove_krel/weak-updates"
+ module_has_changed $weak_modules $remove_krel
+ doit rm -rf "$weak_modules"
+}
+
+################################################################################
+################################## MAIN GUTS ###################################
+################################################################################
+
+options=`getopt -o h --long help,add-modules,remove-modules \
+ --long add-kernel,remove-kernel \
+ --long dry-run,no-initramfs,verbose,delete-modules -- "$@"`
+
+[ $? -eq 0 ] || usage 1
+
+eval set -- "$options"
+
+while :; do
+ case "$1" in
+ --add-modules)
+ do_add_modules=1
+ ;;
+ --remove-modules)
+ do_remove_modules=1
+ ;;
+ --add-kernel)
+ do_add_kernel=1
+ ;;
+ --remove-kernel)
+ do_remove_kernel=1
+ ;;
+ --dry-run)
+ dry_run=1
+ ;;
+ --no-initramfs)
+ no_initramfs=1
+ ;;
+ --verbose)
+ verbose=1
+ ;;
+ --delete-modules)
+ do_delete_modules=1
+ ;;
+ -h|--help)
+ usage 0
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+ shift
+done
+
+if [ -n "$do_add_modules" ]; then
+ add_modules
+
+elif [ -n "$do_remove_modules" ]; then
+ if [ -n "$do_delete_modules" ]; then
+ remove_modules "noreplace"
+ else
+ remove_modules
+ fi
+
+elif [ -n "$do_add_kernel" ]; then
+ kernel=${1:-$(uname -r)}
+ add_kernel $kernel
+
+elif [ -n "$do_remove_kernel" ]; then
+ kernel=${1:-$(uname -r)}
+ remove_kernel $kernel
+
+ exit 0
+else
+ usage 1
+fi
+
+################################################################################
+###################### CLEANUP POST ADD/REMOVE MODULE/KERNEL ###################
+################################################################################
+
+# run depmod and dracut as needed
+for krel in ${!changed_modules_*}; do
+ krel=${!krel}
+
+ doit /sbin/depmod -ae -F /boot/System.map-$krel $krel
+done
+
+for krel in ${!changed_initramfs_*}; do
+ krel=${!krel}
+
+ if [ ! -n "$no_initramfs" ]; then
+ check_initramfs $krel
+ fi
+done
11 years, 1 month