Bug#550584: Initial triggers patch and tracking of highest kernel
Hey
I've read through the bug, but still didn't setup a test environment,
but "triggered" by Hector and Clint's activity on the bug I thought I'd
rather share patches and proposals early.
First, quick problem statement:
a) flash-kernel isn't called when installing a new kernel ABI
b) flash-kernel might be called more times than strictly needed
c) flash-kernel doesn't have a clear contract on what to do when
multiple kernels are installed on the system or when kernels are
removed
== triggers ==
In the middle of this bug's thread, there is a proposal to add
triggers; it wasn't entirely obvious to me what part of the problem
triggers would solve. I think triggers are good to avoid running
things multiple time, so they would mostly help with the problem b).
This would be helpful if for instance linux-2.6's postinst would call
flash-kernel, and initramfs-tools' postinst would also call
flash-kernel. However in practice that's not what happens; instead,
pretty much all packages arrange to call update-initramfs -u which is
implemented as a trigger -- and hence only runs once -- which calls
flash-kernel. Some packages like linux-2.6 will also call the
update-initramfs -c or -d, but that doesn't call flash-kernel.
One area where triggers would be helpful is to avoid multiple calls
when doing installation or upgrades of multiple kernels.
Unfortunately, you can't pass arguments to triggers, so only one
flash-kernel call type can be implemented as a trigger, for instance
the "flash-kernel --supported" and "flash-kernel 2.6.38-2" calls
wouldn't be implemented as triggers, but "flash-kernel" would be. I'm
attaching a sample patch doing this (untested, but it's just to support
the discussion). The current implementation of "flash-kernel" without
a kernel ABI is to use /vmlinuz and /initrd.img or /boot/vmlinuz and
/boot/initrd.img, but I don't think we can rely on these symlinks being
up-to-date on all Debian installs; does anybody think so?
== getting flash-kernel called on new kernels ABIs ==
I think this one is relatively simple, flash-kernel always requires an
initrd (and it depends on initramfs-tools), and if a kernel is updated,
its initrd will be updated as well; once update-initramfs is done, it
will call /etc/initramfs/post-update.d/* per:
http://kernel-handbook.alioth.debian.org/ch-update-hooks.html#s-initramfs-hooks
We should probably change update-initramfs-tools to not hardcode the
call to flash-kernel anymore and rely on /etc/initramfs/post-update.d
for this as well.
== multiple kernels and removals ==
The hard part is dealing with multiple kernels being installed, or
kernels being removed. The good news is that for most boards, when a
kernel is removed the system should remain mostly bootable (at least up
to mounting the root) since flash-kernel copies the kernel and initrd
data in NAND or generates an uImage, except the GTA02 initrd.
The best thing I could think of is having all
/etc/initramfs/post-update.d and /etc/kernel/postinst.d calls keep a
note of which kernel initrd are being touched, and update
/var/lib/flash-kernel/known-kernels with the data. flash-kernel would
install the highest version according to dpkg --compare-versions and we
could implement a config file to force a specific kernel later (e.g.
/etc/flash-kernel.conf) or perhaps even support for chosing between
kernels in future versions (debconf? boot menu?). The reason the
state file is needed is that if you have upgrades for linux-2.6.37 and
linux-2.6.38, and the linux-2.6.37 one is installed after linux-2.6.38,
you still want the linux-2.6.38 update to be the flashed one. The
reason we need to track all versions in the state file is for removals
where we want to select the next highest available version of the
kernel. The main problem is that flash-kernel wont know about all
versions at the time where we introduce this.
I'm attaching a naive implementation which doesn't deal with removals
and only keeps track of the latest initrd ABI (not of the kernel one).
(again, untested, sorry!)
NB: debian/initramfs/post-update.d/flash-kernel needs to be +x in the
native package.
So to sum up, on top of the trigger support, I would propose that we
add an initramfs hook to track available versions in a
/var/lib/flash-kernel/ file and use that in the trigger to select the
highest still installed version we should flash.
Does this make sense? Any issue with this proposal?
Cheers,
--
Loïc Minier
diff -Nru flash-kernel-2.39/debian/changelog flash-kernel-2.40/debian/changelog
--- flash-kernel-2.39/debian/changelog 2011-03-02 18:59:05.000000000 +0100
+++ flash-kernel-2.40/debian/changelog 2011-03-09 02:15:03.000000000 +0100
@@ -1,3 +1,9 @@
+flash-kernel (2.40) UNRELEASED; urgency=low
+
+ * Add support for triggers.
+
+ -- Loïc Minier <lool@debian.org> Wed, 09 Mar 2011 02:14:19 +0100
+
flash-kernel (2.39) unstable; urgency=low
* Add support for Buffalo Linkstation LiveV3 (LS-CHL). Closes: #612167
diff -Nru flash-kernel-2.39/debian/flash-kernel.postinst flash-kernel-2.40/debian/flash-kernel.postinst
--- flash-kernel-2.39/debian/flash-kernel.postinst 1970-01-01 01:00:00.000000000 +0100
+++ flash-kernel-2.40/debian/flash-kernel.postinst 2011-03-09 02:19:34.000000000 +0100
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -e
+
+if [ "$1" = "triggered" ]; then
+ FLASH_KERNEL_NOTRIGGER=y flash-kernel
+fi
+
+#DEBHELPER#
diff -Nru flash-kernel-2.39/debian/triggers flash-kernel-2.40/debian/triggers
--- flash-kernel-2.39/debian/triggers 1970-01-01 01:00:00.000000000 +0100
+++ flash-kernel-2.40/debian/triggers 2011-03-09 02:28:23.000000000 +0100
@@ -0,0 +1 @@
+interest flash-kernel
diff -Nru flash-kernel-2.39/flash-kernel flash-kernel-2.40/flash-kernel
--- flash-kernel-2.39/flash-kernel 2011-03-02 18:59:05.000000000 +0100
+++ flash-kernel-2.40/flash-kernel 2011-03-09 02:13:30.000000000 +0100
@@ -111,6 +111,9 @@
esac
fi
+# kernel + initrd installation/upgrade mode, with optional version
+
+# if an explicit version was given, just try installing that
if [ -n "$1" ]; then
kvers="$1"
kfile="/boot/vmlinuz-$kvers"
@@ -118,6 +121,21 @@
desc="Debian kernel $1"
idesc="Debian ramdisk $1"
else
+ # no version was given, just accumulate multiple calls in a trigger to
+ # only run flash-kernel once; the trigger will just call flash-kernel
+ # again with FLASH_KERNEL_NOTRIGGER set to force a real
+ if [ -z "$FLASH_KERNEL_NOTRIGGER" ] && [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] && dpkg-trigger --check-supported 2>/dev/null; then
+ # flash-kernel trigger isn't disabled, and we're called from
+ # some package maintainer script (e.g. some postinst calls
+ # flash-kernel), and dpkg-trigger is installed and confirms
+ # that the running dpkg support triggers: we can use the
+ # flash-kernel trigger (asynchronously)
+ if dpkg-trigger --no-await flash-kernel; then
+ exit 0
+ fi
+ # dpkg-trigger failed for some reason, proceed to a normal run
+ fi
+
if [ -e /vmlinuz ]; then
kfile=/vmlinuz
ifile=/initrd.img
diff -Nru flash-kernel-2.39/debian/changelog flash-kernel-2.40/debian/changelog
--- flash-kernel-2.39/debian/changelog 2011-03-02 18:59:05.000000000 +0100
+++ flash-kernel-2.40/debian/changelog 2011-03-09 04:07:47.000000000 +0100
@@ -1,3 +1,15 @@
+flash-kernel (2.40) UNRELEASED; urgency=low
+
+ * Add support for triggers.
+ * Add support for tracking and installing only the highest kernel ABI.
+ - Add /etc/initramfs/post-update.d/flash-kernel: write kernel ABI to
+ /var/lib/flash-kernel/highest-abi only if it's the highest we've seen.
+ - Change flash-kernel to call itself with
+ /var/lib/flash-kernel/highest-abi as the explicit ABI to install if it's
+ present.
+
+ -- Loïc Minier <lool@debian.org> Wed, 09 Mar 2011 02:14:19 +0100
+
flash-kernel (2.39) unstable; urgency=low
* Add support for Buffalo Linkstation LiveV3 (LS-CHL). Closes: #612167
diff -Nru flash-kernel-2.39/debian/dirs flash-kernel-2.40/debian/dirs
--- flash-kernel-2.39/debian/dirs 2011-03-02 18:59:05.000000000 +0100
+++ flash-kernel-2.40/debian/dirs 2011-03-09 04:04:15.000000000 +0100
@@ -1 +1,2 @@
usr/sbin
+var/lib/flash-kernel
diff -Nru flash-kernel-2.39/debian/flash-kernel.postinst flash-kernel-2.40/debian/flash-kernel.postinst
--- flash-kernel-2.39/debian/flash-kernel.postinst 1970-01-01 01:00:00.000000000 +0100
+++ flash-kernel-2.40/debian/flash-kernel.postinst 2011-03-09 02:19:34.000000000 +0100
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -e
+
+if [ "$1" = "triggered" ]; then
+ FLASH_KERNEL_NOTRIGGER=y flash-kernel
+fi
+
+#DEBHELPER#
diff -Nru flash-kernel-2.39/debian/initramfs/post-update.d/flash-kernel flash-kernel-2.40/debian/initramfs/post-update.d/flash-kernel
--- flash-kernel-2.39/debian/initramfs/post-update.d/flash-kernel 1970-01-01 01:00:00.000000000 +0100
+++ flash-kernel-2.40/debian/initramfs/post-update.d/flash-kernel 2011-03-09 04:07:08.000000000 +0100
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+set -e
+
+if [ $# != 2 ]; then
+ echo "$0 called without expected arguments (ABI and initrd)" >&2
+ exit 1
+fi
+
+abi="$1"
+# ignored for now
+_initrd="$2"
+
+ABI_FILE="/var/lib/flash-kernel/highest-abi"
+
+current=""
+if [ -r "$ABI_FILE" ]; then
+ current="$(cat "$ABI_FILE")"
+fi
+
+if dpkg --compare-version "$current" ge "$abi"; then
+ echo "$1: Current ABI $current is already as high or higher" >&2
+ exit 0
+fi
+
+echo "$1: Updating to new ABI $abi" >&2
+echo "$abi" >"$ABI_FILE.tmp"
+mv -f "$ABI_FILE.tmp" "$ABI_FILE"
+
diff -Nru flash-kernel-2.39/debian/install flash-kernel-2.40/debian/install
--- flash-kernel-2.39/debian/install 1970-01-01 01:00:00.000000000 +0100
+++ flash-kernel-2.40/debian/install 2011-03-09 04:04:33.000000000 +0100
@@ -0,0 +1 @@
+debian/initramfs/post-update.d/flash-kernel etc/initramfs/post-update.d/
diff -Nru flash-kernel-2.39/debian/triggers flash-kernel-2.40/debian/triggers
--- flash-kernel-2.39/debian/triggers 1970-01-01 01:00:00.000000000 +0100
+++ flash-kernel-2.40/debian/triggers 2011-03-09 02:28:23.000000000 +0100
@@ -0,0 +1 @@
+interest flash-kernel
diff -Nru flash-kernel-2.39/flash-kernel flash-kernel-2.40/flash-kernel
--- flash-kernel-2.39/flash-kernel 2011-03-02 18:59:05.000000000 +0100
+++ flash-kernel-2.40/flash-kernel 2011-03-09 04:04:02.000000000 +0100
@@ -111,6 +111,9 @@
esac
fi
+# kernel + initrd installation/upgrade mode, with optional version
+
+# if an explicit version was given, just try installing that
if [ -n "$1" ]; then
kvers="$1"
kfile="/boot/vmlinuz-$kvers"
@@ -118,6 +121,31 @@
desc="Debian kernel $1"
idesc="Debian ramdisk $1"
else
+ # no version was given, just accumulate multiple calls in a trigger to
+ # only run flash-kernel once; the trigger will just call flash-kernel
+ # again with FLASH_KERNEL_NOTRIGGER set to force a real
+ if [ -z "$FLASH_KERNEL_NOTRIGGER" ] && [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] && dpkg-trigger --check-supported 2>/dev/null; then
+ # flash-kernel trigger isn't disabled, and we're called from
+ # some package maintainer script (e.g. some postinst calls
+ # flash-kernel), and dpkg-trigger is installed and confirms
+ # that the running dpkg support triggers: we can use the
+ # flash-kernel trigger (asynchronously)
+ if dpkg-trigger --no-await flash-kernel; then
+ exit 0
+ fi
+ # dpkg-trigger failed for some reason, proceed to a normal run
+ fi
+
+ # if the highest ABI file information is present, call ourselves again
+ # in "install kernel and initrd for this ABI" mode
+ ABI_FILE="/var/lib/flash-kernel/highest-abi"
+ if [ -r "$ABI_FILE" ]; then
+ abi="$(cat "$ABI_FILE")"
+ if [ -n "$abi" ]; then
+ exec flash-kernel "$abi"
+ fi
+ fi
+
if [ -e /vmlinuz ]; then
kfile=/vmlinuz
ifile=/initrd.img
Reply to: