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

Bug#724931: PATCH: improved ISO loopmount option



This is an improved version of the patch I originally posted to this bug
report. It applies mainly to the "cdrom-detect" udeb, although I suggest
that the ISO volume label (such as "Debian 7.1.0 M-A 1") be included
somewhere in the initrd; currently it does not appear to be. As I said
previously, a dependency on "loop-modules" will have to be added, so
that the "loop.ko" kernel module gets copied into the initrd.

This patch adds support for a boot parameter, "loopmount=", which
specifies an ISO image file to be loaded from another filesystem, and
used to boot from. For example:

    loopmount=KINGSTON:/linux/debian-7.1.0-amd64-i386-netinst.iso

This directs the initrd to look for a block device filesystem with the
label "KINGSTON" (as reported by /sbin/blkid), and to use the file
"debian-7.1.0-amd64-i386-netinst.iso", in the subdirectory "/linux" (the
leading "/" is not actually necessary) as a boot image.

In addition to the filesystem labels found in /dev/disk/by-label/, the
block device can be identified by UUID, as found in /dev/disk/by-uuid/.

If the filesystem label/UUID (and ":") is not specified, then all
available partitions and CD devices will be searched for the specified
ISO image file, in the specified directory.

If the "loopmount" parameter is not used, then the initrd will search
for a direct ISO filesystem in the same way as previously, although any
block device with the expected volume label ("Debian 7.1.0 M-A 1") will
be tried first.

It is expected that this facility will be most useful with USB
flashdrives, although it is in no way limited to those. It can be
applied to any block device with a vfat, ext{2,3,4}, or iso9660
filesystem; others could easily be added.

Testing seems to show that the patch works well; the relevant portion of
the installation log is reproduced below.


Oct  4 06:02:19 cdrom-detect: Searching for Debian installation media...
Oct  4 06:02:19 cdrom-detect: Devices: '/dev/sr0'
Oct  4 06:02:19 cdrom-detect: LOOPDEV='KINGSTON' LOOPFILE='/linux/debian-7.1.0-amd64-i386-netinst.iso'
Oct  4 06:02:19 cdrom-detect: trying loopmount on (/dev/disk/by-label/KINGSTON)...
Oct  4 06:02:19 kernel: [  226.383202] FAT-fs (sdf1): utf8 is not a recommended IO charset for FAT filesystems, filesystem will be case sensitive!
Oct  4 06:02:19 kernel: [  226.395607] loop: module loaded
Oct  4 06:02:19 cdrom-detect: CD-ROM mount succeeded: device=/loop/linux/debian-7.1.0-amd64-i386-netinst.iso fstype=iso9660
Oct  4 06:02:19 kernel: [  226.474076] ISO 9660 Extensions: Microsoft Joliet Level 3
Oct  4 06:02:19 kernel: [  226.474149] ISO 9660 Extensions: RRIP_1991A
Oct  4 06:02:19 cdrom-detect: Detected CD 'Debian GNU/Linux 7.1.0 "Wheezy" - Official Multi-architecture amd64/i386 NETINST #1 20130615-23:44'
Oct  4 06:02:19 cdrom-detect: Detected CD with 'stable' (wheezy) distribution


This patch will increase the size of the (uncompressed) initrd by about
37KB: 36KB for the required "loop.ko" module, and 1KB of extra boot
script. In a 200MB or 300MB ISO image, this is surely immaterial.

Since the patch adds a previously unavailable feature, which will not
operate unless activated by an explicit boot parameter, there seems to
be no reason why it should not be applied. Compare it with the current
procedure for installing Debian from a USB flashdrive:

http://www.debian.org/releases/stable/amd64/ch04s03.html

As an administrative note, I recommend that this bug report be retitled;
the current title no longer reflects what we are discussing, and the
availability of my patch is surely now the most important issue relating
to it.


-- Ian Bruce
--- debian-7.1.0-amd64.orig/var/lib/dpkg/info/cdrom-detect.postinst	2013-09-10 17:45:08.305375296 -0700
+++ debian-7.1.0-amd64/var/lib/dpkg/info/cdrom-detect.postinst	2013-10-03 21:46:39.392315543 -0700
@@ -1,4 +1,8 @@
-#! /bin/sh
+#!/bin/sh
+
+# this should go in /etc/lsb-release or somewhere
+
+DISTRIB_LABEL="Debian 7.1.0 M-A 1"
 
 set -e
 . /usr/share/debconf/confmodule
@@ -14,12 +18,21 @@
 	exit 1
 }
 
