Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions dracut/99kdumpbase/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -683,16 +683,21 @@ kdump_install_pre_post_conf() {
}

default_dump_target_install_conf() {
local _target _fstype
local _target _fstype _subvol _options
local _mntpoint _save_path

is_user_configured_dump_target && return

_save_path=$(get_bind_mount_source "$(get_save_path)")
_target=$(get_target_from_path "$_save_path")
_mntpoint=$(get_mntpoint_from_target "$_target")

_options=$(get_mount_info OPTIONS target "$_save_path" -f)
_fstype=$(get_fs_type_from_target "$_target")
if [[ $_fstype == btrfs ]]; then
_subvol=$(get_btrfs_subvol_from_mntopt "$_options")
fi

_mntpoint=$(get_mntpoint_from_target "$_target" "$_subvol")

if is_fs_type_nfs "$_fstype"; then
kdump_collect_netif_usage "$_target"
_fstype="nfs"
Expand Down
22 changes: 18 additions & 4 deletions kdump-lib-initramfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,29 @@ get_fs_type_from_target()

get_mntpoint_from_target()
{
# get the first TARGET when SOURCE doesn't end with ].
# In most cases, a SOURCE ends with ] when fsroot or subvol exists.
_mntpoint=$(get_mount_info TARGET,SOURCE source "$1" | grep -v "\]$" | awk 'NR==1 { print $1 }')

_subvol="$2"
if [ -z "$_subvol" ]; then
# get the first TARGET when SOURCE doesn't end with ].
# In most cases, a SOURCE ends with ] when fsroot or subvol exists.
_mntpoint=$(get_mount_info TARGET,SOURCE source "$1" | grep -v "\]$" | awk 'NR==1 { print $1 }')
else
# btrfs with subvol
_mntpoint=$(get_mount_info TARGET,SOURCE source "$1" | grep "\[$_subvol\]$" | awk 'NR==1 { print $1 }')
fi
# fallback to the old way when _mntpoint is empty.
[ -n "$_mntpoint" ] || _mntpoint=$(get_mount_info TARGET source "$1" -f)
echo "$_mntpoint"
}

get_btrfs_subvol_from_mntopt()
{
_subvol=${1#*subvol=}
# mount option may not contain subvol
[ "$1" != "$_subvol" ] || return 0
_subvol=${_subvol%%,*}
echo "$_subvol"
}

is_ssh_dump_target()
{
kdump_get_conf_val ssh | grep -q @
Expand Down
13 changes: 6 additions & 7 deletions kdump-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ get_kdump_targets()
# part is the bind mounted directory which quotes by bracket "[]".
get_bind_mount_source()
{
local _mnt _path _src _opt _fstype
local _mnt _path _src _opt _fstype _subvol
local _fsroot _src_nofsroot

_mnt=$(df "$1" | tail -1 | awk '{print $NF}')
Expand All @@ -200,15 +200,13 @@ get_bind_mount_source()

_fsroot=${_src#"${_src_nofsroot}"[}
_fsroot=${_fsroot%]}
_mnt=$(get_mntpoint_from_target "$_src_nofsroot")

# for btrfs, _fsroot will also contain the subvol value as well, strip it
if [[ $_fstype == btrfs ]]; then
local _subvol
_subvol=${_opt#*subvol=}
_subvol=${_subvol%,*}
_subvol=$(get_btrfs_subvol_from_mntopt "$_opt")
_fsroot=${_fsroot#"$_subvol"}
fi
_mnt=$(get_mntpoint_from_target "$_src_nofsroot" "$_subvol")

echo "$_mnt$_fsroot$_path"
}

Expand All @@ -219,11 +217,12 @@ get_mntopt_from_target()

# Get the path where the target will be mounted in kdump kernel
# $1: kdump target device
# $2: btrfs subvol
get_kdump_mntpoint_from_target()
{
local _mntpoint

_mntpoint=$(get_mntpoint_from_target "$1")
_mntpoint=$(get_mntpoint_from_target "$1" "$2")
# mount under /sysroot if dump to root disk or mount under
# mount under /kdumproot if dump target is not mounted in first kernel
# mount under /kdumproot/$_mntpoint in other cases in 2nd kernel.
Expand Down
24 changes: 16 additions & 8 deletions mkdumprd
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,13 @@ to_mount()
{
local _target=$1 _fstype=$2 _options=$3 _sed_cmd _new_mntpoint _pdev

_new_mntpoint=$(get_kdump_mntpoint_from_target "$_target")
_fstype="${_fstype:-$(get_fs_type_from_target "$_target")}"
_options="${_options:-$(get_mntopt_from_target "$_target")}"
_options="${_options:-defaults}"
if [[ $_fstype == btrfs ]]; then
_subvol=$(get_btrfs_subvol_from_mntopt "$_options")
fi
_new_mntpoint=$(get_kdump_mntpoint_from_target "$_target" "$_subvol")

if [[ $_fstype == "nfs"* ]]; then
_pdev=$_target
Expand Down Expand Up @@ -146,7 +149,7 @@ mkdir_save_path_ssh()
#$1=dump target
get_fs_size()
{
df --output=avail "$(get_mntpoint_from_target "$1")/$SAVE_PATH" | tail -1
df --output=avail "$(get_mntpoint_from_target "$1" "$2")/$SAVE_PATH" | tail -1
}

#Function: get_raw_size
Expand All @@ -159,6 +162,7 @@ get_raw_size()
#Function: check_size
#$1: dump type string ('raw', 'fs', 'ssh')
#$2: dump target
#$3: btrfs subvol
check_size()
{
local avail memtotal
Expand All @@ -172,7 +176,7 @@ check_size()
avail=$(get_ssh_size "$2")
;;
fs)
avail=$(get_fs_size "$2")
avail=$(get_fs_size "$2" "$3")
;;
*)
return
Expand Down Expand Up @@ -302,20 +306,24 @@ add_mount()
#handle the case user does not specify the dump target explicitly
handle_default_dump_target()
{
local _target
local _mntpoint
local _target _mntpoint _fstype _subvol _options

is_user_configured_dump_target && return

check_save_path_fs "$SAVE_PATH"

_save_path=$(get_bind_mount_source "$SAVE_PATH")
_options=$(get_mount_info OPTIONS target "$_save_path" -f)
_target=$(get_target_from_path "$_save_path")
_mntpoint=$(get_mntpoint_from_target "$_target")
_fstype=$(get_fs_type_from_target "$_target")
if [[ $_fstype == btrfs ]]; then
_subvol=$(get_btrfs_subvol_from_mntopt "$_options")
fi

_mntpoint=$(get_mntpoint_from_target "$_target" "$_subvol")
SAVE_PATH=${_save_path##"$_mntpoint"}
add_mount "$_target"
check_size fs "$_target"
add_mount "$_target" "$_fstype" "$_options"
check_size fs "$_target" "$_subvol"
}

# firstly get right SSH_KEY_LOCATION
Expand Down
50 changes: 44 additions & 6 deletions spec/kdump-lib-initramfs_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ Describe 'kdump-lib-initramfs'
else
printf '/var %s[/ostree/deploy/default/var]\n/sysroot %s\n' "$7" "$7"
fi
elif [[ "$7" == '/dev/nvme0n1p3' ]]; then
if [[ "$8" == "-f" ]]; then
printf '/ /dev/nvme0n1p3[/root]\n'
else
printf '/ /dev/nvme0n1p3[/root]\n/var /dev/nvme0n1p3[/var]\n'
fi
fi
}

Expand All @@ -76,19 +82,51 @@ Describe 'kdump-lib-initramfs'
# - IPv6 NFS target also contain '[' in the export
# - local dumping target that has '[' in the name
# - has bind mint
# - has subvol
Parameters
'eng.redhat.com:/srv/[nfs]' '/mnt'
'[2620:52:0:a1:217:38ff:fe01:131]:/srv/[nfs]' '/mnt'
'/dev/mapper/rhel[disk]' '/'
'/dev/vda4' '/sysroot'
'eng.redhat.com:/srv/[nfs]' '' '/mnt'
'[2620:52:0:a1:217:38ff:fe01:131]:/srv/[nfs]' '' '/mnt'
'/dev/mapper/rhel[disk]' '' '/'
'/dev/vda4' '' '/sysroot'
'/dev/nvme0n1p3' '/var' '/var'
End

It 'should handle all cases correctly'
When call get_mntpoint_from_target "$1"
The output should equal "$2"
When call get_mntpoint_from_target "$1" "$2"
The output should equal "$3"
End
End

End

Describe 'Test get_btrfs_subvol_from_mntopt'
Context 'Given different mount option formats'
# Test the following cases:
# - Standard subvol option at the beginning
# - Standard subvol option in the middle
# - Standard subvol option at the end
# - Subvol with @ prefix (common btrfs pattern)
# - Subvol with complex path
# - No subvol option present
# - Empty mount options
# - Subvol option with no value
# - Similar but different option names
Parameters
"subvol=/home,rw,relatime" "/home"
"rw,subvol=/root,defaults" "/root"
"rw,relatime,subvol=/root" "/root"
"subvol=@home" "@home"
"subvol=/path/to/subvolume,rw" "/path/to/subvolume"
"rw,relatime,defaults" ""
true ''
"subvol=,rw" ""
"rw,subvolume=@home" ""
End

It 'should extract subvolume correctly'
When call get_btrfs_subvol_from_mntopt "$1"
The output should equal "$2"
End
End
End
End
48 changes: 48 additions & 0 deletions spec/kdump-lib_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,52 @@ Describe 'kdump-lib'
End
End

Describe "get_kdump_mntpoint_from_target with btrfs subvolume support"
# Mock get_mntpoint_from_target to simulate different mount scenarios
get_mntpoint_from_target() {
local device="$1" subvol="$2"
case "$device" in
'/dev/sda1')
if [[ "$subvol" == "@home" ]]; then
echo "/mnt/btrfs"
elif [[ "$subvol" == "/root" ]]; then
echo "/"
else
echo "/"
fi
;;
'/dev/sdb1')
if [[ "$subvol" == "@backup" ]]; then
echo "/backup"
else
echo "/backup"
fi
;;
*)
echo "/"
;;
esac
}

Context 'Given various mount point scenarios with subvolumes'
# Test the following cases:
# - Root filesystem with @ subvolume -> /sysroot
# - Home subvolume on non-root -> /kdumproot/mnt/btrfs
# - Backup subvolume -> /kdumproot/backup
# - Regular filesystem without subvolume -> /sysroot
Parameters
'/dev/sda1 /root /sysroot'
'/dev/sda1 @home /kdumproot/mnt/btrfs'
'/dev/sdb1 @backup /kdumproot/backup'
'/dev/vda2 "" /sysroot'
End

It 'should handle btrfs subvolumes correctly'
# Parse parameters: device subvol expected_result
read -r device subvol expected_result <<< "$1"
When call get_kdump_mntpoint_from_target "$device" "$subvol"
The output should equal "$expected_result"
End
End
End
End
Loading