Check if block device as dump target is resettable

Some Smart Array (hpsa/cciss) adapters don't support reset, we need
to disable kdump on those devices, like rhel6 did.

In this patch, the dump target  is checked according to below
criteria if it's a block device.
If it's cciss disk but is resettbale, can be used as dump target.
If it's cciss disk but is not resettable, can not be used as dump
target.
If it's cciss disk and not resettable, but user set OVERRIDE_RESETTABLE
to 1 in /etc/sysconfig/kdump, can be taken as dump target. Because
user know the situation and want to have a try.

In this patch, added codes include 4 parts:
1)Add an option "override_resettable <0 | 1>" into kdump.conf, and
add related section into kdump.conf man page. In mkdumprd, will check
whether user has set a value, get that value if yes. By default, the
value is 0.

2)port utility functions from dracut-functions.sh.

3)The check_resettable function checks if dump target is a resettable
block device. This includes the case where default action dump_to_rootfs
is set.

Signed-off-by: Baoquan He <bhe@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
This commit is contained in:
Baoquan 2013-03-29 15:32:31 +08:00 committed by Baoquan He
parent bbe46f9e22
commit 4b850d2f3a
3 changed files with 206 additions and 0 deletions

View File

@ -113,6 +113,12 @@
# - By default, kdump initrd only will be rebuilt when
# necessary. Specify 1 to force rebuilding kdump
# initrd every time when kdump service starts.
#
#override_resettable <0 | 1>
# - Usually a unresettable block device can't be dump target.
# Specifying 1 means though block target is unresettable, user
# understand this situation and want to try dumping. By default,
# it's set to 0, means not to try a destined failure.
#raw /dev/vg/lv_kdump
#ext4 /dev/vg/lv_kdump

View File

@ -163,6 +163,14 @@ By default, kdump initrd only will be rebuilt when necessary.
Specify 1 to force rebuilding kdump initrd every time when kdump service starts.
.RE
.B override_resettable <0 | 1>
.RS
Usually a unresettable block device can't be dump target. Specifying 1 means
though block target is unresettable, user understand this situation and want
to try dumping. By default, it's set to 0, means not to try a destined failure.
.RE
.SH DEPRECATED OPTIONS
.B net <nfs mount>|<user@server>

192
mkdumprd
View File

@ -14,6 +14,7 @@ SAVE_PATH=$(grep ^path $conf_file| cut -d' ' -f2)
[ -z "$SAVE_PATH" ] && SAVE_PATH="/var/crash"
extra_modules=""
dracut_args=("--hostonly" "-o" "plymouth dash")
OVERRIDE_RESETTABLE=0
perror_exit() {
echo $@ >&2
@ -188,6 +189,11 @@ check_size() {
fi
}
is_nfs_dump_target()
{
grep -q "^nfs" $conf_file
}
is_ssh_dump_target()
{
grep -q "^ssh.*@" $conf_file
@ -219,6 +225,192 @@ add_mount() {
fi
}
# get_maj_min <device>
# Prints the major and minor of a device node.
# Example:
# $ get_maj_min /dev/sda2
# 8:2
get_maj_min() {
local _dev
_dev=$(stat -L -c '$((0x%t)):$((0x%T))' "$1" 2>/dev/null)
_dev=$(eval "echo $_dev")
echo $_dev
}
# ugly workaround for the lvm design
# There is no volume group device,
# so, there are no slave devices for volume groups.
# Logical volumes only have the slave devices they really live on,
# but you cannot create the logical volume without the volume group.
# And the volume group might be bigger than the devices the LV needs.
check_vol_slaves() {
local _lv _vg _pv
for i in /dev/mapper/*; do
_lv=$(get_maj_min $i)
if [[ $_lv = $2 ]]; then
_vg=$(lvm lvs --noheadings -o vg_name $i 2>/dev/null)
# strip space
_vg=$(echo $_vg)
if [[ $_vg ]]; then
for _pv in $(lvm vgs --noheadings -o pv_name "$_vg" 2>/dev/null)
do
check_block_and_slaves $1 $(get_maj_min $_pv) && return 0
done
fi
fi
done
return 1
}
# Walk all the slave relationships for a given block device.
# Stop when our helper function returns success
# $1 = function to call on every found block device
# $2 = block device in major:minor format
check_block_and_slaves() {
local _x
[[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry.
"$1" $2 && return
check_vol_slaves "$@" && return 0
if [[ -f /sys/dev/block/$2/../dev ]]; then
check_block_and_slaves $1 $(cat "/sys/dev/block/$2/../dev") && return 0
fi
[[ -d /sys/dev/block/$2/slaves ]] || return 1
for _x in /sys/dev/block/$2/slaves/*/dev; do
[[ -f $_x ]] || continue
check_block_and_slaves $1 $(cat "$_x") && return 0
done
return 1
}
to_dev_name() {
local dev="${1//\"/}"
case "$dev" in
UUID=*)
dev=`blkid -U "${dev#UUID=}"`
;;
LABEL=*)
dev=`blkid -L "${dev#LABEL=}"`
;;
esac
echo $dev
}
get_block_dump_target()
{
local _target
if is_ssh_dump_target || is_nfs_dump_target; then
return
fi
_target=$(egrep "^ext[234]|^xfs|^btrfs|^minix|^raw" /etc/kdump.conf 2>/dev/null |awk '{print $2}')
[ -n "$_target" ] && echo $(to_dev_name $_target) && return
#get rootfs device name
_target=$(findmnt -k -f -n -o SOURCE /)
[ -b "$_target" ] && echo $(to_dev_name $_target)
}
get_default_action_target()
{
local _target
local _action=$(grep "^default" /etc/kdump.conf 2>/dev/null | awk '{print $2}')
if [ -n "$_action" ] && [ "$_action" = "dump_to_rootfs" ]; then
#get rootfs device name
_target=$(findmnt -k -f -n -o SOURCE /)
[ -b "$_target" ] && echo $(to_dev_name $_target)
fi
return
}
get_override_resettable()
{
local override_resettable
override_resettable=$(grep "^override_resettable" $conf_file)
if [ -n "$override_resettable" ]; then
OVERRIDE_RESETTABLE=$(echo $override_resettable | cut -d' ' -f2)
if [ "$OVERRIDE_RESETTABLE" != "0" ] && [ "$OVERRIDE_RESETTABLE" != "1" ];then
perror_exit "override_resettable value $OVERRIDE_RESETTABLE is invalid"
fi
fi
}
# $1: function name
for_each_block_target()
{
local dev majmin
#check dump target
dev=$(get_block_dump_target)
if [ -n "$dev" ]; then
majmin=$(get_maj_min $dev)
check_block_and_slaves $1 $majmin && return 1
fi
#check rootfs when default action dump_to_rootfs is set
dev=$(get_default_action_target)
if [ -n "$dev" ]; then
majmin=$(get_maj_min $dev)
check_block_and_slaves $1 $majmin && return 2
fi
return 0
}
#judge if a specific device with $1 is unresettable
#return false if unresettable.
is_unresettable()
{
local path="/sys/$(udevadm info --query=all --path=/sys/dev/block/$1 | awk '/^P:/ {print $2}' | sed -e 's/\(cciss[0-9]\+\/\).*/\1/g' -e 's/\/block\/.*$//')/resettable"
local resettable=1
if [ -f "$path" ]
then
resettable="$(cat $path)"
[ $resettable -eq 0 -a "$OVERRIDE_RESETTABLE" -eq 0 ] && {
local device=$(udevadm info --query=all --path=/sys/dev/block/$1 | awk -F= '/DEVNAME/{print $2}')
echo "Device $device is unresettable"
return 0
}
fi
return 1
}
#check if machine is resettable.
#return true if resettable
check_resettable()
{
local _ret _target
get_override_resettable
for_each_block_target is_unresettable
_ret=$?
[ $_ret -eq 0 ] && return
if [ $_ret -eq 1 ]; then
_target=$(get_block_dump_target)
perror "Can not save vmcore to target device $_target . This device can not be initialized in kdump kernel as it is not resettable"
elif [ $_ret -eq 2 ]; then
_target=$(get_default_action_target)
perror "Rootfs device $_target is not resettable, can not be used as the default target, please specify a default action"
fi
return 1
}
if ! check_resettable; then
exit 1
fi
# firstly get right SSH_KEY_LOCATION
keyfile=$(awk '/^sshkey/ {print $2}' $conf_file)
if [ -f "$keyfile" ]; then