From: Kairui Song <kasong at redhat.com>
Move and adjusted the code slightly to make it work within a seperate
file.
Estimate depends on some vairables defined in kdumpctl, export them.
Signed-off-by: Kairui Song <kasong(a)redhat.com>
Signed-off-by: Lichen Liu <lichliu(a)redhat.com>
---
kdump-estimate.sh | 186 +++++++++++++++++++++++++++++++++++++++++++
kdumpctl | 199 ++++------------------------------------------
kexec-tools.spec | 2 +
3 files changed, 205 insertions(+), 182 deletions(-)
create mode 100755 kdump-estimate.sh
diff --git a/kdump-estimate.sh b/kdump-estimate.sh
new file mode 100755
index 0000000..063a6d2
--- /dev/null
+++ b/kdump-estimate.sh
@@ -0,0 +1,186 @@
+#!/bin/bash
+
+[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
+. $dracutbasedir/dracut-functions.sh
+. /lib/kdump/kdump-lib.sh
+. /lib/kdump/kdump-logger.sh
+
+if [[ -f /etc/sysconfig/kdump ]]; then
+ . /etc/sysconfig/kdump
+fi
+
+if ! dlog_init; then
+ echo "failed to initiate the kdump logger."
+ exit 1
+fi
+
+check_vmlinux()
+{
+ # Use readelf to check if it's a valid ELF
+ readelf -h "$1" &> /dev/null || return 1
+}
+
+get_vmlinux_size()
+{
+ local size=0 _msize
+
+ while read -r _msize; do
+ size=$((size + _msize))
+ done <<< "$(readelf -l -W "$1" | awk '/^ LOAD/{print
$6}' 2> /dev/stderr)"
+
+ echo $size
+}
+
+try_decompress()
+{
+ # The obscure use of the "tr" filter is to work around older versions of
+ # "grep" that report the byte offset of the line instead of the pattern.
+
+ # Try to find the header ($1) and decompress from here
+ for pos in $(tr "$1\n$2" "\n$2=" < "$4" | grep -abo
"^$2"); do
+ if ! type -P "$3" > /dev/null; then
+ ddebug "Signiature detected but '$3' is missing, skip this
decompressor"
+ break
+ fi
+
+ pos=${pos%%:*}
+ tail "-c+$pos" "$img" | $3 > "$5" 2> /dev/null
+ if check_vmlinux "$5"; then
+ ddebug "Kernel is extracted with '$3'"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+# Borrowed from linux/scripts/extract-vmlinux
+get_kernel_size()
+{
+ # Prepare temp files:
+ local tmp img=$1
+
+ tmp=$(mktemp /tmp/vmlinux-XXX)
+ trap 'rm -f "$tmp"' 0
+
+ # Try to check if it's a vmlinux already
+ check_vmlinux "$img" && get_vmlinux_size "$img" &&
return 0
+
+ # That didn't work, so retry after decompression.
+ try_decompress '\037\213\010' xy gunzip "$img" "$tmp" ||
+ try_decompress '\3757zXZ\000' abcde unxz "$img" "$tmp" ||
+ try_decompress 'BZh' xy bunzip2 "$img" "$tmp" ||
+ try_decompress '\135\0\0\0' xxx unlzma "$img" "$tmp" ||
+ try_decompress '\211\114\132' xy 'lzop -d' "$img"
"$tmp" ||
+ try_decompress '\002!L\030' xxx 'lz4 -d' "$img"
"$tmp" ||
+ try_decompress '(\265/\375' xxx unzstd "$img" "$tmp"
+
+ # Finally check for uncompressed images or objects:
+ [[ $? -eq 0 ]] && get_vmlinux_size "$tmp" && return 0
+
+ # Fallback to use iomem
+ local _size=0 _seg
+ while read -r _seg; do
+ _size=$((_size + 0x${_seg#*-} - 0x${_seg%-*}))
+ done <<< "$(grep -E "Kernel (code|rodata|data|bss)" /proc/iomem
| cut -d ":" -f 1)"
+ echo $_size
+}
+
+do_estimate_simple()
+{
+ local kdump_mods
+ local -A large_mods
+ local baseline
+ local kernel_size mod_size initrd_size baseline_size runtime_size reserved_size
estimated_size recommended_size _cryptsetup_overhead
+ local size_mb=$((1024 * 1024))
+
+ # TODO: fix TARGET_INITRD reference
+ kdump_mods="$(lsinitrd "$TARGET_INITRD" -f
/usr/lib/dracut/hostonly-kernel-modules.txt | tr '\n' ' ')"
+ baseline=$(kdump_get_arch_recommend_size)
+ if [[ ${baseline: -1} == "M" ]]; then
+ baseline=${baseline%M}
+ elif [[ ${baseline: -1} == "G" ]]; then
+ baseline=$((${baseline%G} * 1024))
+ elif [[ ${baseline: -1} == "T" ]]; then
+ baseline=$((${baseline%Y} * 1048576))
+ fi
+
+ # The default pre-reserved crashkernel value
+ baseline_size=$((baseline * size_mb))
+ # Current reserved crashkernel size
+ reserved_size=$(< /sys/kernel/kexec_crash_size)
+ # A pre-estimated value for userspace usage and kernel
+ # runtime allocation, 64M should good for most cases
+ runtime_size=$((64 * size_mb))
+ # Kernel image size
+ kernel_size=$(get_kernel_size "$KDUMP_KERNEL")
+ # Kdump initramfs size
+ initrd_size=$(du -b "$TARGET_INITRD" | awk '{print $1}')
+ # Kernel modules static size after loaded
+ mod_size=0
+ while read -r _name _size _; do
+ if [[ " $kdump_mods " != *" $_name "* ]]; then
+ continue
+ fi
+ mod_size=$((mod_size + _size))
+
+ # Mark module with static size larger than 2M as large module
+ if [[ $((_size / size_mb)) -ge 1 ]]; then
+ large_mods[$_name]=$_size
+ fi
+ done <<< "$(< /proc/modules)"
+
+ # Extra memory usage required for LUKS2 decryption
+ crypt_size=0
+ for _dev in $(get_all_kdump_crypt_dev); do
+ _crypt_info=$(cryptsetup luksDump "/dev/block/$_dev")
+ [[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p") ==
"2" ]] || continue
+ for _mem in $(echo "$_crypt_info" | sed -n
"s/\sMemory:\s*\(.*\)/\1/p" | sort -n -r); do
+ crypt_size=$((crypt_size + _mem * 1024))
+ break
+ done
+ done
+
+ if [[ $crypt_size -ne 0 ]]; then
+ if [[ $(uname -m) == aarch64 ]]; then
+ _cryptsetup_overhead=50
+ else
+ _cryptsetup_overhead=20
+ fi
+
+ crypt_size=$((crypt_size + _cryptsetup_overhead * size_mb))
+ echo -e "Encrypted kdump target requires extra memory, assuming using the keyslot
with maximum memory requirement\n"
+ fi
+
+ estimated_size=$((kernel_size + mod_size + initrd_size + runtime_size + crypt_size))
+ if [[ $baseline_size -gt $estimated_size ]]; then
+ recommended_size=$baseline_size
+ else
+ recommended_size=$estimated_size
+ fi
+
+ echo "Reserved crashkernel: $((reserved_size / size_mb))M"
+ echo "Recommended crashkernel: $((recommended_size / size_mb))M"
+ echo
+ echo "Kernel image size: $((kernel_size / size_mb))M"
+ echo "Kernel modules size: $((mod_size / size_mb))M"
+ echo "Initramfs size: $((initrd_size / size_mb))M"
+ echo "Runtime reservation: $((runtime_size / size_mb))M"
+ [[ $crypt_size -ne 0 ]] &&
+ echo "LUKS required size: $((crypt_size / size_mb))M"
+ echo -n "Large modules:"
+ if [[ ${#large_mods[@]} -eq 0 ]]; then
+ echo " <none>"
+ else
+ echo ""
+ for _mod in "${!large_mods[@]}"; do
+ echo " $_mod: ${large_mods[$_mod]}"
+ done
+ fi
+
+ if [[ $reserved_size -le $recommended_size ]]; then
+ echo "WARNING: Current crashkernel size is lower than recommended size
$((recommended_size / size_mb))M."
+ fi
+}
+
+do_estimate_simple
diff --git a/kdumpctl b/kdumpctl
index 8add4ce..ef3aa74 100755
--- a/kdumpctl
+++ b/kdumpctl
@@ -1165,187 +1165,6 @@ rebuild()
rebuild_initrd
}
-check_vmlinux()
-{
- # Use readelf to check if it's a valid ELF
- readelf -h "$1" &> /dev/null || return 1
-}
-
-get_vmlinux_size()
-{
- local size=0 _msize
-
- while read -r _msize; do
- size=$((size + _msize))
- done <<< "$(readelf -l -W "$1" | awk '/^ LOAD/{print
$6}' 2> /dev/stderr)"
-
- echo $size
-}
-
-try_decompress()
-{
- # The obscure use of the "tr" filter is to work around older versions of
- # "grep" that report the byte offset of the line instead of the pattern.
-
- # Try to find the header ($1) and decompress from here
- for pos in $(tr "$1\n$2" "\n$2=" < "$4" | grep -abo
"^$2"); do
- if ! type -P "$3" > /dev/null; then
- ddebug "Signiature detected but '$3' is missing, skip this
decompressor"
- break
- fi
-
- pos=${pos%%:*}
- tail "-c+$pos" "$img" | $3 > "$5" 2> /dev/null
- if check_vmlinux "$5"; then
- ddebug "Kernel is extracted with '$3'"
- return 0
- fi
- done
-
- return 1
-}
-
-# Borrowed from linux/scripts/extract-vmlinux
-get_kernel_size()
-{
- # Prepare temp files:
- local tmp img=$1
-
- tmp="$KDUMP_TMPDIR/vmlinux"
-
- # Try to check if it's a vmlinux already
- check_vmlinux "$img" && get_vmlinux_size "$img" &&
return 0
-
- # That didn't work, so retry after decompression.
- try_decompress '\037\213\010' xy gunzip "$img" "$tmp" ||
- try_decompress '\3757zXZ\000' abcde unxz "$img" "$tmp" ||
- try_decompress 'BZh' xy bunzip2 "$img" "$tmp" ||
- try_decompress '\135\0\0\0' xxx unlzma "$img" "$tmp" ||
- try_decompress '\211\114\132' xy 'lzop -d' "$img"
"$tmp" ||
- try_decompress '\002!L\030' xxx 'lz4 -d' "$img"
"$tmp" ||
- try_decompress '(\265/\375' xxx unzstd "$img" "$tmp"
-
- # Finally check for uncompressed images or objects:
- [[ $? -eq 0 ]] && get_vmlinux_size "$tmp" && return 0
-
- # Fallback to use iomem
- local _size=0 _seg
- while read -r _seg; do
- _size=$((_size + 0x${_seg#*-} - 0x${_seg%-*}))
- done <<< "$(grep -E "Kernel (code|rodata|data|bss)" /proc/iomem
| cut -d ":" -f 1)"
- echo $_size
-}
-
-do_estimate()
-{
- local kdump_mods
- local -A large_mods
- local baseline
- local kernel_size mod_size initrd_size baseline_size runtime_size reserved_size
estimated_size recommended_size _cryptsetup_overhead
- local size_mb=$((1024 * 1024))
-
- setup_initrd
- is_system_modified
- case "$?" in
- 0)
- # Nothing to do
- ;;
- 1)
- rebuild_initrd || return
- ;;
- *)
- return
- ;;
- esac
-
- kdump_mods="$(lsinitrd "$TARGET_INITRD" -f
/usr/lib/dracut/hostonly-kernel-modules.txt | tr '\n' ' ')"
- baseline=$(kdump_get_arch_recommend_size)
- if [[ ${baseline: -1} == "M" ]]; then
- baseline=${baseline%M}
- elif [[ ${baseline: -1} == "G" ]]; then
- baseline=$((${baseline%G} * 1024))
- elif [[ ${baseline: -1} == "T" ]]; then
- baseline=$((${baseline%Y} * 1048576))
- fi
-
- # The default pre-reserved crashkernel value
- baseline_size=$((baseline * size_mb))
- # Current reserved crashkernel size
- reserved_size=$(< /sys/kernel/kexec_crash_size)
- # A pre-estimated value for userspace usage and kernel
- # runtime allocation, 64M should good for most cases
- runtime_size=$((64 * size_mb))
- # Kernel image size
- kernel_size=$(get_kernel_size "$KDUMP_KERNEL")
- # Kdump initramfs size
- initrd_size=$(du -b "$TARGET_INITRD" | awk '{print $1}')
- # Kernel modules static size after loaded
- mod_size=0
- while read -r _name _size _; do
- if [[ " $kdump_mods " != *" $_name "* ]]; then
- continue
- fi
- mod_size=$((mod_size + _size))
-
- # Mark module with static size larger than 2M as large module
- if [[ $((_size / size_mb)) -ge 1 ]]; then
- large_mods[$_name]=$_size
- fi
- done <<< "$(< /proc/modules)"
-
- # Extra memory usage required for LUKS2 decryption
- crypt_size=0
- for _dev in $(get_all_kdump_crypt_dev); do
- _crypt_info=$(cryptsetup luksDump "/dev/block/$_dev")
- [[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p") ==
"2" ]] || continue
- for _mem in $(echo "$_crypt_info" | sed -n
"s/\sMemory:\s*\(.*\)/\1/p" | sort -n -r); do
- crypt_size=$((crypt_size + _mem * 1024))
- break
- done
- done
-
- if [[ $crypt_size -ne 0 ]]; then
- if [[ $(uname -m) == aarch64 ]]; then
- _cryptsetup_overhead=50
- else
- _cryptsetup_overhead=20
- fi
-
- crypt_size=$((crypt_size + _cryptsetup_overhead * size_mb))
- echo -e "Encrypted kdump target requires extra memory, assuming using the keyslot
with maximum memory requirement\n"
- fi
-
- estimated_size=$((kernel_size + mod_size + initrd_size + runtime_size + crypt_size))
- if [[ $baseline_size -gt $estimated_size ]]; then
- recommended_size=$baseline_size
- else
- recommended_size=$estimated_size
- fi
-
- echo "Reserved crashkernel: $((reserved_size / size_mb))M"
- echo "Recommended crashkernel: $((recommended_size / size_mb))M"
- echo
- echo "Kernel image size: $((kernel_size / size_mb))M"
- echo "Kernel modules size: $((mod_size / size_mb))M"
- echo "Initramfs size: $((initrd_size / size_mb))M"
- echo "Runtime reservation: $((runtime_size / size_mb))M"
- [[ $crypt_size -ne 0 ]] &&
- echo "LUKS required size: $((crypt_size / size_mb))M"
- echo -n "Large modules:"
- if [[ ${#large_mods[@]} -eq 0 ]]; then
- echo " <none>"
- else
- echo ""
- for _mod in "${!large_mods[@]}"; do
- echo " $_mod: ${large_mods[$_mod]}"
- done
- fi
-
- if [[ $reserved_size -lt $recommended_size ]]; then
- echo "WARNING: Current crashkernel size is lower than recommended size
$((recommended_size / size_mb))M."
- fi
-}
-
get_default_crashkernel()
{
local _dump_mode=$1
@@ -1823,7 +1642,23 @@ main()
show_reserved_mem
;;
estimate)
- do_estimate
+ export KDUMP_KERNEL
+ export TARGET_INITRD
+ export DEFAULT_INITRD
+ setup_initrd
+ is_system_modified
+ case "$?" in
+ 0)
+ # Nothing to do
+ ;;
+ 1)
+ rebuild_initrd || return
+ ;;
+ *)
+ return
+ ;;
+ esac
+ exec /lib/kdump/kdump-estimate.sh "$@"
;;
get-default-crashkernel)
get_default_crashkernel "$2"
diff --git a/kexec-tools.spec b/kexec-tools.spec
index 5a6648e..9990d92 100644
--- a/kexec-tools.spec
+++ b/kexec-tools.spec
@@ -39,6 +39,7 @@ Source34: crashkernel-howto.txt
Source35: kdump-migrate-action.sh
Source36: kdump-restart.sh
Source37: 60-fadump.install
+Source38: kdump-estimate.sh
#######################################
# These are sources for mkdumpramfs
@@ -194,6 +195,7 @@ install -m 644 %{SOURCE12} $RPM_BUILD_ROOT%{_mandir}/man8/mkdumprd.8
install -m 644 %{SOURCE25} $RPM_BUILD_ROOT%{_mandir}/man8/kdumpctl.8
install -m 755 %{SOURCE20} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-lib.sh
install -m 755 %{SOURCE23} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-lib-initramfs.sh
+install -m 755 %{SOURCE38} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-estimate.sh
install -m 755 %{SOURCE31} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-logger.sh
%ifarch ppc64 ppc64le
install -m 755 %{SOURCE32} $RPM_BUILD_ROOT/usr/sbin/mkfadumprd
--
2.40.1