@@ -329,7 +329,7 @@ mount_zfs() {
329329 fi
330330
331331 # zfsutil is required for non-legacy mounts and omitted for legacy mounts or snapshots
332- if [ " $( zfs get -H -o value mountpoint " ${fs} " ) " = " legacy" ] || is_snapshot " ${fs} " ; then
332+ if [ " $( zfs get -H -o value mountpoint " ${fs} " ) " = " legacy" ] || is_snapshot " ${fs} " ; then
333333 zdebug " mounting ${fs} at ${mnt} (${rwo} )"
334334 mount -o " ${rwo} " -t zfs " ${fs} " " ${mnt} "
335335 ret=$?
@@ -388,7 +388,7 @@ kexec_kernel() {
388388 ZBM_SELECTED_MOUNTPOINT=" ${mnt} " \
389389 /libexec/zfsbootmenu-run-hooks " boot-sel.d"
390390
391- cli_args=" $( load_be_cmdline " ${fs} " ) "
391+ cli_args=" $( load_be_cmdline " ${fs} " " ${kernel} " ) "
392392 root_prefix=" $( find_root_prefix " ${fs} " " ${mnt} " ) "
393393
394394 dtb_prop=" $( zfs get -H -o value org.zfsbootmenu:devicetree " ${fs} " 2> /dev/null ) "
@@ -866,7 +866,7 @@ find_be_initramfs() {
866866
867867find_be_kernels () {
868868 local fs mnt
869- local kpath ipath kernel_records
869+ local kpath ipath kernel_records kcl_path
870870
871871 fs=" ${1} "
872872 if [ -z " ${fs} " ]; then
@@ -885,6 +885,13 @@ find_be_kernels() {
885885 kernel_records=" ${mnt%/* } /kernels"
886886 : > " ${kernel_records} "
887887
888+ # Clear any existing KCL cache before enumerating kernels
889+ if kcl_path=" $( kernel_kcl_cache " ${fs} " " ." ) " ; then
890+ kcl_path=" ${kcl_path%/ ..kcl} "
891+ mkdir -p " ${kcl_path} "
892+ rm -f " ${kcl_path} " /* .kcl
893+ fi
894+
888895 # Look for kernels and matching initramfs, sorted in version order
889896 while read -r kpath; do
890897 # Strip mount point from path
@@ -900,6 +907,12 @@ find_be_kernels() {
900907 else
901908 zdebug " kernel ${mnt}${kpath} has no initramfs"
902909 fi
910+
911+ if [ -r " ${mnt} /${kpath} .kcl" ]; then
912+ if kcl_path=" $( kernel_kcl_cache " ${fs} " " ${kpath} " ) " ; then
913+ cp " ${mnt} /${kpath} .kcl" " ${kcl_path} "
914+ fi
915+ fi
903916 done <<< " $(
904917 for k in " ${mnt} /boot" /{{vm,}linu{x,z},kernel}{,-*}; do
905918 [ -e " ${k} " ] && echo " ${k} "
@@ -1060,11 +1073,42 @@ validate_cmdline_cache() {
10601073}
10611074
10621075# arg1: ZFS filesystem
1076+ # arg2: optional path to kernel
1077+ # prints: path to kernel-specific KCL cache
1078+ # returns: 0 on success
1079+
1080+ kernel_kcl_cache () {
1081+ local fs kernel
1082+
1083+ fs=" ${1} "
1084+ if [ -z " ${fs} " ]; then
1085+ zerror " filesystem is undefined"
1086+ return 1
1087+ fi
1088+
1089+ kernel=" ${2} "
1090+ if [ -z " ${kernel} " ]; then
1091+ zdebug " no kernel specified for ${fs} "
1092+ return 1
1093+ fi
1094+
1095+ # Flatten the kernel hierarchy for the kcl cache
1096+ # - Replace "/" with ":", but change literal ":" to "::" to avoid ambiguity
1097+ kernel=" ${kernel#/ } "
1098+ kernel=" ${kernel//:/:: } "
1099+ kernel=" ${kernel// \/ /: } "
1100+
1101+ echo " $( be_location " ${fs} " ) /kcl/${kernel} .kcl"
1102+ return 0
1103+ }
1104+
1105+ # arg1: ZFS filesystem
1106+ # arg2: optional kernel to select
10631107# prints: kernel command line arguments
10641108# returns: nothing
10651109
10661110load_be_cmdline () {
1067- local fs args spl_hostid kcl cache rems adds
1111+ local fs kern_kcl args spl_hostid kcl cache rems adds
10681112
10691113 fs=" ${1} "
10701114 if [ -z " ${fs} " ]; then
@@ -1073,7 +1117,13 @@ load_be_cmdline() {
10731117 fi
10741118 zdebug " fs set to ${fs} "
10751119
1076- cache=" $( be_location " ${fs} " ) /cmdline"
1120+ # Ignore a pre-existing cache if a kernel-specific command-line is specified
1121+ [ -n " ${2} " ] && kern_kcl=" $( kernel_kcl_cache " ${fs} " " ${2} " ) "
1122+ if [ -r " ${kern_kcl} " ]; then
1123+ zdebug " found kernel KCL ${kern_kcl} on ${fs} , ignoring KCL cache"
1124+ else
1125+ cache=" $( kernel_kcl_cache " ${fs} " " default" ) "
1126+ fi
10771127
10781128 if [ -r " ${BASE} /cmdline" ]; then
10791129 # Always prefer a user-entered KCL
@@ -1093,8 +1143,9 @@ load_be_cmdline() {
10931143 # Nothing is added by default
10941144 adds=()
10951145
1096- # In all other cases, build and attempt to cache the KCL
1097- args=" $( read_kcl_prop " ${fs} " | kcl_tokenize && exit " ${PIPESTATUS[0]} " ) " || args=" "
1146+ args=" $( read_kcl_value " ${fs} " " ${kern_kcl} " ) " || args=" "
1147+ args=" $( kcl_tokenize <<< " ${args}" ) " || args=" "
1148+
10981149 # Use a very basic default KCL if none is specified
10991150 [ -n " ${args} " ] || args=" quiet loglevel=4"
11001151
@@ -1125,10 +1176,13 @@ load_be_cmdline() {
11251176 adds+=( " ${spl_hostid} " )
11261177 fi
11271178
1128- # Write the cached command line, if possible
1129- zdebug " caching KCL for ${fs} at ${cache} "
11301179 args=" $( kcl_suppress " ${rems[@]} " <<< " ${args}" | kcl_append " ${adds[@]} " ) "
1131- printf " %s\n" " ${args} " > " ${cache} "
1180+
1181+ if [ -n " ${cache} " ]; then
1182+ # Write the cached command line, if possible
1183+ zdebug " caching KCL for ${fs} at ${cache} "
1184+ printf " %s\n" " ${args} " > " ${cache} "
1185+ fi
11321186
11331187 kcl=" $( kcl_assemble <<< " ${args}" ) "
11341188 zdebug " assembled commandline: '${kcl} '"
@@ -1794,7 +1848,7 @@ cache_key() {
17941848 fi
17951849
17961850 relkeyloc=" "
1797- if ksmount=" $( zfs get -o value -H mountpoint " ${keysrc} " 2> /dev/null ) " ; then
1851+ if ksmount=" $( zfs get -o value -H mountpoint " ${keysrc} " 2> /dev/null ) " ; then
17981852 case " ${ksmount} " in
17991853 none|legacy)
18001854 zdebug " no discernable mountpoint for ${keysrc} , using only absolute key path"
@@ -2010,8 +2064,8 @@ emergency_shell() {
20102064 cat << -EOF
20112065 $( colorize green " emergency shell" ) ${1: +: $1 }
20122066
2013- type '$( colorize red " help" ) ' for online documentation
2014- type '$( colorize red " exit" ) ' to return to ZFSBootMenu
2067+ type '$( colorize red " help" ) ' for online documentation
2068+ type '$( colorize red " exit" ) ' to return to ZFSBootMenu
20152069
20162070 EOF
20172071
@@ -2185,7 +2239,7 @@ is_mountpoint() {
21852239 return
21862240 fi
21872241
2188- if ! mount_path=" $( readlink -f " ${1} " ) " ; then
2242+ if ! mount_path=" $( readlink -f " ${1} " ) " ; then
21892243 zerror " parent of ${1} does not exist"
21902244 return 1
21912245 fi
@@ -2197,7 +2251,7 @@ is_mountpoint() {
21972251
21982252 # shellcheck disable=SC2034
21992253 while read -r dev path opts; do
2200- path=" $( readlink -f " ${path} " ) " || continue
2254+ path=" $( readlink -f " ${path} " ) " || continue
22012255 [ " ${path} " = " ${mount_path} " ] && return 0
22022256 done < /proc/self/mounts
22032257
0 commit comments