[Yaird-devel] [TuxOnIce-users] Patch to support rootfs UUID and resume UUID using vol_id from udev and mount -u

Jonas Smedegaard dr at jones.dk
Tue Jan 20 01:51:02 UTC 2009


Hi Warren and Nigel (and others following this issue),

On Mon, Jan 19, 2009 at 10:08:48PM +0100, Warren Crossing wrote:
>
> Nigel Cunningham wrote:
>> Does the patch relate to a bug filed somewhere? If so, would you let 
>> me know where? Perhaps it's buried somewhere in the text of the 
>> previous message, but if so I couldn't spot it.
>
> No I believe this is an enhancement. also support for suspend2 
> tuxonice UUID support.  I think it will require a very new version of 
> vol_id to work with suspend2.  Forgive me, I have included the entire 
> Template in an effort to provide you with some more meaningful info in 
> the interim.


Thanks for the template file.

Attached is a cleanup of same enhanced file to use consistent 
indentation style (also touching other areas than those actually 
enhanced here).

Attached is also a unified diff of cleaned file against current default 
template file, ignoring whitespace-only changes to ease following what 
the enhancements actually are.

The changes seem to be the following:

   1) include (without using) chroot and pivot_root commands
   2) include (without using) ls command
   3) improve error message when switchroot fails
   4) fix kernel cmdline option resume2 (merge with resume)
   5) support kernel cmdline option blkfsdelay
   5) support kernel cmdline option rootfs
   6) support kernel cmdline option rootwait
   7) create all devices in /proc/partitions
   8) support rootfs being a UUID
   9) improve suspend/suspend2/TuxOnIce support

It seems that 3) will never succeed, as switchroot is exec'ed without 
execfail set (and I believe execfail is a bashism so do not know how to 
fix that without bloating the ramdisk).

It seems that 7) was intended to happen only as fallback (or when rootfs 
is explicitly set?, but in reality gets done unconditionally (and thus 
is superfluous to invoke again further down).

9) require locally installed tuxonice when suspend is used. It really 
should be using the files from tuxonice-ui instead, and also be 
separated from main suspend template and disabled by default, to not 
have yaird depend on both tuxonice-ui and (I guess) usplash.


All in all interesting, but needs more work before it can be adopted for 
default yaird config.

I recommend splitting up each of the enhancements and post against 
existing bugreports concerning same issue - or post as new bugreports 
for issues not already bugged about.


Kind regards,

   - Jonas

-- 
* Jonas Smedegaard - idealist og Internet-arkitekt
* Tlf.: +45 40843136  Website: http://dr.jones.dk/

    [x] quote me freely  [ ] ask before reusing  [ ] keep private
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Templates.cfg.diff
Type: text/x-diff
Size: 5371 bytes
Desc: not available
Url : http://lists.alioth.debian.org/pipermail/yaird-devel/attachments/20090120/6070e24f/attachment.diff 
-------------- next part --------------
#
# Template -- for translation general intentions to exact initrd layout
#   Copyright (C) 2005  Erik van Konijnenburg, Marco Amadori
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#
# These templates define the translation from general intentions in the
# plan to exact lists of files and script fragments to be included
# on the initrd image.  Templates are indexed by an action name, and include:
# 	- files to be copied from current system to initrd;
# 	  often executables.
# 	- directories to be created
# 	- fragments to be appended to scripts on the image,
# 	  these are in a hash from script name to script content.
#
# Everything is processed by HTML::Template before being added to the
# image: script fragments, but also file names and script names.
# Leading spaces are dropped from template lines.
#
# If you want to implement busybox support, this is the place to do it.
#
# Obviously, the template names and the attributes used in the template
# should match what is provided by the planner.
#
#

