1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

blkdeactivate: fix handling of nested mountpoints and mangled mount paths.

If there was a nested mountpoint inside an existing mount path,
blkdeactivate could fail to unmount such a mountpoint as it
needs to deactivate the deepest path first and continue upwards.

For example the simplest reproducer:

[root@rhel6-a ~]# lsblk
NAME                        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                           8:0    0    4G  0 disk
|-vg-lvol0 (dm-2)           253:2    0   32M  0 lvm  /mnt/a
`-vg-lvol1 (dm-3)           253:3    0   32M  0 lvm  /mnt/a/b

Before this patch:

[root@rhel6-a ~]# blkdeactivate -u
Deactivating block devices:
  UMOUNT: unmounting vg-lvol0 (dm-2) mounted on /mnt/a
umount: /mnt/a: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
  UMOUNT: unmounting vg-lvol1 (dm-3) mounted on /mnt/a/b
  LVM: deactivating Logical Volume vg/lvol1

(deactivation of vg/lvol0 is skipped as /mnt/a that is on lvol0
can't be unmounted - it still has /mnt/a/b as nested mountpoint!)

With this patch applied:

[root@rhel6-a ~]# blkdeactivate -u
Deactivating block devices:
  UMOUNT: unmounting vg-lvol1 (dm-3) mounted on /mnt/a/b
  UMOUNT: unmounting vg-lvol0 (dm-2) mounted on /mnt/a
  LVM: deactivating Logical Volume vg/lvol0
  LVM: deactivating Logical Volume vg/lvol1

===

Also, this patch contains a fix for processing mangled mount paths:

[root@rhel6-a ~]# lsblk
NAME                        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                           8:0    0    4G  0 disk
`-vg-lvol0 (dm-2)           253:2    0   32M  0 lvm  /mnt/x y z

[root@rhel6-a ~]# lsblk -r
vg-lvol0 253:2 0 32M 0 lvm /mnt/x\x20y\x20z

(the mount path is mangled with \xNN that is visible in raw
lsblk output only and which is used in blkdeactive as well)

Before this patch:

[root@rhel6-a ~]# blkdeactivate -u
Deactivating block devices:
  umount: /mnt/x\x20y\x20z: not found

After this patch applied:

[root@rhel6-a ~]# blkdeactivate -u
Deactivating block devices:
  UMOUNT: unmounting vg-lvol0 (dm-2) mounted on /mnt/x\x20y\x20z
  LVM: deactivating Logical Volume vg/lvol0
This commit is contained in:
Peter Rajnoha 2013-01-23 14:45:41 +01:00
parent 8bcc1da2f3
commit f7da1caf8d
2 changed files with 25 additions and 6 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.99 - Version 2.02.99 -
=================================== ===================================
Fix blkdeactivate to handle nested mountpoints and mangled mount paths.
Set locales with LC_ALL instead of lower priority LANG variable. Set locales with LC_ALL instead of lower priority LANG variable.
Fix a crash-inducing race condition in lvmetad. Fix a crash-inducing race condition in lvmetad.
Add log/debug_classes to lvm.conf to control debug log messages. Add log/debug_classes to lvm.conf to control debug log messages.

View File

@ -39,6 +39,7 @@ LVM="@sbindir@/lvm"
LSBLK="/bin/lsblk -r --noheadings -o TYPE,KNAME,NAME,MOUNTPOINT" LSBLK="/bin/lsblk -r --noheadings -o TYPE,KNAME,NAME,MOUNTPOINT"
LSBLK_VARS="local devtype local kname local name local mnt" LSBLK_VARS="local devtype local kname local name local mnt"
LSBLK_READ="read -r devtype kname name mnt" LSBLK_READ="read -r devtype kname name mnt"
SORT_MNT="/bin/sort -r -k 4"
# Do not unmount mounted devices by default. # Do not unmount mounted devices by default.
DO_UMOUNT=0 DO_UMOUNT=0
@ -122,9 +123,11 @@ is_top_level_device() {
device_umount () { device_umount () {
test -z "$mnt" && return 0; test -z "$mnt" && return 0;
test "$devtype" != "lvm" && test "${kname:0:3}" != "dm-" && return 0
if test -z "${SKIP_UMOUNT_LIST["$mnt"]}" -a "$DO_UMOUNT" -eq "1"; then if test -z "${SKIP_UMOUNT_LIST["$mnt"]}" -a "$DO_UMOUNT" -eq "1"; then
echo " UMOUNT: unmounting $name ($kname) mounted on $mnt" echo " UMOUNT: unmounting $name ($kname) mounted on $mnt"
$UMOUNT "$mnt" || add_device_to_skip_list $UMOUNT "$(printf $mnt)" || add_device_to_skip_list
else else
echo " [SKIP]: unmount of $name ($kname) mounted on $mnt" echo " [SKIP]: unmount of $name ($kname) mounted on $mnt"
add_device_to_skip_list add_device_to_skip_list
@ -142,9 +145,6 @@ deactivate_holders () {
# check if the device not on the skip list already # check if the device not on the skip list already
test -z ${SKIP_DEVICE_LIST["$kname"]} || return 1 test -z ${SKIP_DEVICE_LIST["$kname"]} || return 1
# try to unmount it if mounted
device_umount || return 1
# try to deactivate the holder # try to deactivate the holder
test $skip -eq 1 && skip=0 && continue test $skip -eq 1 && skip=0 && continue
deactivate || return 1 deactivate || return 1
@ -226,7 +226,16 @@ deactivate_all() {
echo "Deactivating block devices:" echo "Deactivating block devices:"
if test $# -eq 0; then if test $# -eq 0; then
# Deactivate all devices #######################
# Process all devices #
#######################
# Unmount all relevant mountpoints first
while $LSBLK_READ; do
device_umount
done <<< "`$LSBLK | $SORT_MNT`"
# Do deactivate
while $LSBLK_READ; do while $LSBLK_READ; do
# 'disk' is at the bottom already and it's a real device # 'disk' is at the bottom already and it's a real device
test "$devtype" = "disk" && continue test "$devtype" = "disk" && continue
@ -249,8 +258,17 @@ deactivate_all() {
deactivate || skip=1 deactivate || skip=1
done <<< "`$LSBLK -s`" done <<< "`$LSBLK -s`"
else else
# Deactivate only specified devices ##################################
# Process only specified devices #
##################################
while test $# -ne 0; do while test $# -ne 0; do
# Unmount all relevant mountpoints first
while $LSBLK_READ; do
device_umount
done <<< "`$LSBLK $1 | $SORT_MNT`"
# Do deactivate
# Single dm device tree deactivation. # Single dm device tree deactivation.
if test -b "$1"; then if test -b "$1"; then
$LSBLK_READ <<< "`$LSBLK --nodeps $1`" $LSBLK_READ <<< "`$LSBLK --nodeps $1`"