summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/blkdeactivate.8_main12
-rw-r--r--scripts/blkdeactivate.sh.in70
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