TEMPLATE SET
	TEMPLATE prologue
	BEGIN
		# In principle, we don't want device files on the initrd
		# image: device numbers can change between kernels.
		# Instead, create device files at boot time based on info
		# in sysfs.  However, /dev/null and /dev/console are needed
		# to mount sysfs.
		FILE "/dev/null"
		FILE "/dev/console"
		FILE "/bin/dash"
		FILE "/bin/cat"
		FILE "/bin/mkdir"
		FILE "/bin/mount"
		FILE "/bin/umount"
		FILE "/bin/mknod"
		FILE "/sbin/pivot_root"
		FILE "/usr/sbin/chroot"
		FILE "/bin/sleep"
		FILE "/bin/ls"
		FILE "/usr/bin/awk"
		FILE "<TMPL_VAR NAME=auxDir>/run_init"

		DIRECTORY "/mnt"
		DIRECTORY "/proc"
		DIRECTORY "/sys"
		DIRECTORY "/dev"
		DIRECTORY "/etc"
		DIRECTORY "/var"

		#
		# We can provide debugging opportunities in the
		# initramfs image; the question is when and how
		# to enable this.  Consider two types of user:
		# - a developer, working on the template
		# - an end user, who has a boot problem with
		#   an image that was generated automatically
		#   after installing a new distribution kernel.
		#
		# The developer can simply add debugging code
		# to the template.
		# For the end user, adding an option to the kernel
		# command line is easier to enable debugging
		# than rebuilding the boot image with special
		# options or a modified configuration file.
		#
		# For this reason, we won't provide a template
		# parameter to control debugging, instead we
		# interpret a new kernel command line parameter:
		# ydebug.
		#
		SCRIPT "/init"
		BEGIN
			!#!/bin/dash
			!#
			!# Generator version: yaird <TMPL_VAR NAME=appVersion>.
			!# Kernel version: <TMPL_VAR NAME=version>.
			!#
			!INIT_DEBUG=
			!if [ "$INIT_DEBUG" != "" ]
			!then
			!	set -x
			!fi
			!
			!#
			!#  Utility functions
			!#
			!mksymdev () {
			!	devfile="$1"
			!	sysfile="$2"
			!	cb="$3"
			!	devpair=$(/bin/cat "$sysfile")
			!	for delay in 1 2 4 8 16
			!	do
			!		if [ "$devpair" = "" ]
			!		then
			!			echo "Waiting $delay seconds for $sysfile to show up"
			!			sleep $delay
			!		fi
			!		devpair=$(/bin/cat "$sysfile")
			!	done
			!
			!	if [ "$devpair" = "" ]
			!	then
			!		echo "Device $sysfile seems to be down."
			!		if [ "$INIT_DEBUG" != "" ]
			!		then
			!			echo "Debugging opportunity, type ^D to continue."
			!			/bin/dash
			!		fi
			!	fi
			!
			!	maj=${devpair%:*}
			!	min=${devpair#*:}
			!	/bin/mknod "$devfile" $cb $maj $min
			!}
			!mkcdev () {
			!	mksymdev "$1" "/sys/class/$2/dev" c
			!}
			!mkbdev () {
			!	mksymdev "$1" "/sys/block/$2/dev" b
			!}
			!
			!switchroot () {
			!	if [ "$INIT_DEBUG" != "" ]
			!	then
			!		echo "Debugging opportunity, ^D to continue."
			!		/bin/dash
			!	fi
			!
			!	echo "Switching root ..."
			!	/bin/umount -n /sys
			!	/bin/umount -n /proc
			!
			!	echo "Waiting for rootfs ..."
			!	if [ -x <TMPL_VAR NAME=auxDir>/run_init ]
			!	then
			!		exec <TMPL_VAR NAME=auxDir>/run_init /mnt $init -- "$@"
			!		result=$?
			!		if [ "$result" -ne 0 ]
			!		then
			!			echo "run_init failed"
			!			sleep 15
			!		fi
			!	else
			!		echo "run_init not found"
			!		sleep 15
			!	fi
			!}
			!
			!#
			!# Setting up mounts
			!#
			!/bin/mount -nt sysfs sysfs /sys
			!/bin/mount -nt proc proc /proc
			!#
			!# We don't set up a separate /dev file system,
			!# since rootfs is writable without problem.
			!#
			!
			!# /dev/tty is needed for eg cryptsetup.
			!mkcdev /dev/tty tty/tty
			!
			!#
			!# Command line processing
			!# init - first proc to start on next root
			!# root - to be done: how should it relate
			!# 	to file system selection?
			!# ro,rw - mount root read-only or read-write.
			!# 	This is like a mount -r; it overrules
			!# 	a -o rw.
			!# noresume, resume= - should we resume from a
			!# 	suspend-to-disk?  The resume parameter
			!# 	is optional, but overrides automatic
			!# 	detection of the resume partition if present.
			!# 	noresume prevents us from attempting to resume.
			!# ide - options for module ide_core.
			!# 	need a way to append these to proper
			!# 	module.  do a check on module name
			!# 	in insmod template?
			!# ip=, nfsaddrs=, nfsroot= - support NFS boot
			!#
			!ro=-r
			!ip=
			!nfsroot=
			!noresume=
			!resume=
			!resume2=
			!rootwait=0
			!blkfsdelay=7
			!init=/sbin/init
			!for i in $(cat /proc/cmdline)
			!do
			!	case "$i" in
			!	init=*)
			!		init=${i#init=}
			!		;;
			!	ro)
			!		ro=-r
			!		;;
			!	rw)
			!		ro=
			!		;;
			!	ip=*|nfsaddrs=*)
			!		ip="$ip $i"
			!		;;
			!	nfsroot=*)
			!		nfsroot="$i"
			!		;;
			!	noresume)
			!		noresume=1
			!		;;
			!	resume=*)
			!		resume=${i#resume=}
			!		;;
			!	resume2=*)
			!		resume=${i#resume=}
			!		;;
			!	blkfsdelay=*)
			!		blkfsdelay=${i#blkfsdelay=}
			!		;;
			!	rootfs=*)
			!		rootfs=${i#rootfs=}
			!		;;
			!	rootwait)
			!		rootwait=1
			!		;;
			!	ydebug)
			!		INIT_DEBUG=yes
			!		;;
			!	esac
			!done
			!if [ "$INIT_DEBUG" != "" ]
			!then
			!	set -x
			!fi
		END SCRIPT
	END TEMPLATE


	TEMPLATE insmod
	BEGIN
		FILE "<TMPL_VAR NAME=target>"
		FILE "/sbin/insmod"

		# optionList may be undef
		# and already is suitably escaped.
		SCRIPT "/init"
		BEGIN
			!/sbin/insmod '<TMPL_VAR NAME=target>' <TMPL_VAR NAME=optionList>
		END SCRIPT
	END TEMPLATE


	TEMPLATE mkbdev
	BEGIN
		SCRIPT "/init"
		BEGIN
			!mkbdev '<TMPL_VAR NAME=target>' '<TMPL_VAR NAME=sysname>'
			!dyn_mkblkdev() {
			!	echo waiting $blkfsdelay for block devices
			!	sleep $blkfsdelay
			!	MKBLKDEV=done
			!	IFS=
			!	dash -c `awk '/^   [0-9]/ {print("/bin/mknod /dev/" $4 " b " $1 " " $2" ")}' /proc/partitions` > /dev/null 2>&1
			!	# may be able to use these to wait for device partition scanning to complete
			!	#cat /sys/block/sda/device/device_blocked
			!	#cat /sys/block/sda/device/state
			!	unset IFS
			!	echo made special block devices
			!}
			!if [ -z "$MKBLKDEV" ]
			!then
			!	dyn_mkblkdev
			!fi
		END SCRIPT
	END TEMPLATE



	TEMPLATE evms_activate
	BEGIN
		#
		# Note that evms_active will not do a single device,
		# but everything it encounters.
		#
		TREE "/lib/evms/<TMPL_VAR NAME=evmsVersion>"
		FILE "/sbin/evms_activate"
		FILE "/etc/evms.conf"
		SCRIPT "/init"
		BEGIN
			!# activate for <TMPL_VAR NAME=target>
			!if [ ! -c /dev/evms ]
			!then
			!	/bin/mkdir /dev/evms
			!fi
			!/sbin/evms_activate
		END SCRIPT
	END TEMPLATE

	#
	# We cannot make mapper/control any earlier,
	# since dm-mod needs to be loaded to be able
	# to determine devno.
	#
	# Hmm. cf debian bug 335315.  The config file is needed
	# on machines where an LVM volume is on an encrypted
	# partition.  However, requiring this might get in
	# the way of machines that do not have a config file.
	#
	TEMPLATE vgchange
	BEGIN
		FILE "/etc/lvm/lvm.conf"
		# Older Debian releases needs this one
		#FILE "/lib/lvm-200/vgchange"
		FILE "/sbin/vgchange"
		SCRIPT "/init"
		BEGIN
			!if [ ! -c /dev/mapper/control ]
			!then
			!	/bin/mkdir /dev/mapper
			!	mkcdev /dev/mapper/control misc/device-mapper
			!fi
			!/sbin/vgchange -a y '<TMPL_VAR NAME=target>'
		END SCRIPT
	END TEMPLATE

	#
	# NOTE: mdadm can operate without knowledge
	# of device numbers; it will assign an unused
	# one to the new device.  Thus you could have
	# device name /dev/md/boot that is stable,
	# regardless of which other raid devices are
	# operational.  However, debian installer
	# consistently uses device names like /dev/md0,
	# where the name depends on earlier minors
	# that happen to have been assigned.
	# To work around this problem, we forego
	# the --auto option, and mknod the device
	# before putting an md under it.  Better hope
	# the major number is not going to change ...
	#
	TEMPLATE mdadm
	BEGIN
		FILE "/sbin/mdadm"
		SCRIPT "/init"
		BEGIN
			!mknod <TMPL_VAR NAME=target> b <TMPL_VAR NAME=major> <TMPL_VAR NAME=minor>
			!<TMPL_IF NAME=supports_device_renaming>
			!	mdadm -Ac partitions <TMPL_VAR NAME=target> --run --uuid <TMPL_VAR NAME=uuid>
			!<TMPL_ELSE>
			!	mdadm --assemble <TMPL_VAR NAME=target> --run --uuid <TMPL_VAR NAME=uuid> \
			!		<TMPL_LOOP NAME=components> <TMPL_VAR NAME=dev></TMPL_LOOP>
			!</TMPL_IF>
		END SCRIPT
	END TEMPLATE


	#
	# cryptsetup arguments:
	# - target
	# - cipher
	# - keySize (always there, 0 for NULL crypto)
	# - hash (hashname or undef)
	# - src
	# - verify (yes or undef)
	#
	# A loop around 'cryptsetup --verify' can help detect
	# and correct typo's in the crypt password.
	#
	TEMPLATE cryptsetup
	BEGIN
		FILE "/sbin/cryptsetup"
		FILE "/bin/loadkeys"
		FILE "/bin/gzip"
		FILE "/etc/console/boottime.kmap.gz"
		FILE "/sbin/blkid"
		SCRIPT "/init"
		BEGIN
			!# loadkeys from the kbd package has problems
			!# uncompressing the keymap on-the-fly when
			!# run from initramfs, don't know why
			!if [ -e /etc/console/boottime.kmap.gz ]
			!then
			!	gzip -d /etc/console/boottime.kmap.gz
			!fi
			!if [ -e /etc/console/boottime.kmap ]
			!then
			!	loadkeys /etc/console/boottime.kmap
			!fi
			!DOCRYPT=1
			!while [ "$DOCRYPT" != "0" ]
			!do
			!	/sbin/cryptsetup \
			!		-c <TMPL_VAR NAME=cipher> \
			!		-s <TMPL_VAR NAME=keySize> \
			!		<TMPL_IF NAME=hash> \
			!			-h '<TMPL_VAR NAME=hash>' \
			!		</TMPL_IF> \
			!		<TMPL_IF NAME=verify>-y </TMPL_IF> \
			!		create '<TMPL_VAR NAME=target>' \
			!		'<TMPL_VAR NAME=src>'
			!	DOCRYPT=$?
			!	while [ "$DOCRYPT" = "0" ] \
			!		&& [ -x /sbin/blkid ] \
			!		&& [ -z "`/sbin/blkid '/dev/mapper/<TMPL_VAR NAME=target>'`" ]
			!	do
			!		echo 'Unable to identify the filesystem on volume <TMPL_VAR NAME=target>.'
			!		echo 'Reenter, Ignore, Shell?'
			!		read a
			!		case "$a" in
			!		i|I)
			!			break
			!			;;
			!		s|S)
			!			/bin/dash
			!			;;
			!		r|R|*)
			!			/sbin/cryptsetup remove '<TMPL_VAR NAME=target>'
			!			DOCRYPT=1
			!			;;
			!		esac
			!	done
			!done
		END SCRIPT
	END TEMPLATE


	#
	# cryptsetup arguments:
	# - target
	# - src
	# - verify (yes or undef)
	#
	# A loop around 'cryptsetup --verify' can help detect
	# and correct typo's in the crypt password.
	#
	TEMPLATE cryptsetup_luks
	BEGIN
		FILE "/sbin/cryptsetup"
		FILE "/bin/loadkeys"
		FILE "/bin/gzip"
		FILE "/etc/console/boottime.kmap.gz"
		FILE "/sbin/blkid"
		SCRIPT "/init"
		BEGIN
			!# loadkeys from the kbd package has problems
			!# uncompressing the keymap on-the-fly when
			!# run from initramfs, don't know why
			!if [ -e /etc/console/boottime.kmap.gz ]
			!then
			!	gzip -d /etc/console/boottime.kmap.gz
			!fi
			!if [ -e /etc/console/boottime.kmap ]
			!then
			!	loadkeys /etc/console/boottime.kmap
			!fi
			!DOCRYPT=1
			!while [ "$DOCRYPT" != "0" ]
			!do
			!	/sbin/cryptsetup \
			!		<TMPL_IF NAME=verify>-y </TMPL_IF> \
			!		luksOpen '<TMPL_VAR NAME=src>' \
			!		'<TMPL_VAR NAME=target>'
			!	DOCRYPT=$?
			!	while [ "$DOCRYPT" = "0" ] \
			!		&& [ -x /sbin/blkid ] \
			!		&& [ -z "`/sbin/blkid '/dev/mapper/<TMPL_VAR NAME=target>'`" ]
			!	do
			!		echo 'Unable to identify the filesystem on volume <TMPL_VAR NAME=target>.'
			!		echo 'Reenter, Ignore, Shell?'
			!		read a
			!		case "$a" in
			!		i|I)
			!			break
			!			;;
			!		s|S)
			!			/bin/dash
			!			;;
			!		r|R|*)
			!			/sbin/cryptsetup luksClose '<TMPL_VAR NAME=target>'
			!			DOCRYPT=1
			!			;;
			!		esac
			!	done
			!done
		END SCRIPT
	END TEMPLATE


	#
	# Do a resume from swap, unless 'noresume' is on the command-line.
	#
	TEMPLATE resume
	BEGIN
		FILE "/usr/bin/awk"
		FILE "/lib/udev/vol_id"
		FILE "/usr/local/sbin/tuxoniceui_fbsplash"
		FILE "/usr/local/sbin/tuxoniceui_text"
		FILE "/usr/local/sbin/tuxoniceui_usplash"
		FILE "/etc/splash/suspend2/1024x768.cfg"
		FILE "/etc/splash/suspend2/Vera.ttf"
		FILE "/etc/splash/suspend2/VeraBd.ttf"
		FILE "/etc/splash/suspend2/images/silent-1024x768.png"
		SCRIPT "/init"
		BEGIN
			!if [ -z "$noresume" ]
			!then
			!	TARGET=/sys/power/resume
			!	INIT_RESUME=/sys/power/resume
			!	echo looking for resume device $resume
			!	# for suspend2 (>= 2.2-rc8)
			!	if [ -w /sys/power/tuxonice/version ]
			!	then
			!		mknod /dev/fb0 c 29 0
			!		TARGET=/sys/power/tuxonice/resume
			!		INIT_RESUME=/sys/power/tuxonice/do_resume
			!	fi
			!	# for suspend2 (< 2.2-rc8)
			!	if [ -w /proc/software_suspend/do_resume ]
			!	then
			!		INIT_RESUME=/proc/software_suspend/do_resume
			!	fi
			!	# for swsusp
			!	if [ -n "$resume" ]
			!	then
			!		# uuid to dev translation
			!		case "$resume" in
			!		swap:UUID=[0-9a-zA-Z-]*)
			!			uuid=${resume#swap:UUID=}
			!			for i in `/usr/bin/awk '{print $4}' /proc/partitions `
			!			do
			!				#echo $i
			!				case `/lib/udev/vol_id --uuid /dev/$i 2> /dev/null` in
			!				*$uuid)
			!					SOURCE=/dev/$i
			!					echo found resume device at $SOURCE
			!					;;
			!				esac
			!			done
			!			# no error condition handling
			!			;;
			!		[0-9]*:[0-9]*)
			!			SOURCE=$resume
			!			;;
			!		*[a-z]*[0-9])
			!			SOURCE=`cat /sys/block/*/${resume#/dev/}/dev`
			!			;;
			!		esac
			!		#echo $SOURCE $TARGET $INIT_RESUME
			!		echo "$SOURCE" > $TARGET
			!		echo "$SOURCE" > $INIT_RESUME
			!	else
			!		echo <TMPL_VAR NAME=devno> > /sys/power/resume
			!	fi
			!fi
		END SCRIPT
	END TEMPLATE


	#
	# NOTE: honouring the kernel cmdline option ro,rw
	# is very nice, but...  If you have an ext3 in a
	# file loopback-mounted from vfat, it's unlikely
	# that a remount rw of root will also make the
	# underlying vfat read-write.  Underlying filesystems
	# should ignore the kernel ro/rw option; we
	# have an attribute isRoot that's defined iff
	# this is the real root.
	#
	# always -n, since we dont have writable /etc/mtab.
	#
	TEMPLATE mount
	BEGIN
		SCRIPT "/init"
		BEGIN
			!echo "looking for root device $rootfs"
			!
			!case "$rootfs" in
			!UUID=[0-9a-zA-Z-]*)
			!	uuid=${rootfs#UUID=}
			!	if [ -n $uuid ]
			!	then
			!		echo "Using UUID $uuid"
			!		rootfs="-U $uuid"
			!	fi
			!	;;
			!esac
			!
			!mount_rootfs() {
			!	/bin/mount -n \
			!		<TMPL_IF NAME=isRoot>$ro</TMPL_IF> \
			!		-t <TMPL_VAR NAME=fsType> \
			!		<TMPL_VAR NAME=options> \
			!		$rootfs \
			!		'<TMPL_VAR NAME=target>'
			!	result=$?
			!	if [ $result -ne 0 ]
			!	then
			!		echo "failed result from mount was $result"
			!	fi
			!	return $result
			!}
			!if [ $rootwait -eq 1 ]
			!then
			!	echo "Waiting for rootfs (rootwait)"
			!	mount_rootfs
			!	while [ $? -ne 0 ]
			!	do
			!		echo "Still Waiting for rootfs (rootwait)"
			!		sleep 3
			!		dyn_mkblkdev
			!		mount_rootfs
			!	done
			!else
			!	echo "Not waiting for rootfs"
			!	mount_rootfs
			!fi
		END SCRIPT
	END TEMPLATE

	TEMPLATE nfsstart
	BEGIN
		FILE "<TMPL_VAR NAME=auxDir>/trynfs"
		SCRIPT "/init"
		BEGIN
			!if [ "$ip" != "" ]
			!then
			!	<TMPL_VAR NAME=auxDir>/trynfs $ip $nfsroot /mnt
			!	switchroot "$@"
			!fi
		END SCRIPT
	END TEMPLATE

	TEMPLATE postlude
	BEGIN
		SCRIPT "/init"
		BEGIN
			!switchroot "$@"
		END SCRIPT
	END TEMPLATE
END TEMPLATE SET


More information about the Yaird-devel mailing list