Skip to content

Commit 40f7928

Browse files
committed
zfsbootmenu-core: optimize initramfs search
1 parent 1eec513 commit 40f7928

File tree

1 file changed

+80
-41
lines changed

1 file changed

+80
-41
lines changed

zfsbootmenu/lib/zfsbootmenu-core.sh

Lines changed: 80 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -715,13 +715,82 @@ set_default_env() {
715715
fi
716716
}
717717

718+
# arg1: path of the kernel for which the initramfs is sought
719+
# prints: path of a matching initramfs
720+
# returns: 0 if initramfs was found, 1 otherwise
721+
722+
find_be_initramfs() {
723+
local kpath
724+
local kdir kern kver ifile candidates
725+
726+
kpath="$1"
727+
if [ ! -r "${kpath}" ]; then
728+
zerror "specified kernel does not exist"
729+
return 1
730+
fi
731+
732+
# Split kernel path into file and directory
733+
kern="${kpath##*/}"
734+
kdir="${kpath%"${kern}"}"
735+
kdir="${kdir%/}"
736+
zdebug "kernel path: '${kpath}', directory: '${kdir}', file: '${kern}'"
737+
738+
# Kernel "base" extends to first hyphen, "version" follows and may be empty
739+
kver="${kern#"${kern%%-*}"}"
740+
zdebug "kernel version: '${kver}'"
741+
742+
# Try some common cases before doing an exhaustive search
743+
744+
candidates=(
745+
# Void, Arch
746+
"initramfs-${kern}.img"
747+
"initramfs${kver}.img"
748+
749+
# Debian and other initramfs-tools users
750+
"initrd.img-${kern}"
751+
"initrd.img${kver}"
752+
753+
# Alpine
754+
"initramfs-${kern}"
755+
"initramfs${kver}"
756+
)
757+
758+
for ifile in "${candidates[@]}"; do
759+
if [ -e "${kdir}/${ifile}" ]; then
760+
zdebug "short-matching '${ifile}' to '${kern}'"
761+
echo "${kdir}/${ifile}"
762+
return 0
763+
fi
764+
done
765+
766+
# Common cases have failed, try a more exhaustive search
767+
768+
local ext pfx lbl ifile
769+
770+
# Use loops instead of a clever brace-expansion for clarity and control
771+
for ext in {.img,""}{"",.{gz,bz2,xz,lzma,lz4,lzo,zstd}}; do
772+
for pfx in initramfs initrd; do
773+
for lbl in "${kern}" "${kver}"; do
774+
for ifile in "${pfx}${lbl}${ext}" "${pfx}${ext}${lbl}"; do
775+
[ -e "${kdir}/${ifile}" ] || continue
776+
zdebug "matching '${ifile}' to '${kern}'"
777+
echo "${kdir}/${ifile}"
778+
return 0
779+
done
780+
done
781+
done
782+
done
783+
784+
return 1
785+
}
786+
718787
# arg1: ZFS filesystem
719788
# prints: nothing
720789
# returns: 0 if kernels were found, 1 otherwise
721790

722791
find_be_kernels() {
723792
local fs mnt
724-
local kpath kdir kernel kernel_base labels version kernel_records
793+
local kpath ipath kernel_records
725794

726795
fs="${1}"
727796
if [ -z "${fs}" ]; then
@@ -740,51 +809,21 @@ find_be_kernels() {
740809
kernel_records="${mnt%/*}/kernels"
741810
: > "${kernel_records}"
742811

743-
# Look for kernels in / and /boot, sorted in version order
812+
# Look for kernels and matching initramfs, sorted in version order
744813
while read -r kpath; do
745814
# Strip mount point from path
815+
[ -n "${kpath}" ] || continue;
746816
kpath="${kpath#"${mnt}"}"
747-
# Ensure kpath has leading slash
748817
kpath="/${kpath#/}"
749-
zdebug "found kernel: ${mnt}${kpath}"
750-
751-
# Extract base name and kernel directory
752-
kernel="${kpath##*/}"
753-
kdir="${kpath%"${kernel}"}"
754-
# Trim trailing slash (note: kdir will be empty if kernel is at root)
755-
kdir="${kdir%/}"
756-
zdebug "kernel directory: '${kdir}', file: '${kernel}'"
757-
758-
# Kernel "base" extends to first hyphen
759-
kernel_base="${kernel%%-*}"
760-
761-
# Kernel "version" is everything after base and may be empty
762-
version="${kernel#"${kernel_base}"}"
763-
version="${version#-}"
764-
zdebug "kernel base: '${kernel_base}', version: '${version}'"
765-
766-
# initramfs images can take many forms, look for a sensible one
767-
labels=( "$kernel" )
768-
if [ -n "$version" ]; then
769-
labels+=( "$version" )
770-
fi
771-
772-
# Use a mess of loops instead better brace expansions to control priorities
773-
local ext pfx lbl i ipath
774-
for ext in {.img,""}{"",.{gz,bz2,xz,lzma,lz4,lzo,zstd}}; do
775-
for pfx in initramfs initrd; do
776-
for lbl in "${labels[@]}"; do
777-
for i in "${pfx}-${lbl}${ext}" "${pfx}${ext}-${lbl}"; do
778-
ipath="${kdir}/${i}"
779-
[ -e "${mnt}${ipath}" ] || continue
780-
zdebug "matching '${i}' to '${kernel}'"
781-
echo "${fs} ${kpath} ${ipath}" >> "${kernel_records}"
782-
break 4
783-
done
784-
done
785-
done
786-
done
787818

819+
if ipath="$( find_be_initramfs "${mnt}${kpath}" )"; then
820+
zdebug "found kernel: ${mnt}${kpath}, initramfs ${mnt}${ipath}"
821+
ipath="${ipath#"${mnt}"}"
822+
ipath="/${ipath#/}"
823+
echo "${fs} ${kpath} ${ipath}" >> "${kernel_records}"
824+
else
825+
zdebug "kernel ${mnt}${kpath} has no initramfs"
826+
fi
788827
done <<<"$(
789828
for k in "${mnt}/boot"/{{vm,}linu{x,z},kernel}{,-*}; do
790829
[ -e "${k}" ] && echo "${k}"

0 commit comments

Comments
 (0)