[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: