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

Bug#688336: os-probe: subvol: patches to provide bootloaders with all the subvolume info.



Here are corrected versions of these patches.  Filesystem raid is
almost certainly a separate bug.
From 3d4b580dea4592793af3411fc0543af36de0e958 Mon Sep 17 00:00:00 2001
From: Michael Mestnik <cheako+github_com@mikemestnik.net>
Date: Fri, 9 Jun 2017 13:04:05 -0500
Subject: [PATCH 2/6] Process filesystem raid entries

---
 common.sh | 14 ++++++++++++--
 os-prober |  5 +++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/common.sh b/common.sh
index e1646d4..d6fee58 100644
--- a/common.sh
+++ b/common.sh
@@ -146,12 +146,22 @@ is_dos_extended_partition() {
 	return 1
 }
 
+canonical_dev () {
+	local dev="${1#/dev/}"
+	local sys="$(find /sys/fs/btrfs -path \*/devices/"$dev")"
+	if [ -e "$sys" ]; then
+		echo /dev/"$(ls "${sys%/$dev}" | head -n1)"
+	else
+		echo "$1"
+	fi
+}
+
 parse_proc_mounts () {
 	while read -r line; do
 		set -f
 		set -- $line
 		set +f
-		printf '%s %s %s\n' "$(mapdevfs "$1")" "$2" "$3"
+		printf '%s %s %s\n' "$(canonical_dev "$(mapdevfs "$1")")" "$2" "$3"
 	done
 }
 
@@ -245,7 +255,7 @@ linux_mount_boot () {
 				fi
 			fi
 			shift
-			set -- "$(mapdevfs "$tmppart")" "$@"
+			set -- "$(canonical_dev "$(mapdevfs "$tmppart")")" "$@"
 
 			if grep -q "^$1 " "$OS_PROBER_TMP/mounted-map"; then
 				bindfrom="$(grep "^$1 " "$OS_PROBER_TMP/mounted-map" | head -n1 | cut -d " " -f 2)"
diff --git a/os-prober b/os-prober
index a48863e..e4439a7 100755
--- a/os-prober
+++ b/os-prober
@@ -137,6 +137,11 @@ for partition in $(partitions); do
 		continue
 	fi
 
+	if ! [ "$mapped" = "$(canonical_dev "$mapped")" ]; then
+		log "Device '$mapped' is part of filesystem raid; skipping"
+		continue
+	fi
+
 	# Skip partitions used in software RAID arrays
 	if grep -q "^$mapped" "$OS_PROBER_TMP/raided-map" ; then
 		debug "$partition: part of software raid array"
-- 
2.11.0

From bd6d7a78e88eba3a03940e84f6e1222268ab5c8d Mon Sep 17 00:00:00 2001
From: Michael Mestnik <cheako+github_com@mikemestnik.net>
Date: Mon, 5 Jun 2017 11:08:42 -0500
Subject: [PATCH 5/6] Pass subvol data for /boot to bootloadter(s)

---
 common.sh                                   | 36 +++++++++++++++++++++++++++++
 linux-boot-prober                           |  6 +++--
 linux-boot-probes/common/50mounted-tests    |  3 ++-
 linux-boot-probes/mounted/common/40grub2    |  3 ++-
 linux-boot-probes/mounted/common/90fallback |  5 ++--
 linux-boot-probes/mounted/powerpc/40yaboot  |  3 ++-
 linux-boot-probes/mounted/sparc/50silo      |  3 ++-
 linux-boot-probes/mounted/x86/40grub        |  3 ++-
 linux-boot-probes/mounted/x86/50lilo        |  3 ++-
 9 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/common.sh b/common.sh
index 1001c74..ff278c3 100644
--- a/common.sh
+++ b/common.sh
@@ -253,6 +253,42 @@ linux_mount_boot () {
 			shift
 			set -- "$(mapdevfs "$tmppart")" "$@"
 
+			if bootsubvolid="$(echo "$4" | grep -o 'subvolid=[0-9][0-9]*')"; then
+				bootsubvolid="$(echo "$bootsubvolid" | cut -d= -f2-)"
+				if mount -o "subvolid=$bootsubvolid" "$1" "$tmpmnt/boot"; then
+					if [ "$bootsubvolid" = "$(get_default_subvolid "$tmpmnt/boot")" ]; then
+						mountboot="$1 1"
+						return
+					else
+						mountboot="$1 1 $bootsubvolid"
+						return
+					fi
+				else
+					debug "failed to subvolid-mount $1 onto $tmpmnt/boot"
+					mountboot="$1 0 $bootsubvolid"
+					return
+				fi
+			else
+				if bootsubvol="$(echo "$4" | grep -o 'subvol=[^,]*')"; then
+					bootsubvol="$(echo "$bootsubvol" | cut -d= -f2-)"
+					bootsubvol="${bootsubvol#/}"
+					if mount -o "subvol=${bootsubvol:=/}" "$1" "$tmpmnt/boot"; then
+						bootsubvolid="$(grep "^/dev/" /proc/mounts | parse_proc_mounts | grep " $tmpmnt/boot " | cut -d ' ' -f 4)"
+						if [ "$bootsubvolid" = "$(get_default_subvolid "$tmpmnt/boot")" ]; then
+							mountboot="$1 1"
+							return
+						else
+							mountboot="$1 1 ${bootsubvolid:-@$bootsubvol}"
+							return
+						fi
+					else
+						debug "failed to subvol-mount $1 onto $tmpmnt/boot"
+						mountboot="$1 0 @$bootsubvol"
+						return
+					fi
+				fi
+			fi
+
 			if grep -q "^$1 " "$OS_PROBER_TMP/mounted-map"; then
 				bindfrom="$(grep "^$1 " "$OS_PROBER_TMP/mounted-map" | head -n1 | cut -d " " -f 2)"
 				bindfrom="$(unescape_mount "$bindfrom")"
diff --git a/linux-boot-prober b/linux-boot-prober
index 4a86119..ae34670 100755
--- a/linux-boot-prober
+++ b/linux-boot-prober
@@ -36,19 +36,21 @@ else
 	mpoint="$(unescape_mount "$mpoint")"
 	if [ "$mpoint" != "/target/boot" ] && [ "$mpoint" != "/target" ] && [ "$mpoint" != "/" ]; then
 		type="$(echo "$mrecord" | head -n1 | cut -d ' ' -f 3)"
-		if ! grep -q " $mpoint/boot " "$OS_PROBER_TMP/mounted-map"; then
+		if ! bootrecord="$(grep -q " $mpoint/boot " "$OS_PROBER_TMP/mounted-map")"; then
 			linux_mount_boot "$partition" "$mpoint" "$subvolid"
 			set -- $mountboot
 			bootpart="$1"
 			bootmounted="$2"
+			bootsubvolid="$3"
 		else
 			bootpart="$partition"
 			bootmounted=0
+			bootsubvolid="$(echo "$bootrecord" | head -n1 | cut -d ' ' -f 4)"
 		fi
 		for test in /usr/lib/linux-boot-probes/mounted/*; do
 			if [ -f $test ] && [ -x $test ]; then
 				debug "running $test on mounted $partition"
-				if $test "$partition" "$bootpart" "$mpoint" "$type" "$subvolid"; then
+				if $test "$partition" "$bootpart" "$mpoint" "$type" "$subvolid" "$bootsubvolid"; then
 					debug "$test succeeded"
 					break
 				fi
diff --git a/linux-boot-probes/common/50mounted-tests b/linux-boot-probes/common/50mounted-tests
index 65264f5..d150d23 100755
--- a/linux-boot-probes/common/50mounted-tests
+++ b/linux-boot-probes/common/50mounted-tests
@@ -67,11 +67,12 @@ if [ "$mounted" ]; then
 	set -- $mountboot
 	bootpart="$1"
 	bootmounted="$2"
+	bootsubvolid="$3"
 
 	for test in /usr/lib/linux-boot-probes/mounted/*; do
 		if [ -f "$test" ] && [ -x "$test" ]; then
 			debug "running $test $partition $bootpart $tmpmnt $type"
-			if $test "$partition" "$bootpart" "$tmpmnt" "$type" "$subvolid"; then
+			if $test "$partition" "$bootpart" "$tmpmnt" "$type" "$subvolid" "$bootsubvolid"; then
 				debug "$test succeeded"
 				do_unmount
 				exit 0
diff --git a/linux-boot-probes/mounted/common/40grub2 b/linux-boot-probes/mounted/common/40grub2
index 9d0b48c..06b8744 100755
--- a/linux-boot-probes/mounted/common/40grub2
+++ b/linux-boot-probes/mounted/common/40grub2
@@ -7,6 +7,7 @@ bootpart="$2"
 mpoint="$3"
 type="$4"
 subvolid="$5"
+bootsubvolid="$6"
 
 found_item=0
 
@@ -14,7 +15,7 @@ entry_result () {
 	if [ "$ignore_item" = 0 ] && \
 	   [ -n "$kernel" ] && \
 	   [ -e "$mpoint/$kernel" ]; then
-		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
+		result "$rootpart:$bootpart${bootsubvolid:+@$bootsubvolid}:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 		found_item=1
 	fi
 	kernel=""
diff --git a/linux-boot-probes/mounted/common/90fallback b/linux-boot-probes/mounted/common/90fallback
index da0d22d..7a5b001 100755
--- a/linux-boot-probes/mounted/common/90fallback
+++ b/linux-boot-probes/mounted/common/90fallback
@@ -9,6 +9,7 @@ bootpart="$2"
 mpoint="$3"
 type="$4"
 subvolid="$5"
+bootsubvolid="$6"
 
 mappedpartition=$(mapdevfs "$partition" 2>/dev/null) || mappedpartition="$partition"
 
@@ -39,13 +40,13 @@ for kernpat in /vmlinuz /vmlinux /boot/vmlinuz /boot/vmlinux "/boot/vmlinuz*" \
 			for initrd in $(eval ls "$initrdname" "$initrdname1" "$initrdname2" "$initrdname3" "$initrdname4" 2>/dev/null); do
 				if [ "$initrd" != "$kernfile" ] && [ -f "$initrd" ] && [ ! -L "$initrd" ]; then
 					initrd=$(echo "$initrd" | sed "s!^$mpoint!!")
-					result "$partition:$kernbootpart::$kernbasefile:$initrd:root=$mappedpartition${subvolid:+ rootflags=subvolid=$subvolid}"
+					result "$partition:$kernbootpart${bootsubvolid:+@$bootsubvolid}::$kernbasefile:$initrd:root=$mappedpartition${subvolid:+ rootflags=subvolid=$subvolid}"
 					exitcode=0
 					foundinitrd=1
 				fi
 			done
 			if [ "$foundinitrd" = 0 ]; then
-				result "$partition:$kernbootpart::$kernbasefile::root=$mappedpartition${subvolid:+ rootflags=subvolid=$subvolid}"
+				result "$partition:$kernbootpart${bootsubvolid:+@$bootsubvolid}::$kernbasefile::root=$mappedpartition${subvolid:+ rootflags=subvolid=$subvolid}"
 				exitcode=0
 			fi
 		fi
diff --git a/linux-boot-probes/mounted/powerpc/40yaboot b/linux-boot-probes/mounted/powerpc/40yaboot
index 44ca0bc..05f4c82 100755
--- a/linux-boot-probes/mounted/powerpc/40yaboot
+++ b/linux-boot-probes/mounted/powerpc/40yaboot
@@ -7,6 +7,7 @@ bootpart="$2"
 mpoint="$3"
 type="$4"
 subvolid="$5"
+bootsubvolid="$6"
 
 found_item=0
 
@@ -37,7 +38,7 @@ recordstanza () {
 			parameters="root=$rootdev $parameters"
 		fi
 		parameters="${parameters% }"
-		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
+		result "$rootpart:$bootpart${bootsubvolid:+@$bootsubvolid}:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 		found_item=1
 
 		title=
diff --git a/linux-boot-probes/mounted/sparc/50silo b/linux-boot-probes/mounted/sparc/50silo
index da6579b..71098e1 100755
--- a/linux-boot-probes/mounted/sparc/50silo
+++ b/linux-boot-probes/mounted/sparc/50silo
@@ -7,6 +7,7 @@ bootpart="$2"
 mpoint="$3"
 type="$4"
 subvolid="$5"
+bootsubvolid="$6"
 
 found_item=0
 
@@ -38,7 +39,7 @@ recordstanza () {
 					parameters="root=$rootdev $parameters"
 				fi
 				parameters="${parameters% }"
-				result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
+				result "$rootpart:$bootpart${bootsubvolid:+@$bootsubvolid}:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 				found_item=1
 			else
 				debug "cannot find $initrd, not recording"
diff --git a/linux-boot-probes/mounted/x86/40grub b/linux-boot-probes/mounted/x86/40grub
index 4e2eaf1..3cd2839 100755
--- a/linux-boot-probes/mounted/x86/40grub
+++ b/linux-boot-probes/mounted/x86/40grub
@@ -7,6 +7,7 @@ bootpart="$2"
 mpoint="$3"
 type="$4"
 subvolid="$5"
+bootsubvolid="$6"
 
 found_item=0
 
@@ -14,7 +15,7 @@ entry_result () {
 	if [ "$ignore_item" = 0 ] && \
 	   [ -n "$kernel" ] && \
 	   [ -e "$mpoint/$kernel" ]; then
-		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
+		result "$rootpart:$bootpart${bootsubvolid:+@$bootsubvolid}:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 		found_item=1
 	fi
 	kernel=""
diff --git a/linux-boot-probes/mounted/x86/50lilo b/linux-boot-probes/mounted/x86/50lilo
index d0f3c1d..6918a1b 100755
--- a/linux-boot-probes/mounted/x86/50lilo
+++ b/linux-boot-probes/mounted/x86/50lilo
@@ -7,6 +7,7 @@ bootpart="$2"
 mpoint="$3"
 type="$4"
 subvolid="$5"
+bootsubvolid="$6"
 
 found_item=0
 
@@ -49,7 +50,7 @@ recordstanza () {
 				parameters="root=$rootdev $parameters"
 			fi
 			parameters="${parameters% }"
-			result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
+			result "$rootpart:$bootpart${bootsubvolid:+@$bootsubvolid}:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 			found_item=1
 		else
 			debug "cannot find $kernel or $initrd, not recording"
-- 
2.11.0

From f1898d06ac877f013ba9f02b2ccc72e18a8b5d48 Mon Sep 17 00:00:00 2001
From: Michael Mestnik <cheako+github_com@mikemestnik.net>
Date: Tue, 6 Jun 2017 21:42:19 -0500
Subject: [PATCH 4/6] Handle subvol during boot probe

---
 common.sh                                   |  2 +-
 linux-boot-prober                           | 18 ++++++++++--------
 linux-boot-probes/common/50mounted-tests    | 15 +++++++++++----
 linux-boot-probes/mounted/common/40grub2    |  3 ++-
 linux-boot-probes/mounted/common/90fallback |  5 +++--
 linux-boot-probes/mounted/powerpc/40yaboot  |  3 ++-
 linux-boot-probes/mounted/sparc/50silo      |  3 ++-
 linux-boot-probes/mounted/x86/40grub        |  3 ++-
 linux-boot-probes/mounted/x86/50lilo        |  3 ++-
 9 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/common.sh b/common.sh
index 8942a91..1001c74 100644
--- a/common.sh
+++ b/common.sh
@@ -166,7 +166,7 @@ parsefstab () {
 				set -f
 				set -- $line
 				set +f
-				printf '%s %s %s\n' "$1" "$2" "$3"
+				printf '%s %s %s %s\n' "$1" "$2" "$3" "$4"
 			;;
 		esac
 	done
diff --git a/linux-boot-prober b/linux-boot-prober
index e32dc84..4a86119 100755
--- a/linux-boot-prober
+++ b/linux-boot-prober
@@ -9,6 +9,7 @@ require_tmpdir
 grep "^/dev/" /proc/mounts | parse_proc_mounts >"$OS_PROBER_TMP/mounted-map" || true
 
 partition="$1"
+subvolid="$2"
 
 if [ -z "$partition" ]; then
 	echo "usage: linux-boot-prober partition" >&2
@@ -20,25 +21,26 @@ if ! mapped="$(mapdevfs "$partition")"; then
 	continue
 fi
 
-if ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map"; then
+if ! mrecord="$(grep "^$mapped [^ ]* [^ ]* $subvolid" "$OS_PROBER_TMP/mounted-map")"; then
 	for test in /usr/lib/linux-boot-probes/*; do
 		debug "running $test"
 		if [ -x $test ] && [ -f $test ]; then
-			if $test "$partition"; then
+			if $test "$partition" "$subvolid"; then
 				debug "linux detected by $test"
 				break
 			fi
 		fi
 	done
 else
-	mpoint=$(grep "^$mapped " "$OS_PROBER_TMP/mounted-map" | head -n1 | cut -d " " -f 2)
+	mpoint="$(echo "$mrecord" | head -n1 | cut -d ' ' -f 2)"
 	mpoint="$(unescape_mount "$mpoint")"
 	if [ "$mpoint" != "/target/boot" ] && [ "$mpoint" != "/target" ] && [ "$mpoint" != "/" ]; then
-		type=$(grep "^$mapped " "$OS_PROBER_TMP/mounted-map" | head -n1 | cut -d " " -f 3)
+		type="$(echo "$mrecord" | head -n1 | cut -d ' ' -f 3)"
 		if ! grep -q " $mpoint/boot " "$OS_PROBER_TMP/mounted-map"; then
-			linux_mount_boot "$partition" "$mpoint"
-			bootpart="${mountboot%% *}"
-			bootmounted="${mountboot#* }"
+			linux_mount_boot "$partition" "$mpoint" "$subvolid"
+			set -- $mountboot
+			bootpart="$1"
+			bootmounted="$2"
 		else
 			bootpart="$partition"
 			bootmounted=0
@@ -46,7 +48,7 @@ else
 		for test in /usr/lib/linux-boot-probes/mounted/*; do
 			if [ -f $test ] && [ -x $test ]; then
 				debug "running $test on mounted $partition"
-				if $test "$partition" "$bootpart" "$mpoint" "$type"; then
+				if $test "$partition" "$bootpart" "$mpoint" "$type" "$subvolid"; then
 					debug "$test succeeded"
 					break
 				fi
diff --git a/linux-boot-probes/common/50mounted-tests b/linux-boot-probes/common/50mounted-tests
index ad68874..65264f5 100755
--- a/linux-boot-probes/common/50mounted-tests
+++ b/linux-boot-probes/common/50mounted-tests
@@ -14,6 +14,7 @@ do_unmount() {
 }
 
 partition="$1"
+subvolid="$2"
 
 types="$(fs_type "$partition")"
 if [ "$types" = NOT-DETECTED ]; then
@@ -48,6 +49,10 @@ if [ ! -d "$tmpmnt" ]; then
 fi
 
 mounted=
+if [ "$subvolid" ]; then
+	mount "$partition" "$tmpmnt" -o subvolid="$subvolid" &&
+		mounted=1
+else
 if type grub-mount >/dev/null 2>&1 && \
    type grub-probe >/dev/null 2>&1 && \
    grub-mount "$partition" "$tmpmnt" 2>/dev/null; then
@@ -55,16 +60,18 @@ if type grub-mount >/dev/null 2>&1 && \
 	type="$(grub-probe -d "$partition" -t fs)"
 	[ "$type" ] || type=fuseblk
 fi
+fi
 
 if [ "$mounted" ]; then
-	linux_mount_boot "$partition" "$tmpmnt"
-	bootpart="${mountboot%% *}"
-	mounted="${mountboot#* }"
+	linux_mount_boot "$partition" "$tmpmnt" "$subvolid"
+	set -- $mountboot
+	bootpart="$1"
+	bootmounted="$2"
 
 	for test in /usr/lib/linux-boot-probes/mounted/*; do
 		if [ -f "$test" ] && [ -x "$test" ]; then
 			debug "running $test $partition $bootpart $tmpmnt $type"
-			if $test "$partition" "$bootpart" "$tmpmnt" "$type"; then
+			if $test "$partition" "$bootpart" "$tmpmnt" "$type" "$subvolid"; then
 				debug "$test succeeded"
 				do_unmount
 				exit 0
diff --git a/linux-boot-probes/mounted/common/40grub2 b/linux-boot-probes/mounted/common/40grub2
index 885614e..9d0b48c 100755
--- a/linux-boot-probes/mounted/common/40grub2
+++ b/linux-boot-probes/mounted/common/40grub2
@@ -6,6 +6,7 @@ partition="$1"
 bootpart="$2"
 mpoint="$3"
 type="$4"
+subvolid="$5"
 
 found_item=0
 
@@ -13,7 +14,7 @@ entry_result () {
 	if [ "$ignore_item" = 0 ] && \
 	   [ -n "$kernel" ] && \
 	   [ -e "$mpoint/$kernel" ]; then
-		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
+		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 		found_item=1
 	fi
 	kernel=""
diff --git a/linux-boot-probes/mounted/common/90fallback b/linux-boot-probes/mounted/common/90fallback
index 9ff78e1..da0d22d 100755
--- a/linux-boot-probes/mounted/common/90fallback
+++ b/linux-boot-probes/mounted/common/90fallback
@@ -8,6 +8,7 @@ partition="$1"
 bootpart="$2"
 mpoint="$3"
 type="$4"
+subvolid="$5"
 
 mappedpartition=$(mapdevfs "$partition" 2>/dev/null) || mappedpartition="$partition"
 
@@ -38,13 +39,13 @@ for kernpat in /vmlinuz /vmlinux /boot/vmlinuz /boot/vmlinux "/boot/vmlinuz*" \
 			for initrd in $(eval ls "$initrdname" "$initrdname1" "$initrdname2" "$initrdname3" "$initrdname4" 2>/dev/null); do
 				if [ "$initrd" != "$kernfile" ] && [ -f "$initrd" ] && [ ! -L "$initrd" ]; then
 					initrd=$(echo "$initrd" | sed "s!^$mpoint!!")
-					result "$partition:$kernbootpart::$kernbasefile:$initrd:root=$mappedpartition"
+					result "$partition:$kernbootpart::$kernbasefile:$initrd:root=$mappedpartition${subvolid:+ rootflags=subvolid=$subvolid}"
 					exitcode=0
 					foundinitrd=1
 				fi
 			done
 			if [ "$foundinitrd" = 0 ]; then
-				result "$partition:$kernbootpart::$kernbasefile::root=$mappedpartition"
+				result "$partition:$kernbootpart::$kernbasefile::root=$mappedpartition${subvolid:+ rootflags=subvolid=$subvolid}"
 				exitcode=0
 			fi
 		fi
diff --git a/linux-boot-probes/mounted/powerpc/40yaboot b/linux-boot-probes/mounted/powerpc/40yaboot
index 764621c..44ca0bc 100755
--- a/linux-boot-probes/mounted/powerpc/40yaboot
+++ b/linux-boot-probes/mounted/powerpc/40yaboot
@@ -6,6 +6,7 @@ partition="$1"
 bootpart="$2"
 mpoint="$3"
 type="$4"
+subvolid="$5"
 
 found_item=0
 
@@ -36,7 +37,7 @@ recordstanza () {
 			parameters="root=$rootdev $parameters"
 		fi
 		parameters="${parameters% }"
-		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
+		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 		found_item=1
 
 		title=
diff --git a/linux-boot-probes/mounted/sparc/50silo b/linux-boot-probes/mounted/sparc/50silo
index bb5c41c..da6579b 100755
--- a/linux-boot-probes/mounted/sparc/50silo
+++ b/linux-boot-probes/mounted/sparc/50silo
@@ -6,6 +6,7 @@ partition="$1"
 bootpart="$2"
 mpoint="$3"
 type="$4"
+subvolid="$5"
 
 found_item=0
 
@@ -37,7 +38,7 @@ recordstanza () {
 					parameters="root=$rootdev $parameters"
 				fi
 				parameters="${parameters% }"
-				result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
+				result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 				found_item=1
 			else
 				debug "cannot find $initrd, not recording"
diff --git a/linux-boot-probes/mounted/x86/40grub b/linux-boot-probes/mounted/x86/40grub
index 08f6605..4e2eaf1 100755
--- a/linux-boot-probes/mounted/x86/40grub
+++ b/linux-boot-probes/mounted/x86/40grub
@@ -6,6 +6,7 @@ partition="$1"
 bootpart="$2"
 mpoint="$3"
 type="$4"
+subvolid="$5"
 
 found_item=0
 
@@ -13,7 +14,7 @@ entry_result () {
 	if [ "$ignore_item" = 0 ] && \
 	   [ -n "$kernel" ] && \
 	   [ -e "$mpoint/$kernel" ]; then
-		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
+		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 		found_item=1
 	fi
 	kernel=""
diff --git a/linux-boot-probes/mounted/x86/50lilo b/linux-boot-probes/mounted/x86/50lilo
index a011b56..d0f3c1d 100755
--- a/linux-boot-probes/mounted/x86/50lilo
+++ b/linux-boot-probes/mounted/x86/50lilo
@@ -6,6 +6,7 @@ partition="$1"
 bootpart="$2"
 mpoint="$3"
 type="$4"
+subvolid="$5"
 
 found_item=0
 
@@ -48,7 +49,7 @@ recordstanza () {
 				parameters="root=$rootdev $parameters"
 			fi
 			parameters="${parameters% }"
-			result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
+			result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters${subvolid:+ rootflags=subvolid=$subvolid}"
 			found_item=1
 		else
 			debug "cannot find $kernel or $initrd, not recording"
-- 
2.11.0

From ce34b0a3ea289bb712a0841c2ad4bbd67df47754 Mon Sep 17 00:00:00 2001
From: Michael Mestnik <cheako+github_com@mikemestnik.net>
Date: Sun, 4 Jun 2017 20:42:11 -0500
Subject: [PATCH 3/6] Iterate over and insert, subvol, into output

---
 common.sh                               |  8 ++++-
 debian/os-prober.prerm                  | 34 +++++++++++++++++++++
 os-prober                               | 52 +++++++++++++++++++++++++++++++++
 os-probes/common/50mounted-tests        |  8 ++++-
 os-probes/mounted/common/40lsb          |  3 +-
 os-probes/mounted/common/90linux-distro |  3 +-
 6 files changed, 104 insertions(+), 4 deletions(-)
 create mode 100644 debian/os-prober.prerm

diff --git a/common.sh b/common.sh
index e1646d4..8942a91 100644
--- a/common.sh
+++ b/common.sh
@@ -151,7 +151,8 @@ parse_proc_mounts () {
 		set -f
 		set -- $line
 		set +f
-		printf '%s %s %s\n' "$(mapdevfs "$1")" "$2" "$3"
+		printf '%s %s %s %s\n' "$(mapdevfs "$1")" "$2" "$3" "$(
+		echo "$4" | grep -o 'subvolid=[0-9][0-9]*' | cut -d= -f2)"
 	done
 }
 
@@ -204,6 +205,11 @@ find_uuid () {
 	fi
 }
 
+get_default_subvolid () {
+	btrfs subvolume get-default "$1" 2>/dev/null |
+	cut -d ' ' -f 2 | head -n1
+}
+
 # Sets $mountboot as output variables.  This is very messy, but POSIX shell
 # isn't really up to the task of doing it more cleanly.
 linux_mount_boot () {
diff --git a/debian/os-prober.prerm b/debian/os-prober.prerm
new file mode 100644
index 0000000..957d6ef
--- /dev/null
+++ b/debian/os-prober.prerm
@@ -0,0 +1,34 @@
+#!/bin/sh
+# prerm script for os-prober
+#
+# see: dh_installdeb(1)
+
+set -e
+
+case "$1" in
+  remove)
+    # Cleanup script temp files/folders
+    # in case of crash and user uninstalls.
+    # The last thing we want is for our pkg
+    # to generate even more errors on it's
+    # way out.
+    tmpmnt=/var/lib/os-prober/mnt
+    umount "$tmpmnt" 2>/dev/null || true
+    rmdir "$tmpmnt" 2>/dev/null || true
+  ;;
+
+  upgrade|deconfigure|failed-upgrade)
+  ;;
+
+  *)
+    echo "prerm called with unknown argument \`$1'" >&2
+    exit 1
+  ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/os-prober b/os-prober
index a48863e..955020d 100755
--- a/os-prober
+++ b/os-prober
@@ -149,6 +149,58 @@ for partition in $(partitions); do
 		continue
 	fi
 
+	# Scan btrfs subvol(s)
+	type="$(fs_type "$mapped")"
+	if [ "$type" = "btrfs" ] && type btrfs >/dev/null 2>&1; then
+		tmpmnt=/var/lib/os-prober/mnt
+		if [ ! -d "$tmpmnt" ]; then
+			mkdir "$tmpmnt"
+		fi
+		# any fs supporting subvol has no fear of multi-mount
+		mount "$mapped" "$tmpmnt"
+		# 5 is special for btrfs and not listed as a subvol
+		subvols="$(echo 5; btrfs subvolume list "$tmpmnt" | cut -d ' ' -f 2)"
+		rosubvols="$(btrfs subvolume list -r "$tmpmnt" | cut -d ' ' -f 2)"
+		sssubvols="$(btrfs subvolume list -s "$tmpmnt" | cut -d ' ' -f 2)"
+		defaultsv="$(get_default_subvolid "$tmpmnt")"
+		umount "$tmpmnt"
+		for subvol in $subvols; do
+			if echo "$rosubvols" | grep -q -x "$subvol"; then
+				continue
+			fi
+			if echo "$sssubvols" | grep -q -x "$subvol"; then
+				continue
+			fi
+			if [ "$defaultsv" = "$subvol" ]; then
+				mount "$mapped" "$tmpmnt"
+				for test in /usr/lib/os-probes/mounted/*; do
+					if [ -f "$test" ] && [ -x "$test" ]; then
+						debug "running $test on $mapped default subvol "
+						if "$test" "$mapped" "$tmpmnt" "$type"; then
+							debug "os detected by $test"
+							break
+						fi
+					fi
+				done
+				umount "$tmpmnt"
+				continue
+			fi
+			mount -o "subvolid=$subvol" "$mapped" "$tmpmnt"
+			for test in /usr/lib/os-probes/mounted/*; do
+				if [ -f "$test" ] && [ -x "$test" ]; then
+					debug "running $test on $mapped subvolid $subvol"
+					if "$test" "$mapped" "$tmpmnt" "$type" "$subvol"; then
+						debug "os detected by $test"
+						break
+					fi
+				fi
+			done
+			umount "$tmpmnt"
+		done
+		rmdir "$tmpmnt"
+		continue
+	fi
+
 	if ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map" ; then
 		for test in /usr/lib/os-probes/*; do
 			if [ -f "$test" ] && [ -x "$test" ]; then
diff --git a/os-probes/common/50mounted-tests b/os-probes/common/50mounted-tests
index fca15cb..389f8d9 100755
--- a/os-probes/common/50mounted-tests
+++ b/os-probes/common/50mounted-tests
@@ -2,6 +2,7 @@
 # Sub-tests that require a mounted partition.
 set -e
 partition="$1"
+subvolid="$2"
 
 . /usr/share/os-prober/common.sh
 
@@ -58,6 +59,10 @@ if [ ! -d "$tmpmnt" ]; then
 fi
 
 mounted=
+if [ "$subvolid" ]; then
+        mount "$partition" "$tmpmnt" -o subvolid="$subvolid" &&
+                mounted=1
+else
 if type grub-mount >/dev/null 2>&1 && \
    type grub-probe >/dev/null 2>&1 && \
    grub-mount "$partition" "$tmpmnt" 2>/dev/null; then
@@ -70,12 +75,13 @@ if type grub-mount >/dev/null 2>&1 && \
 		type=fuseblk
 	fi
 fi
+fi
 
 if [ "$mounted" ]; then
 	for test in /usr/lib/os-probes/mounted/*; do
 		debug "running subtest $test"
 		if [ -f "$test" ] && [ -x "$test" ]; then
-			if "$test" "$partition" "$tmpmnt" "$type"; then
+			if "$test" "$partition" "$tmpmnt" "$type" "$subvolid"; then
 				debug "os found by subtest $test"
 				do_unmount
 				exit 0
diff --git a/os-probes/mounted/common/40lsb b/os-probes/mounted/common/40lsb
index ce8d4e1..da58b8f 100755
--- a/os-probes/mounted/common/40lsb
+++ b/os-probes/mounted/common/40lsb
@@ -7,6 +7,7 @@ set -e
 partition="$1"
 dir="$2"
 type="$3"
+subvolid="$4"
 
 lsb_field () {
 	file="$1"
@@ -44,5 +45,5 @@ if [ -z "$short" ]; then
 fi
 
 label="$(count_next_label "$short")"
-result "$partition:$long:$label:linux"
+result "$partition${subvolid:+@$subvolid}:$long:$label:linux${subvolid:+-subvolid}"
 exit 0
diff --git a/os-probes/mounted/common/90linux-distro b/os-probes/mounted/common/90linux-distro
index badfbb1..adba52d 100755
--- a/os-probes/mounted/common/90linux-distro
+++ b/os-probes/mounted/common/90linux-distro
@@ -7,6 +7,7 @@ set -e
 partition="$1"
 dir="$2"
 type="$3"
+subvolid="$4"
 
 # This test is inaccurate, but given separate / and /boot partitions and the
 # fact that only some architectures have ld-linux.so, I can't see anything
@@ -143,7 +144,7 @@ if (ls "$dir"/lib*/ld*.so* && [ -d "$dir/boot" ] || ls "$dir"/usr/lib*/ld*.so*)
 	fi
 	
         label="$(count_next_label "$short")"
-	result "$partition:$long:$label:linux"
+	result "$partition${subvolid:+@$subvolid}:$long:$label:linux${subvolid:+-subvolid}"
 	exit 0
 else
 	exit 1
-- 
2.11.0


Reply to: