Skip to content

Commit

Permalink
zfsbootmenu-core: optimize initramfs search
Browse files Browse the repository at this point in the history
  • Loading branch information
ahesford committed Sep 20, 2023
1 parent 1eec513 commit 40f7928
Showing 1 changed file with 80 additions and 41 deletions.
121 changes: 80 additions & 41 deletions zfsbootmenu/lib/zfsbootmenu-core.sh
Original file line number Diff line number Diff line change
Expand Up @@ -715,13 +715,82 @@ set_default_env() {
fi
}

# arg1: path of the kernel for which the initramfs is sought
# prints: path of a matching initramfs
# returns: 0 if initramfs was found, 1 otherwise

find_be_initramfs() {
local kpath
local kdir kern kver ifile candidates

kpath="$1"
if [ ! -r "${kpath}" ]; then
zerror "specified kernel does not exist"
return 1
fi

# Split kernel path into file and directory
kern="${kpath##*/}"
kdir="${kpath%"${kern}"}"
kdir="${kdir%/}"
zdebug "kernel path: '${kpath}', directory: '${kdir}', file: '${kern}'"

# Kernel "base" extends to first hyphen, "version" follows and may be empty
kver="${kern#"${kern%%-*}"}"
zdebug "kernel version: '${kver}'"

# Try some common cases before doing an exhaustive search

candidates=(
# Void, Arch
"initramfs-${kern}.img"
"initramfs${kver}.img"

# Debian and other initramfs-tools users
"initrd.img-${kern}"
"initrd.img${kver}"

# Alpine
"initramfs-${kern}"
"initramfs${kver}"
)

for ifile in "${candidates[@]}"; do
if [ -e "${kdir}/${ifile}" ]; then
zdebug "short-matching '${ifile}' to '${kern}'"
echo "${kdir}/${ifile}"
return 0
fi
done

# Common cases have failed, try a more exhaustive search

local ext pfx lbl ifile

# Use loops instead of a clever brace-expansion for clarity and control
for ext in {.img,""}{"",.{gz,bz2,xz,lzma,lz4,lzo,zstd}}; do
for pfx in initramfs initrd; do
for lbl in "${kern}" "${kver}"; do
for ifile in "${pfx}${lbl}${ext}" "${pfx}${ext}${lbl}"; do
[ -e "${kdir}/${ifile}" ] || continue
zdebug "matching '${ifile}' to '${kern}'"
echo "${kdir}/${ifile}"
return 0
done
done
done
done

return 1
}

# arg1: ZFS filesystem
# prints: nothing
# returns: 0 if kernels were found, 1 otherwise

find_be_kernels() {
local fs mnt
local kpath kdir kernel kernel_base labels version kernel_records
local kpath ipath kernel_records

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

# Look for kernels in / and /boot, sorted in version order
# Look for kernels and matching initramfs, sorted in version order
while read -r kpath; do
# Strip mount point from path
[ -n "${kpath}" ] || continue;
kpath="${kpath#"${mnt}"}"
# Ensure kpath has leading slash
kpath="/${kpath#/}"
zdebug "found kernel: ${mnt}${kpath}"

# Extract base name and kernel directory
kernel="${kpath##*/}"
kdir="${kpath%"${kernel}"}"
# Trim trailing slash (note: kdir will be empty if kernel is at root)
kdir="${kdir%/}"
zdebug "kernel directory: '${kdir}', file: '${kernel}'"

# Kernel "base" extends to first hyphen
kernel_base="${kernel%%-*}"

# Kernel "version" is everything after base and may be empty
version="${kernel#"${kernel_base}"}"
version="${version#-}"
zdebug "kernel base: '${kernel_base}', version: '${version}'"

# initramfs images can take many forms, look for a sensible one
labels=( "$kernel" )
if [ -n "$version" ]; then
labels+=( "$version" )
fi

# Use a mess of loops instead better brace expansions to control priorities
local ext pfx lbl i ipath
for ext in {.img,""}{"",.{gz,bz2,xz,lzma,lz4,lzo,zstd}}; do
for pfx in initramfs initrd; do
for lbl in "${labels[@]}"; do
for i in "${pfx}-${lbl}${ext}" "${pfx}${ext}-${lbl}"; do
ipath="${kdir}/${i}"
[ -e "${mnt}${ipath}" ] || continue
zdebug "matching '${i}' to '${kernel}'"
echo "${fs} ${kpath} ${ipath}" >> "${kernel_records}"
break 4
done
done
done
done

if ipath="$( find_be_initramfs "${mnt}${kpath}" )"; then
zdebug "found kernel: ${mnt}${kpath}, initramfs ${mnt}${ipath}"
ipath="${ipath#"${mnt}"}"
ipath="/${ipath#/}"
echo "${fs} ${kpath} ${ipath}" >> "${kernel_records}"
else
zdebug "kernel ${mnt}${kpath} has no initramfs"
fi
done <<<"$(
for k in "${mnt}/boot"/{{vm,}linu{x,z},kernel}{,-*}; do
[ -e "${k}" ] && echo "${k}"
Expand Down

0 comments on commit 40f7928

Please sign in to comment.