[kexec-tools/f19] Check if block device as dump target is resettable

Baoquan He baoquan at fedoraproject.org
Tue Apr 2 02:54:21 UTC 2013


commit ce1a217bc673f9d79f51b22dadfcf70d6da50666
Author: Baoquan <bhe at redhat.com>
Date:   Fri Mar 29 15:32:31 2013 +0800

    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 at redhat.com>
    Acked-by: Vivek Goyal <vgoyal at redhat.com>

 kdump.conf   |    6 ++
 kdump.conf.5 |    8 +++
 mkdumprd     |  192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+), 0 deletions(-)
---
diff --git a/kdump.conf b/kdump.conf
index afa2af8..de3ad4a 100644
--- a/kdump.conf
+++ b/kdump.conf
@@ -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
diff --git a/kdump.conf.5 b/kdump.conf.5
index 31761f8..9e498c5 100644
--- a/kdump.conf.5
+++ b/kdump.conf.5
@@ -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 at server>
diff --git a/mkdumprd b/mkdumprd
index b925c09..c85fe2a 100644
--- a/mkdumprd
+++ b/mkdumprd
@@ -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


More information about the scm-commits mailing list