+list_devices_by_id()
+{
+	local dir disk="$(echo "$1" | sed 's/ /\\x20/g')"
+	for dir in /dev/disk/by-label /dev/disk/by-uuid ; do
+		[ -e ${dir}/${disk} ] && echo ${dir}/${disk} || true
+	done
+}
+
 try_mount() {
 	local device=$1
 	local type=$2
+	local options=$3
 
 	local ret=1
-	if mount -t $type -o $OPTIONS $device /cdrom; then
+	if mount -t $type -o $options $device /cdrom; then
 		log "CD-ROM mount succeeded: device=$device fstype=$type"
 		if [ -e /cdrom/.disk/info ]; then
 			CDNAME=$(cat /cdrom/.disk/info)
@@ -68,6 +81,7 @@
 		CDFS=iso9660
 		FATFS=vfat
 		OPTIONS=ro,exec
+		LOOPFS=vfat,ext4,iso9660
 		;;
 	hurd)
 		CDFS=iso9660fs
@@ -95,12 +109,26 @@
 
 mkdir /cdrom 2>/dev/null || true
 
+for arg in $(cat /proc/cmdline); do
+	case $arg in
+	loopmount=*)
+		LOOPMOUNT=${arg#loopmount=}
+		LOOPFILE=${LOOPMOUNT#*:}
+		[ "$LOOPFILE" != "$LOOPMOUNT" ] && LOOPDEV=${LOOPMOUNT%:*}
+		;;
+	esac
+done
+
+if [ "$LOOPMOUNT" ]; then
+	mkdir /loop 2>/dev/null || true
+fi
+
 # Need to wait for the usb device scan to complete
 if [ "$OS" = "linux" ]; then
   for count in 1 2 3 4 5 6 8 9 10; do
     devices="$(list-devices cd; list-devices maybe-usb-floppy)"
     log "Devices: '$devices'"
-    if [ -n "$devices" ]; then
+    if [ "$devices" ]; then
       break 2
     else
       sleep 1
@@ -109,27 +137,62 @@
 fi
 
 while true; do
-	WRONG=
+	WRONG=''
 
-	devices="$(list-devices cd; list-devices maybe-usb-floppy)"
-	for device in $devices; do
-		if try_mount $device $CDFS; then
-			break 2
-		fi
-	done
-	
-	devices="$(list-devices usb-partition)"
-	for device in $devices; do
-		if try_mount $device $CDFS; then
-			db_set cdrom-detect/hybrid true
-			break 2
-		fi
-		if try_mount $device $FATFS; then
-			db_set cdrom-detect/usb-hdd true
-			break 2
+	if [ "$LOOPMOUNT" ]
+	then
+
+		log "LOOPDEV='$LOOPDEV' LOOPFILE='$LOOPFILE'"
+
+		loopfile=/loop/${LOOPFILE#/}
+
+		if [ "$LOOPDEV" ] ; then
+			devices="$(list_devices_by_id "$LOOPDEV")"
+		else
+			devices="$(list-devices partition; list-devices cd)"
 		fi
-	done
 
+		log "trying loopmount on ($devices)..."
+
+		for device in $devices; do
+			if mount -o $OPTIONS -t $LOOPFS $device /loop; then
+				if [ -f $loopfile ] && try_mount $loopfile $CDFS loop,$OPTIONS ; then
+					break 2
+				else
+					umount /loop
+				fi
+			fi
+		done
+
+	else
+
+		devices="$(list_devices_by_id "$DISTRIB_LABEL")"
+		for device in $devices; do
+			if try_mount $device $CDFS $OPTIONS; then
+				break 2
+			fi
+		done
+
+		devices="$(list-devices cd; list-devices maybe-usb-floppy)"
+		for device in $devices; do
+			if try_mount $device $CDFS $OPTIONS; then
+				break 2
+			fi
+		done
+
+		devices="$(list-devices usb-partition)"
+		for device in $devices; do
+			if try_mount $device $CDFS $OPTIONS; then
+				db_set cdrom-detect/hybrid true
+				break 2
+			fi
+			if try_mount $device $FATFS $OPTIONS; then
+				db_set cdrom-detect/usb-hdd true
+				break 2
+			fi
+		done
+
+	fi
 
 	if [ "$WRONG" ]; then
 		db_input critical cdrom-detect/wrong-cd || [ $? -eq 30 ]
@@ -138,7 +201,7 @@
 	fi
 
 	# If a device was detected but the mount failed, ask for the CD.
-	if [ -n "$devices" ]; then
+	if [ "$devices" ]; then
 		db_input critical cdrom-detect/retry || [ $? -eq 30 ]
 		db_go
 		db_get cdrom-detect/retry

Reply to: