123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- diff --git a/common.sh b/common.sh
- index c2c5f46..8fb3c5f 100644
- --- a/common.sh
- +++ b/common.sh
- @@ -155,6 +155,7 @@ parse_proc_mounts () {
- done
- }
-
- +# add forth parameter to pickup btrfs subvol info
- parsefstab () {
- while read -r line; do
- case "$line" in
- @@ -165,12 +166,22 @@ 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
- }
-
- +#check_btrfs_mounted $bootsv $bootuuid)
- +check_btrfs_mounted () {
- + bootsv="$1"
- + bootuuid="$2"
- + bootdev=$(blkid | grep "$bootuuid" | cut -d ':' -f 1)
- + bindfrom=$(grep " btrfs " /proc/self/mountinfo |
- + grep " $bootdev " | grep " /$bootsv " | cut -d ' ' -f 5)
- + printf "%s" "$bindfrom"
- +}
- +
- unescape_mount () {
- printf %s "$1" | \
- sed 's/\\011/ /g; s/\\012/\n/g; s/\\040/ /g; s/\\134/\\/g'
- diff --git a/linux-boot-prober b/linux-boot-prober
- index e32dc84..2a60fa2 100755
- --- a/linux-boot-prober
- +++ b/linux-boot-prober
- @@ -5,16 +5,143 @@ set -e
-
- newns "$@"
- require_tmpdir
- +ERR="n"
- +
- +tmpmnt=/var/lib/os-prober/mount
- +if [ ! -d "$tmpmnt" ]; then
- + mkdir "$tmpmnt"
- +fi
- +
- +mounted=
- +bootmnt=
- +bootsv=
- +bootuuid=
-
- grep "^/dev/" /proc/mounts | parse_proc_mounts >"$OS_PROBER_TMP/mounted-map" || true
-
- -partition="$1"
- +if [ -z "$1" ]; then
- + ERR=y
- +elif [ "$1" = btrfs -a -z "$2" ]; then
- + ERR=y
- +elif [ "$1" = btrfs -a -z "$3" ]; then
- + ERR=y
- +elif [ "$1" = btrfs ]; then
- + type=btrfs
- + echo "$2" | grep -q "^UUID=" || ERR=y
- + echo "$3" | grep -q "^subvol=" || ERR=y
- + export "$2"
- + export "$3"
- + partition=$(blkid | grep "$UUID" | cut -d ':' -f 1 | tr '\n' ' ' | cut -d ' ' -f 1)
- + debug "btrfs: partition=$partition, UUID=$UUID, subvol=$subvol"
- +else
- + partition="$1"
- + type=other
- +fi
-
- -if [ -z "$partition" ]; then
- +if [ "x$ERR" != xn ]; then
- echo "usage: linux-boot-prober partition" >&2
- + echo " linux-boot-prober btrfs UUID=<> subvol=<>" >&2
- exit 1
- fi
-
- +if [ "$type" = btrfs ]; then
- + # handle all of the btrfs stuff here
- + if [ ! -e "/proc/self/mountinfo" ]; then
- + warn "/proc/self/mountinfo does not exist, exiting"
- + umount "$tmpmnt" 2>/dev/null
- + rmdir "$tmpmnt" 2>/dev/null
- + exit 1
- + fi
- + mpoint=$(grep "btrfs" /proc/self/mountinfo | grep " /$subvol " | grep " $partition " | cut -d ' ' -f 5)
- + if [ "$mpoint" = "/" ]; then
- + warn "specifying active root not valid, exiting"
- + umount "$tmpmnt" 2>/dev/null
- + rmdir "$tmpmnt" 2>/dev/null
- + exit 1
- + fi
- + if [ "$mpoint" = "$tmpmnt" ]; then
- + warn "btrfs subvol=$subvool, UUID=$UUID, already mounted on $tmpmnt **ERROR**"
- + umount "$tmpmnt" 2>/dev/null
- + rmdir "$tmpmnt" 2>/dev/null
- + exit 1
- + fi
- + if [ -z "$mpoint" ]; then
- + # mount the btrfs root
- + if ! mount -o subvol=$subvol -t btrfs -U $UUID "$tmpmnt" 2>/dev/null; then
- + warn "error mounting btrfs subvol=$subvol UUID=$UUID"
- + umount "$tmpmnt/boot" 2>/dev/null
- + umount "$tmpmnt" 2>/dev/null
- + rmdir "$tmpmnt" 2>/dev/null
- + exit 1
- + fi
- + else
- + # bind-mount
- + if ! mount -o bind "$mpoint" "$tmpmnt" 2>/dev/null; then
- + warn "error mounting btrfs bindfrom=$mpoint subvol=$subvol UUID=$UUID"
- + umount "$tmpmnt/boot" 2>/dev/null
- + umount "$tmpmnt" 2>/dev/null
- + rmdir "$tmpmnt" 2>/dev/null
- + exit 1
- + fi
- + fi
- + debug "mounted btrfs $partition, subvol=$subvol on $tmpmnt"
- + if [ ! -e "$tmpmnt/etc/fstab" ]; then
- + warn "btrfs subvol=$subvol not root"
- + umount "$tmpmnt" 2>/dev/null
- + rmdir "$tmpmnt" 2>/dev/null
- + exit 1
- + fi
- + bootmnt=$(parsefstab < "$tmpmnt/etc/fstab" | grep " /boot ") || true
- + if [ -z "$bootmnt" ]; then
- + # /boot is part of the root
- + bootpart="$partition"
- + bootsv="$subvol"
- + elif echo "$bootmnt" | cut -d ' ' -f 3 | grep -q "btrfs"; then
- + # separate btrfs /boot subvolume
- + bootsv=$(echo "$bootmnt" | cut -d ' ' -f 4 | grep "^subvol=" | sed "s/subvol=//" )
- + bootuuid=$(echo "$bootmnt" | cut -d ' ' -f 1 | grep "^UUID=" | sed "s/UUID=//" )
- + debug "mounting btrfs $tmpmnt/boot UUID=$bootuuid subvol=$bootsv"
- + bindfrom=$(check_btrfs_mounted $bootsv $bootuuid)
- + if [ -n "$bindfrom" ]; then
- + # already mounted some place
- + if ! mount -o bind $bindfrom "$tmpmnt/boot" 2>/dev/null; then
- + warn "error bind mounting btrfs boot subvol=$bootsv, from=$bindfrom"
- + umount "$tmpmnt/boot" 2>/dev/null
- + umount "$tmpmnt" 2>/dev/null
- + rmdir "$tmpmnt" 2>/dev/null
- + exit 1
- + fi
- + elif ! mount -o subvol=$bootsv -t btrfs -U $bootuuid "$tmpmnt/boot" 2>/dev/null; then
- + warn "error mounting btrfs boot partition subvol=$bootsv, UUID=$bootuuid"
- + umount "$tmpmnt/boot" 2>/dev/null
- + umount "$tmpmnt" 2>/dev/null
- + rmdir "$tmpmnt" 2>/dev/null
- + exit 1
- + fi
- + bootpart=$(grep " btrfs " /proc/self/mountinfo | grep " /$bootsv " | cut -d ' ' -f 10)
- + else
- + # non-btrfs partition or logical volume
- + linux_mount_boot $partition $tmpmnt
- + bootpart="${mountboot%% *}"
- + bootsv=
- + fi
- +
- + test="/usr/lib/linux-boot-probes/mounted/40grub2"
- + if [ -f $test ] && [ -x $test ]; then
- + debug "running $test $partition $bootpart $tmpmnt $type $subvol $bootsv"
- + if $test "$partition" "$bootpart" "$tmpmnt" "$type" "$subvol" "$bootsv"; then
- + debug "$test succeeded"
- + fi
- + fi
- + umount "$tmpmnt/boot" 2>/dev/null || true
- + if ! umount "$tmpmnt" 2>/dev/null; then
- + warn "problem umount $tmpmnt"
- + fi
- + rmdir "$tmpmnt" 2>/dev/null || true
- +
- + exit 0
- +fi
- +
- if ! mapped="$(mapdevfs "$partition")"; then
- log "Device '$partition' does not exist; skipping"
- continue
- @@ -22,8 +149,8 @@ fi
-
- if ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map"; then
- for test in /usr/lib/linux-boot-probes/*; do
- - debug "running $test"
- if [ -x $test ] && [ -f $test ]; then
- + debug "running $test"
- if $test "$partition"; then
- debug "linux detected by $test"
- break
- diff --git a/linux-boot-probes/mounted/common/40grub2 b/linux-boot-probes/mounted/common/40grub2
- index 885614e..db5cbfd 100755
- --- a/linux-boot-probes/mounted/common/40grub2
- +++ b/linux-boot-probes/mounted/common/40grub2
- @@ -2,17 +2,30 @@
- . /usr/share/os-prober/common.sh
- set -e
-
- +# add support for btrfs with no separate /boot
- +# that is, rootsv = bootsv
- partition="$1"
- bootpart="$2"
- mpoint="$3"
- type="$4"
- +rootsv="$5"
- +bootsv="$6"
-
- found_item=0
-
- entry_result () {
- + if [ "x$type" = "xbtrfs" -a "$partition" = "$bootpart" ]; then
- + # trim off the leading subvol
- + kernelfile=$(echo "$kernel" | cut -d '/' -f 2- | cut -d '/' -f 2-)
- + if [ "x$rootsv" != "x$bootsv" ]; then
- + kernelfile="/boot/$kernelfile"
- + fi
- + else
- + kernelfile=$kernel
- + fi
- if [ "$ignore_item" = 0 ] && \
- [ -n "$kernel" ] && \
- - [ -e "$mpoint/$kernel" ]; then
- + [ -e "$mpoint/$kernelfile" ]; then
- result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
- found_item=1
- fi
- diff --git a/os-prober b/os-prober
- index 8852887..482c3c2 100755
- --- a/os-prober
- +++ b/os-prober
- @@ -76,9 +76,12 @@ partitions () {
-
- # Also detect OSes on LVM volumes (assumes LVM is active)
- if type lvs >/dev/null 2>&1; then
- - echo "$(LVM_SUPPRESS_FD_WARNINGS=1 log_output lvs --noheadings --separator : -o vg_name,lv_name |
- + echo "$(LVM_SUPPRESS_FD_WARNINGS=1 log_output lvs --noheadings --separator : -o vg_name,lv_name 2>/dev/null |
- sed "s|-|--|g;s|^[[:space:]]*\(.*\):\(.*\)$|/dev/mapper/\1-\2|")"
- fi
- +
- + # now lets make sure we got all of the btrfs partitions and disks
- + blkid | grep 'TYPE="btrfs"' | cut -d ':' -f 1
- }
-
- parse_proc_swaps () {
- @@ -136,6 +139,8 @@ if [ -f /proc/mdstat ] ; then
- grep "^md" /proc/mdstat | cut -d: -f2- | parse_proc_mdstat >"$OS_PROBER_TMP/raided-map" || true
- fi
-
- +: >"$OS_PROBER_TMP/btrfs-vols"
- +
- for partition in $(partitions); do
- if ! mapped="$(mapdevfs "$partition")"; then
- log "Device '$partition' does not exist; skipping"
- @@ -154,7 +159,26 @@ for partition in $(partitions); do
- continue
- fi
-
- - if ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map" ; then
- + # do btrfs processing here; both mounted and unmounted will
- + # be handled by 50mounted-tests so we can do a subvol only once.
- + type=$(blkid -o value -s TYPE $mapped || true)
- + if [ "$type" = btrfs ]; then
- + uuid=$(blkid -o value -s UUID $mapped)
- + if grep -q "^$uuid" "$OS_PROBER_TMP/btrfs-vols" ; then
- + continue
- + fi
- + debug "btrfs volume uuid=$uuid partition=$partition"
- + echo "$uuid" >>"$OS_PROBER_TMP/btrfs-vols"
- + test="/usr/lib/os-probes/50mounted-tests"
- + if [ -f "$test" ] && [ -x "$test" ]; then
- + debug "running $test on btrfs $partition"
- + if "$test" btrfs "$uuid" "$partition"; then
- + debug "os detected by $test"
- + continue
- + fi
- + fi
- +
- + elif ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map" ; then
- for test in /usr/lib/os-probes/*; do
- if [ -f "$test" ] && [ -x "$test" ]; then
- debug "running $test on $partition"
- diff --git a/os-probes/common/50mounted-tests b/os-probes/common/50mounted-tests
- index 2951ef9..e33eb82 100755
- --- a/os-probes/common/50mounted-tests
- +++ b/os-probes/common/50mounted-tests
- @@ -19,19 +19,31 @@ do_unmount() {
- rmdir "$tmpmnt" || true
- }
-
- -types="$(fs_type "$partition")"
- +if [ "x$1" = xbtrfs ]; then
- + types=btrfs
- + if [ -z "$2" -o -z "$3" ]; then
- + debug "missing btrfs parameters, exiting"
- + exit 1
- + fi
- + UUID="$2"
- + BTRFSDEV="$3"
- +else
- + partition="$1"
- + types="$(fs_type "$partition")" || types=NOT-DETECTED
- +fi
- +
- if [ "$types" = NOT-DETECTED ]; then
- debug "$1 type not recognised; skipping"
- - exit 0
- + exit 1
- elif [ "$types" = swap ]; then
- debug "$1 is a swap partition; skipping"
- - exit 0
- + exit 1
- elif [ "$types" = crypto_LUKS ]; then
- debug "$1 is a LUKS partition; skipping"
- - exit 0
- + exit 1
- elif [ "$types" = LVM2_member ]; then
- debug "$1 is an LVM member; skipping"
- - exit 0
- + exit 1
- elif [ "$types" = ntfs ]; then
- if type ntfs-3g >/dev/null 2>&1; then
- types='ntfs-3g ntfs'
- @@ -40,7 +52,7 @@ elif [ -z "$types" ]; then
- if type cryptsetup >/dev/null 2>&1 && \
- cryptsetup luksDump "$partition" >/dev/null 2>&1; then
- debug "$1 is a LUKS partition; skipping"
- - exit 0
- + exit 1
- fi
- for type in $(grep -v nodev /proc/filesystems); do
- # hfsplus filesystems are mountable as hfs. Try hfs last so
- @@ -63,6 +75,108 @@ if [ ! -d "$tmpmnt" ]; then
- fi
-
- mounted=
- +
- +# all btrfs processing here. Handle both unmounted and
- +# mounted subvolumes.
- +if [ "$types" = btrfs ]; then
- + partition="$BTRFSDEV"
- + debug "begin btrfs processing for $UUID"
- + # note that the btrfs volume must not be mounted ro
- + if mount -t btrfs -U "$UUID" "$tmpmnt" 2>/dev/null; then
- + debug "btrfs volume $UUID mounted"
- + else
- + warn "cannot mount btrfs volume $UUID, exiting"
- + rmdir "$tmpmnt" || true
- + exit 1
- + fi
- + # besides regular subvols, get ro and snapshot so thet can be excluded
- + subvols=$(btrfs subvolume list "$tmpmnt" | cut -d ' ' -f 9)
- + rosubvols=$(btrfs subvolume list -r "$tmpmnt" | cut -d ' ' -f 9)
- + sssubvols=$(btrfs subvolume list -s "$tmpmnt" | cut -d ' ' -f 14)
- + if ! umount "$tmpmnt"; then
- + warn "failed to umount btrfs volume on $tmpmnt"
- + rmdir "$tmpmnt" || true
- + exit 1
- + fi
- +
- + found=
- + mounted=
- +
- + mpoint="$(grep btrfs /proc/self/mountinfo | grep "$partition " | cut -d ' ' -f 5)"
- + if [ -n "$mpoint" -a "x$mpoint" = "x/" ]; then
- + debug "This is the root for the running system" #running system must be done elsewhere
- + else
- + #partition was not root of running system, so lets look for bootable subvols
- + if [ -n "$mpoint" ] ; then
- + mounted=1 #partition was already mounted,so lets not unmount it when done
- + else
- + # again, do not mount btrfs ro
- + mount -t btrfs -U "$UUID" "$tmpmnt"
- + mpoint="$tmpmnt"
- + fi
- +
- + test="/usr/lib/os-probes/mounted/90linux-distro"
- + if [ -f "$test" ] && [ -x "$test" ]; then
- + debug "running subtest $test"
- + if "$test" "$partition" "$mpoint" btrfs "UUID=$UUID"; then
- + debug "os found by subtest $test on $partition"
- + found=1
- + fi
- + fi
- + if [ -z "$mounted" ]; then
- + if ! umount "$tmpmnt"; then
- + warn "failed to umount $tmpmnt"
- + fi
- + fi
- + fi
- +
- + if [ -z "$subvols" ]; then
- + debug "no subvols found on btrfs volume $UUID"
- + else
- + found=
- + for subvol in $subvols; do
- + debug "begin btrfs processing for $UUID subvol=$subvol"
- + if echo "$rosubvols" | grep -q -x "$subvol"; then
- + continue
- + fi
- + if echo "$sssubvols" | grep -q -x "$subvol"; then
- + continue
- + fi
- + mounted=
- + mpoint="$(grep btrfs /proc/self/mountinfo | grep "$partition " | grep "/$subvol " | cut -d ' ' -f 5)"
- + if [ -n "$mpoint" ]; then
- + if [ "x$mpoint" = "x/" ]; then
- + continue # this is the root for the running system
- + fi
- + mounted=1
- + else
- + # again, do not mount btrfs ro
- + mount -t btrfs -o subvol="$subvol" -U "$UUID" "$tmpmnt"
- + mpoint="$tmpmnt"
- + fi
- + test="/usr/lib/os-probes/mounted/90linux-distro"
- + if [ -f "$test" ] && [ -x "$test" ]; then
- + debug "running subtest $test"
- + if "$test" "$partition" "$mpoint" btrfs "UUID=$UUID" "subvol=$subvol"; then
- + debug "os found by subtest $test on subvol $subvol"
- + found=1
- + fi
- + fi
- + if [ -z "$mounted" ]; then
- + if ! umount "$tmpmnt"; then
- + warn "failed to umount $tmpmnt"
- + fi
- + fi
- + done
- + fi
- + rmdir "$tmpmnt" || true
- + if [ "$found" ]; then
- + exit 0
- + else
- + exit 1
- + fi
- +fi
- +
- if type grub-mount >/dev/null 2>&1 && \
- type grub-probe >/dev/null 2>&1 && \
- grub-mount "$partition" "$tmpmnt" 2>/dev/null; then
- diff --git a/os-probes/mounted/common/90linux-distro b/os-probes/mounted/common/90linux-distro
- index badfbb1..9bc5154 100755
- --- a/os-probes/mounted/common/90linux-distro
- +++ b/os-probes/mounted/common/90linux-distro
- @@ -7,6 +7,8 @@ set -e
- partition="$1"
- dir="$2"
- type="$3"
- +uuid="$4"
- +subvol="$5"
-
- # 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 +145,11 @@ 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"
- + if [ "x$type" = "xbtrfs" -a "x$uuid" != "x" -a "x$subvol" != "x" ]; then
- + result "$partition:$long:$label:linux:$type:$uuid:$subvol"
- + else
- + result "$partition:$long:$label:linux"
- + fi
- exit 0
- else
- exit 1
|