From 5d0756fc33bced8453fb5cf5807c5a3fa2b59dbb Mon Sep 17 00:00:00 2001 From: Zdenek Kabelac Date: Tue, 31 Aug 2021 20:52:26 +0200 Subject: [PATCH 1/5] vdo: fixes Better identify VDO device with major:minor. Handle different LV name from originally converted origin LV. Improve --dry-run handling. (cherry picked from commit 1ae157a0f67e984ef3037d19d62b84a3b0201c84) --- WHATS_NEW | 4 +++ scripts/lvm_import_vdo.sh | 70 +++++++++++++++++++++++++++++++++++------------ test/shell/vdo-convert.sh | 28 ++++++++++++++----- 3 files changed, 78 insertions(+), 24 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 3637e31..b751009 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,9 @@ Version 2.03.14 - ================================== + Improve lvm_import_vdo script. + Support VDO LV with lvcreate -ky. + Fix lvconvert for VDO LV bigger then 2T. + Create VDO LVs automatically without zeroing. Rename vdoimport to lvm_import_vdo. Version 2.03.13 - diff --git a/scripts/lvm_import_vdo.sh b/scripts/lvm_import_vdo.sh index 35140a0..bc73306 100755 --- a/scripts/lvm_import_vdo.sh +++ b/scripts/lvm_import_vdo.sh @@ -41,10 +41,15 @@ BLOCKDEV="blockdev" READLINK="readlink" READLINK_E="-e" MKDIR="mkdir" +DMSETUP="dmsetup" TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$" DM_DEV_DIR="${DM_DEV_DIR:-/dev}" +DEVICENAME="" +DEVMAJOR=0 +DEVMINOR=0 + DRY=0 VERB="" FORCE="" @@ -147,8 +152,6 @@ get_largest_extent_size_() { # dereference device name if it is symbolic link detect_lv_() { local DEVICE=$1 - local MAJOR - local MINOR local SYSVOLUME local MAJORMINOR @@ -161,17 +164,21 @@ detect_lv_() { /dev/dm-[0-9]*) read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME" read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"." - MAJOR=${MAJORMINOR%%:*} - MINOR=${MAJORMINOR##*:} + DEVMAJOR=${MAJORMINOR%%:*} + DEVMINOR=${MAJORMINOR##*:} ;; *) - STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE") + STAT=$(stat --format "DEVMAJOR=\$((0x%t)) DEVMINOR=\$((0x%T))" "$RDEVICE") test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"." eval "$STAT" ;; esac - eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')" + DEV="$("$DMSETUP" info -c -j "$DEVMAJOR" -m "$DEVMINOR" -o uuid,name --noheadings --nameprefixes --separator ' ' 2>/dev/null)" + case "$DEV" in + Device*) ;; # no devices + *) eval "$DEV" ;; + esac } # parse yaml config files into 'prefix_yaml_part_names=("value")' strings @@ -226,20 +233,26 @@ convert2lvm_() { local TRVDONAME local EXTENTSZ local IS_LV=1 + local FOUND="" + local MAJOR=0 + local MINOR=0 + local DM_VG_NAME + local DM_LV_NAME DM_UUID="" detect_lv_ "$DEVICE" case "$DM_UUID" in - LVM-*) eval "$(dmsetup splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")" + LVM-*) eval "$("$DMSETUP" splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")" if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then VGNAME=$DM_VG_NAME + LVNAME=$DM_LV_NAME elif test "$VGNAME" != "$DM_VG_NAME" ; then error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"." fi ;; *) IS_LV=0 # Check $VGNANE does not already exists - "$LVM" vgs "$VGNAME" && error "Cannot use already existing volume group name \"$VGNAME\"." + "$LVM" vgs "$VGNAME" >/dev/null 2>&1 && error "Cannot use already existing volume group name \"$VGNAME\"." ;; esac @@ -247,15 +260,37 @@ convert2lvm_() { "$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR." + # TODO: might use directly /etc/vdoconf.yml (avoding need of 'vdo' manager) verbose "Getting YAML VDO configuration." "$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml" - VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml") + # Check list of devices in VDO configure file for their major:minor + # and match with given $DEVICE devmajor:devminor + for i in $(awk '/.*device:/ {print $2}' "$TEMPDIR/vdoconf.yml") ; do + local DEV + DEV=$("$READLINK" $READLINK_E "$i") || continue + STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$DEV" 2>/dev/null) || continue + eval "$STAT" + test "$MAJOR" = "$DEVMAJOR" && test "$MINOR" = "$DEVMINOR" && { + test -z "$FOUND" || error "VDO configuration contains duplicate entries $FOUND and $i" + FOUND=$i + } + done + + test -n "$FOUND" || error "Can't find matching device in vdo configuration file." + verbose "Found matching device $FOUND $MAJOR:$MINOR" + + VDONAME=$(awk -v DNAME="$FOUND" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml") TRVDONAME=$(echo "$VDONAME" | tr '-' '_') # When VDO volume is 'active', check it's not mounted/being used - eval "$(dmsetup info -c -o open "$VDONAME" --noheadings --nameprefixes || true)" - test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!" + DM_OPEN="$("$DMSETUP" info -c -o open "$VDONAME" --noheadings --nameprefixes 2>/dev/null || true)" + case "$DM_OPEN" in + Device*) ;; # no devices + *) eval "$DM_OPEN" + test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!" + ;; + esac #parse_yaml_ "$TEMPDIR/vdoconf.yml" _ eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")" @@ -263,8 +298,7 @@ convert2lvm_() { vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize") vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize") - verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB." - verbose "With logical volume of size $vdo_logicalSize KiB." + verbose "Converted VDO device has logical/physical size $vdo_logicalSize/$vdo_physicalSize KiB." PARAMS=$(cat </dev/null || true + +lvremove -f $vg + + +# Test user can specify different VDO LV name (so the original LV is renamed) +lvcreate -y -L5G -n $lv1 $vg + +vdo create $VDOCONF --name "$VDONAME" --device="$DM_DEV_DIR/$vg/$lv1" --vdoLogicalSize=10G + +lvm_import_vdo -y --name $vg/$lv2 "$DM_DEV_DIR/$vg/$lv1" + +check lv_exists $vg $lv2 +check lv_not_exists $vg $lv1 vgremove -f $vg +# ensure VDO device is not left in config file +vdo remove $VDOCONF --force --name "$VDONAME" 2>/dev/null || true + aux wipefs_a "$dev1" # prepare 'unused' $vg2 vgcreate $vg2 "$dev2" # -# Check conversion of VDO volume on non-LV device +# Check conversion of VDO volume on non-LV device and with >2T size # -vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=31G - -mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME" +vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=3T # Fail with an already existing volume group $vg2 not lvm_import_vdo --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err @@ -87,7 +101,7 @@ vdo stop $VDOCONF --name "$VDONAME" lvm_import_vdo -y -v --name $vg/$lv1 "$dev1" -fsck -n "$DM_DEV_DIR/$vg/$lv1" +check lv_field $vg/$lv1 size "3.00t" vgremove -f $vg -- 1.8.3.1