diff options
-rw-r--r-- | man/blkdeactivate.8_main | 12 | ||||
-rw-r--r-- | scripts/blkdeactivate.sh.in | 70 |
2 files changed, 73 insertions, 9 deletions
diff --git a/man/blkdeactivate.8_main b/man/blkdeactivate.8_main index 06af52e52..eec663eca 100644 --- a/man/blkdeactivate.8_main +++ b/man/blkdeactivate.8_main @@ -52,6 +52,12 @@ Retry removal several times in case of failure. Deactivate the whole LVM Volume Group when processing a Logical Volume. Deactivating the Volume Group as a whole is quicker than deactivating each Logical Volume separately. +.IP \fIforcevg\fP +Forcibly deactivate the whole LVM Volume Group as soon as possible. +The primary job of this option is to flush the in-flight I/O operation +and then replace the LV's device-mapper table with 'error' target. +This is accomplished by using command "dmsetup wipe_table". +When this option is used, any other options (e.g. "-d retry|force", "-u") will be ignored. .RE .TP .BR -m ", " --mpathoptions \ \fImpath_options\fP @@ -118,6 +124,12 @@ Volume Group at once when processing an LVM Logical Volume. .B blkdeactivate -u -d retry -l wholevg .BR .P +Forcibly deactivate the whole vg. +.BR +# +.B blkdeactivate -l forcevg testvg +.BR +.P Deactivate all supported block devices found in the system. If the deactivation of a device-mapper device fails, retry it and force removal. .BR diff --git a/scripts/blkdeactivate.sh.in b/scripts/blkdeactivate.sh.in index 7c517b87b..db3291ae8 100644 --- a/scripts/blkdeactivate.sh.in +++ b/scripts/blkdeactivate.sh.in @@ -72,6 +72,8 @@ DO_UMOUNT=0 # Deactivate each LV separately by default (not the whole VG). LVM_DO_WHOLE_VG=0 +# Forcily deactivate the whole VG by wiping DM table +LVM_DO_FORCE_VG=0 # Do not retry LV deactivation by default. LVM_CONFIG="activation{retry_deactivation=0}" @@ -137,6 +139,7 @@ usage() { echo " LVM_OPTIONS:" echo " retry retry removal several times in case of failure" echo " wholevg deactivate the whole VG when processing an LV" + echo " forcevg force deactivate (wipe_table) the whole VG" echo " MDRAID_OPTIONS:" echo " wait wait for resync, recovery or reshape to complete first" echo " MPATH_OPTIONS:" @@ -287,6 +290,49 @@ deactivate_lvm () { fi } +is_top_level_lv() { + is_top_level_device && return 0 + skip=1 + while $LSBLK_READ; do + # First line self device + test "$skip" -eq 1 && skip=0 && continue + + # not top device but top lv in this VG, return 0 + test "$devtype" != "lvm" && return 0 + test ${name:0:${#DM_VG_NAME}+1} != $DM_VG_NAME"-" && return 0 + test ${name:0:${#DM_VG_NAME}+2} = $DM_VG_NAME"--" && return 0 + # the same vg, hidden lv + test ${name:0:${#DM_VG_NAME}+1} = $DM_VG_NAME"-" && return 1 + done <<< "$($LSBLK $DEV_DIR/$kname)" +} + +deactivate_vg () { + local VG_NAME; local LV_NAME; + local DM_VG_NAME; local DM_LV_NAME; + local LVS; + local skip_disablequeue=0 + + VG_NAME=$name + DM_VG_NAME=${name/-/--} + test -z "${SKIP_VG_LIST["$DM_VG_NAME"]}" || return 1 + test "$LVM_AVAILABLE" -eq 0 && { + add_device_to_skip_list + return 1 + } + + # Replace DM table with 'error' target. + # The reason for not using command "lvchange" ahead if because it may hang + # for a long time for the failed device. + echo -n " [LVM]: force deactivating Logical Volumes for $VG_NAME... " + "$DMSETUP" info -c -S "uuid=~LVM && vgname=$VG_NAME && lv_layer=\"\"" \ + -o name --noheadings | xargs "$DMSETUP" wipe_table + if [ "$?" = "0" ]; then + echo "wipe table done" + else + echo "wipe table failed" && return 1 + fi +} + deactivate_md () { local xname xname=$(printf "%s" "$name") @@ -361,7 +407,9 @@ deactivate () { # deactivate_holders first to recursively deactivate any existing # # holders it might have before deactivating the device it processes. # ###################################################################### - if test "$devtype" = "lvm"; then + if test "$devtype" = "vg"; then + deactivate_vg + elif test "$devtype" = "lvm"; then deactivate_lvm elif test "$devtype" = "vdo"; then deactivate_vdo @@ -425,14 +473,17 @@ deactivate_all() { ################################## 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 + # Force deactivate the whole vg + if test $LVM_DO_FORCE_VG -ne 0; then + $LSBLK_READ <<< "vg $1 $1" + deactivate || return 1 + elif -b "$1"; then + # Single dm device tree deactivation. + # Unmount all relevant mountpoints first + while $LSBLK_READ; do + device_umount + done <<< "$($LSBLK "$1" | $SORT_MNT)" + $LSBLK_READ <<< "$($LSBLK --nodeps "$1")" # check if the device is not on the skip list already @@ -474,6 +525,7 @@ get_lvmopts() { "") ;; "retry") LVM_CONFIG="activation{retry_deactivation=1}" ;; "wholevg") LVM_DO_WHOLE_VG=1 ;; + "forcevg") LVM_DO_FORCE_VG=1 ;; *) echo "$opt: unknown LVM option" esac done |