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 <kasong@redhat.com>
Acked-by: Pingfan Liu <piliu@redhat.com>
This commit is contained in:
Kairui Song 2020-11-25 17:06:12 +08:00
parent 08d9846eba
commit 9966b0a12e

View File

@ -211,8 +211,8 @@ get_kdump_targets()
# /mnt/bind -> /path/to/src, /mnt/bind/dump -> /path/to/src/dump # /mnt/bind -> /path/to/src, /mnt/bind/dump -> /path/to/src/dump
# #
# findmnt uses the option "-v, --nofsroot" to exclusive the [/dir] # findmnt uses the option "-v, --nofsroot" to exclusive the [/dir]
# in the SOURCE column for bind-mounts, then if $_mntpoint equals to # in the SOURCE column for bind-mounts, then if $_src equals to
# $_mntpoint_nofsroot, the mountpoint is not bind mounted directory. # $_src_nofsroot, the mountpoint is not bind mounted directory.
# #
# Below is just an example for mount info # Below is just an example for mount info
# /dev/mapper/atomicos-root[/ostree/deploy/rhel-atomic-host/var], if the # /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 "[]". # part is the bind mounted directory which quotes by bracket "[]".
get_bind_mount_source() get_bind_mount_source()
{ {
local _path=$1 local _mnt=$(df $1 | tail -1 | awk '{print $NF}')
# In case it's a sub path in a mount point, get the mount point first local _path=${1#$_mnt}
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}')
if [[ "$_mntpoint" = $_mntpoint_nofsroot ]]; then local _src=$(get_mount_info SOURCE target $_mnt -f)
echo $_path && return 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 fi
_mntpoint=${_mntpoint#*$_mntpoint_nofsroot} # direct mount
_mntpoint=${_mntpoint#[} local _src_nofsroot=$(get_mount_info SOURCE target $_mnt -v -f)
_mntpoint=${_mntpoint%]} if [[ $_src_nofsroot = $_src ]]; then
_path=${_path#$_mnt_top} 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 # Return the current underlaying device of a path, ignore bind mounts