1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-10 16:58:47 +03:00

blkdeactive: Introduce option "forcevg" to forcibly deactivate VG

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>
This commit is contained in:
Zhang Huan 2021-03-02 11:32:54 -06:00 committed by David Teigland
parent 71a453a25b
commit 37796aa7bf
2 changed files with 72 additions and 8 deletions

View File

@ -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

View File

@ -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)"
# 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)"
# Do deactivate
# Single dm device tree deactivation.
if test -b "$1"; then
$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