diff options
author | Peter Rajnoha <prajnoha@redhat.com> | 2013-01-23 14:45:41 +0100 |
---|---|---|
committer | Peter Rajnoha <prajnoha@redhat.com> | 2013-01-23 14:45:41 +0100 |
commit | f7da1caf8deaf50e0597ec377fb035ea3de1ac36 (patch) | |
tree | 388c37b6fbea0c72bc1ad4f1ef5503d4b5004605 /scripts | |
parent | 8bcc1da2f3f8e5f62af7b9e3a0967f7d1a60b582 (diff) | |
download | lvm2-f7da1caf8deaf50e0597ec377fb035ea3de1ac36.tar.gz |
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
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/blkdeactivate.sh.in | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/scripts/blkdeactivate.sh.in b/scripts/blkdeactivate.sh.in index 740bac5ef..849c61ddf 100644 --- a/scripts/blkdeactivate.sh.in +++ b/scripts/blkdeactivate.sh.in @@ -39,6 +39,7 @@ LVM="@sbindir@/lvm" LSBLK="/bin/lsblk -r --noheadings -o TYPE,KNAME,NAME,MOUNTPOINT" LSBLK_VARS="local devtype local kname local name local mnt" LSBLK_READ="read -r devtype kname name mnt" +SORT_MNT="/bin/sort -r -k 4" # Do not unmount mounted devices by default. DO_UMOUNT=0 @@ -122,9 +123,11 @@ is_top_level_device() { device_umount () { 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 echo " UMOUNT: unmounting $name ($kname) mounted on $mnt" - $UMOUNT "$mnt" || add_device_to_skip_list + $UMOUNT "$(printf $mnt)" || add_device_to_skip_list else echo " [SKIP]: unmount of $name ($kname) mounted on $mnt" add_device_to_skip_list @@ -142,9 +145,6 @@ deactivate_holders () { # check if the device not on the skip list already test -z ${SKIP_DEVICE_LIST["$kname"]} || return 1 - # try to unmount it if mounted - device_umount || return 1 - # try to deactivate the holder test $skip -eq 1 && skip=0 && continue deactivate || return 1 @@ -226,7 +226,16 @@ deactivate_all() { echo "Deactivating block devices:" 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 # 'disk' is at the bottom already and it's a real device test "$devtype" = "disk" && continue @@ -249,8 +258,17 @@ deactivate_all() { deactivate || skip=1 done <<< "`$LSBLK -s`" else - # Deactivate only specified devices + ################################## + # Process only specified devices # + ################################## + 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. if test -b "$1"; then $LSBLK_READ <<< "`$LSBLK --nodeps $1`" |