When updating kernel arg in /etc/default/grub, grubby will replace the given arg with new value if the arg is the last one. If given arg isn't the last one, it would insert it in the end. So it's quite likely there are multiple values for the same kernel arg. e.g GRUB_CMDLINE_LINUX="crashkernel=110M crashkernel=220M fadump=on crashkernel=330M".
So all values should be removed when removing a kernel arg from /etc/default/grub.
Now _update_kernel_cmdline_in_grub_etc_default is split into {_add,_remove}_kernel_arg_in_grub_etc_default to address this case.
Note 1. to be consist with grubby, _add_kernel_arg_in_grub_etc_default will always make sure the new value appears in the end 2. sed command group and conditional control hasn't bee used to get rid of grep. 3. Fully supporting kernel cmdline as documented in Documentation/admin-guide/kernel-parameters.rst is complex and in foreseeable future a full implementation is not needed. So simply document the unsupported cases instead.
Reported-by: Philipp Rudo prudo@redhat.com Suggested-by: Philipp Rudo prudo@redhat.com Signed-off-by: Coiby Xu coxu@redhat.com --- kdumpctl | 85 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 15 deletions(-)
diff --git a/kdumpctl b/kdumpctl index 9fd76ac..d9edc4b 100755 --- a/kdumpctl +++ b/kdumpctl @@ -1399,25 +1399,77 @@ _get_all_kernels_from_grubby() }
GRUB_ETC_DEFAULT="/etc/default/grub" -# modify the kernel command line parameter in default grub conf +# Add a kernel arguement in default grub conf +# +# As is the same with grubby, this function would replace the given parameter +# with new value if given parameter appears in the end. Otherwise, it insert +# the entry in the end. +# +# Note as similar to grubby, this function doesn't address the following cases +# either, +# 1. The kernel ignores everything on the command line after a '--'. So +# simply adding the the new entry to the end will fail if the cmdline +# contains a --. +# 2. If the value for a parameter contains spaces it can be quoted using +# double quotes, for example param="value with spaces". This will +# break the [^[:space:]"] regex for the value. +# 3. Dashes and underscores in the parameter name are equivalent. So +# some_parameter and some-parameter are identical. +# 4. multiple variables have the same name but with different values +# e.g. efivar_ssdt +# +# Besides, this function doesn't support adding a kernel parameter +# that doesn't have a value # # $1: the name of the kernel command line parameter # $2: new value. If empty, the parameter would be removed -_update_kernel_cmdline_in_grub_etc_default() +_add_kernel_arg_in_grub_etc_default() { - local _para=$1 _val=$2 _para_val _regex + local _para=$1 _val=$2 _para_val
- if [[ -n $_val ]]; then - _para_val="$_para=$_val" + if [[ -z $_val ]]; then + derror "value not specified for $_para" + return 1 fi
- _regex='^(GRUB_CMDLINE_LINUX=.*)([[:space:]"])'"$_para"'=[^[:space:]"]*(.*)$' - if grep -q -E "$_regex" "$GRUB_ETC_DEFAULT"; then - sed -i -E 's/'"$_regex"'/\1\2'"$_para_val"'\3/' "$GRUB_ETC_DEFAULT" - elif [[ -n $_para_val ]]; then - # If the kernel parameter doesn't exist, put it in the first - sed -i -E 's/^(GRUB_CMDLINE_LINUX=")/\1'"$_para_val"' /' "$GRUB_ETC_DEFAULT" - fi + _para_val="$_para=$_val" + # Update the command line /etc/default/grub, i.e. + # on the line that starts with 'GRUB_CMDLINE_LINUX=', + # 1) if given parameter appear in the end, replace it with new entry + # 2) otherwise, insert the entry in the end + sed -i -E "/^GRUB_CMDLINE_LINUX=/ { + s/([[:space:]"])${_para}=[^[:space:]"]*[[:space:]]*"$/\1${_para_val}"/; + # t: jump to a label only if a s/// command has succeeded. + # Since there is no label, it would jump to the end i.e. + # skip the last command if the parameter already exists + t; + s/"$/ ${_para_val}"/ + }" "$GRUB_ETC_DEFAULT" +} + +# Remove a kernel argument from default grub conf +# +# Note removing a kernel parameter that doesn't have a value isn't supported +# e.g. quiet. +# +# $1: the name of the kernel parameter +_remove_kernel_arg_in_grub_etc_default() +{ + local _para=$1 + + # On the line that starts with 'GRUB_CMDLINE_LINUX=' do + # 1) remove $para=$val if the it's the first arg + # 2) remove all occurences of $para=$val + # 3) remove duplicate spaces left over by 1) or 2) + # 4) remove space at the beginning of the string left over by 1) or 2) + # 5) remove space at the end of the string left over by 1) or 2) + sed -i -E "/^GRUB_CMDLINE_LINUX=/ { + s/"${_para}=[^[:space:]"]*/"/g; + s/[[:space:]]+${_para}=[^[:space:]"]*/ /g; + s/[[:space:]]+/ /g; + s/(")[[:space:]]+/\1/g; + s/[[:space:]]+(")/\1/g; + }" "$GRUB_ETC_DEFAULT" }
reset_crashkernel() @@ -1496,10 +1548,13 @@ reset_crashkernel() # - set the dump mode as kdump for non-ppc64le cases # - retrieved the default crashkernel value for given dump mode if [[ $_grubby_kernel_path == ALL && -n $_dump_mode ]]; then - _update_kernel_cmdline_in_grub_etc_default crashkernel "$_crashkernel" + _add_kernel_arg_in_grub_etc_default crashkernel "$_crashkernel" # remove the fadump if fadump is disabled - [[ $_fadump_val == off ]] && _fadump_val="" - _update_kernel_cmdline_in_grub_etc_default fadump "$_fadump_val" + if [[ $_fadump_val == off ]]; then + _remove_kernel_arg_in_grub_etc_default fadump + else + _add_kernel_arg_in_grub_etc_default fadump "$_fadump_val" + fi fi
# If kernel-path not specified, either
If GRUB_ETC_DEFAULT use crashkernel=auto or crashkernel=OLD_DEFAULT_CRASHKERNEL, it should be updated as well.
Note a helper function to read kernel cmdline parameter from GRUB_ETC_DEFAULT. This function would be used to read kernel cmdline parameter like fadump or crashkernel.
Signed-off-by: Coiby Xu coxu@redhat.com --- kdumpctl | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/kdumpctl b/kdumpctl index d9edc4b..92451aa 100755 --- a/kdumpctl +++ b/kdumpctl @@ -1472,6 +1472,16 @@ _remove_kernel_arg_in_grub_etc_default() }" "$GRUB_ETC_DEFAULT" }
+# Read the kernel arg in default grub conf. + +# Note removing a kernel parameter that doesn't have a value isn't supported. +# +# $1: the name of the kernel command line parameter +_read_kernel_arg_in_grub_etc_default() +{ + sed -n -E "s/^GRUB_CMDLINE_LINUX=.*[[:space:]"]${1}=([^[:space:]"]*).*$/\1/p" "$GRUB_ETC_DEFAULT" +} + reset_crashkernel() { local _opt _val _dump_mode _fadump_val _reboot _grubby_kernel_path _kernel _kernels @@ -1606,6 +1616,34 @@ reset_crashkernel() fi }
+# update the crashkernel value in GRUB_ETC_DEFAULT if necessary +# +# called by reset_crashkernel_after_update and inherit its array variable +# _crashkernel_vals +update_crashkernel_in_grub_etc_default_after_update() +{ + local _crashkernel _fadump_val + local _dump_mode _old_default_crashkernel _new_default_crashkernel + + _crashkernel=$(_read_kernel_cmdline_in_grub_etc_default crashkernel) + + if [[ -z $_crashkernel ]]; then + return + fi + + _fadump_val=$(read_kernel_cmdline_in_grub_etc_default fadump) + _dump_mode=$(get_dump_mode_by_fadump_val "$_fadump_val") + + _old_default_crashkernel=${_crashkernel_vals[old_${_dump_mode}]} + _new_default_crashkernel=${_crashkernel_vals[new_${_dump_mode}]} + + if [[ $_crashkernel == auto ]] || + [[ $_crashkernel == "$_old_default_crashkernel" && + $_new_default_crashkernel != "$_old_default_crashkernel" ]]; then + _add_kernel_arg_in_grub_etc_default crashkernel "$_new_default_crashkernel" + fi +} + # shellcheck disable=SC2154 # false positive when dereferencing an array reset_crashkernel_after_update() { @@ -1634,6 +1672,8 @@ reset_crashkernel_after_update() fi fi done + + update_crashkernel_in_grub_etc_default_after_update }
# read the value of an environ variable from given environ file path
Hi Coiby,
the code looks good to me. A few typos though.
Reviewed-by: Philipp Rudo prudo@redhat.com
On Mon, 21 Feb 2022 15:21:15 +0800 Coiby Xu coxu@redhat.com wrote:
If GRUB_ETC_DEFAULT use crashkernel=auto or crashkernel=OLD_DEFAULT_CRASHKERNEL, it should be updated as well.
Note a helper function to read kernel cmdline parameter from
s/Note/Add/ ?
GRUB_ETC_DEFAULT. This function would be used to read kernel cmdline
s/would be/is/
parameter like fadump or crashkernel.
Signed-off-by: Coiby Xu coxu@redhat.com
kdumpctl | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/kdumpctl b/kdumpctl index d9edc4b..92451aa 100755 --- a/kdumpctl +++ b/kdumpctl @@ -1472,6 +1472,16 @@ _remove_kernel_arg_in_grub_etc_default() }" "$GRUB_ETC_DEFAULT" }
+# Read the kernel arg in default grub conf.
+# Note removing a kernel parameter that doesn't have a value isn't supported.
s/removing/reading/
Thanks Philipp
+# +# $1: the name of the kernel command line parameter +_read_kernel_arg_in_grub_etc_default() +{
- sed -n -E "s/^GRUB_CMDLINE_LINUX=.*[[:space:]"]${1}=([^[:space:]"]*).*$/\1/p" "$GRUB_ETC_DEFAULT"
+}
reset_crashkernel() { local _opt _val _dump_mode _fadump_val _reboot _grubby_kernel_path _kernel _kernels @@ -1606,6 +1616,34 @@ reset_crashkernel() fi }
+# update the crashkernel value in GRUB_ETC_DEFAULT if necessary +# +# called by reset_crashkernel_after_update and inherit its array variable +# _crashkernel_vals +update_crashkernel_in_grub_etc_default_after_update() +{
- local _crashkernel _fadump_val
- local _dump_mode _old_default_crashkernel _new_default_crashkernel
- _crashkernel=$(_read_kernel_cmdline_in_grub_etc_default crashkernel)
- if [[ -z $_crashkernel ]]; then
return
- fi
- _fadump_val=$(read_kernel_cmdline_in_grub_etc_default fadump)
- _dump_mode=$(get_dump_mode_by_fadump_val "$_fadump_val")
- _old_default_crashkernel=${_crashkernel_vals[old_${_dump_mode}]}
- _new_default_crashkernel=${_crashkernel_vals[new_${_dump_mode}]}
- if [[ $_crashkernel == auto ]] ||
[[ $_crashkernel == "$_old_default_crashkernel" &&
$_new_default_crashkernel != "$_old_default_crashkernel" ]]; then
_add_kernel_arg_in_grub_etc_default crashkernel "$_new_default_crashkernel"
- fi
+}
# shellcheck disable=SC2154 # false positive when dereferencing an array reset_crashkernel_after_update() { @@ -1634,6 +1672,8 @@ reset_crashkernel_after_update() fi fi done
- update_crashkernel_in_grub_etc_default_after_update
}
# read the value of an environ variable from given environ file path
Hi Philipp,
On Tue, Feb 22, 2022 at 10:15:30AM +0100, Philipp Rudo wrote:
Hi Coiby,
the code looks good to me. A few typos though.
Reviewed-by: Philipp Rudo prudo@redhat.com
On Mon, 21 Feb 2022 15:21:15 +0800 Coiby Xu coxu@redhat.com wrote:
If GRUB_ETC_DEFAULT use crashkernel=auto or crashkernel=OLD_DEFAULT_CRASHKERNEL, it should be updated as well.
Note a helper function to read kernel cmdline parameter from
s/Note/Add/ ?
GRUB_ETC_DEFAULT. This function would be used to read kernel cmdline
s/would be/is/
parameter like fadump or crashkernel.
Signed-off-by: Coiby Xu coxu@redhat.com
kdumpctl | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/kdumpctl b/kdumpctl index d9edc4b..92451aa 100755 --- a/kdumpctl +++ b/kdumpctl @@ -1472,6 +1472,16 @@ _remove_kernel_arg_in_grub_etc_default() }" "$GRUB_ETC_DEFAULT" }
+# Read the kernel arg in default grub conf.
+# Note removing a kernel parameter that doesn't have a value isn't supported.
s/removing/reading/
Thanks for reviewing the patch and catching these typos.
Thanks Philipp
+# +# $1: the name of the kernel command line parameter +_read_kernel_arg_in_grub_etc_default() +{
- sed -n -E "s/^GRUB_CMDLINE_LINUX=.*[[:space:]"]${1}=([^[:space:]"]*).*$/\1/p" "$GRUB_ETC_DEFAULT"
+}
reset_crashkernel() { local _opt _val _dump_mode _fadump_val _reboot _grubby_kernel_path _kernel _kernels @@ -1606,6 +1616,34 @@ reset_crashkernel() fi }
+# update the crashkernel value in GRUB_ETC_DEFAULT if necessary +# +# called by reset_crashkernel_after_update and inherit its array variable +# _crashkernel_vals +update_crashkernel_in_grub_etc_default_after_update() +{
- local _crashkernel _fadump_val
- local _dump_mode _old_default_crashkernel _new_default_crashkernel
- _crashkernel=$(_read_kernel_cmdline_in_grub_etc_default crashkernel)
- if [[ -z $_crashkernel ]]; then
return
- fi
- _fadump_val=$(read_kernel_cmdline_in_grub_etc_default fadump)
- _dump_mode=$(get_dump_mode_by_fadump_val "$_fadump_val")
- _old_default_crashkernel=${_crashkernel_vals[old_${_dump_mode}]}
- _new_default_crashkernel=${_crashkernel_vals[new_${_dump_mode}]}
- if [[ $_crashkernel == auto ]] ||
[[ $_crashkernel == "$_old_default_crashkernel" &&
$_new_default_crashkernel != "$_old_default_crashkernel" ]]; then
_add_kernel_arg_in_grub_etc_default crashkernel "$_new_default_crashkernel"
- fi
+}
# shellcheck disable=SC2154 # false positive when dereferencing an array reset_crashkernel_after_update() { @@ -1634,6 +1672,8 @@ reset_crashkernel_after_update() fi fi done
- update_crashkernel_in_grub_etc_default_after_update
}
# read the value of an environ variable from given environ file path
Hi Coiby,
it's a little bit frustrating to have those limitations but unfortunately it's the best that can be achieved with a reasonable effort...
There are a few typos. But other than that
Reviewed-by: Philipp Rudo prudo@redhat.com
On Mon, 21 Feb 2022 15:21:14 +0800 Coiby Xu coxu@redhat.com wrote:
When updating kernel arg in /etc/default/grub, grubby will replace the given arg with new value if the arg is the last one. If given arg isn't the last one, it would insert it in the end. So it's quite likely there are multiple values for the same kernel arg. e.g GRUB_CMDLINE_LINUX="crashkernel=110M crashkernel=220M fadump=on crashkernel=330M".
So all values should be removed when removing a kernel arg from /etc/default/grub.
Now _update_kernel_cmdline_in_grub_etc_default is split into {_add,_remove}_kernel_arg_in_grub_etc_default to address this case.
How about:
When updating the kernel command line in /etc/default/grub, grubby only replaces a given entry if it is the last entry on the command line. In all other cases it appends a new entry to it. This behavior makes it quite likely that there are multiple entries of the same parameter on the command line, e.g. GRUB_CMDLINE_LINUX="crashkernel=110M crashkernel=220M fadump=on crashkernel=330M".
In such an situation _update_kernel_cmdline_in_grub_etc_default only updates/removes the first entry. Which is usually not what you want as the kernel (for crashkernel) takes the last entry it can find.
Thus make sure the case with multiple entries of the same parameter is handled properly. To make implementation easier split _update_kernel_cmdline_in_grub_etc_default into {_add,_remove}_kernel_arg_in_grub_etc_default.
Note
- to be consist with grubby, _add_kernel_arg_in_grub_etc_default will always make sure the new value appears in the end
- sed command group and conditional control hasn't bee used to get rid of grep.
s/hasn't bee/has been/
- Fully supporting kernel cmdline as documented in Documentation/admin-guide/kernel-parameters.rst is complex and in foreseeable future a full implementation is not needed. So simply document the unsupported cases instead.
Reported-by: Philipp Rudo prudo@redhat.com Suggested-by: Philipp Rudo prudo@redhat.com Signed-off-by: Coiby Xu coxu@redhat.com
kdumpctl | 85 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 15 deletions(-)
diff --git a/kdumpctl b/kdumpctl index 9fd76ac..d9edc4b 100755 --- a/kdumpctl +++ b/kdumpctl @@ -1399,25 +1399,77 @@ _get_all_kernels_from_grubby() }
GRUB_ETC_DEFAULT="/etc/default/grub" -# modify the kernel command line parameter in default grub conf +# Add a kernel arguement in default grub conf +# +# As is the same with grubby, this function would replace the given parameter +# with new value if given parameter appears in the end. Otherwise, it insert +# the entry in the end. +# +# Note as similar to grubby, this function doesn't address the following cases +# either, +# 1. The kernel ignores everything on the command line after a '--'. So +# simply adding the the new entry to the end will fail if the cmdline
s/the the/the/
+# contains a --. +# 2. If the value for a parameter contains spaces it can be quoted using +# double quotes, for example param="value with spaces". This will +# break the [^[:space:]"] regex for the value. +# 3. Dashes and underscores in the parameter name are equivalent. So +# some_parameter and some-parameter are identical. +# 4. multiple variables have the same name but with different values +# e.g. efivar_ssdt
How about:
4. Some parameters, e.g. efivar_ssdt, can be given multiple times.
Thanks Philipp
+# Besides, this function doesn't support adding a kernel parameter +# that doesn't have a value # # $1: the name of the kernel command line parameter # $2: new value. If empty, the parameter would be removed -_update_kernel_cmdline_in_grub_etc_default() +_add_kernel_arg_in_grub_etc_default() {
- local _para=$1 _val=$2 _para_val _regex
- local _para=$1 _val=$2 _para_val
- if [[ -n $_val ]]; then
_para_val="$_para=$_val"
- if [[ -z $_val ]]; then
derror "value not specified for $_para"
fireturn 1
- _regex='^(GRUB_CMDLINE_LINUX=.*)([[:space:]"])'"$_para"'=[^[:space:]"]*(.*)$'
- if grep -q -E "$_regex" "$GRUB_ETC_DEFAULT"; then
sed -i -E 's/'"$_regex"'/\1\2'"$_para_val"'\3/' "$GRUB_ETC_DEFAULT"
- elif [[ -n $_para_val ]]; then
# If the kernel parameter doesn't exist, put it in the first
sed -i -E 's/^(GRUB_CMDLINE_LINUX=")/\1'"$_para_val"' /' "$GRUB_ETC_DEFAULT"
- fi
- _para_val="$_para=$_val"
- # Update the command line /etc/default/grub, i.e.
- # on the line that starts with 'GRUB_CMDLINE_LINUX=',
- # 1) if given parameter appear in the end, replace it with new entry
- # 2) otherwise, insert the entry in the end
- sed -i -E "/^GRUB_CMDLINE_LINUX=/ {
s/([[:space:]\"])${_para}=[^[:space:]\"]*[[:space:]]*\"$/\1${_para_val}\"/;
# t: jump to a label only if a s/// command has succeeded.
# Since there is no label, it would jump to the end i.e.
# skip the last command if the parameter already exists
t;
s/\"$/ ${_para_val}\"/
}" "$GRUB_ETC_DEFAULT"
+}
+# Remove a kernel argument from default grub conf +# +# Note removing a kernel parameter that doesn't have a value isn't supported +# e.g. quiet. +# +# $1: the name of the kernel parameter +_remove_kernel_arg_in_grub_etc_default() +{
- local _para=$1
- # On the line that starts with 'GRUB_CMDLINE_LINUX=' do
- # 1) remove $para=$val if the it's the first arg
- # 2) remove all occurences of $para=$val
- # 3) remove duplicate spaces left over by 1) or 2)
- # 4) remove space at the beginning of the string left over by 1) or 2)
- # 5) remove space at the end of the string left over by 1) or 2)
- sed -i -E "/^GRUB_CMDLINE_LINUX=/ {
s/\"${_para}=[^[:space:]\"]*/\"/g;
s/[[:space:]]+${_para}=[^[:space:]\"]*/ /g;
s/[[:space:]]+/ /g;
s/(\")[[:space:]]+/\1/g;
s/[[:space:]]+(\")/\1/g;
}" "$GRUB_ETC_DEFAULT"
}
reset_crashkernel() @@ -1496,10 +1548,13 @@ reset_crashkernel() # - set the dump mode as kdump for non-ppc64le cases # - retrieved the default crashkernel value for given dump mode if [[ $_grubby_kernel_path == ALL && -n $_dump_mode ]]; then
_update_kernel_cmdline_in_grub_etc_default crashkernel "$_crashkernel"
# remove the fadump if fadump is disabled_add_kernel_arg_in_grub_etc_default crashkernel "$_crashkernel"
[[ $_fadump_val == off ]] && _fadump_val=""
_update_kernel_cmdline_in_grub_etc_default fadump "$_fadump_val"
if [[ $_fadump_val == off ]]; then
_remove_kernel_arg_in_grub_etc_default fadump
else
_add_kernel_arg_in_grub_etc_default fadump "$_fadump_val"
fi
fi
# If kernel-path not specified, either
Hi Philipp,
On Tue, Feb 22, 2022 at 10:14:37AM +0100, Philipp Rudo wrote:
Hi Coiby,
it's a little bit frustrating to have those limitations but unfortunately it's the best that can be achieved with a reasonable effort...
Unfortunately, I just notice grubby would also delete given parameter if they are the first ones, e.g GRUB_CMDLINE_LINUX="crashkernel=110M crashkernel=220M fadump=on crashkernel=330M". would be changed to, GRUB_CMDLINE_LINUX="fadump=on crashkernel=NEW_VALUE".
And systems on beaker just put crashkernel=auto on the first, so it's likely we could receive complaint if we use v3. Since we have stated parameters like efivar_ssdt are not supported and it's quite likely we only need to deal with two kernel parameters i.e. crashkernel and fadump, I decide to use an early solution proposed by you except for a slight change to fix the issue of given parameter is suffix of another parameter in v4.
There are a few typos. But other than that
Reviewed-by: Philipp Rudo prudo@redhat.com
On Mon, 21 Feb 2022 15:21:14 +0800 Coiby Xu coxu@redhat.com wrote:
When updating kernel arg in /etc/default/grub, grubby will replace the given arg with new value if the arg is the last one. If given arg isn't the last one, it would insert it in the end. So it's quite likely there are multiple values for the same kernel arg. e.g GRUB_CMDLINE_LINUX="crashkernel=110M crashkernel=220M fadump=on crashkernel=330M".
So all values should be removed when removing a kernel arg from /etc/default/grub.
Now _update_kernel_cmdline_in_grub_etc_default is split into {_add,_remove}_kernel_arg_in_grub_etc_default to address this case.
How about:
When updating the kernel command line in /etc/default/grub, grubby only replaces a given entry if it is the last entry on the command line. In all other cases it appends a new entry to it. This behavior makes it quite likely that there are multiple entries of the same parameter on the command line, e.g. GRUB_CMDLINE_LINUX="crashkernel=110M crashkernel=220M fadump=on crashkernel=330M".
In such an situation _update_kernel_cmdline_in_grub_etc_default only updates/removes the first entry. Which is usually not what you
Only one nit, it's actually the last entry.
want as the kernel (for crashkernel) takes the last entry it can find.
Thus make sure the case with multiple entries of the same parameter is handled properly. To make implementation easier split _update_kernel_cmdline_in_grub_etc_default into {_add,_remove}_kernel_arg_in_grub_etc_default.
Thanks for improving the wording and catching the typos! All of them have been applied except for changes due to v4.
Note
- to be consist with grubby, _add_kernel_arg_in_grub_etc_default will always make sure the new value appears in the end
- sed command group and conditional control hasn't bee used to get rid of grep.
s/hasn't bee/has been/
- Fully supporting kernel cmdline as documented in Documentation/admin-guide/kernel-parameters.rst is complex and in foreseeable future a full implementation is not needed. So simply document the unsupported cases instead.
Reported-by: Philipp Rudo prudo@redhat.com Suggested-by: Philipp Rudo prudo@redhat.com Signed-off-by: Coiby Xu coxu@redhat.com
kdumpctl | 85 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 15 deletions(-)
diff --git a/kdumpctl b/kdumpctl index 9fd76ac..d9edc4b 100755 --- a/kdumpctl +++ b/kdumpctl @@ -1399,25 +1399,77 @@ _get_all_kernels_from_grubby() }
GRUB_ETC_DEFAULT="/etc/default/grub" -# modify the kernel command line parameter in default grub conf +# Add a kernel arguement in default grub conf +# +# As is the same with grubby, this function would replace the given parameter +# with new value if given parameter appears in the end. Otherwise, it insert +# the entry in the end. +# +# Note as similar to grubby, this function doesn't address the following cases +# either, +# 1. The kernel ignores everything on the command line after a '--'. So +# simply adding the the new entry to the end will fail if the cmdline
s/the the/the/
+# contains a --. +# 2. If the value for a parameter contains spaces it can be quoted using +# double quotes, for example param="value with spaces". This will +# break the [^[:space:]"] regex for the value. +# 3. Dashes and underscores in the parameter name are equivalent. So +# some_parameter and some-parameter are identical. +# 4. multiple variables have the same name but with different values +# e.g. efivar_ssdt
How about:
- Some parameters, e.g. efivar_ssdt, can be given multiple times.
Thanks Philipp
+# Besides, this function doesn't support adding a kernel parameter +# that doesn't have a value # # $1: the name of the kernel command line parameter # $2: new value. If empty, the parameter would be removed -_update_kernel_cmdline_in_grub_etc_default() +_add_kernel_arg_in_grub_etc_default() {
- local _para=$1 _val=$2 _para_val _regex
- local _para=$1 _val=$2 _para_val
- if [[ -n $_val ]]; then
_para_val="$_para=$_val"
- if [[ -z $_val ]]; then
derror "value not specified for $_para"
fireturn 1
- _regex='^(GRUB_CMDLINE_LINUX=.*)([[:space:]"])'"$_para"'=[^[:space:]"]*(.*)$'
- if grep -q -E "$_regex" "$GRUB_ETC_DEFAULT"; then
sed -i -E 's/'"$_regex"'/\1\2'"$_para_val"'\3/' "$GRUB_ETC_DEFAULT"
- elif [[ -n $_para_val ]]; then
# If the kernel parameter doesn't exist, put it in the first
sed -i -E 's/^(GRUB_CMDLINE_LINUX=")/\1'"$_para_val"' /' "$GRUB_ETC_DEFAULT"
- fi
- _para_val="$_para=$_val"
- # Update the command line /etc/default/grub, i.e.
- # on the line that starts with 'GRUB_CMDLINE_LINUX=',
- # 1) if given parameter appear in the end, replace it with new entry
- # 2) otherwise, insert the entry in the end
- sed -i -E "/^GRUB_CMDLINE_LINUX=/ {
s/([[:space:]\"])${_para}=[^[:space:]\"]*[[:space:]]*\"$/\1${_para_val}\"/;
# t: jump to a label only if a s/// command has succeeded.
# Since there is no label, it would jump to the end i.e.
# skip the last command if the parameter already exists
t;
s/\"$/ ${_para_val}\"/
}" "$GRUB_ETC_DEFAULT"
+}
+# Remove a kernel argument from default grub conf +# +# Note removing a kernel parameter that doesn't have a value isn't supported +# e.g. quiet. +# +# $1: the name of the kernel parameter +_remove_kernel_arg_in_grub_etc_default() +{
- local _para=$1
- # On the line that starts with 'GRUB_CMDLINE_LINUX=' do
- # 1) remove $para=$val if the it's the first arg
- # 2) remove all occurences of $para=$val
- # 3) remove duplicate spaces left over by 1) or 2)
- # 4) remove space at the beginning of the string left over by 1) or 2)
- # 5) remove space at the end of the string left over by 1) or 2)
- sed -i -E "/^GRUB_CMDLINE_LINUX=/ {
s/\"${_para}=[^[:space:]\"]*/\"/g;
s/[[:space:]]+${_para}=[^[:space:]\"]*/ /g;
s/[[:space:]]+/ /g;
s/(\")[[:space:]]+/\1/g;
s/[[:space:]]+(\")/\1/g;
}" "$GRUB_ETC_DEFAULT"
}
reset_crashkernel() @@ -1496,10 +1548,13 @@ reset_crashkernel() # - set the dump mode as kdump for non-ppc64le cases # - retrieved the default crashkernel value for given dump mode if [[ $_grubby_kernel_path == ALL && -n $_dump_mode ]]; then
_update_kernel_cmdline_in_grub_etc_default crashkernel "$_crashkernel"
# remove the fadump if fadump is disabled_add_kernel_arg_in_grub_etc_default crashkernel "$_crashkernel"
[[ $_fadump_val == off ]] && _fadump_val=""
_update_kernel_cmdline_in_grub_etc_default fadump "$_fadump_val"
if [[ $_fadump_val == off ]]; then
_remove_kernel_arg_in_grub_etc_default fadump
else
_add_kernel_arg_in_grub_etc_default fadump "$_fadump_val"
fi
fi
# If kernel-path not specified, either