On 02/11/15 at 12:39pm, Karel Zak wrote:
On Wed, Feb 11, 2015 at 03:17:48PM +0800, Dave Young wrote:
> Karel Zak is maintaining util-linux, he as a blog about bind mount:
>
http://karelzak.blogspot.sg/2011/04/bind-mounts-mtab-and-read-only.html
>
> Ccing him. Karel, can you help reviewing this patch to differenciate
> bind mount?
It seems I need new blog post to more explicitly explain that there is
no "bind mounts" at all, the "bind" is operation, not status.
> On 02/10/15 at 06:46pm, Minfei Huang wrote:
> > To solve this issue, we should determine the real mountpont, if the
> > directory is a bind mounted directory.
There is no real and bind mountpoint, both is the same thing. The
bind operation creates another independent connection to the filesystem.
> > +# findmnt uses the option "-v, --nofsroot" to exclusive the [/dir]
> > +# in the SOURCE column for bind-mounts, then if $_dev equals to
> > +# $_dev_no_bind, the mountpoint is not bind mounted directory.
The [/dir] means that you have mounted subdirectory rather than root
of the filesystem.
mount /dev/sdc1 /mnt/A
mkdir /mnt/A/subdir
mount --bind /mnt/A/subdir /mnt/B
mount --bind /mnt/A /mnt/C
TARGET SOURCE FSTYPE OPTIONS
/mnt/A /dev/sdc1 ext4 rw,relatime,seclabel,stripe=32,data=ordered
/mnt/B /dev/sdc1[/subdir] ext4 rw,relatime,seclabel,stripe=32,data=ordered
/mnt/C /dev/sdc1 ext4 rw,relatime,seclabel,stripe=32,data=ordered
... for /mnt/C there is no [/dir]
Note that btrfs uses the same if you mount btrfs subvolume.
> > +is_bind_mount()
> > +{
> > + local _dev=$(findmnt -k -n -r -o SOURCE $1)
> > + local _dev_no_bind=$(findmnt -k -n -r -v -o SOURCE $1)
> > +
> > + if [[ $_dev = $_dev_no_bind ]]; then
> > + return 1
> > + else
> > + return 0
> > + fi
> > +}
> > +
> > +# We are looking to see if a part of dump path is mounted on some disk.
> > +# But we don't want to look for bind mounted directories. So we should
> > +# determine the real mountpoint, if the directory is a bind mounted
> > +# directory.
> > get_mntpoint_from_path()
> > {
> > - echo $(df $1 | tail -1 | awk '{print $NF}')
> > + local _mnt=$(df $1 | tail -1 | awk '{print $NF}')
local _mnt=$(findmnt -n -o TARGET --target $1)
> > +
> > + if is_bind_mount $mnt; then
> > + # bind mounted directory, we should find the real mount point
> > + # where the device mounts.
> > + for m in `findmnt -k -n -r -o TARGET $_dev_no_bind`; do
> > + if ! is_bind_mount $m; then
> > + echo $m
> > + break
> > + fi
> > + done
The mountpoint created by bind operation is independent on previous
mounts,
mount /mnt/sda1 /A
mount --bind /A /B
umount /A
is pretty valid situation and /B still points to the filesystem.
> > + else
> > + echo $_mnt
> > + fi
> > }
I'm not sure if I good understand the original problem, but I'm sure
that care about bind mounts is mistake ;-) If the problem is that
dump is not in the filesystem root then you can try to check if the
root of the filesystem is mounted somewhere else, but maybe the best
would be avoid such fragile setup at all.
It is complicate for kdump, if we deal with the bind mounted. So in
order to simplify the process, how about add the bind mounted path to
the dump target, if the target is bind mounted?
Following is an example:
-bash-4.2# cat /etc/kdump.conf |grep ^path
path /var/crash
-bash-4.2# findmnt /var | tail -n 1 | awk '{print $2}'
/dev/mapper/atomicos-root[/ostree/deploy/rhel-atomic-host/var]
-bash-4.2# findmnt -v /var | tail -n 1 | awk '{print $2}'
/dev/mapper/atomicos-root
Then we can found it that the real path of dumping core is
/ostree/deploy/rhel-atomic-host/var/crash.
Here is the scratch path to fix this issue.
diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh
index 6a7da8c..5b45714 100755
--- a/dracut-module-setup.sh
+++ b/dracut-module-setup.sh
@@ -345,6 +345,16 @@ kdump_install_net() {
fi
}
+adjust_dump_target()
+{
+ local _fstype=$1 _target=$2 _path=$3
+ echo "$_fstype $_target" >> /tmp/$$-kdump.conf
+
+ #erase the old path line, then insert the parsed path
+ sed -i "/^path/d" /tmp/$$-kdump.conf
+ echo "path $_path" >> /tmp/$$-kdump.conf
+}
+
default_dump_target_install_conf()
{
local _target _fstype
@@ -359,23 +369,23 @@ default_dump_target_install_conf()
_mntpoint=$(get_mntpoint_from_path $_save_path)
_target=$(get_target_from_path $_save_path)
- if [ "$_mntpoint" != "/" ]; then
- _fstype=$(get_fs_type_from_target $_target)
+ _fstype=$(get_fs_type_from_target $_target)
+ if is_bind_mount $_mntpoint; then
+ _path=${_save_path##"$_mntpoint"}
+ _path=$(get_bind_mount_directory $_mntpoint)/$_path
+
+ adjust_dump_target $_fstype $_target $_path
+ elif [ "$_mntpoint" != "/" ]; then
if $(is_fs_type_nfs $_fstype); then
kdump_install_net "$_target"
_fstype="nfs"
else
_target=$(kdump_to_udev_name $_target)
fi
-
- echo "$_fstype $_target" >> /tmp/$$-kdump.conf
-
_path=${_save_path##"$_mntpoint"}
- #erase the old path line, then insert the parsed path
- sed -i "/^path/d" /tmp/$$-kdump.conf
- echo "path $_path" >> /tmp/$$-kdump.conf
-
_path=${_save_path##"$_mntpoint"}
- #erase the old path line, then insert the parsed path
- sed -i "/^path/d" /tmp/$$-kdump.conf
- echo "path $_path" >> /tmp/$$-kdump.conf
+ adjust_dump_target $_fstype $_target $_path
fi
}
diff --git a/kdump-lib.sh b/kdump-lib.sh
index cb1bab7..02b4253 100755
--- a/kdump-lib.sh
+++ b/kdump-lib.sh
@@ -86,6 +86,31 @@ get_root_fs_device()
return
}
+is_bind_mount()
+{
+ local _mntpoint=$(findmnt $1 | tail -n 1 | awk '{print $2}')
+ local _mntpoint_nofsroot=$(findmnt -v $1 | tail -n 1 | awk '{print $2}')
+
+ if [[ $_mntpoint = $_mntpoint_nofsroot ]]; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+get_bind_mount_directory()
+{
+ local _mntpoint=$(findmnt $1 | tail -n 1 | awk '{print $2}')
+ local _mntpoint_nofsroot=$(findmnt -v $1 | tail -n 1 | awk '{print $2}')
+
+ _mntpoint=${_mntpoint##$_mntpoint_nofsroot}
+
+ _mntpoint=${_mntpoint#[}
+ _mntpoint=${_mntpoint%]}
+
+ echo $_mntpoint
+}
+
get_mntpoint_from_path()
{
echo $(df $1 | tail -1 | awk '{print $NF}')
Thanks
Minfei
Karel
--
Karel Zak <kzak(a)redhat.com>
http://karelzak.blogspot.com