kdump-lib: fix prepare_cmdline
A recently added unit test found that prepare_cmdline has several problems. For example an empty remove list will remove all spaces or when the cmdline contains a parameter with quoted values containing spaces will only remove the beginning up to the first space. Furthermore the old design requires lots of subshells and pipes. This patch rewrites prepare_cmdline in a way that makes the unit test happy and tries to use as many bash built-ins as possible. Signed-off-by: Philipp Rudo <prudo@redhat.com> Reviewed-by: Coiby Xu <coxu@redhat.com>
This commit is contained in:
parent
d55a056558
commit
0f6ad91be8
126
kdump-lib.sh
126
kdump-lib.sh
@ -526,24 +526,6 @@ is_kernel_loaded()
|
|||||||
[[ $(< $_sysfs) -eq 1 ]]
|
[[ $(< $_sysfs) -eq 1 ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>]
|
|
||||||
# Remove a list of kernel parameters from a given kernel cmdline and print the result.
|
|
||||||
# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists.
|
|
||||||
remove_cmdline_param()
|
|
||||||
{
|
|
||||||
local cmdline=$1
|
|
||||||
shift
|
|
||||||
|
|
||||||
for arg in "$@"; do
|
|
||||||
cmdline=$(echo "$cmdline" |
|
|
||||||
sed -e "s/\b$arg=[^ ]*//g" \
|
|
||||||
-e "s/^$arg\b//g" \
|
|
||||||
-e "s/[[:space:]]$arg\b//g" \
|
|
||||||
-e "s/\s\+/ /g")
|
|
||||||
done
|
|
||||||
echo "$cmdline"
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# This function returns the "apicid" of the boot
|
# This function returns the "apicid" of the boot
|
||||||
# cpu (cpu 0) if present.
|
# cpu (cpu 0) if present.
|
||||||
@ -558,23 +540,6 @@ get_bootcpu_apicid()
|
|||||||
/proc/cpuinfo
|
/proc/cpuinfo
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# append_cmdline <kernel cmdline> <parameter name> <parameter value>
|
|
||||||
# This function appends argument "$2=$3" to string ($1) if not already present.
|
|
||||||
#
|
|
||||||
append_cmdline()
|
|
||||||
{
|
|
||||||
local cmdline=$1
|
|
||||||
local newstr=${cmdline/$2/""}
|
|
||||||
|
|
||||||
# unchanged str implies argument wasn't there
|
|
||||||
if [[ $cmdline == "$newstr" ]]; then
|
|
||||||
cmdline="${cmdline} ${2}=${3}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$cmdline"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function check iomem and determines if we have more than
|
# This function check iomem and determines if we have more than
|
||||||
# 4GB of ram available. Returns 1 if we do, 0 if we dont
|
# 4GB of ram available. Returns 1 if we do, 0 if we dont
|
||||||
need_64bit_headers()
|
need_64bit_headers()
|
||||||
@ -792,26 +757,46 @@ get_watchdog_drvs()
|
|||||||
echo "$_wdtdrvs"
|
echo "$_wdtdrvs"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cmdline_parse()
|
||||||
|
{
|
||||||
|
local opt val
|
||||||
|
|
||||||
|
while read -r opt; do
|
||||||
|
if [[ $opt =~ = ]]; then
|
||||||
|
val=${opt#*=}
|
||||||
|
opt=${opt%%=*}
|
||||||
|
# ignore options like 'foo='
|
||||||
|
[[ -z $val ]] && continue
|
||||||
|
# xargs removes quotes, add them again
|
||||||
|
[[ $val =~ [[:space:]] ]] && val="\"$val\""
|
||||||
|
else
|
||||||
|
val=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$opt $val"
|
||||||
|
done <<< "$(echo "$1" | xargs -n 1 echo)"
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# prepare_cmdline <commandline> <commandline remove> <commandline append>
|
# prepare_cmdline <commandline> <commandline remove> <commandline append>
|
||||||
# This function performs a series of edits on the command line.
|
# This function performs a series of edits on the command line.
|
||||||
# Store the final result in global $KDUMP_COMMANDLINE.
|
# Store the final result in global $KDUMP_COMMANDLINE.
|
||||||
prepare_cmdline()
|
prepare_cmdline()
|
||||||
{
|
{
|
||||||
local cmdline id arg
|
local in out append opt val id drv
|
||||||
|
local -A remove
|
||||||
|
|
||||||
|
in=${1:-$(< /proc/cmdline)}
|
||||||
|
while read -r opt val; do
|
||||||
|
[[ -n "$opt" ]] || continue
|
||||||
|
remove[$opt]=1
|
||||||
|
done <<< "$(_cmdline_parse "$2")"
|
||||||
|
append=$3
|
||||||
|
|
||||||
if [[ -z $1 ]]; then
|
|
||||||
cmdline=$(< /proc/cmdline)
|
|
||||||
else
|
|
||||||
cmdline="$1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# These params should always be removed
|
# These params should always be removed
|
||||||
cmdline=$(remove_cmdline_param "$cmdline" crashkernel panic_on_warn)
|
remove[crashkernel]=1
|
||||||
# These params can be removed configurably
|
remove[panic_on_warn]=1
|
||||||
while read -r arg; do
|
|
||||||
cmdline=$(remove_cmdline_param "$cmdline" "$arg")
|
|
||||||
done <<< "$(echo "$2" | xargs -n 1 echo)"
|
|
||||||
|
|
||||||
# Always remove "root=X", as we now explicitly generate all kinds
|
# Always remove "root=X", as we now explicitly generate all kinds
|
||||||
# of dump target mount information including root fs.
|
# of dump target mount information including root fs.
|
||||||
@ -819,43 +804,62 @@ prepare_cmdline()
|
|||||||
# We do this before KDUMP_COMMANDLINE_APPEND, if one really cares
|
# We do this before KDUMP_COMMANDLINE_APPEND, if one really cares
|
||||||
# about it(e.g. for debug purpose), then can pass "root=X" using
|
# about it(e.g. for debug purpose), then can pass "root=X" using
|
||||||
# KDUMP_COMMANDLINE_APPEND.
|
# KDUMP_COMMANDLINE_APPEND.
|
||||||
cmdline=$(remove_cmdline_param "$cmdline" root)
|
remove[root]=1
|
||||||
|
|
||||||
# With the help of "--hostonly-cmdline", we can avoid some interitage.
|
# With the help of "--hostonly-cmdline", we can avoid some interitage.
|
||||||
cmdline=$(remove_cmdline_param "$cmdline" rd.lvm.lv rd.luks.uuid rd.dm.uuid rd.md.uuid fcoe)
|
remove[rd.lvm.lv]=1
|
||||||
|
remove[rd.luks.uuid]=1
|
||||||
|
remove[rd.dm.uuid]=1
|
||||||
|
remove[rd.md.uuid]=1
|
||||||
|
remove[fcoe]=1
|
||||||
|
|
||||||
# Remove netroot, rd.iscsi.initiator and iscsi_initiator since
|
# Remove netroot, rd.iscsi.initiator and iscsi_initiator since
|
||||||
# we get duplicate entries for the same in case iscsi code adds
|
# we get duplicate entries for the same in case iscsi code adds
|
||||||
# it as well.
|
# it as well.
|
||||||
cmdline=$(remove_cmdline_param "$cmdline" netroot rd.iscsi.initiator iscsi_initiator)
|
remove[netroot]=1
|
||||||
|
remove[rd.iscsi.initiator]=1
|
||||||
|
remove[iscsi_initiator]=1
|
||||||
|
|
||||||
cmdline="${cmdline} $3"
|
while read -r opt val; do
|
||||||
|
[[ -n "$opt" ]] || continue
|
||||||
|
[[ -n "${remove[$opt]}" ]] && continue
|
||||||
|
|
||||||
|
if [[ -n "$val" ]]; then
|
||||||
|
out+="$opt=$val "
|
||||||
|
else
|
||||||
|
out+="$opt "
|
||||||
|
fi
|
||||||
|
done <<< "$(_cmdline_parse "$in")"
|
||||||
|
|
||||||
|
out+="$append "
|
||||||
|
|
||||||
id=$(get_bootcpu_apicid)
|
id=$(get_bootcpu_apicid)
|
||||||
if [[ -n ${id} ]]; then
|
if [[ -n "${id}" ]]; then
|
||||||
cmdline=$(append_cmdline "$cmdline" disable_cpu_apicid "$id")
|
out+="disable_cpu_apicid=$id "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If any watchdog is used, set it's pretimeout to 0. pretimeout let
|
# If any watchdog is used, set it's pretimeout to 0. pretimeout let
|
||||||
# watchdog panic the kernel first, and reset the system after the
|
# watchdog panic the kernel first, and reset the system after the
|
||||||
# panic. If the system is already in kdump, panic is not helpful
|
# panic. If the system is already in kdump, panic is not helpful
|
||||||
# and only increase the chance of watchdog failure.
|
# and only increase the chance of watchdog failure.
|
||||||
for i in $(get_watchdog_drvs); do
|
for drv in $(get_watchdog_drvs); do
|
||||||
cmdline+=" $i.pretimeout=0"
|
out+="$drv.pretimeout=0 "
|
||||||
|
|
||||||
if [[ $i == hpwdt ]]; then
|
if [[ $drv == hpwdt ]]; then
|
||||||
# hpwdt have a special parameter kdumptimeout, is's only suppose
|
# hpwdt have a special parameter kdumptimeout, it is
|
||||||
# to be set to non-zero in first kernel. In kdump, non-zero
|
# only supposed to be set to non-zero in first kernel.
|
||||||
# value could prevent the watchdog from resetting the system.
|
# In kdump, non-zero value could prevent the watchdog
|
||||||
cmdline+=" $i.kdumptimeout=0"
|
# from resetting the system.
|
||||||
|
out+="$drv.kdumptimeout=0 "
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# This is a workaround on AWS platform. Always remove irqpoll since it
|
# This is a workaround on AWS platform. Always remove irqpoll since it
|
||||||
# may cause the hot-remove of some pci hotplug device.
|
# may cause the hot-remove of some pci hotplug device.
|
||||||
is_aws_aarch64 && cmdline=$(remove_cmdline_param "${cmdline}" irqpoll)
|
is_aws_aarch64 && out=$(echo "$out" | sed -e "/\<irqpoll\>//")
|
||||||
|
|
||||||
echo "$cmdline"
|
# Trim unnecessary whitespaces
|
||||||
|
echo "$out" | sed -e "s/^ *//g" -e "s/ *$//g" -e "s/ \+/ /g"
|
||||||
}
|
}
|
||||||
|
|
||||||
PROC_IOMEM=/proc/iomem
|
PROC_IOMEM=/proc/iomem
|
||||||
|
Loading…
Reference in New Issue
Block a user