aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorPeter Rajnoha <prajnoha@redhat.com>2013-01-23 14:45:41 +0100
committerPeter Rajnoha <prajnoha@redhat.com>2013-01-23 14:45:41 +0100
commitf7da1caf8deaf50e0597ec377fb035ea3de1ac36 (patch)
tree388c37b6fbea0c72bc1ad4f1ef5503d4b5004605 /scripts
parent8bcc1da2f3f8e5f62af7b9e3a0967f7d1a60b582 (diff)
downloadlvm2-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.in30
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`"