summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhang Huan <zhanghuan@huayun.com>2021-03-02 11:32:54 -0600
committerDavid Teigland <teigland@redhat.com>2021-03-02 11:32:54 -0600
commit37796aa7bf81393c2d07ff245dd4c496a00218d6 (patch)
treebde2bc041c0d0235b7af669d634deda828a8301f
parent71a453a25bb305425f1f8f5b6b65a5fd9ec08f5f (diff)
downloadlvm2-dev-dct-lvmlockctl-kill-2.tar.gz
blkdeactive: Introduce option "forcevg" to forcibly deactivate VGdev-dct-lvmlockctl-kill-2
This patch introduces new option "forcevg" for LVM, the main purpose is to flush in-flight I/O operations and replace the LV's device mapper table with 'error' target, this is accomplished by using command "dmsetup wipe_table". To handle the failure as soon as possible, it will not deactivate holders and not try to use command "lvchange", thus can speed up wiping table. This option is supposed to be used by "lvmlockctl" command to forcibly deactivate volume group, this can avoid watchdog reset when detect drive failures. Signed-off-by: Zhang Huan <zhanghuan@huayun.com> [Refactored changes and commit log] Signed-off-by: Leo Yan <leo.yan@linaro.org>
-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