From 9966b0a12e775f7446a6810647201451af700655 Mon Sep 17 00:00:00 2001 From: Kairui Song Date: Wed, 25 Nov 2020 17:06:12 +0800 Subject: [PATCH] kdump-lib: Fix get_bind_mount_source to support btrfs and fstab Currently get_bind_mount_source will not work on btrfs, that's because this function relies on findmnt to detect bind mount. For a bind mount, findmnt will return different value with "-v" option. For example, we have /dev/sdc mounted on /mnt/source, and then bind mount /mnt/source/sub/path to /mnt/bind: $ findmnt /mnt/bind TARGET SOURCE FSTYPE OPTIONS /mnt/bind /dev/sdc[/sub/path] ext4 rw,relatime,seclabel $ findmnt -v /mnt/bind TARGET SOURCE FSTYPE OPTIONS /mnt/bind /dev/sdc ext4 rw,relatime,seclabel But findmnt also return similiar result for btrfs, on a fresh installed Fedora 33: $ findmnt / TARGET SOURCE FSTYPE OPTIONS / /dev/sdb7[/root] btrfs rw,relatime,seclabel,ssd,space_cache,subvolid=256,subvol=/root $ findmnt -v / TARGET SOURCE FSTYPE OPTIONS / /dev/sdb7 btrfs rw,relatime,seclabel,ssd,space_cache,subvolid=256,subvol=/root The [...] indicator will contain the subvol of btrfs as well. And if it's bind mounted under btrfs, it will contain a mixup of btrfs subvol and the actuall fsroot. And also, if the bind mount source device is not mounted on /, get_bind_mount_source will also not work. So rewrite the get_bind_mount_source function, make it work in every cases. Tested with: - Silverblue's bind mount - Bind mount with source device mounted not under / - Btrfs - Bind mount and source device is Btrfs Signed-off-by: Kairui Song Acked-by: Pingfan Liu --- kdump-lib.sh | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/kdump-lib.sh b/kdump-lib.sh index f04095a..0e38580 100755 --- a/kdump-lib.sh +++ b/kdump-lib.sh @@ -211,8 +211,8 @@ get_kdump_targets() # /mnt/bind -> /path/to/src, /mnt/bind/dump -> /path/to/src/dump # # findmnt uses the option "-v, --nofsroot" to exclusive the [/dir] -# in the SOURCE column for bind-mounts, then if $_mntpoint equals to -# $_mntpoint_nofsroot, the mountpoint is not bind mounted directory. +# in the SOURCE column for bind-mounts, then if $_src equals to +# $_src_nofsroot, the mountpoint is not bind mounted directory. # # Below is just an example for mount info # /dev/mapper/atomicos-root[/ostree/deploy/rhel-atomic-host/var], if the @@ -220,22 +220,36 @@ get_kdump_targets() # part is the bind mounted directory which quotes by bracket "[]". get_bind_mount_source() { - local _path=$1 - # In case it's a sub path in a mount point, get the mount point first - local _mnt_top=$(df $_path | tail -1 | awk '{print $NF}') - local _mntpoint=$(findmnt $_mnt_top | tail -n 1 | awk '{print $2}') - local _mntpoint_nofsroot=$(findmnt -v $_mnt_top | tail -n 1 | awk '{print $2}') + local _mnt=$(df $1 | tail -1 | awk '{print $NF}') + local _path=${1#$_mnt} - if [[ "$_mntpoint" = $_mntpoint_nofsroot ]]; then - echo $_path && return + local _src=$(get_mount_info SOURCE target $_mnt -f) + local _opt=$(get_mount_info OPTIONS target $_mnt -f) + local _fstype=$(get_mount_info FSTYPE target $_mnt -f) + + # bind mount in fstab + if [[ -d "$_src" ]] && [[ "$_fstype" = none ]] && (echo "$_opt" | grep -q "\bbind\b"); then + echo $_src$_path && return fi - _mntpoint=${_mntpoint#*$_mntpoint_nofsroot} - _mntpoint=${_mntpoint#[} - _mntpoint=${_mntpoint%]} - _path=${_path#$_mnt_top} + # direct mount + local _src_nofsroot=$(get_mount_info SOURCE target $_mnt -v -f) + if [[ $_src_nofsroot = $_src ]]; then + echo $_mnt$_path && return + fi - echo $_mntpoint$_path + local _fsroot=${_src#$_src_nofsroot[} + _fsroot=${_fsroot%]} + _mnt=$(get_mount_info TARGET source $_src_nofsroot -f) + + # for btrfs, _fsroot will also contain the subvol value as well, strip it + if [[ "$_fstype" = btrfs ]]; then + local _subvol + _subvol=${_opt#*subvol=} + _subvol=${_subvol%,*} + _fsroot=${_fsroot#$_subvol} + fi + echo $_mnt$_fsroot$_path } # Return the current underlaying device of a path, ignore bind mounts