diff --git a/.gitignore b/.gitignore index 35fd4e4..c51efd3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/LVM2.2.03.17.tgz +SOURCES/LVM2.2.03.21.tgz diff --git a/.lvm2.metadata b/.lvm2.metadata index eda57a2..a387c8e 100644 --- a/.lvm2.metadata +++ b/.lvm2.metadata @@ -1 +1 @@ -8a0043a552c17be61234989c02ef501eda971fd1 SOURCES/LVM2.2.03.17.tgz +b6d4a84bf1f0306f43f447c7531021d5c126edbf SOURCES/LVM2.2.03.21.tgz diff --git a/SOURCES/0001-device_id-fix-segfault-verifying-serial-for-non-pv.patch b/SOURCES/0001-device_id-fix-segfault-verifying-serial-for-non-pv.patch deleted file mode 100644 index 5832580..0000000 --- a/SOURCES/0001-device_id-fix-segfault-verifying-serial-for-non-pv.patch +++ /dev/null @@ -1,133 +0,0 @@ -From b01433cdc841133500a0ed4041b9b35838d45e87 Mon Sep 17 00:00:00 2001 -From: David Teigland -Date: Fri, 2 Dec 2022 11:59:09 -0600 -Subject: [PATCH] device_id: fix segfault verifying serial for non-pv - -The recent change that verifies sys_serial system.devices entries -using the PVID did not exclude non-PV devices from being checked. -The verification code would attempt to use du->pvid which was null -for the non-PVs causing a segfault. - -(cherry picked from commit 6613a61d3b5ce4d12a6fef79195eac34f30ef4da) ---- - lib/device/device_id.c | 6 ++- - test/shell/devicesfile-serial.sh | 79 ++++++++++++++++++++++++++++++++ - 2 files changed, 83 insertions(+), 2 deletions(-) - -diff --git a/lib/device/device_id.c b/lib/device/device_id.c -index aae875776..96726a448 100644 ---- a/lib/device/device_id.c -+++ b/lib/device/device_id.c -@@ -2237,8 +2237,8 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, - * number is correct, since serial numbers may not be unique. - * Search for the PVID on other devs in device_ids_check_serial. - */ -- if ((du->idtype == DEV_ID_TYPE_SYS_SERIAL) && -- (!du->pvid || memcmp(dev->pvid, du->pvid, ID_LEN))) { -+ if ((du->idtype == DEV_ID_TYPE_SYS_SERIAL) && du->pvid && -+ memcmp(dev->pvid, du->pvid, ID_LEN)) { - log_debug("suspect device id serial %s for %s", du->idname, dev_name(dev)); - str_list_add(cmd->mem, &cmd->device_ids_check_serial, dm_pool_strdup(cmd->mem, du->idname)); - *device_ids_invalid = 1; -@@ -2570,6 +2570,8 @@ void device_ids_check_serial(struct cmd_context *cmd, struct dm_list *scan_devs, - dm_list_iterate_items(dul, &dus_check) { - if (!dul->du->dev) - continue; -+ if (!dul->du->pvid) -+ continue; - /* save previously matched devs so they can be dropped from - lvmcache at the end if they are no longer used */ - if (!(dil = dm_pool_zalloc(cmd->mem, sizeof(*dil)))) -diff --git a/test/shell/devicesfile-serial.sh b/test/shell/devicesfile-serial.sh -index b7bfce29e..a88c1906a 100644 ---- a/test/shell/devicesfile-serial.sh -+++ b/test/shell/devicesfile-serial.sh -@@ -772,6 +772,85 @@ grep $SERIAL1 out2 - grep $dev3 out3 - grep $SERIAL3 out3 - -+# non-PV devices -+ -+aux wipefs_a $dev1 -+aux wipefs_a $dev2 -+aux wipefs_a $dev3 -+aux wipefs_a $dev4 -+ -+echo $SERIAL1 > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial -+echo $SERIAL2 > $SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial -+echo $SERIAL2 > $SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial -+echo $SERIAL4 > $SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial -+ -+rm $DF -+touch $DF -+vgcreate $vg4 $dev4 -+lvmdevices --adddev "$dev1" -+lvmdevices --adddev "$dev2" -+lvmdevices --adddev "$dev3" -+cat $DF -+ -+grep $dev1 $DF |tee out1 -+grep $dev2 $DF |tee out2 -+grep $dev3 $DF |tee out3 -+grep $dev4 $DF |tee out4 -+ -+grep $SERIAL1 out1 -+grep $SERIAL2 out2 -+grep $SERIAL2 out3 -+grep $SERIAL4 out4 -+ -+pvs |tee out -+grep $dev4 out -+not grep $dev1 out -+not grep $dev2 out -+not grep $dev3 out -+ -+pvcreate $dev1 -+pvs |tee out -+grep $dev1 out -+grep $dev4 out -+not grep $dev2 out -+not grep $dev3 out -+ -+pvcreate $dev2 -+pvs |tee out -+grep $dev1 out -+grep $dev4 out -+grep $dev2 out -+not grep $dev3 out -+ -+pvcreate $dev3 -+pvs |tee out -+grep $dev1 out -+grep $dev4 out -+grep $dev2 out -+grep $dev3 out -+ -+PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'` -+PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'` -+PVID3=`pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}'` -+PVID4=`pvs "$dev4" --noheading -o uuid | tr -d - | awk '{print $1}'` -+OPVID1=`pvs "$dev1" --noheading -o uuid | awk '{print $1}'` -+OPVID2=`pvs "$dev2" --noheading -o uuid | awk '{print $1}'` -+OPVID3=`pvs "$dev3" --noheading -o uuid | awk '{print $1}'` -+OPVID4=`pvs "$dev4" --noheading -o uuid | awk '{print $1}'` -+ -+grep $dev1 $DF |tee out1 -+grep $dev2 $DF |tee out2 -+grep $dev3 $DF |tee out3 -+grep $dev4 $DF |tee out4 -+ -+grep $PVID1 out1 -+grep $PVID2 out2 -+grep $PVID3 out3 -+grep $PVID4 out4 -+ -+vgcreate $vg2 $dev2 $dev3 -+vgs | grep $vg2 -+ - remove_base - rmmod brd - --- -2.38.1 - diff --git a/SOURCES/0001-fix-dev_name-use-in-add_areas_line.patch b/SOURCES/0001-fix-dev_name-use-in-add_areas_line.patch new file mode 100644 index 0000000..0b55391 --- /dev/null +++ b/SOURCES/0001-fix-dev_name-use-in-add_areas_line.patch @@ -0,0 +1,84 @@ +From ecea7b14c453a58831f2dda5a0aa869ee4601dff Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Mon, 24 Apr 2023 15:47:45 -0500 +Subject: [PATCH 1/2] fix dev_name use in add_areas_line + +This function was relying on dev_name() returning NULL +to indicate no device, but dev_name never returns NULL. + +(cherry picked from commit 31cfcf7ce9aab5dd16ba15e48bfe33be849fad4c) +--- + lib/activate/dev_manager.c | 45 ++++++++++++++++++++++++-------------- + 1 file changed, 29 insertions(+), 16 deletions(-) + +diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c +index 07d58733e..ac3f01718 100644 +--- a/lib/activate/dev_manager.c ++++ b/lib/activate/dev_manager.c +@@ -3000,34 +3000,47 @@ static int _add_error_area(struct dev_manager *dm, struct dm_tree_node *node, + return 1; + } + ++static int _bad_pv_area(struct lv_segment *seg, uint32_t s) ++{ ++ struct stat info; ++ const char *name; ++ struct device *dev; ++ ++ if (!seg_pvseg(seg, s)) ++ return 1; ++ if (!seg_pv(seg, s)) ++ return 1; ++ if (!(dev = seg_dev(seg, s))) ++ return 1; ++ if (dm_list_empty(&dev->aliases)) ++ return 1; ++ /* FIXME Avoid repeating identical stat in dm_tree_node_add_target_area */ ++ name = dev_name(dev); ++ if (stat(name, &info) < 0) ++ return 1; ++ if (!S_ISBLK(info.st_mode)) ++ return 1; ++ return 0; ++} ++ + int add_areas_line(struct dev_manager *dm, struct lv_segment *seg, + struct dm_tree_node *node, uint32_t start_area, + uint32_t areas) + { ++ struct cmd_context *cmd = seg->lv->vg->cmd; + uint64_t extent_size = seg->lv->vg->extent_size; + uint32_t s; + char *dlid; +- struct stat info; + const char *name; + unsigned num_error_areas = 0; + unsigned num_existing_areas = 0; + +- /* FIXME Avoid repeating identical stat in dm_tree_node_add_target_area */ + for (s = start_area; s < areas; s++) { +- +- /* FIXME: dev_name() does not return NULL! It needs to check if dm_list_empty(&dev->aliases) +- but this knot of logic is too complex to pull apart without careful deconstruction. */ +- +- if ((seg_type(seg, s) == AREA_PV && +- (!seg_pvseg(seg, s) || !seg_pv(seg, s) || !seg_dev(seg, s) || +- !(name = dev_name(seg_dev(seg, s))) || !*name || +- stat(name, &info) < 0 || !S_ISBLK(info.st_mode))) || +- (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s))) { +- if (!seg->lv->vg->cmd->partial_activation) { +- if (!seg->lv->vg->cmd->degraded_activation || +- !lv_is_raid_type(seg->lv)) { +- log_error("Aborting. LV %s is now incomplete " +- "and '--activationmode partial' was not specified.", ++ if (((seg_type(seg, s) == AREA_PV) && _bad_pv_area(seg, s)) || ++ ((seg_type(seg, s) == AREA_LV) && !seg_lv(seg, s))) { ++ if (!cmd->partial_activation) { ++ if (!cmd->degraded_activation || !lv_is_raid_type(seg->lv)) { ++ log_error("Aborting. LV %s is incomplete and --activationmode partial was not specified.", + display_lvname(seg->lv)); + return 0; + } +-- +2.40.1 + diff --git a/SOURCES/0002-lvextend-fix-overprovisioning-check-for-thin-lvs.patch b/SOURCES/0002-lvextend-fix-overprovisioning-check-for-thin-lvs.patch deleted file mode 100644 index 1e42978..0000000 --- a/SOURCES/0002-lvextend-fix-overprovisioning-check-for-thin-lvs.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 20c6961e37bf6f5010f9d2035dbc1ce03f9b0223 Mon Sep 17 00:00:00 2001 -From: David Teigland -Date: Thu, 15 Dec 2022 09:57:04 -0600 -Subject: [PATCH] lvextend: fix overprovisioning check for thin lvs - -18722dfdf4d3 lvresize: restructure code -mistakenly changed the overprovisioning check from applying -to all lv_is_thin_type lvs to only lv_is_thin_pool lvs, so -it no longer applied when extending thin lvs. The result -was missing warning messages when extending thin lvs. - -(cherry picked from commit 4baef0f93f608403b6f2db445e7bf1e80f8f3ee6) ---- - lib/metadata/lv_manip.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c -index 4cdbc19a0..f8eae0447 100644 ---- a/lib/metadata/lv_manip.c -+++ b/lib/metadata/lv_manip.c -@@ -7007,9 +7007,10 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv, - if (lv_is_thin_pool(lv_top)) { - if (!update_thin_pool_lv(lv_top, 1)) - goto_out; -- if (is_extend) -- thin_pool_check_overprovisioning(lv_top); - } -+ if (lv_is_thin_type(lv_top) && is_extend) -+ thin_pool_check_overprovisioning(lv_top); -+ - if (lv_main && lv_is_cow_covering_origin(lv_main)) { - if (!monitor_dev_for_events(cmd, lv_main, 0, 0)) - stack; --- -2.38.1 - diff --git a/SOURCES/0002-raidintegrity-allow-snapshots.patch b/SOURCES/0002-raidintegrity-allow-snapshots.patch new file mode 100644 index 0000000..ae92f75 --- /dev/null +++ b/SOURCES/0002-raidintegrity-allow-snapshots.patch @@ -0,0 +1,510 @@ +From fb1e53f229f4bcde07df4b562927e213bd7f8d17 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 22 Mar 2023 13:05:43 -0500 +Subject: [PATCH 2/2] raidintegrity: allow snapshots + +(cherry picked from commit fd6e113bba5fed5ee41152cde33220294c24ce2b) +--- + lib/activate/dev_manager.c | 6 +- + lib/metadata/integrity_manip.c | 5 - + lib/metadata/snapshot_manip.c | 2 - + test/shell/snapshot-raid.sh | 441 +++++++++++++++++++++++++++++++++ + 4 files changed, 446 insertions(+), 8 deletions(-) + create mode 100644 test/shell/snapshot-raid.sh + +diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c +index ac3f01718..1f4d7c98b 100644 +--- a/lib/activate/dev_manager.c ++++ b/lib/activate/dev_manager.c +@@ -3039,7 +3039,11 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg, + if (((seg_type(seg, s) == AREA_PV) && _bad_pv_area(seg, s)) || + ((seg_type(seg, s) == AREA_LV) && !seg_lv(seg, s))) { + if (!cmd->partial_activation) { +- if (!cmd->degraded_activation || !lv_is_raid_type(seg->lv)) { ++ if (!cmd->degraded_activation || ++ (!lv_is_raid_type(seg->lv) && ++ !lv_is_integrity(seg->lv) && ++ !lv_is_integrity_metadata(seg->lv) && ++ !lv_is_integrity_origin(seg->lv))) { + log_error("Aborting. LV %s is incomplete and --activationmode partial was not specified.", + display_lvname(seg->lv)); + return 0; +diff --git a/lib/metadata/integrity_manip.c b/lib/metadata/integrity_manip.c +index 456795532..506b9f06b 100644 +--- a/lib/metadata/integrity_manip.c ++++ b/lib/metadata/integrity_manip.c +@@ -508,11 +508,6 @@ int lv_add_integrity_to_raid(struct logical_volume *lv, struct integrity_setting + return 0; + } + +- if (lv_is_origin(lv)) { +- log_error("Integrity cannot be added to snapshot origins."); +- return 0; +- } +- + seg_top = first_seg(lv); + area_count = seg_top->area_count; + +diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c +index 822b8da77..b34079d08 100644 +--- a/lib/metadata/snapshot_manip.c ++++ b/lib/metadata/snapshot_manip.c +@@ -423,8 +423,6 @@ int validate_snapshot_origin(const struct logical_volume *origin_lv) + } + } else if (lv_is_raid_type(origin_lv) && !lv_is_raid(origin_lv)) { + err = "raid subvolumes"; +- } else if (lv_is_raid(origin_lv) && lv_raid_has_integrity((struct logical_volume *)origin_lv)) { +- err = "raid with integrity"; + } + + out: +diff --git a/test/shell/snapshot-raid.sh b/test/shell/snapshot-raid.sh +new file mode 100644 +index 000000000..757bf911e +--- /dev/null ++++ b/test/shell/snapshot-raid.sh +@@ -0,0 +1,441 @@ ++#!/usr/bin/env bash ++ ++# Copyright (C) 2018 Red Hat, Inc. All rights reserved. ++# ++# This copyrighted material is made available to anyone wishing to use, ++# modify, copy, or redistribute it subject to the terms and conditions ++# of the GNU General Public License v.2. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software Foundation, ++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ ++# Test snapshots of raid ++ ++SKIP_WITH_LVMPOLLD=1 ++ ++. lib/inittest ++ ++which mkfs.ext4 || skip ++ ++mount_dir="mnt" ++mkdir -p "$mount_dir" ++ ++snap_dir="mnt_snap" ++mkdir -p "$snap_dir" ++ ++_sync_percent() { ++ local checklv=$1 ++ get lv_field "$checklv" sync_percent | cut -d. -f1 ++} ++ ++_wait_sync() { ++ local checklv=$1 ++ ++ for i in $(seq 1 10) ; do ++ sync=$(_sync_percent "$checklv") ++ echo "sync_percent is $sync" ++ ++ if test "$sync" = "100"; then ++ return ++ fi ++ ++ sleep 1 ++ done ++ echo "timeout waiting for recalc" ++ dmsetup status "$DM_DEV_DIR/mapper/${checklv/\//-}" ++ return 1 ++} ++ ++ ++# add and remove a snapshot ++ ++test_add_del_snap() { ++ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ touch "$mount_dir/A" ++ ++ lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++ mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" ++ ++ touch "$mount_dir/B" ++ not ls "$snap_dir/B" ++ touch "$snap_dir/C" ++ not ls "$mount_dir/C" ++ ls "$mount_dir/A" ++ ls "$snap_dir/A" ++ ++ umount "$snap_dir" ++ lvremove -y $vg/snap ++ umount "$mount_dir" ++} ++ ++# add and remove snapshot while origin has a missing raid image ++ ++test_snap_with_missing_image() { ++ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ touch "$mount_dir/A" ++ ++ aux disable_dev "$dev1" ++ lvs -a -o+devices $vg ++ ++ not lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++ ++ aux enable_dev "$dev1" ++ _wait_sync $vg/$lv1 ++ ++ lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++ ++ aux disable_dev "$dev1" ++ lvs -a -o+devices $vg ++ ++ lvremove -y $vg/snap ++ ++ aux enable_dev "$dev1" ++ vgextend --restoremissing $vg "$dev1" ++ lvs -a -o+devices $vg ++ _wait_sync $vg/$lv1 ++ ++ umount "$mount_dir" ++} ++ ++# raid image is lost and restored while a snapshot exists ++ ++test_missing_image_with_snap() { ++ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ touch "$mount_dir/A" ++ ++ lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++ mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" ++ ++ aux disable_dev "$dev1" ++ lvs -a -o+devices $vg ++ ++ touch "$mount_dir/B" ++ not ls "$snap_dir/B" ++ touch "$snap_dir/C" ++ not ls "$mount_dir/C" ++ ls "$mount_dir/A" ++ ls "$snap_dir/A" ++ ++ aux enable_dev "$dev1" ++ _wait_sync $vg/$lv1 ++ ++ ls "$mount_dir/B" ++ ls "$snap_dir/C" ++ ++ umount "$snap_dir" ++ lvremove -y $vg/snap ++ umount "$mount_dir" ++} ++ ++# add and remove raid image while snapshot exists ++ ++test_add_del_image_with_snap() { ++ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ touch "$mount_dir/A" ++ ++ lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++ mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" ++ ++ touch "$mount_dir/B" ++ touch "$snap_dir/C" ++ ++ lvconvert -y -m+1 $vg/$lv1 "$dev4" ++ _wait_sync $vg/$lv1 ++ ++ ls "$mount_dir/B" ++ ls "$snap_dir/C" ++ ls "$mount_dir/A" ++ ls "$snap_dir/A" ++ ++ touch "$mount_dir/B2" ++ touch "$snap_dir/C2" ++ ++ lvconvert -y -m-1 $vg/$lv1 "$dev4" ++ ++ ls "$mount_dir/B" ++ ls "$snap_dir/C" ++ ls "$mount_dir/A" ++ ls "$snap_dir/A" ++ ls "$mount_dir/B2" ++ ls "$snap_dir/C2" ++ umount "$snap_dir" ++ lvremove -y $vg/snap ++ ++ umount "$mount_dir" ++} ++ ++test_replace_image_with_snap() { ++ # add an image to replace ++ lvconvert -y -m+1 $vg/$lv1 "$dev4" ++ _wait_sync $vg/$lv1 ++ ++ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ touch "$mount_dir/A" ++ ++ lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++ mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" ++ ++ touch "$mount_dir/B" ++ touch "$snap_dir/C" ++ ++ lvconvert -y --replace "$dev4" $vg/$lv1 "$dev5" ++ _wait_sync $vg/$lv1 ++ ++ ls "$mount_dir/B" ++ ls "$snap_dir/C" ++ ls "$mount_dir/A" ++ ls "$snap_dir/A" ++ ++ touch "$mount_dir/B2" ++ touch "$snap_dir/C2" ++ ++ umount "$snap_dir" ++ lvremove -y $vg/snap ++ ++ # put lv1 back to original state with images on dev1 and dev2 ++ lvconvert -y -m-1 $vg/$lv1 "$dev5" ++ ++ umount "$mount_dir" ++} ++ ++test_repair_image_with_snap() { ++ # add an image to repair ++ lvconvert -y -m+1 $vg/$lv1 "$dev4" ++ _wait_sync $vg/$lv1 ++ ++ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ touch "$mount_dir/A" ++ ++ lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++ mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" ++ ++ touch "$mount_dir/B" ++ touch "$snap_dir/C" ++ ++ aux disable_dev "$dev4" ++ lvs -a -o+devices $vg ++ ++ lvconvert -y --repair $vg/$lv1 "$dev5" ++ _wait_sync $vg/$lv1 ++ ++ ls "$mount_dir/B" ++ ls "$snap_dir/C" ++ ls "$mount_dir/A" ++ ls "$snap_dir/A" ++ ++ touch "$mount_dir/B2" ++ touch "$snap_dir/C2" ++ ++ umount "$snap_dir" ++ lvremove -y $vg/snap ++ ++ aux enable_dev "$dev4" ++ lvs -a -o+devices $vg ++ vgck --updatemetadata $vg ++ ++ # put lv1 back to original state with images on dev1 and dev2 ++ lvconvert -y -m-1 $vg/$lv1 "$dev5" ++ ++ umount "$mount_dir" ++} ++ ++test_merge_snap() ++{ ++ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ touch "$mount_dir/A" ++ ++ lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++ mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" ++ ++ touch "$mount_dir/B" ++ touch "$snap_dir/C" ++ ++ umount "$snap_dir" ++ ++ lvconvert --merge $vg/snap ++ ++ # the merge will begin once the origin is not in use ++ umount "$mount_dir" ++ ++ lvs -a $vg ++ lvchange -an $vg/$lv1 ++ lvchange -ay $vg/$lv1 ++ lvs -a $vg ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ ls "$mount_dir/A" ++ ls "$mount_dir/C" ++ not ls "$mount_dir/B" ++ ++ umount "$mount_dir" ++} ++ ++test_extend_snap() ++{ ++ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ touch "$mount_dir/A" ++ ++ lvcreate -s -n snap -L8M $vg/$lv1 "$dev3" ++ mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" ++ ++ touch "$mount_dir/B" ++ touch "$snap_dir/C" ++ ++ lvextend -L+8M $vg/snap ++ ++ umount "$mount_dir" ++ umount "$snap_dir" ++ lvremove -y $vg/snap ++} ++ ++test_fill_snap() ++{ ++ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++ mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++ touch "$mount_dir/A" ++ ++ lvcreate -s -n snap -L4M $vg/$lv1 "$dev3" ++ ++ lvs -a $vg ++ get lv_field $vg/snap lv_attr | grep "swi-a-s---" ++ ++ dd if=/dev/zero of="$mount_dir/1" bs=1M count=1 oflag=sync ++ dd if=/dev/zero of="$mount_dir/2" bs=1M count=1 oflag=sync ++ dd if=/dev/zero of="$mount_dir/3" bs=1M count=1 oflag=sync ++ dd if=/dev/zero of="$mount_dir/4" bs=1M count=1 oflag=sync ++ dd if=/dev/zero of="$mount_dir/5" bs=1M count=1 oflag=sync ++ ++ lvs -a $vg ++ get lv_field $vg/snap lv_attr | grep "swi-I-s---" ++ check lv_field $vg/snap data_percent "100.00" ++ ++ umount "$mount_dir" ++ lvremove -y $vg/snap ++} ++ ++aux prepare_devs 5 200 ++ ++vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" ++ ++lvcreate --type raid1 -m1 -n $lv1 -L128M $vg "$dev1" "$dev2" ++_wait_sync $vg/$lv1 ++test_add_del_snap ++test_snap_with_missing_image ++test_missing_image_with_snap ++test_add_del_image_with_snap ++test_replace_image_with_snap ++test_repair_image_with_snap ++test_merge_snap ++test_extend_snap ++test_fill_snap ++lvremove -y $vg/$lv1 ++ ++lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -L128M $vg "$dev1" "$dev2" ++_wait_sync $vg/${lv1}_rimage_0 ++_wait_sync $vg/${lv1}_rimage_1 ++_wait_sync $vg/$lv1 ++test_add_del_snap ++test_snap_with_missing_image ++test_missing_image_with_snap ++test_add_del_image_with_snap ++test_replace_image_with_snap ++test_repair_image_with_snap ++test_merge_snap ++test_extend_snap ++test_fill_snap ++lvremove -y $vg/$lv1 ++ ++# Repeat above with cache|writecache on the raid image? ++ ++# ++# Add/remove integrity while a snapshot exists ++# ++ ++lvcreate --type raid1 -m1 -n $lv1 -L128M $vg "$dev1" "$dev2" ++_wait_sync $vg/$lv1 ++mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++touch "$mount_dir/A" ++ ++lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" ++ ++touch "$mount_dir/B" ++touch "$snap_dir/C" ++ ++lvconvert --raidintegrity y $vg/$lv1 ++_wait_sync $vg/${lv1}_rimage_0 ++_wait_sync $vg/${lv1}_rimage_1 ++ ++ls "$mount_dir/B" ++ls "$snap_dir/C" ++ls "$mount_dir/A" ++ls "$snap_dir/A" ++ ++touch "$mount_dir/B2" ++touch "$snap_dir/C2" ++ ++lvconvert --raidintegrity n $vg/$lv1 ++ ++ls "$mount_dir/B" ++ls "$snap_dir/C" ++ls "$mount_dir/A" ++ls "$snap_dir/A" ++ls "$mount_dir/B2" ++ls "$snap_dir/C2" ++umount "$snap_dir" ++umount "$mount_dir" ++lvremove -y $vg/snap ++lvremove -y $vg/$lv1 ++ ++# ++# Add integrity not allowed with missing image and snapshot exists ++# ++ ++lvcreate --type raid1 -m1 -n $lv1 -L128M $vg "$dev1" "$dev2" ++_wait_sync $vg/$lv1 ++mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" ++ ++mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" ++touch "$mount_dir/A" ++ ++lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" ++mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" ++ ++touch "$mount_dir/B" ++touch "$snap_dir/C" ++ ++aux disable_dev "$dev1" ++lvs -a $vg ++ ++not lvconvert --raidintegrity y $vg/$lv1 ++ ++aux enable_dev "$dev1" ++lvs -a $vg ++ ++umount "$snap_dir" ++umount "$mount_dir" ++lvremove -y $vg/snap ++lvremove -y $vg/$lv1 ++ ++vgremove -ff $vg ++ +-- +2.40.1 + diff --git a/SOURCES/0003-lvmdbus-preserve-PATH-envvar.patch b/SOURCES/0003-lvmdbus-preserve-PATH-envvar.patch new file mode 100644 index 0000000..c975821 --- /dev/null +++ b/SOURCES/0003-lvmdbus-preserve-PATH-envvar.patch @@ -0,0 +1,26 @@ +From 1835574e39e9417b3800469fe80ce47d2210b9a7 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Sun, 23 Apr 2023 12:49:37 +0200 +Subject: [PATCH 3/8] lvmdbus: preserve PATH envvar + +(cherry picked from commit afc02ae6e7234e1190cedf5c74ca3d6367efd7d1) +--- + daemons/lvmdbusd/lvm_shell_proxy.py.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/daemons/lvmdbusd/lvm_shell_proxy.py.in b/daemons/lvmdbusd/lvm_shell_proxy.py.in +index b8c8fa565..02a776e1d 100755 +--- a/daemons/lvmdbusd/lvm_shell_proxy.py.in ++++ b/daemons/lvmdbusd/lvm_shell_proxy.py.in +@@ -154,6 +154,8 @@ class LVMShellProxy(object): + + # If any env variables contain LVM we will propagate them too + for k, v in os.environ.items(): ++ if "PATH" in k: ++ local_env[k] = v + if "LVM" in k: + local_env[k] = v + +-- +2.40.1 + diff --git a/SOURCES/0003-lvresize-fix-cryptsetup-resize-in-helper.patch b/SOURCES/0003-lvresize-fix-cryptsetup-resize-in-helper.patch deleted file mode 100644 index ec63d69..0000000 --- a/SOURCES/0003-lvresize-fix-cryptsetup-resize-in-helper.patch +++ /dev/null @@ -1,32 +0,0 @@ -From db067b9054d87ada6aa133394e65e3af9d75fc08 Mon Sep 17 00:00:00 2001 -From: David Teigland -Date: Tue, 3 Jan 2023 11:38:33 -0600 -Subject: [PATCH] lvresize: fix cryptsetup resize in helper - -typo used "cryptresize" as command name - -this affects cases where the file system is resized -independently, and then the lvresize command is used -which only needs to resize the crypt device and the LV. - -(cherry picked from commit 81acde7ffdf9fbe522ada16f89e429d9f729dc0c) ---- - scripts/lvresize_fs_helper.sh | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/lvresize_fs_helper.sh b/scripts/lvresize_fs_helper.sh -index 031b8453b..f531dd447 100755 ---- a/scripts/lvresize_fs_helper.sh -+++ b/scripts/lvresize_fs_helper.sh -@@ -224,7 +224,7 @@ fsreduce() { - cryptresize() { - NEWSIZESECTORS=$(($NEWSIZEBYTES/512)) - logmsg "cryptsetup resize ${NEWSIZESECTORS} sectors ${DEVPATH}" -- cryptresize resize --size "$NEWSIZESECTORS" "$DEVPATH" -+ cryptsetup resize --size "$NEWSIZESECTORS" "$DEVPATH" - if [ $? -eq 0 ]; then - logmsg "cryptsetup done" - else --- -2.39.0 - diff --git a/SOURCES/0004-lvmcache-fix-valgrind-error-when-dropping-md-duplica.patch b/SOURCES/0004-lvmcache-fix-valgrind-error-when-dropping-md-duplica.patch new file mode 100644 index 0000000..0f69401 --- /dev/null +++ b/SOURCES/0004-lvmcache-fix-valgrind-error-when-dropping-md-duplica.patch @@ -0,0 +1,43 @@ +From 80b73e2901d470fd3d1f45664626980167091f02 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 25 Apr 2023 14:46:36 -0500 +Subject: [PATCH 4/8] lvmcache: fix valgrind error when dropping md duplicate + +When lvmcache info is dropped because it's an md component, +then the lvmcache vginfo can also be dropped, but the list +iterator was still using the list head in vginfo, so break +from the loop earlier to avoid it. + +(cherry picked from commit 6d262eaf640dead7861c1a7716e216b9bcea75e5) +--- + lib/cache/lvmcache.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c +index b8a9eac25..127d29229 100644 +--- a/lib/cache/lvmcache.c ++++ b/lib/cache/lvmcache.c +@@ -1503,6 +1503,9 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd) + */ + + dm_list_iterate_items_safe(vginfo, vginfo2, &_vginfos) { ++ char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 }; ++ memcpy(vgid, vginfo->vgid, ID_LEN); ++ + dm_list_iterate_items_safe(info, info2, &vginfo->infos) { + dev = info->dev; + device_hint = _get_pvsummary_device_hint(dev->pvid); +@@ -1557,6 +1560,10 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd) + /* lvmcache_del will also delete vginfo if info was last one */ + lvmcache_del(info); + cmd->filter->wipe(cmd, cmd->filter, dev, NULL); ++ ++ /* If vginfo was deleted don't continue using vginfo->infos */ ++ if (!_search_vginfos_list(NULL, vgid)) ++ break; + } + } + } +-- +2.40.1 + diff --git a/SOURCES/0004-vgimportclone-fix-importing-PV-without-metadata.patch b/SOURCES/0004-vgimportclone-fix-importing-PV-without-metadata.patch deleted file mode 100644 index becc161..0000000 --- a/SOURCES/0004-vgimportclone-fix-importing-PV-without-metadata.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 8f7b4456ad93c3907a82fd03d0feceb9785e3bfc Mon Sep 17 00:00:00 2001 -From: David Teigland -Date: Thu, 5 Jan 2023 14:28:31 -0600 -Subject: [PATCH 1/3] vgimportclone: fix importing PV without metadata - -If one of the PVs in the VG does not hold metadata, then the -command would fail, thinking that PV was from a different VG. -Also add missing free on that error path. - -(cherry picked from commit c4b898a53eec39bc28b5451e7fde87945303a644) ---- - tools/vgimportclone.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/tools/vgimportclone.c b/tools/vgimportclone.c -index 60ef20762..93fa3b18d 100644 ---- a/tools/vgimportclone.c -+++ b/tools/vgimportclone.c -@@ -203,7 +203,7 @@ int vgimportclone(struct cmd_context *cmd, int argc, char **argv) - struct device *dev; - struct device_list *devl; - struct dm_list other_devs; -- struct volume_group *vg, *error_vg; -+ struct volume_group *vg, *error_vg = NULL; - const char *vgname; - char base_vgname[NAME_LEN] = { 0 }; - char tmp_vgname[NAME_LEN] = { 0 }; -@@ -322,7 +322,7 @@ int vgimportclone(struct cmd_context *cmd, int argc, char **argv) - goto out; - } - -- if (!(vgname = lvmcache_vgname_from_info(info))) { -+ if (!(vgname = lvmcache_vgname_from_info(info)) || is_orphan_vg(vgname)) { - /* The PV may not have metadata, this will be resolved in - the process_each_vg/vg_read at the end. */ - continue; -@@ -503,6 +503,8 @@ retry_name: - } - ret = ECMD_PROCESSED; - out: -+ if (error_vg) -+ release_vg(error_vg); - unlock_devices_file(cmd); - return ret; - } --- -2.39.1 - diff --git a/SOURCES/0005-lvmdbusd-Move-get_error_msg-to-utils.patch b/SOURCES/0005-lvmdbusd-Move-get_error_msg-to-utils.patch deleted file mode 100644 index a250689..0000000 --- a/SOURCES/0005-lvmdbusd-Move-get_error_msg-to-utils.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 4e34edd6e4e52328dd77b6a55aeadd9b0454c743 Mon Sep 17 00:00:00 2001 -From: Tony Asleson -Date: Tue, 29 Nov 2022 10:00:39 -0600 -Subject: [PATCH 2/3] lvmdbusd: Move get_error_msg to utils - -Moving this so we can re-use outside of lvm_shell_proxy. - -(cherry picked from commit 8f60c494515ddccb20e4afb804edb6b9599e65c0) ---- - daemons/lvmdbusd/lvm_shell_proxy.py.in | 23 +++-------------------- - daemons/lvmdbusd/utils.py | 17 +++++++++++++++++ - 2 files changed, 20 insertions(+), 20 deletions(-) - -diff --git a/daemons/lvmdbusd/lvm_shell_proxy.py.in b/daemons/lvmdbusd/lvm_shell_proxy.py.in -index ac6d51e65..37d73218b 100755 ---- a/daemons/lvmdbusd/lvm_shell_proxy.py.in -+++ b/daemons/lvmdbusd/lvm_shell_proxy.py.in -@@ -28,7 +28,7 @@ except ImportError: - - import lvmdbusd.cfg as cfg - from lvmdbusd.utils import log_debug, log_error, add_no_notify, make_non_block,\ -- read_decoded, extract_stack_trace, LvmBug -+ read_decoded, extract_stack_trace, LvmBug, get_error_msg - - SHELL_PROMPT = "lvm> " - -@@ -191,24 +191,7 @@ class LVMShellProxy(object): - def get_last_log(self): - self._write_cmd('lastlog\n') - report_json = self._read_response()[1] -- return LVMShellProxy.get_error_msg(report_json) -- -- @staticmethod -- def get_error_msg(report_json): -- # Get the error message from the returned JSON -- if 'log' in report_json: -- error_msg = "" -- # Walk the entire log array and build an error string -- for log_entry in report_json['log']: -- if log_entry['log_type'] == "error": -- if error_msg: -- error_msg += ', ' + log_entry['log_message'] -- else: -- error_msg = log_entry['log_message'] -- -- return error_msg -- -- return None -+ return get_error_msg(report_json) - - def call_lvm(self, argv, debug=False): - rc = 1 -@@ -245,7 +228,7 @@ class LVMShellProxy(object): - # report json too. - error_msg = self.get_last_log() - if error_msg is None: -- error_msg = LVMShellProxy.get_error_msg(report_json) -+ error_msg = get_error_msg(report_json) - if error_msg is None: - error_msg = 'No error reason provided! (missing "log" section)' - -diff --git a/daemons/lvmdbusd/utils.py b/daemons/lvmdbusd/utils.py -index 5aecb1fff..0b81591b2 100644 ---- a/daemons/lvmdbusd/utils.py -+++ b/daemons/lvmdbusd/utils.py -@@ -859,3 +859,20 @@ class LvmDebugData: - self._close_fd() - # In case lvm_complete doesn't get called. - self._remove_file() -+ -+ -+def get_error_msg(report_json): -+ # Get the error message from the returned JSON -+ if 'log' in report_json: -+ error_msg = "" -+ # Walk the entire log array and build an error string -+ for log_entry in report_json['log']: -+ if log_entry['log_type'] == "error": -+ if error_msg: -+ error_msg += ', ' + log_entry['log_message'] -+ else: -+ error_msg = log_entry['log_message'] -+ -+ return error_msg -+ -+ return None --- -2.39.1 - diff --git a/SOURCES/0005-pvck-improve-error-for-write-to-existing-file.patch b/SOURCES/0005-pvck-improve-error-for-write-to-existing-file.patch new file mode 100644 index 0000000..00440d6 --- /dev/null +++ b/SOURCES/0005-pvck-improve-error-for-write-to-existing-file.patch @@ -0,0 +1,31 @@ +From 0a9228807d0b3901be4ccf29311a955efba4877e Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Fri, 28 Apr 2023 13:31:39 -0500 +Subject: [PATCH 5/8] pvck: improve error for write to existing file + +(cherry picked from commit c4440b5b495a2d11ff541dd7e7791e2a83c83609) +--- + tools/pvck.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/tools/pvck.c b/tools/pvck.c +index 879810b76..0998caaf5 100644 +--- a/tools/pvck.c ++++ b/tools/pvck.c +@@ -1444,8 +1444,13 @@ static int _dump_metadata(struct cmd_context *cmd, const char *dump, struct sett + int bad = 0; + + if (arg_is_set(cmd, file_ARG)) { ++ struct stat sb; + if (!(tofile = arg_str_value(cmd, file_ARG, NULL))) + return 0; ++ if (!stat(tofile, &sb)) { ++ log_error("File already exists."); ++ return 0; ++ } + } + + if (set->mda_num) +-- +2.40.1 + diff --git a/SOURCES/0006-lvmdbusd-Add-command_log_selection-to-command-line.patch b/SOURCES/0006-lvmdbusd-Add-command_log_selection-to-command-line.patch deleted file mode 100644 index 6a41458..0000000 --- a/SOURCES/0006-lvmdbusd-Add-command_log_selection-to-command-line.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0441d340e752427d0d355a85e5e5e465e911a102 Mon Sep 17 00:00:00 2001 -From: Tony Asleson -Date: Tue, 29 Nov 2022 10:04:17 -0600 -Subject: [PATCH 3/3] lvmdbusd: Add command_log_selection to command line - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2145114 -(cherry picked from commit e63b0c7262f50ab43fcde1c50b6d880acab68407) ---- - daemons/lvmdbusd/cmdhandler.py | 33 +++++++++++++++++---------------- - 1 file changed, 17 insertions(+), 16 deletions(-) - -diff --git a/daemons/lvmdbusd/cmdhandler.py b/daemons/lvmdbusd/cmdhandler.py -index 0c7bd8528..9a76db4c9 100644 ---- a/daemons/lvmdbusd/cmdhandler.py -+++ b/daemons/lvmdbusd/cmdhandler.py -@@ -17,7 +17,7 @@ import os - - from lvmdbusd import cfg - from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify,\ -- make_non_block, read_decoded, extract_stack_trace, LvmBug, add_config_option -+ make_non_block, read_decoded, extract_stack_trace, LvmBug, add_config_option, get_error_msg - from lvmdbusd.lvm_shell_proxy import LVMShellProxy - - try: -@@ -121,6 +121,9 @@ def call_lvm(command, debug=False, line_cb=None, - command.insert(0, cfg.LVM_CMD) - command = add_no_notify(command) - -+ # Ensure we get an error message when we fork & exec the lvm command line -+ command = add_config_option(command, "--config", 'log/command_log_selection="log_context!=''"') -+ - process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True, - env=os.environ) - -@@ -167,7 +170,17 @@ def call_lvm(command, debug=False, line_cb=None, - if debug or (process.returncode != 0 and (process.returncode != 5 and "fullreport" in command)): - _debug_c(command, process.returncode, (stdout_text, stderr_text)) - -- return process.returncode, stdout_text, stderr_text -+ try: -+ report_json = json.loads(stdout_text) -+ except json.decoder.JSONDecodeError: -+ # Some lvm commands don't return json even though we are asking for it to do so. -+ return process.returncode, stdout_text, stderr_text -+ -+ error_msg = get_error_msg(report_json) -+ if error_msg: -+ stderr_text += error_msg -+ -+ return process.returncode, report_json, stderr_text - else: - if cfg.run.value == 0: - raise SystemExit -@@ -619,20 +632,8 @@ def lvm_full_report_json(): - rc, out, err = call(cmd) - # When we have an exported vg the exit code of lvs or fullreport will be 5 - if rc == 0 or rc == 5: -- # If the 'call' implementation is lvmshell, the out is a dictionary as lvmshell has to -- # parse the output to get the exit value. When doing fork & exec, out is a string -- # representing the JSON. TODO: Make this consistent between implementations. -- if cfg.SHELL_IN_USE: -- assert(type(out) == dict) -- return out -- else: -- try: -- return json.loads(out) -- except json.decoder.JSONDecodeError as joe: -- log_error("JSONDecodeError %s, \n JSON=\n%s\n" % -- (str(joe), out)) -- raise LvmBug("'fullreport' returned invalid JSON") -- -+ assert(type(out) == dict) -+ return out - raise LvmBug("'fullreport' exited with code '%d'" % rc) - - --- -2.39.1 - diff --git a/SOURCES/0006-lvreduce-make-_lvseg_get_stripes-handle-integrity-la.patch b/SOURCES/0006-lvreduce-make-_lvseg_get_stripes-handle-integrity-la.patch new file mode 100644 index 0000000..e8b8233 --- /dev/null +++ b/SOURCES/0006-lvreduce-make-_lvseg_get_stripes-handle-integrity-la.patch @@ -0,0 +1,87 @@ +From 7702262444a5af924d0fc94ff956663aab3505df Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Tue, 2 May 2023 16:12:23 -0500 +Subject: [PATCH 6/8] lvreduce: make _lvseg_get_stripes handle integrity layer + +lvreduce uses _lvseg_get_stripes() which was unable to get raid stripe +info with an integrity layer present. This caused lvreduce on a +raid+integrity LV to fail prematurely when checking stripe parameters. +An unhelpful error message about stripe size would be printed. + +(cherry picked from commit 368381fd4022dc99ffe551b30ed75c3ddbc5c5c8) +--- + lib/metadata/lv_manip.c | 35 ++++++++++++++++++++++++++--------- + 1 file changed, 26 insertions(+), 9 deletions(-) + +diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c +index 2a4e0e88a..add9512ff 100644 +--- a/lib/metadata/lv_manip.c ++++ b/lib/metadata/lv_manip.c +@@ -5144,22 +5144,39 @@ int lv_extend_policy_calculate_percent(struct logical_volume *lv, + + static uint32_t _lvseg_get_stripes(struct lv_segment *seg, uint32_t *stripesize) + { +- uint32_t s; +- struct lv_segment *seg_mirr; ++ uint32_t s, a; ++ struct lv_segment *seg_get, *seg_image, *seg_iorig; ++ struct logical_volume *lv_image, *lv_iorig; + + /* If segment mirrored, check if images are striped */ +- if (seg_is_mirrored(seg)) ++ if (seg_is_mirrored(seg)) { + for (s = 0; s < seg->area_count; s++) { + if (seg_type(seg, s) != AREA_LV) + continue; +- seg_mirr = first_seg(seg_lv(seg, s)); + +- if (seg_is_striped(seg_mirr)) { +- seg = seg_mirr; ++ lv_image = seg_lv(seg, s); ++ seg_image = first_seg(lv_image); ++ seg_get = NULL; ++ ++ if (seg_is_integrity(seg_image)) { ++ /* Get stripe values from the iorig layer. */ ++ for (a = 0; a < seg_image->area_count; a++) { ++ lv_iorig = seg_lv(seg_image, a); ++ seg_iorig = first_seg(lv_iorig); ++ seg_get = seg_iorig; ++ break; ++ } ++ } else { ++ /* Get stripe values from the image layer. */ ++ seg_get = seg_image; ++ } ++ ++ if (seg_get && seg_is_striped(seg_get)) { ++ seg = seg_get; + break; + } + } +- ++ } + + if (seg_is_striped(seg)) { + *stripesize = seg->stripe_size; +@@ -5168,7 +5185,7 @@ static uint32_t _lvseg_get_stripes(struct lv_segment *seg, uint32_t *stripesize) + + if (seg_is_raid(seg)) { + *stripesize = seg->stripe_size; +- return _raid_stripes_count(seg); ++ return _raid_stripes_count(seg); + } + + *stripesize = 0; +@@ -5593,7 +5610,7 @@ static int _lvresize_adjust_extents(struct logical_volume *lv, + seg_size /= seg_mirrors; + lp->extents = logical_extents_used + seg_size; + break; +- } ++ } + } else if (new_extents <= logical_extents_used + seg_logical_extents) { + seg_size = new_extents - logical_extents_used; + lp->extents = new_extents; +-- +2.40.1 + diff --git a/SOURCES/0007-tests-lvresize-fs-crypt-using-helper-only-for-crypt-.patch b/SOURCES/0007-tests-lvresize-fs-crypt-using-helper-only-for-crypt-.patch deleted file mode 100644 index 2a97a50..0000000 --- a/SOURCES/0007-tests-lvresize-fs-crypt-using-helper-only-for-crypt-.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 380e3855fbc661eed490665cf1e3d05e985da189 Mon Sep 17 00:00:00 2001 -From: David Teigland -Date: Tue, 3 Jan 2023 14:35:26 -0600 -Subject: [PATCH 1/4] tests: lvresize-fs-crypt using helper only for crypt dev - -(cherry picked from commit 2580f007f0aaa3bf22c43295caa2c60c6142494f) ---- - test/shell/lvresize-fs-crypt.sh | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/test/shell/lvresize-fs-crypt.sh b/test/shell/lvresize-fs-crypt.sh -index e7b8b9426..61a6de022 100644 ---- a/test/shell/lvresize-fs-crypt.sh -+++ b/test/shell/lvresize-fs-crypt.sh -@@ -135,6 +135,31 @@ cryptsetup close $cr - lvchange -an $vg/$lv - lvremove $vg/$lv - -+# lvresize uses helper only for crypt dev resize -+# because the fs was resized separately beforehand -+lvcreate -n $lv -L 456M $vg -+echo 93R4P4pIqAH8 | cryptsetup luksFormat -i1 --type luks1 "$DM_DEV_DIR/$vg/$lv" -+echo 93R4P4pIqAH8 | cryptsetup luksOpen "$DM_DEV_DIR/$vg/$lv" $cr -+mkfs.ext4 /dev/mapper/$cr -+mount /dev/mapper/$cr "$mount_dir" -+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=100 conv=fdatasync -+df --output=size "$mount_dir" |tee df1 -+# resize only the fs (to 256M), not the crypt dev or LV -+umount "$mount_dir" -+resize2fs /dev/mapper/$cr 262144k -+mount /dev/mapper/$cr "$mount_dir" -+# this lvresize will not resize the fs (which is already reduced -+# to smaller than the requested LV size), but lvresize will use -+# the helper to resize the crypt dev before resizing the LV. -+lvresize -L-100M $vg/$lv -+check lv_field $vg/$lv lv_size "356.00m" -+df --output=size "$mount_dir" |tee df2 -+not diff df1 df2 -+umount "$mount_dir" -+cryptsetup close $cr -+lvchange -an $vg/$lv -+lvremove $vg/$lv -+ - # test with LUKS2? - - vgremove -ff $vg --- -2.39.1 - diff --git a/SOURCES/0008-lvresize-only-resize-crypt-when-fs-resize-is-enabled.patch b/SOURCES/0008-lvresize-only-resize-crypt-when-fs-resize-is-enabled.patch deleted file mode 100644 index 36f9669..0000000 --- a/SOURCES/0008-lvresize-only-resize-crypt-when-fs-resize-is-enabled.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 7e0c2e1581225a916269edc8f04fb10e4ef5e952 Mon Sep 17 00:00:00 2001 -From: David Teigland -Date: Thu, 19 Jan 2023 11:36:51 -0600 -Subject: [PATCH 2/4] lvresize: only resize crypt when fs resize is enabled - -There were a couple of cases where lvresize, without --fs resize, -was resizing the crypt layer above the LV. Resizing the crypt -layer should only be done when fs resizing is enabled (even if the -fs is already small enough due to being independently reduced.) - -Also, check the size of the crypt device to see if it's already -been reduced independently, and skip the cryptsetup resize if -it's not needed. - -(cherry picked from commit 3bb55765286dc8e4f0000957d85a6b8ee2752852) ---- - lib/device/filesystem.c | 12 ++++++++++++ - lib/device/filesystem.h | 1 + - lib/metadata/lv_manip.c | 18 +++++++++++++++++- - test/shell/lvresize-fs-crypt.sh | 7 ++++++- - 4 files changed, 36 insertions(+), 2 deletions(-) - -diff --git a/lib/device/filesystem.c b/lib/device/filesystem.c -index bdc230175..b4c43a626 100644 ---- a/lib/device/filesystem.c -+++ b/lib/device/filesystem.c -@@ -106,6 +106,7 @@ int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, - struct fs_info info; - FILE *fme = NULL; - struct mntent *me; -+ int fd; - int ret; - - if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", lv->vg->cmd->dev_dir, -@@ -151,6 +152,17 @@ int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, - log_print("File system found on crypt device %s on LV %s.", - crypt_path, display_lvname(lv)); - -+ if ((fd = open(crypt_path, O_RDONLY)) < 0) { -+ log_error("Failed to open crypt path %s", crypt_path); -+ return 0; -+ } -+ if (ioctl(fd, BLKGETSIZE64, &info.crypt_dev_size_bytes) < 0) { -+ log_error("Failed to get crypt device size %s", crypt_path); -+ close(fd); -+ return 0; -+ } -+ close(fd); -+ - if (!fs_get_blkid(crypt_path, &info)) { - log_error("No file system info from blkid for dm-crypt device %s on LV %s.", - crypt_path, display_lvname(lv)); -diff --git a/lib/device/filesystem.h b/lib/device/filesystem.h -index 7a34d2ae0..fd1af0416 100644 ---- a/lib/device/filesystem.h -+++ b/lib/device/filesystem.h -@@ -25,6 +25,7 @@ struct fs_info { - uint64_t fs_last_byte; /* last byte on the device used by the fs */ - uint32_t crypt_offset_bytes; /* offset in bytes of crypt data on LV */ - dev_t crypt_devt; /* dm-crypt device between the LV and FS */ -+ uint64_t crypt_dev_size_bytes; - - unsigned nofs:1; - unsigned unmounted:1; -diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c -index f8eae0447..a2e9db2c9 100644 ---- a/lib/metadata/lv_manip.c -+++ b/lib/metadata/lv_manip.c -@@ -6397,7 +6397,23 @@ static int _fs_reduce(struct cmd_context *cmd, struct logical_volume *lv, - * but the crypt dev over the LV should be shrunk to correspond with - * the LV size, so that the FS does not see an incorrect device size. - */ -- if (!fsinfo.needs_reduce && fsinfo.needs_crypt && !test_mode()) { -+ if (!fsinfo.needs_reduce && fsinfo.needs_crypt) { -+ /* Check if the crypt device is already sufficiently reduced. */ -+ if (fsinfo.crypt_dev_size_bytes <= newsize_bytes_fs) { -+ log_print("crypt device is already reduced to %llu bytes.", -+ (unsigned long long)fsinfo.crypt_dev_size_bytes); -+ ret = 1; -+ goto out; -+ } -+ if (!strcmp(lp->fsopt, "checksize")) { -+ log_error("crypt reduce is required (see --resizefs or cryptsetup resize.)"); -+ ret = 0; -+ goto out; -+ } -+ if (test_mode()) { -+ ret = 1; -+ goto_out; -+ } - ret = crypt_resize_script(cmd, lv, &fsinfo, newsize_bytes_fs); - goto out; - } -diff --git a/test/shell/lvresize-fs-crypt.sh b/test/shell/lvresize-fs-crypt.sh -index 61a6de022..4bef771dc 100644 ---- a/test/shell/lvresize-fs-crypt.sh -+++ b/test/shell/lvresize-fs-crypt.sh -@@ -151,7 +151,12 @@ mount /dev/mapper/$cr "$mount_dir" - # this lvresize will not resize the fs (which is already reduced - # to smaller than the requested LV size), but lvresize will use - # the helper to resize the crypt dev before resizing the LV. --lvresize -L-100M $vg/$lv -+# Using --fs resize is required to allow lvresize to look above -+# the lv at crypt&fs layers for potential resizing. Without -+# --fs resize, lvresize fails because it sees that crypt resize -+# is needed and --fs resize is needed to enable that. -+not lvresize -L-100 $vg/$lv -+lvresize -L-100M --fs resize $vg/$lv - check lv_field $vg/$lv lv_size "356.00m" - df --output=size "$mount_dir" |tee df2 - not diff df1 df2 --- -2.39.1 - diff --git a/SOURCES/0008-tests-integrity-snapshots-now-work-on-raid-integrity.patch b/SOURCES/0008-tests-integrity-snapshots-now-work-on-raid-integrity.patch new file mode 100644 index 0000000..923ba3a --- /dev/null +++ b/SOURCES/0008-tests-integrity-snapshots-now-work-on-raid-integrity.patch @@ -0,0 +1,37 @@ +From 41d16e42f88997fda991f86d598bffc19fcd937f Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 17 May 2023 11:10:45 -0500 +Subject: [PATCH 8/8] tests: integrity: snapshots now work on raid+integrity + +(cherry picked from commit 3a757047560d75a28d7e4c7d9a5253a72d786544) +--- + test/shell/integrity.sh | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/test/shell/integrity.sh b/test/shell/integrity.sh +index a7dd5b565..d1683a08e 100644 +--- a/test/shell/integrity.sh ++++ b/test/shell/integrity.sh +@@ -626,7 +626,6 @@ not lvconvert --splitmirrors 1 -n tmp -y $vg/$lv1 + not lvconvert --splitmirrors 1 --trackchanges -y $vg/$lv1 + not lvchange --syncaction repair $vg/$lv1 + not lvreduce -L4M $vg/$lv1 +-not lvcreate -s -n snap -L4M $vg/$lv1 + not pvmove -n $vg/$lv1 "$dev1" + not pvmove "$dev1" + _verify_data_on_mnt +@@ -810,11 +809,4 @@ not lvconvert --raidintegrity y $vg/${lv2}_cpool_cdata + not lvconvert --raidintegrity y $vg/${lv2}_cpool_cmeta + lvremove -y $vg/$lv1 + +-# cannot add integrity to raid that has a snapshot +- +-lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +-lvcreate -s -n $lv2 -l 8 $vg/$lv1 +-not lvconvert --raidintegrity y $vg/$lv1 +-lvremove -y $vg/$lv1 +- + vgremove -ff $vg +-- +2.40.1 + diff --git a/SOURCES/0009-lvresize-fail-early-if-mounted-LV-was-renamed.patch b/SOURCES/0009-lvresize-fail-early-if-mounted-LV-was-renamed.patch deleted file mode 100644 index 3a87788..0000000 --- a/SOURCES/0009-lvresize-fail-early-if-mounted-LV-was-renamed.patch +++ /dev/null @@ -1,188 +0,0 @@ -From fba3614c3ed596b99d8adf2fe6c60886db10b2c0 Mon Sep 17 00:00:00 2001 -From: David Teigland -Date: Thu, 26 Jan 2023 14:00:00 -0600 -Subject: [PATCH 3/4] lvresize: fail early if mounted LV was renamed - -If a mounted LV is renamed, then fs resizing utilities will fail, -so detect this condition and fail the command before any changes -are made. - -(cherry picked from commit 5374a44c57127cdd832a675545c1d2bbf0b3751a) ---- - lib/device/filesystem.c | 110 ++++++++++++++++++++++++++++++++++++++ - lib/device/filesystem.h | 2 + - lib/metadata/lv_manip.c | 3 ++ - test/shell/lvresize-fs.sh | 11 ++++ - 4 files changed, 126 insertions(+) - -diff --git a/lib/device/filesystem.c b/lib/device/filesystem.c -index b4c43a626..db507bdda 100644 ---- a/lib/device/filesystem.c -+++ b/lib/device/filesystem.c -@@ -214,6 +214,116 @@ int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, - return ret; - } - -+int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *lv, char *lv_path, char *fstype) -+{ -+ FILE *fp; -+ char proc_line[PATH_MAX]; -+ char proc_fstype[FSTYPE_MAX]; -+ char proc_devpath[1024]; -+ char proc_mntpath[1024]; -+ char lv_mapper_path[1024]; -+ char mntent_mount_dir[1024]; -+ char *dm_name; -+ struct stat st_lv; -+ struct stat stme; -+ FILE *fme = NULL; -+ struct mntent *me; -+ int renamed = 0; -+ int found_dir = 0; -+ int found_dev = 0; -+ int dev_match, dir_match; -+ -+ if (stat(lv_path, &st_lv) < 0) { -+ log_error("Failed to get LV path %s", lv_path); -+ return 0; -+ } -+ -+ /* -+ * If LVs have been renamed while their file systems were mounted, then -+ * inconsistencies appear in the device path and mount point info -+ * provided by getmntent and /proc/mounts. If there's any -+ * inconsistency or duplication of info for the LV name or the mount -+ * point, then give up and don't try fs resize which is likely to fail -+ * due to kernel problems where mounts reference old device names -+ * causing fs resizing tools to fail. -+ */ -+ -+ if (!(fme = setmntent("/etc/mtab", "r"))) -+ return_0; -+ -+ while ((me = getmntent(fme))) { -+ if (strcmp(me->mnt_type, fstype)) -+ continue; -+ if (me->mnt_dir[0] != '/') -+ continue; -+ if (me->mnt_fsname[0] != '/') -+ continue; -+ if (stat(me->mnt_dir, &stme) < 0) -+ continue; -+ if (stme.st_dev != st_lv.st_rdev) -+ continue; -+ strncpy(mntent_mount_dir, me->mnt_dir, PATH_MAX-1); -+ } -+ endmntent(fme); -+ -+ if (!(dm_name = dm_build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL))) -+ return_0; -+ -+ if ((dm_snprintf(lv_mapper_path, 1024, "%s/%s", dm_dir(), dm_name) < 0)) -+ return_0; -+ -+ if (!(fp = fopen("/proc/mounts", "r"))) -+ return_0; -+ -+ while (fgets(proc_line, sizeof(proc_line), fp)) { -+ if (proc_line[0] != '/') -+ continue; -+ if (sscanf(proc_line, "%s %s %s", proc_devpath, proc_mntpath, proc_fstype) != 3) -+ continue; -+ if (strcmp(fstype, proc_fstype)) -+ continue; -+ -+ dir_match = !strcmp(mntent_mount_dir, proc_mntpath); -+ dev_match = !strcmp(lv_mapper_path, proc_devpath); -+ -+ if (dir_match) -+ found_dir++; -+ if (dev_match) -+ found_dev++; -+ -+ if (dir_match != dev_match) { -+ log_error("LV %s mounted at %s may have been renamed (from %s).", -+ lv_mapper_path, proc_mntpath, proc_devpath); -+ renamed = 1; -+ } -+ } -+ -+ if (fclose(fp)) -+ stack; -+ -+ /* -+ * Don't try resizing if: -+ * - different device names apppear for the mount point -+ * (LVs probably renamed while mounted), or -+ * - the mount point for the LV appears multiple times, or -+ * - the LV device is listed for multiple mounts. -+ */ -+ if (renamed) { -+ log_error("File system resizing not supported: fs utilities do not support renamed devices."); -+ return 1; -+ } -+ /* These two are likely detected as renamed, but include checks in case. */ -+ if (found_dir > 1) { -+ log_error("File system resizing not supported: %s appears more than once in /proc/mounts.", mntent_mount_dir); -+ return 1; -+ } -+ if (found_dev > 1) { -+ log_error("File system resizing not supported: %s appears more than once in /proc/mounts.", lv_mapper_path); -+ return 1; -+ } -+ return 0; -+} -+ - #define FS_CMD_MAX_ARGS 16 - - int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, -diff --git a/lib/device/filesystem.h b/lib/device/filesystem.h -index fd1af0416..77eac34d0 100644 ---- a/lib/device/filesystem.h -+++ b/lib/device/filesystem.h -@@ -48,4 +48,6 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct - uint64_t newsize_bytes, char *fsmode); - int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, - uint64_t newsize_bytes_fs); -+ -+int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *lv, char *lv_path, char *fstype); - #endif -diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c -index a2e9db2c9..25e16d41d 100644 ---- a/lib/metadata/lv_manip.c -+++ b/lib/metadata/lv_manip.c -@@ -6928,6 +6928,9 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv, - log_error("File system not found for --resizefs or --fs options."); - goto out; - } -+ /* FS utils will fail if LVs were renamed while mounted. */ -+ if (fs_mount_state_is_misnamed(cmd, lv_top, lv_path, fstype)) -+ goto_out; - } - - /* -diff --git a/test/shell/lvresize-fs.sh b/test/shell/lvresize-fs.sh -index 0be6911a0..f437652d6 100644 ---- a/test/shell/lvresize-fs.sh -+++ b/test/shell/lvresize-fs.sh -@@ -262,6 +262,17 @@ umount "$mount_dir" - lvchange -an $vg/$lv - lvremove $vg/$lv - -+# lvextend|lvreduce, ext4, active, mounted, --fs resize, renamed LV -+lvcreate -n $lv -L 256M $vg -+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" -+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" -+lvrename $vg/$lv $vg/$lv2 -+not lvextend --fs resize -L+32M $vg/$lv2 -+not lvreduce --fs resize -L-32M $vg/$lv2 -+umount "$mount_dir" -+lvchange -an $vg/$lv2 -+lvremove $vg/$lv2 -+ - - # - # lvextend, xfs --- -2.39.1 - diff --git a/SOURCES/0009-lvresize-fix-multiple-mounts.patch b/SOURCES/0009-lvresize-fix-multiple-mounts.patch new file mode 100644 index 0000000..f0e672c --- /dev/null +++ b/SOURCES/0009-lvresize-fix-multiple-mounts.patch @@ -0,0 +1,102 @@ +From e96cdaca1d2fec1d225ff09ef81f66edd7df7513 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Fri, 16 Jun 2023 12:06:40 -0500 +Subject: [PATCH 09/14] lvresize: fix multiple mounts + +which was mistaken as a mounted LV that had been renamed. + +(cherry picked from commit 7c3eca833ff7878d6d32198ed76380c91fdc15fc) +--- + lib/device/filesystem.c | 47 +++++++++++++++++++++-------------------- + 1 file changed, 24 insertions(+), 23 deletions(-) + +diff --git a/lib/device/filesystem.c b/lib/device/filesystem.c +index 2163276ed..bca29747a 100644 +--- a/lib/device/filesystem.c ++++ b/lib/device/filesystem.c +@@ -243,8 +243,6 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l + FILE *fme = NULL; + struct mntent *me; + int renamed = 0; +- int found_dir = 0; +- int found_dev = 0; + int dev_match, dir_match; + + if (stat(lv_path, &st_lv) < 0) { +@@ -281,6 +279,9 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l + } + endmntent(fme); + ++ if (mtab_mntpath[0]) ++ log_debug("%s mtab mntpath %s", display_lvname(lv), mtab_mntpath); ++ + /* + * In mtab dir path, replace each ascii space character with the + * four characters \040 which is how /proc/mounts represents spaces. +@@ -319,15 +320,31 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l + if (strcmp(fstype, proc_fstype)) + continue; + ++ /* ++ * When an LV is mounted on two dirs, it appears in /proc/mounts twice as ++ * /dev/mapper/vg-lvol0 on /foo type xfs ... ++ * /dev/mapper/vg-lvol0 on /bar type xfs ... ++ * All entries match dm_devpath, one entry matches mntpath, ++ * and other entries don't match mntpath. ++ * ++ * When an LV is mounted on one dir, and is renamed from lvol0 to lvol1, ++ * it appears in /proc/mounts once as ++ * /dev/mapper/vg-lvol0 on /foo type xfs ... ++ */ ++ + dir_match = !strcmp(mtab_mntpath, proc_mntpath); + dev_match = !strcmp(dm_devpath, proc_devpath); + +- if (dir_match) +- found_dir++; +- if (dev_match) +- found_dev++; ++ if (!dir_match && !dev_match) ++ continue; ++ ++ if (dev_match && !dir_match) { ++ log_debug("LV %s mounted at %s also mounted at %s.", ++ dm_devpath, mtab_mntpath, proc_mntpath); ++ continue; ++ } + +- if (dir_match != dev_match) { ++ if (!dev_match && dir_match) { + log_error("LV %s mounted at %s may have been renamed (from %s).", + dm_devpath, proc_mntpath, proc_devpath); + renamed = 1; +@@ -337,26 +354,10 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l + if (fclose(fp)) + stack; + +- /* +- * Don't try resizing if: +- * - different device names apppear for the mount point +- * (LVs probably renamed while mounted), or +- * - the mount point for the LV appears multiple times, or +- * - the LV device is listed for multiple mounts. +- */ + if (renamed) { + log_error("File system resizing not supported: fs utilities do not support renamed devices."); + return 1; + } +- /* These two are likely detected as renamed, but include checks in case. */ +- if (found_dir > 1) { +- log_error("File system resizing not supported: %s appears more than once in /proc/mounts.", mtab_mntpath); +- return 1; +- } +- if (found_dev > 1) { +- log_error("File system resizing not supported: %s appears more than once in /proc/mounts.", dm_devpath); +- return 1; +- } + return 0; + } + +-- +2.41.0 + diff --git a/SOURCES/0010-device_id-ignore-trailing-underscores-in-t10-wwid-fr.patch b/SOURCES/0010-device_id-ignore-trailing-underscores-in-t10-wwid-fr.patch new file mode 100644 index 0000000..d7ba1cb --- /dev/null +++ b/SOURCES/0010-device_id-ignore-trailing-underscores-in-t10-wwid-fr.patch @@ -0,0 +1,247 @@ +From 9e35daea0212e12ea556c04830a91db08a7f3505 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Fri, 19 May 2023 12:52:48 -0500 +Subject: [PATCH 10/14] device_id: ignore trailing underscores in t10 wwid from + devices file + +In previous lvm versions, trailing spaces at the end of a t10 wwid would +be replaced with underscores, so the IDNAME string in system.devices +would look something like "t10.123_". Current versions of lvm ignore +trailing spaces in a t10 wwid, so the IDNAME string used would be +"t10.123". The different values would cause lvm to not recognize a +device in system.devices with the trailing _. Fix this by ignoring +trailing underscores in the IDNAME string from system.devices. + +(cherry picked from commit 4cdb178968b44125c41dee6dd28997283c0afefa) +--- + lib/device/device_id.c | 46 ++++++++++-- + test/shell/devicesfile-vpd-ids.sh | 113 ++++++++++++++++++++++++++++++ + 2 files changed, 152 insertions(+), 7 deletions(-) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 79da12884..7db6c9b86 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -1728,7 +1728,8 @@ static int _match_dm_devnames(struct cmd_context *cmd, struct device *dev, + return 0; + } + +-static void _reduce_underscores(char *in, int in_len, char *out, int out_size) ++/* More than one _ in a row is replaced with one _ */ ++static void _reduce_repeating_underscores(char *in, int in_len, char *out, int out_size) + { + int us = 0, i, j = 0; + +@@ -1750,6 +1751,17 @@ static void _reduce_underscores(char *in, int in_len, char *out, int out_size) + } + } + ++/* Remove any _ at the end of the string. */ ++static void _remove_trailing_underscores(char *buf) ++{ ++ char *end; ++ ++ end = buf + strlen(buf) - 1; ++ while ((end > buf) && (*end == '_')) ++ end--; ++ end[1] = '\0'; ++} ++ + /* + * du is a devices file entry. dev is any device on the system. + * check if du is for dev by comparing the device's ids to du->idname. +@@ -1764,6 +1776,7 @@ static void _reduce_underscores(char *in, int in_len, char *out, int out_size) + static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct device *dev) + { + char du_t10[DEV_WWID_SIZE] = { 0 }; ++ char id_t10[DEV_WWID_SIZE]; + struct dev_id *id; + const char *idname; + int part; +@@ -1818,10 +1831,17 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + * for IDNAME were saved in the past with each space replaced + * by one _. Now we convert multiple spaces to a single _. + * So, convert a df entry with the old style to the new shorter +- * style to compare. ++ * style to compare. Also, in past versions, trailing spaces ++ * in the wwid would be replaced by _, but now trailing spaces ++ * are ignored. This means devices file entries created by ++ * past versions may have _ at the end of the IDNAME string. ++ * So, exclude trailing underscores when comparing a t10 wwid ++ * from a device with a t10 wwid in the devices file. + */ +- if (du->idtype == DEV_ID_TYPE_SYS_WWID && !strncmp(du->idname, "t10", 3) && strstr(du->idname, "__")) +- _reduce_underscores(du->idname, strlen(du->idname), du_t10, sizeof(du_t10) - 1); ++ if (du->idtype == DEV_ID_TYPE_SYS_WWID && !strncmp(du->idname, "t10", 3) && strchr(du->idname, '_')) { ++ _reduce_repeating_underscores(du->idname, strlen(du->idname), du_t10, sizeof(du_t10) - 1); ++ _remove_trailing_underscores(du_t10); ++ } + + /* + * Try to match du with ids that have already been read for the dev +@@ -1829,6 +1849,20 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + */ + dm_list_iterate_items(id, &dev->ids) { + if (id->idtype == du->idtype) { ++ ++ /* ++ * For t10 wwids, remove actual trailing underscores from the dev wwid ++ * (in id->idname), because all trailing underscores were removed from ++ * the du->idname read from the devices file. i.e. no trailing _ are ++ * used in t10 wwid comparisons. ++ */ ++ if ((id->idtype == DEV_ID_TYPE_SYS_WWID) && ++ id->idname && !strncmp(id->idname, "t10", 3) && du_t10[0]) { ++ memset(id_t10, 0, sizeof(id_t10)); ++ strncpy(id_t10, id->idname, DEV_WWID_SIZE-1); ++ _remove_trailing_underscores(id_t10); ++ } ++ + if ((id->idtype == DEV_ID_TYPE_DEVNAME) && _match_dm_devnames(cmd, dev, id, du)) { + /* dm devs can have differing names that we know still match */ + du->dev = dev; +@@ -1846,9 +1880,7 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + idtype_to_str(du->idtype), du->idname, dev_name(dev)); + return 1; + +- } else if ((id->idtype == DEV_ID_TYPE_SYS_WWID) && id->idname && +- !strncmp(id->idname, "t10", 3) && du_t10[0] && !strcmp(id->idname, du_t10)) { +- /* Compare the shorter form du t10 wwid to the dev t10 wwid. */ ++ } else if ((id->idtype == DEV_ID_TYPE_SYS_WWID) && du_t10[0] && id_t10[0] && !strcmp(id_t10, du_t10)) { + du->dev = dev; + dev->id = id; + dev->flags |= DEV_MATCHED_USE_ID; +diff --git a/test/shell/devicesfile-vpd-ids.sh b/test/shell/devicesfile-vpd-ids.sh +index b2042fb9a..52805737b 100644 +--- a/test/shell/devicesfile-vpd-ids.sh ++++ b/test/shell/devicesfile-vpd-ids.sh +@@ -80,6 +80,7 @@ echo $DEV1 + DFDIR="$LVM_SYSTEM_DIR/devices" + mkdir -p "$DFDIR" || true + DF="$DFDIR/system.devices" ++DFTMP="$DFDIR/system.devices_tmp" + touch $DF + + pvcreate "$DEV1" +@@ -243,6 +244,118 @@ vgremove $vg + rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid + cleanup_sysfs + ++# Test t10 wwid with trailing space and line feed at the end ++rm $DF ++aux wipefs_a "$DEV1" ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/ ++echo -n "7431 302e 4154 4120 2020 2020 5642 4f58 \ ++2048 4152 4444 4953 4b20 2020 2020 2020 \ ++2020 2020 2020 2020 2020 2020 2020 2020 \ ++2020 2020 5642 3963 3130 6433 3138 2d31 \ ++3838 6439 6562 6320 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++lvmdevices --adddev "$DEV1" ++cat $DF ++vgcreate $vg "$DEV1" ++lvcreate -l1 -an $vg ++cat $DF ++# check wwid string in metadata output ++pvs -o+deviceidtype,deviceid "$DEV1" |tee out ++grep sys_wwid out ++# check wwid string in system.devices ++grep sys_wwid $DF ++lvremove -y $vg ++vgremove $vg ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++cleanup_sysfs ++ ++# Test t10 wwid with trailing space at the end that was created by 9.0/9.1 ++rm $DF ++aux wipefs_a "$DEV1" ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/ ++echo -n "7431 302e 4154 4120 2020 2020 5642 4f58 \ ++2048 4152 4444 4953 4b20 2020 2020 2020 \ ++2020 2020 2020 2020 2020 2020 2020 2020 \ ++2020 2020 5642 3963 3130 6433 3138 2d31 \ ++3838 6439 6562 6320 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++lvmdevices --adddev "$DEV1" ++cat $DF ++vgcreate $vg "$DEV1" ++PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` ++T10_WWID_RHEL91="t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9ebc_" ++lvcreate -l1 -an $vg ++cat $DF ++# check wwid string in metadata output ++pvs -o+deviceidtype,deviceid "$DEV1" |tee out ++grep sys_wwid out ++# check wwid string in system.devices ++grep sys_wwid $DF ++# Replace IDNAME with the IDNAME that 9.0/9.1 created from this wwid ++cat $DF | grep -v IDNAME > $DFTMP ++cat $DFTMP ++echo "IDTYPE=sys_wwid IDNAME=t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9ebc_ DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP ++cp $DFTMP $DF ++cat $DF ++vgs ++pvs ++pvs -o+deviceidtype,deviceid "$DEV1" ++# Removing the trailing _ which should then work ++cat $DF | grep -v IDNAME > $DFTMP ++cat $DFTMP ++echo "IDTYPE=sys_wwid IDNAME=t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9ebc DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP ++cp $DFTMP $DF ++cat $DF ++vgs ++pvs ++pvs -o+deviceidtype,deviceid "$DEV1" ++lvremove -y $vg ++vgremove $vg ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++cleanup_sysfs ++ ++# test a t10 wwid that has actual trailing underscore which ++# is followed by a trailing space. ++rm $DF ++aux wipefs_a "$DEV1" ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/ ++echo -n "7431 302e 4154 4120 2020 2020 5642 4f58 \ ++2048 4152 4444 4953 4b20 2020 2020 2020 \ ++2020 2020 2020 2020 2020 2020 2020 2020 \ ++2020 2020 5642 3963 3130 6433 3138 2d31 \ ++3838 6439 6562 5f20 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++# The wwid has an actual underscore char (5f) followed by a space char (20) ++# 9.1 converts the trailing space to an underscore ++T10_WWID_RHEL91="t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9eb__" ++# 9.2 ignores the trailing space ++T10_WWID_RHEL92="t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9eb_" ++lvmdevices --adddev "$DEV1" ++cat $DF ++vgcreate $vg "$DEV1" ++PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` ++lvcreate -l1 -an $vg ++cat $DF ++# check wwid string in metadata output ++pvs -o+deviceidtype,deviceid "$DEV1" |tee out ++grep sys_wwid out ++# check wwid string in system.devices ++grep sys_wwid $DF ++# Replace IDNAME with the IDNAME that 9.0/9.1 created from this wwid ++cat $DF | grep -v IDNAME > $DFTMP ++cat $DFTMP ++echo "IDTYPE=sys_wwid IDNAME=${T10_WWID_RHEL91} DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP ++cp $DFTMP $DF ++cat $DF ++vgs ++pvs ++pvs -o+deviceidtype,deviceid "$DEV1" ++lvremove -y $vg ++vgremove $vg ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++cleanup_sysfs ++ ++ + # TODO: lvmdevices --adddev --deviceidtype --deviceid + # This would let the user specify the second naa wwid. + +-- +2.41.0 + diff --git a/SOURCES/0010-udev-import-previous-results-of-blkid-when-in-suspen.patch b/SOURCES/0010-udev-import-previous-results-of-blkid-when-in-suspen.patch deleted file mode 100644 index 78c3f72..0000000 --- a/SOURCES/0010-udev-import-previous-results-of-blkid-when-in-suspen.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 285c766877b54b24234f84c313bb5806c0dcfa21 Mon Sep 17 00:00:00 2001 -From: Yu Watanabe -Date: Thu, 2 Feb 2023 00:28:12 +0900 -Subject: [PATCH 4/4] udev: import previous results of blkid when in suspended - state - -Follow-up for e10f67e91728f1e576803df884049ecbd92874d0. - -The commit e10f67e91728f1e576803df884049ecbd92874d0 tries to keep device -node symlinks even if the device is in the suspended state. However, -necessary properties that may previously obtained by the blkid command -were not imported at least in the .rules file. So, unless ID_FS_xyz -properties are imported by another earlier .rules file, the device node -symlinks are still lost when event is processed in the suspended state. - -Let's explicitly import the necessary properties. - -RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=2158628 -GHPR: https://github.com/lvmteam/lvm2/pull/105 -(cherry picked from commit 94f77a4d8d9737fca05fb4e451678ec440c68670) ---- - WHATS_NEW_DM | 4 ++++ - udev/13-dm-disk.rules.in | 14 ++++++++++++-- - 2 files changed, 16 insertions(+), 2 deletions(-) - -diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM -index f676ff7e1..c129c7f8a 100644 ---- a/WHATS_NEW_DM -+++ b/WHATS_NEW_DM -@@ -1,3 +1,7 @@ -+Version 1.02.191 - -+===================================== -+ Import previous ID_FS_* udev records in 13-dm-disk.rules for suspended DM dev. -+ - Version 1.02.187 - 10th November 2022 - ===================================== - Add DM_REPORT_GROUP_JSON_STD for more JSON standard compliant output format. -diff --git a/udev/13-dm-disk.rules.in b/udev/13-dm-disk.rules.in -index 5cc08121e..dca00bc01 100644 ---- a/udev/13-dm-disk.rules.in -+++ b/udev/13-dm-disk.rules.in -@@ -17,12 +17,22 @@ ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}=="1", GOTO="dm_end" - SYMLINK+="disk/by-id/dm-name-$env{DM_NAME}" - ENV{DM_UUID}=="?*", SYMLINK+="disk/by-id/dm-uuid-$env{DM_UUID}" - --ENV{DM_SUSPENDED}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_link" --ENV{DM_NOSCAN}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_link" -+ENV{DM_SUSPENDED}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_import" -+ENV{DM_NOSCAN}=="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", GOTO="dm_import" - ENV{DM_SUSPENDED}=="1", GOTO="dm_end" - ENV{DM_NOSCAN}=="1", GOTO="dm_watch" - - (BLKID_RULE) -+GOTO="dm_link" -+ -+LABEL="dm_import" -+IMPORT{db}="ID_FS_USAGE" -+IMPORT{db}="ID_FS_UUID_ENC" -+IMPORT{db}="ID_FS_LABEL_ENC" -+IMPORT{db}="ID_PART_ENTRY_NAME" -+IMPORT{db}="ID_PART_ENTRY_UUID" -+IMPORT{db}="ID_PART_ENTRY_SCHEME" -+IMPORT{db}="ID_PART_GPT_AUTO_ROOT" - - LABEL="dm_link" - ENV{DM_UDEV_LOW_PRIORITY_FLAG}=="1", OPTIONS="link_priority=-100" --- -2.39.1 - diff --git a/SOURCES/0011-device_id-fix-handling-of-non-PV-with-duplicate-seri.patch b/SOURCES/0011-device_id-fix-handling-of-non-PV-with-duplicate-seri.patch new file mode 100644 index 0000000..0ba66c0 --- /dev/null +++ b/SOURCES/0011-device_id-fix-handling-of-non-PV-with-duplicate-seri.patch @@ -0,0 +1,82 @@ +From 499fd37ff0c2bae1c492c3883f063a332e12ac3d Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 8 Jun 2023 12:24:05 -0500 +Subject: [PATCH 11/14] device_id: fix handling of non-PV with duplicate serial + number + +Fix in the code that matches devices to system.devices entries when +the devices have the same serial number. A non-PV device in +system.devices has no pvid value, and the code was segfaulting +when checking the null pvid value. + +(cherry picked from commit 74feebdab723c1ea46d4316f8a581750c1d8cda3) +--- + lib/device/device_id.c | 2 ++ + test/shell/devicesfile-serial.sh | 38 ++++++++++++++++++++++++++++++++ + 2 files changed, 40 insertions(+) + +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index 7db6c9b86..e3d622ecc 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -2625,6 +2625,8 @@ void device_ids_check_serial(struct cmd_context *cmd, struct dm_list *scan_devs, + * Match du to a dev based on PVID. + */ + dm_list_iterate_items(dul, &dus_check) { ++ if (!dul->du->pvid) ++ continue; + log_debug("Matching suspect serial device id %s PVID %s prev %s", + dul->du->idname, dul->du->pvid, dul->du->devname); + found = 0; +diff --git a/test/shell/devicesfile-serial.sh b/test/shell/devicesfile-serial.sh +index a88c1906a..a4cbd5cb2 100644 +--- a/test/shell/devicesfile-serial.sh ++++ b/test/shell/devicesfile-serial.sh +@@ -851,6 +851,44 @@ grep $PVID4 out4 + vgcreate $vg2 $dev2 $dev3 + vgs | grep $vg2 + ++# 3 devs with duplicate serial, 2 pvs with stale devnames, 1 non-pv device ++ ++aux wipefs_a $dev1 ++aux wipefs_a $dev2 ++aux wipefs_a $dev3 ++ ++echo $SERIAL1 > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial ++echo $SERIAL1 > $SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial ++echo $SERIAL1 > $SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial ++ ++rm $DF ++touch $DF ++vgcreate $vg1 $dev1 $dev2 ++lvmdevices --adddev $dev3 ++cat $DF ++cp $DF $ORIG ++ ++PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'` ++PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'` ++OPVID1=`pvs "$dev1" --noheading -o uuid | awk '{print $1}'` ++OPVID2=`pvs "$dev2" --noheading -o uuid | awk '{print $1}'` ++ ++pvs -o+uuid,deviceid ++ ++sed -e "s|DEVNAME=$dev1|DEVNAME=tmp|" $ORIG > tmp1 ++sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1 > tmp2 ++sed -e "s|DEVNAME=tmp|DEVNAME=$dev2|" tmp2 > $DF ++cat $DF ++ ++# pvs should report the correct info and fix the DF ++pvs -o+uuid,deviceid |tee out ++grep $dev1 out |tee out1 ++grep $dev2 out |tee out2 ++grep $OPVID1 out1 ++grep $OPVID2 out2 ++grep $SERIAL1 out1 ++grep $SERIAL1 out2 ++ + remove_base + rmmod brd + +-- +2.41.0 + diff --git a/SOURCES/0011-filesystem-use-PATH_MAX-for-linux-paths.patch b/SOURCES/0011-filesystem-use-PATH_MAX-for-linux-paths.patch deleted file mode 100644 index 27c2720..0000000 --- a/SOURCES/0011-filesystem-use-PATH_MAX-for-linux-paths.patch +++ /dev/null @@ -1,49 +0,0 @@ -From cbcf65c6518652242aab6960eeb983c6bc771bd3 Mon Sep 17 00:00:00 2001 -From: Zdenek Kabelac -Date: Sun, 12 Feb 2023 19:23:12 +0100 -Subject: [PATCH] filesystem: use PATH_MAX for linux paths - -(cherry picked from commit cf0dc9a13cf365859e7dad3bb1ad02040925ae11) ---- - lib/device/filesystem.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/lib/device/filesystem.c b/lib/device/filesystem.c -index db507bdda..0c902ec14 100644 ---- a/lib/device/filesystem.c -+++ b/lib/device/filesystem.c -@@ -219,10 +219,10 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l - FILE *fp; - char proc_line[PATH_MAX]; - char proc_fstype[FSTYPE_MAX]; -- char proc_devpath[1024]; -- char proc_mntpath[1024]; -- char lv_mapper_path[1024]; -- char mntent_mount_dir[1024]; -+ char proc_devpath[PATH_MAX]; -+ char proc_mntpath[PATH_MAX]; -+ char lv_mapper_path[PATH_MAX]; -+ char mntent_mount_dir[PATH_MAX]; - char *dm_name; - struct stat st_lv; - struct stat stme; -@@ -262,14 +262,14 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l - continue; - if (stme.st_dev != st_lv.st_rdev) - continue; -- strncpy(mntent_mount_dir, me->mnt_dir, PATH_MAX-1); -+ dm_strncpy(mntent_mount_dir, me->mnt_dir, sizeof(mntent_mount_dir)); - } - endmntent(fme); - - if (!(dm_name = dm_build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL))) - return_0; - -- if ((dm_snprintf(lv_mapper_path, 1024, "%s/%s", dm_dir(), dm_name) < 0)) -+ if ((dm_snprintf(lv_mapper_path, sizeof(lv_mapper_path), "%s/%s", dm_dir(), dm_name) < 0)) - return_0; - - if (!(fp = fopen("/proc/mounts", "r"))) --- -2.39.1 - diff --git a/SOURCES/0012-device_id-ignore-leading-and-trailing-spaces-for-sys.patch b/SOURCES/0012-device_id-ignore-leading-and-trailing-spaces-for-sys.patch new file mode 100644 index 0000000..81152cf --- /dev/null +++ b/SOURCES/0012-device_id-ignore-leading-and-trailing-spaces-for-sys.patch @@ -0,0 +1,693 @@ +From 894ae888233ff5026c981500623f4f829d358405 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 15 Jun 2023 13:58:48 -0500 +Subject: [PATCH 12/14] device_id: ignore leading and trailing spaces for + sys_wwid and sys_serial + +Leading and trailing underscores are also ignored to handle device ids +written by previous versions which replaced all spaces with underscores. + +(cherry picked from commit 228a8e8c1fd8e82a2e31a6060614dc3dd2f8bc51) +--- + lib/device/device.h | 1 + + lib/device/device_id.c | 278 +++++++++++++++++++----------- + lib/device/parse_vpd.c | 50 ++++++ + test/shell/devicesfile-vpd-ids.sh | 101 +++++++++-- + 4 files changed, 312 insertions(+), 118 deletions(-) + +diff --git a/lib/device/device.h b/lib/device/device.h +index 446104218..84d87232b 100644 +--- a/lib/device/device.h ++++ b/lib/device/device.h +@@ -239,6 +239,7 @@ int dev_mpath_init(const char *config_wwids_file); + void dev_mpath_exit(void); + int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list *ids); + int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes); ++int format_general_id(const char *in, int in_bytes, unsigned char *out, int out_bytes); + int parse_vpd_serial(const unsigned char *in, char *out, int outsize); + + /* dev_util */ +diff --git a/lib/device/device_id.c b/lib/device/device_id.c +index e3d622ecc..a6fc4a26d 100644 +--- a/lib/device/device_id.c ++++ b/lib/device/device_id.c +@@ -185,6 +185,71 @@ void free_dids(struct dm_list *ids) + } + } + ++/* More than one _ in a row is replaced with one _ */ ++static void _reduce_repeating_underscores(char *buf, int bufsize) ++{ ++ char *tmpbuf; ++ int us = 0, i, j = 0; ++ ++ if (!(tmpbuf = strndup(buf, bufsize-1))) ++ return; ++ ++ memset(buf, 0, bufsize); ++ ++ for (i = 0; i < strlen(tmpbuf); i++) { ++ if (tmpbuf[i] == '_') ++ us++; ++ else ++ us = 0; ++ ++ if (us == 1) ++ buf[j++] = '_'; ++ else if (us > 1) ++ continue; ++ else ++ buf[j++] = tmpbuf[i]; ++ ++ if (j == bufsize) ++ break; ++ } ++ buf[bufsize-1] = '\0'; ++ free(tmpbuf); ++} ++ ++static void _remove_leading_underscores(char *buf, int bufsize) ++{ ++ char *tmpbuf; ++ int i, j = 0; ++ ++ if (buf[0] != '_') ++ return; ++ ++ if (!(tmpbuf = strndup(buf, bufsize-1))) ++ return; ++ ++ memset(buf, 0, bufsize); ++ ++ for (i = 0; i < strlen(tmpbuf); i++) { ++ if (!j && tmpbuf[i] == '_') ++ continue; ++ buf[j++] = tmpbuf[i]; ++ ++ if (j == bufsize) ++ break; ++ } ++ free(tmpbuf); ++} ++ ++static void _remove_trailing_underscores(char *buf, int bufsize) ++{ ++ char *end; ++ ++ end = buf + strlen(buf) - 1; ++ while ((end > buf) && (*end == '_')) ++ end--; ++ end[1] = '\0'; ++} ++ + static int _read_sys_block(struct cmd_context *cmd, struct device *dev, + const char *suffix, char *sysbuf, int sysbufsize, + int binary, int *retlen) +@@ -406,7 +471,7 @@ struct dev_wwid *dev_add_wwid(char *id, int id_type, struct dm_list *ids) + + int dev_read_vpd_wwids(struct cmd_context *cmd, struct device *dev) + { +- unsigned char vpd_data[VPD_SIZE] = { 0 }; ++ char vpd_data[VPD_SIZE] = { 0 }; + int vpd_datalen = 0; + + dev->flags |= DEV_ADDED_VPD_WWIDS; +@@ -417,36 +482,47 @@ int dev_read_vpd_wwids(struct cmd_context *cmd, struct device *dev) + return 0; + + /* adds dev_wwid entry to dev->wwids for each id in vpd data */ +- parse_vpd_ids(vpd_data, vpd_datalen, &dev->wwids); ++ parse_vpd_ids((const unsigned char *)vpd_data, vpd_datalen, &dev->wwids); + return 1; + } + + int dev_read_sys_wwid(struct cmd_context *cmd, struct device *dev, +- char *buf, int bufsize, struct dev_wwid **dw_out) ++ char *outbuf, int outbufsize, struct dev_wwid **dw_out) + { +- char tmpbuf[DEV_WWID_SIZE]; ++ char buf[DEV_WWID_SIZE] = { 0 }; + struct dev_wwid *dw; +- int ret; ++ int is_t10 = 0; ++ int i, ret; + + dev->flags |= DEV_ADDED_SYS_WWID; + +- ret = read_sys_block(cmd, dev, "device/wwid", buf, bufsize); ++ ret = read_sys_block(cmd, dev, "device/wwid", buf, sizeof(buf)); + if (!ret || !buf[0]) { + /* the wwid file is not under device for nvme devs */ +- ret = read_sys_block(cmd, dev, "wwid", buf, bufsize); ++ ret = read_sys_block(cmd, dev, "wwid", buf, sizeof(buf)); + } + if (!ret || !buf[0]) + return 0; + +- /* in t10 id, replace characters like space and quote */ +- if (!strncmp(buf, "t10.", 4)) { +- if (bufsize < DEV_WWID_SIZE) +- return 0; +- memcpy(tmpbuf, buf, DEV_WWID_SIZE); +- memset(buf, 0, bufsize); +- format_t10_id((const unsigned char *)tmpbuf, DEV_WWID_SIZE, (unsigned char *)buf, bufsize); ++ for (i = 0; i < sizeof(buf) - 4; i++) { ++ if (buf[i] == ' ') ++ continue; ++ if (!strncmp(&buf[i], "t10", 3)) ++ is_t10 = 1; ++ break; + } + ++ /* ++ * Remove leading and trailing spaces. ++ * Replace internal spaces with underscores. ++ * t10 wwids have multiple sequential spaces ++ * replaced by a single underscore. ++ */ ++ if (is_t10) ++ format_t10_id((const unsigned char *)buf, sizeof(buf), (unsigned char *)outbuf, outbufsize); ++ else ++ format_general_id((const char *)buf, sizeof(buf), (unsigned char *)outbuf, outbufsize); ++ + /* Note, if wwids are also read from vpd, this same wwid will be added again. */ + + if (!(dw = dev_add_wwid(buf, 0, &dev->wwids))) +@@ -457,9 +533,9 @@ int dev_read_sys_wwid(struct cmd_context *cmd, struct device *dev, + } + + static int _dev_read_sys_serial(struct cmd_context *cmd, struct device *dev, +- char *buf, int bufsize) ++ char *outbuf, int outbufsize) + { +- unsigned char vpd_data[VPD_SIZE] = { 0 }; ++ char buf[VPD_SIZE] = { 0 }; + const char *devname; + int vpd_datalen = 0; + +@@ -471,13 +547,16 @@ static int _dev_read_sys_serial(struct cmd_context *cmd, struct device *dev, + * (Only virtio disks /dev/vdx are known to use /sys/class/block/vdx/serial.) + */ + +- read_sys_block(cmd, dev, "device/serial", buf, bufsize); +- if (buf[0]) +- return 1; ++ read_sys_block(cmd, dev, "device/serial", buf, sizeof(buf)); ++ if (buf[0]) { ++ format_general_id((const char *)buf, sizeof(buf), (unsigned char *)outbuf, outbufsize); ++ if (outbuf[0]) ++ return 1; ++ } + +- if (read_sys_block_binary(cmd, dev, "device/vpd_pg80", (char *)vpd_data, VPD_SIZE, &vpd_datalen) && vpd_datalen) { +- parse_vpd_serial(vpd_data, buf, bufsize); +- if (buf[0]) ++ if (read_sys_block_binary(cmd, dev, "device/vpd_pg80", buf, VPD_SIZE, &vpd_datalen) && vpd_datalen) { ++ parse_vpd_serial((const unsigned char *)buf, outbuf, outbufsize); ++ if (outbuf[0]) + return 1; + } + +@@ -505,12 +584,13 @@ static int _dev_read_sys_serial(struct cmd_context *cmd, struct device *dev, + if (dm_snprintf(path, sizeof(path), "%s/class/block/%s/serial", sysfs_dir, vdx) < 0) + return 0; + +- ret = get_sysfs_value(path, buf, bufsize, 0); ++ ret = get_sysfs_value(path, buf, sizeof(buf), 0); + if (ret && !buf[0]) + ret = 0; + if (ret) { +- buf[bufsize - 1] = '\0'; +- return 1; ++ format_general_id((const char *)buf, sizeof(buf), (unsigned char *)outbuf, outbufsize); ++ if (buf[0]) ++ return 1; + } + } + +@@ -520,6 +600,7 @@ static int _dev_read_sys_serial(struct cmd_context *cmd, struct device *dev, + const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_t idtype) + { + char sysbuf[PATH_MAX] = { 0 }; ++ char sysbuf2[PATH_MAX] = { 0 }; + const char *idname = NULL; + struct dev_wwid *dw; + int i; +@@ -584,16 +665,45 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u + return NULL; + } + +- /* wwids are already munged if needed */ +- if (idtype != DEV_ID_TYPE_SYS_WWID) { ++ /* ++ * Replace all spaces, quotes, control chars with underscores. ++ * sys_wwid, sys_serial, and wwid_* have already been handled, ++ * and with slightly different replacement (see format_t10_id, ++ * format_general_id.) ++ */ ++ if ((idtype != DEV_ID_TYPE_SYS_WWID) && ++ (idtype != DEV_ID_TYPE_SYS_SERIAL) && ++ (idtype != DEV_ID_TYPE_WWID_NAA) && ++ (idtype != DEV_ID_TYPE_WWID_EUI) && ++ (idtype != DEV_ID_TYPE_WWID_T10)) { + for (i = 0; i < strlen(sysbuf); i++) { +- if (sysbuf[i] == '"') +- continue; +- if (isblank(sysbuf[i]) || isspace(sysbuf[i]) || iscntrl(sysbuf[i])) ++ if ((sysbuf[i] == '"') || ++ isblank(sysbuf[i]) || ++ isspace(sysbuf[i]) || ++ iscntrl(sysbuf[i])) + sysbuf[i] = '_'; + } + } + ++ /* ++ * Reduce actual leading and trailing underscores for sys_wwid ++ * and sys_serial, since underscores were previously used as ++ * replacements for leading/trailing spaces which are now ignored. ++ * Also reduce any actual repeated underscores in t10 wwid since ++ * multiple repeated spaces were also once replaced by underscores. ++ */ ++ if ((idtype == DEV_ID_TYPE_SYS_WWID) || ++ (idtype == DEV_ID_TYPE_SYS_SERIAL)) { ++ memcpy(sysbuf2, sysbuf, sizeof(sysbuf2)); ++ _remove_leading_underscores(sysbuf2, sizeof(sysbuf2)); ++ _remove_trailing_underscores(sysbuf2, sizeof(sysbuf2)); ++ if (idtype == DEV_ID_TYPE_SYS_WWID && !strncmp(sysbuf2, "t10", 3) && strstr(sysbuf2, "__")) ++ _reduce_repeating_underscores(sysbuf2, sizeof(sysbuf2)); ++ if (memcmp(sysbuf, sysbuf2, sizeof(sysbuf))) ++ log_debug("device_id_system_read reduced underscores %s to %s", sysbuf, sysbuf2); ++ memcpy(sysbuf, sysbuf2, sizeof(sysbuf)); ++ } ++ + if (!sysbuf[0]) + goto bad; + +@@ -1728,40 +1838,6 @@ static int _match_dm_devnames(struct cmd_context *cmd, struct device *dev, + return 0; + } + +-/* More than one _ in a row is replaced with one _ */ +-static void _reduce_repeating_underscores(char *in, int in_len, char *out, int out_size) +-{ +- int us = 0, i, j = 0; +- +- for (i = 0; i < in_len; i++) { +- if (in[i] == '_') +- us++; +- else +- us = 0; +- +- if (us == 1) +- out[j++] = '_'; +- else if (us > 1) +- continue; +- else +- out[j++] = in[i]; +- +- if (j == out_size) +- break; +- } +-} +- +-/* Remove any _ at the end of the string. */ +-static void _remove_trailing_underscores(char *buf) +-{ +- char *end; +- +- end = buf + strlen(buf) - 1; +- while ((end > buf) && (*end == '_')) +- end--; +- end[1] = '\0'; +-} +- + /* + * du is a devices file entry. dev is any device on the system. + * check if du is for dev by comparing the device's ids to du->idname. +@@ -1775,8 +1851,7 @@ static void _remove_trailing_underscores(char *buf) + + static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct device *dev) + { +- char du_t10[DEV_WWID_SIZE] = { 0 }; +- char id_t10[DEV_WWID_SIZE]; ++ char du_idname[PATH_MAX]; + struct dev_id *id; + const char *idname; + int part; +@@ -1827,20 +1902,30 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + } + + /* +- * Devices file entries with IDTYPE=sys_wwid and a T10 WWID +- * for IDNAME were saved in the past with each space replaced +- * by one _. Now we convert multiple spaces to a single _. +- * So, convert a df entry with the old style to the new shorter +- * style to compare. Also, in past versions, trailing spaces +- * in the wwid would be replaced by _, but now trailing spaces +- * are ignored. This means devices file entries created by +- * past versions may have _ at the end of the IDNAME string. +- * So, exclude trailing underscores when comparing a t10 wwid +- * from a device with a t10 wwid in the devices file. ++ * sys_wwid and sys_serial were saved in the past with leading and ++ * trailing spaces replaced with underscores, and t10 wwids also had ++ * repeated internal spaces replaced with one underscore each. Now we ++ * ignore leading and trailing spaces and replace multiple repeated ++ * spaces with one underscore in t10 wwids. In order to handle ++ * system.devices entries created by older versions, modify the IDNAME ++ * value that's read (du->idname) to remove leading and trailing ++ * underscores, and reduce repeated underscores to one in t10 wwids. ++ * ++ * Example: wwid is reported as " t10.123 456 " (without quotes) ++ * Previous versions would save this in system.devices as: __t10.123__456__ ++ * Current versions will save this in system.devices as: t10.123_456 ++ * device_id_system_read() now returns: t10.123_456 ++ * When this code reads __t10.123__456__ from system.devices, that ++ * string is modified to t10.123_456 so that it will match the value ++ * returned from device_id_system_read(). + */ +- if (du->idtype == DEV_ID_TYPE_SYS_WWID && !strncmp(du->idname, "t10", 3) && strchr(du->idname, '_')) { +- _reduce_repeating_underscores(du->idname, strlen(du->idname), du_t10, sizeof(du_t10) - 1); +- _remove_trailing_underscores(du_t10); ++ strncpy(du_idname, du->idname, PATH_MAX-1); ++ if (((du->idtype == DEV_ID_TYPE_SYS_WWID) || (du->idtype == DEV_ID_TYPE_SYS_SERIAL)) && ++ strchr(du_idname, '_')) { ++ _remove_leading_underscores(du_idname, sizeof(du_idname)); ++ _remove_trailing_underscores(du_idname, sizeof(du_idname)); ++ if (du->idtype == DEV_ID_TYPE_SYS_WWID && !strncmp(du_idname, "t10", 3) && strstr(du_idname, "__")) ++ _reduce_repeating_underscores(du_idname, sizeof(du_idname)); + } + + /* +@@ -1848,21 +1933,14 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + * (and saved on dev->ids to avoid rereading.) + */ + dm_list_iterate_items(id, &dev->ids) { +- if (id->idtype == du->idtype) { ++ if (!id->idname) ++ continue; + ++ if (id->idtype == du->idtype) { + /* +- * For t10 wwids, remove actual trailing underscores from the dev wwid +- * (in id->idname), because all trailing underscores were removed from +- * the du->idname read from the devices file. i.e. no trailing _ are +- * used in t10 wwid comparisons. ++ * dm names can have different forms, so matching names ++ * is not always a direct comparison. + */ +- if ((id->idtype == DEV_ID_TYPE_SYS_WWID) && +- id->idname && !strncmp(id->idname, "t10", 3) && du_t10[0]) { +- memset(id_t10, 0, sizeof(id_t10)); +- strncpy(id_t10, id->idname, DEV_WWID_SIZE-1); +- _remove_trailing_underscores(id_t10); +- } +- + if ((id->idtype == DEV_ID_TYPE_DEVNAME) && _match_dm_devnames(cmd, dev, id, du)) { + /* dm devs can have differing names that we know still match */ + du->dev = dev; +@@ -1871,22 +1949,16 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + log_debug("Match device_id %s %s to %s: dm names", + idtype_to_str(du->idtype), du->idname, dev_name(dev)); + return 1; ++ } + +- } else if (id->idname && !strcmp(id->idname, du->idname)) { ++ if (!strcmp(id->idname, du_idname)) { + du->dev = dev; + dev->id = id; + dev->flags |= DEV_MATCHED_USE_ID; + log_debug("Match device_id %s %s to %s", +- idtype_to_str(du->idtype), du->idname, dev_name(dev)); ++ idtype_to_str(du->idtype), du_idname, dev_name(dev)); + return 1; + +- } else if ((id->idtype == DEV_ID_TYPE_SYS_WWID) && du_t10[0] && id_t10[0] && !strcmp(id_t10, du_t10)) { +- du->dev = dev; +- dev->id = id; +- dev->flags |= DEV_MATCHED_USE_ID; +- log_debug("Match device_id %s %s to %s", +- idtype_to_str(du->idtype), du->idname, dev_name(dev)); +- return 1; + } else { + /* + log_debug("Mismatch device_id %s %s to %s: idname %s", +@@ -1913,12 +1985,12 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + id->dev = dev; + dm_list_add(&dev->ids, &id->list); + +- if (idname && !strcmp(idname, du->idname)) { ++ if (idname && !strcmp(idname, du_idname)) { + du->dev = dev; + dev->id = id; + dev->flags |= DEV_MATCHED_USE_ID; + log_debug("Match device_id %s %s to %s", +- idtype_to_str(du->idtype), du->idname, dev_name(dev)); ++ idtype_to_str(du->idtype), idname, dev_name(dev)); + return 1; + } + +@@ -1944,7 +2016,7 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct + dev_read_vpd_wwids(cmd, dev); + + dm_list_iterate_items(dw, &dev->wwids) { +- if (!strcmp(dw->id, du->idname)) { ++ if (!strcmp(dw->id, du_idname)) { + if (!(id = zalloc(sizeof(struct dev_id)))) + return_0; + /* wwid types are 1,2,3 and idtypes are DEV_ID_TYPE_ */ +diff --git a/lib/device/parse_vpd.c b/lib/device/parse_vpd.c +index c1ac974fd..938277e38 100644 +--- a/lib/device/parse_vpd.c ++++ b/lib/device/parse_vpd.c +@@ -36,7 +36,57 @@ + #include + + /* ++ * Remove leading spaces. ++ * Remove trailing spaces. ++ * Replace each space with underscore. ++ * Skip quotes, non-ascii, non-printable. ++ */ ++int format_general_id(const char *in, int in_bytes, unsigned char *out, int out_bytes) ++{ ++ const char *end; ++ int end_bytes = strlen(in); ++ int retlen = 0; ++ int j = 0; ++ int i; ++ ++ if (!end_bytes) ++ return 0; ++ ++ end = in + end_bytes - 1; ++ while ((end > in) && (*end == ' ')) { ++ end--; ++ end_bytes--; ++ } ++ ++ for (i = 0; i < end_bytes; i++) { ++ if (!in[i]) ++ break; ++ if (j >= (out_bytes - 2)) ++ break; ++ /* skip leading spaces */ ++ if (!retlen && (in[i] == ' ')) ++ continue; ++ /* skip non-ascii non-printable characters */ ++ if (!isascii(in[i]) || !isprint(in[i])) ++ continue; ++ /* skip quote */ ++ if (in[i] == '"') ++ continue; ++ /* replace each space with _ */ ++ if (in[i] == ' ') ++ out[j++] = '_'; ++ else ++ out[j++] = in[i]; ++ retlen++; ++ } ++ return retlen; ++} ++ ++/* ++ * Remove leading spaces. ++ * Remove trailing spaces. + * Replace series of spaces with a single _. ++ * Skip quotes, non-ascii, non-printable. + */ + int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes) + { +diff --git a/test/shell/devicesfile-vpd-ids.sh b/test/shell/devicesfile-vpd-ids.sh +index 52805737b..04dbae7d0 100644 +--- a/test/shell/devicesfile-vpd-ids.sh ++++ b/test/shell/devicesfile-vpd-ids.sh +@@ -223,8 +223,8 @@ cleanup_sysfs + # Test t10 wwid containing quote + rm $DF + aux wipefs_a "$DEV1" +-mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/ +-echo "t10.ATA_2.5\"_SATA_SSD_1112-A___111111111111" > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device ++echo "t10.ATA_2.5\"_SATA_SSD_1112-A___111111111111" > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid + lvmdevices --adddev "$DEV1" + cat $DF + vgcreate $vg "$DEV1" +@@ -241,19 +241,19 @@ grep sys_wwid $DF + grep 2.5_SATA_SSD $DF + lvremove -y $vg + vgremove $vg +-rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid + cleanup_sysfs + + # Test t10 wwid with trailing space and line feed at the end + rm $DF + aux wipefs_a "$DEV1" +-mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/ ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device + echo -n "7431 302e 4154 4120 2020 2020 5642 4f58 \ + 2048 4152 4444 4953 4b20 2020 2020 2020 \ + 2020 2020 2020 2020 2020 2020 2020 2020 \ + 2020 2020 5642 3963 3130 6433 3138 2d31 \ +-3838 6439 6562 6320 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid +-cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++3838 6439 6562 6320 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid ++cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid + lvmdevices --adddev "$DEV1" + cat $DF + vgcreate $vg "$DEV1" +@@ -266,19 +266,19 @@ grep sys_wwid out + grep sys_wwid $DF + lvremove -y $vg + vgremove $vg +-rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid + cleanup_sysfs + + # Test t10 wwid with trailing space at the end that was created by 9.0/9.1 + rm $DF + aux wipefs_a "$DEV1" +-mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/ ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device + echo -n "7431 302e 4154 4120 2020 2020 5642 4f58 \ + 2048 4152 4444 4953 4b20 2020 2020 2020 \ + 2020 2020 2020 2020 2020 2020 2020 2020 \ + 2020 2020 5642 3963 3130 6433 3138 2d31 \ +-3838 6439 6562 6320 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid +-cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++3838 6439 6562 6320 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid ++cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid + lvmdevices --adddev "$DEV1" + cat $DF + vgcreate $vg "$DEV1" +@@ -311,20 +311,20 @@ pvs + pvs -o+deviceidtype,deviceid "$DEV1" + lvremove -y $vg + vgremove $vg +-rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid + cleanup_sysfs + + # test a t10 wwid that has actual trailing underscore which + # is followed by a trailing space. + rm $DF + aux wipefs_a "$DEV1" +-mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/ ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device + echo -n "7431 302e 4154 4120 2020 2020 5642 4f58 \ + 2048 4152 4444 4953 4b20 2020 2020 2020 \ + 2020 2020 2020 2020 2020 2020 2020 2020 \ + 2020 2020 5642 3963 3130 6433 3138 2d31 \ +-3838 6439 6562 5f20 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid +-cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++3838 6439 6562 5f20 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid ++cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid + # The wwid has an actual underscore char (5f) followed by a space char (20) + # 9.1 converts the trailing space to an underscore + T10_WWID_RHEL91="t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9eb__" +@@ -352,9 +352,80 @@ pvs + pvs -o+deviceidtype,deviceid "$DEV1" + lvremove -y $vg + vgremove $vg +-rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid ++cleanup_sysfs ++ ++# ++# Test trailing/leading/center spaces in sys_wwid and sys_serial device ++# ids, and that old system.devices files that have trailing/leading ++# underscores are understood. ++# ++ ++rm $DF ++aux wipefs_a "$DEV1" ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device ++echo -n " s123 456 " > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial ++lvmdevices --adddev "$DEV1" ++cat $DF ++grep "IDNAME=s123__456 DEVNAME" $DF ++vgcreate $vg "$DEV1" ++PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` ++cat $DF | grep -v IDNAME > $DFTMP ++cat $DFTMP ++echo "IDTYPE=sys_serial IDNAME=__s123__456__ DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP ++cp $DFTMP $DF ++cat $DF ++vgs ++pvs -o+deviceidtype,deviceid "$DEV1" ++lvremove -y $vg ++vgremove $vg ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial + cleanup_sysfs + ++rm $DF ++aux wipefs_a "$DEV1" ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device ++echo -n " t10.123 456 " > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid ++lvmdevices --adddev "$DEV1" ++cat $DF ++grep "IDNAME=t10.123_456 DEVNAME" $DF ++vgcreate $vg "$DEV1" ++PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` ++cat $DF | grep -v IDNAME > $DFTMP ++cat $DFTMP ++echo "IDTYPE=sys_wwid IDNAME=__t10.123__456__ DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP ++cp $DFTMP $DF ++cat $DF ++vgs ++pvs -o+deviceidtype,deviceid "$DEV1" ++lvremove -y $vg ++vgremove $vg ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid ++cleanup_sysfs ++ ++rm $DF ++aux wipefs_a "$DEV1" ++mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device ++echo -n " naa.123 456 " > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid ++lvmdevices --adddev "$DEV1" ++cat $DF ++grep "IDNAME=naa.123__456 DEVNAME" $DF ++vgcreate $vg "$DEV1" ++PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` ++cat $DF | grep -v IDNAME > $DFTMP ++cat $DFTMP ++echo "IDTYPE=sys_wwid IDNAME=__naa.123__456__ DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP ++cp $DFTMP $DF ++cat $DF ++vgs ++pvs -o+deviceidtype,deviceid "$DEV1" ++lvremove -y $vg ++vgremove $vg ++rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid ++cleanup_sysfs ++ ++ ++ + + # TODO: lvmdevices --adddev --deviceidtype --deviceid + # This would let the user specify the second naa wwid. +-- +2.41.0 + diff --git a/SOURCES/0013-Fix-multisegment-RAID1-allocator-uses-one-disk-for-b.patch b/SOURCES/0013-Fix-multisegment-RAID1-allocator-uses-one-disk-for-b.patch new file mode 100644 index 0000000..4d29cc8 --- /dev/null +++ b/SOURCES/0013-Fix-multisegment-RAID1-allocator-uses-one-disk-for-b.patch @@ -0,0 +1,79 @@ +From 14cb9d915270634c364d89918f824c538b28dc80 Mon Sep 17 00:00:00 2001 +From: heinzm +Date: Wed, 10 May 2023 18:22:11 +0200 +Subject: [PATCH 13/14] Fix "multisegment RAID1, allocator uses one disk for + both legs" + +In case of e.g. 3 PVs, creating or extending a RaidLV causes SubLV +collocation thus putting segments of diffent rimage (and potentially +larger rmeta) SubLVs onto the same PV. For redundant RaidLVs this'll +compromise redundancy. Fix by detecting such bogus allocation on +lvcreate/lvextend and reject the request. + +(cherry picked from commit 05c2b10c5d0a99993430ffbcef684a099ba810ad) +--- + lib/metadata/lv_manip.c | 41 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c +index add9512ff..e4799e082 100644 +--- a/lib/metadata/lv_manip.c ++++ b/lib/metadata/lv_manip.c +@@ -4455,6 +4455,38 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah, + return 1; + } + ++/* Check either RAID images and metas are being allocated redundantly. */ ++static int _lv_raid_redundant(struct logical_volume *lv, ++ struct dm_list *allocatable_pvs, int meta) ++{ ++ uint32_t nlvs, s; ++ struct lv_segment *seg = first_seg(lv); ++ struct pv_list *pvl; ++ ++ if (meta && !seg->meta_areas) ++ return 1; ++ ++ dm_list_iterate_items(pvl, allocatable_pvs) { ++ nlvs = 0; ++ ++ for (s = 0; s < seg->area_count; s++) { ++ struct logical_volume *slv = meta ? seg_metalv(seg, s) : seg_lv(seg, s); ++ ++ if (slv && lv_is_on_pv(slv, pvl->pv) && nlvs++) ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++/* Check both RAID images and metas are being allocated redundantly. */ ++static int _lv_raid_redundant_allocation(struct logical_volume *lv, struct dm_list *allocatable_pvs) ++{ ++ return _lv_raid_redundant(lv, allocatable_pvs, 0) && ++ _lv_raid_redundant(lv, allocatable_pvs, 1); ++} ++ + /* + * Entry point for single-step LV allocation + extension. + * Extents is the number of logical extents to append to the LV unless +@@ -4557,6 +4589,15 @@ int lv_extend(struct logical_volume *lv, + mirrors, stripes, stripe_size))) + goto_out; + ++ if (segtype_is_raid(segtype) && ++ alloc != ALLOC_ANYWHERE && ++ !(r = _lv_raid_redundant_allocation(lv, allocatable_pvs))) { ++ log_error("Insufficient suitable allocatable extents for logical volume %s", display_lvname(lv)); ++ if (!lv_remove(lv) || !vg_write(lv->vg) || !vg_commit(lv->vg)) ++ return_0; ++ goto out; ++ } ++ + if (lv_raid_has_integrity(lv)) { + if (!lv_extend_integrity_in_raid(lv, allocatable_pvs)) { + r = 0; +-- +2.41.0 + diff --git a/SOURCES/0014-tests-integrity-caching-ensure-raid-redundancy.patch b/SOURCES/0014-tests-integrity-caching-ensure-raid-redundancy.patch new file mode 100644 index 0000000..67140e1 --- /dev/null +++ b/SOURCES/0014-tests-integrity-caching-ensure-raid-redundancy.patch @@ -0,0 +1,117 @@ +From 4e28d22cc152fd9c753e5584a5ae99e7a5d1ac96 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Wed, 17 May 2023 14:15:25 -0500 +Subject: [PATCH 14/14] tests: integrity-caching: ensure raid redundancy + +The recent fix 05c2b10c5d0a9 ensures that raid LV images are not +using the same devices. This was happening in the lvextend commands +used by this test, so fix the test to use more devices to ensue +redundancy. + +(cherry picked from commit 24e4b6df1182d0d41763176c175e98e5fa6153ab) +--- + lib/metadata/lv_manip.c | 5 ++++- + test/shell/integrity-caching.sh | 27 ++++++++++++++++++--------- + 2 files changed, 22 insertions(+), 10 deletions(-) + +diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c +index e4799e082..70c969de5 100644 +--- a/lib/metadata/lv_manip.c ++++ b/lib/metadata/lv_manip.c +@@ -4472,8 +4472,11 @@ static int _lv_raid_redundant(struct logical_volume *lv, + for (s = 0; s < seg->area_count; s++) { + struct logical_volume *slv = meta ? seg_metalv(seg, s) : seg_lv(seg, s); + +- if (slv && lv_is_on_pv(slv, pvl->pv) && nlvs++) ++ if (slv && lv_is_on_pv(slv, pvl->pv) && nlvs++) { ++ log_error("LV %s using PV %s is not redundant.", ++ display_lvname(slv), dev_name(pvl->pv->dev)); + return 0; ++ } + } + } + +diff --git a/test/shell/integrity-caching.sh b/test/shell/integrity-caching.sh +index 5539ac575..06fc04928 100644 +--- a/test/shell/integrity-caching.sh ++++ b/test/shell/integrity-caching.sh +@@ -23,7 +23,7 @@ aux kernel_at_least 5 10 || export LVM_TEST_PREFER_BRD=0 + mnt="mnt" + mkdir -p $mnt + +-aux prepare_devs 6 80 ++aux prepare_devs 9 80 + + # Use awk instead of anoyingly long log out from printf + #printf "%0.sA" {1..16384} >> fileA +@@ -319,7 +319,7 @@ vgremove -ff $vg + # Test lvextend while inactive + + _prepare_vg +-lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg ++lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" + _wait_recalc $vg/${lv1}_rimage_0 + _wait_recalc $vg/${lv1}_rimage_1 + _wait_recalc $vg/$lv1 +@@ -329,7 +329,11 @@ lvs -a -o name,size,segtype,devices,sync_percent $vg + _add_new_data_to_mnt + umount $mnt + lvchange -an $vg/$lv1 +-lvextend -l 16 $vg/$lv1 ++# use two new devs for raid extend to ensure redundancy ++vgextend $vg "$dev7" "$dev8" ++lvs -a -o name,segtype,devices $vg ++lvextend -l 16 $vg/$lv1 "$dev7" "$dev8" ++lvs -a -o name,segtype,devices $vg + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + xfs_growfs $mnt +@@ -346,16 +350,19 @@ vgremove -ff $vg + # Test lvextend while active + + _prepare_vg +-lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg ++lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" + _wait_recalc $vg/${lv1}_rimage_0 + _wait_recalc $vg/${lv1}_rimage_1 + _wait_recalc $vg/$lv1 + lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" + lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 ++# use two new devs for raid extend to ensure redundancy ++vgextend $vg "$dev7" "$dev8" + lvs -a -o name,size,segtype,devices,sync_percent $vg + _add_new_data_to_mnt +-lvextend -l 16 $vg/$lv1 +-xfs_growfs $mnt ++lvextend -l 16 $vg/$lv1 "$dev7" "$dev8" ++lvs -a -o name,size,segtype,devices,sync_percent $vg ++resize2fs "$DM_DEV_DIR/$vg/$lv1" + _wait_recalc $vg/${lv1}_${suffix}_rimage_0 + _wait_recalc $vg/${lv1}_${suffix}_rimage_1 + _add_more_data_to_mnt +@@ -367,17 +374,19 @@ lvremove $vg/$lv1 + vgremove -ff $vg + + _prepare_vg +-lvcreate --type raid5 --raidintegrity y -n $lv1 -l 8 $vg ++lvcreate --type raid5 --raidintegrity y -n $lv1 -I4 -l 8 $vg "$dev1" "$dev2" "$dev3" + _wait_recalc $vg/${lv1}_rimage_0 + _wait_recalc $vg/${lv1}_rimage_1 + _wait_recalc $vg/${lv1}_rimage_2 + _wait_recalc $vg/$lv1 + lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" + lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 ++vgextend $vg "$dev7" "$dev8" "$dev9" + lvs -a -o name,size,segtype,devices,sync_percent $vg + _add_new_data_to_mnt +-lvextend -l 16 $vg/$lv1 +-xfs_growfs $mnt ++lvextend -l 16 $vg/$lv1 "$dev7" "$dev8" "$dev9" ++lvs -a -o name,size,segtype,devices,sync_percent $vg ++resize2fs "$DM_DEV_DIR/$vg/$lv1" + _wait_recalc $vg/${lv1}_${suffix}_rimage_0 + _wait_recalc $vg/${lv1}_${suffix}_rimage_1 + _add_more_data_to_mnt +-- +2.41.0 + diff --git a/SPECS/lvm2.spec b/SPECS/lvm2.spec index cad29ba..160c44a 100644 --- a/SPECS/lvm2.spec +++ b/SPECS/lvm2.spec @@ -1,7 +1,6 @@ -%global device_mapper_version 1.02.187 +%global device_mapper_version 1.02.195 %global enable_cache 1 -%global enable_cluster 1 %global enable_lvmdbusd 1 %global enable_lvmlockd 1 %global enable_lvmpolld 1 @@ -29,7 +28,6 @@ %if 0%{?rhel} && 0%{?rhel} <= 8 %ifnarch i686 x86_64 ppc64le s390x - %global enable_cluster 0 %global enable_lockd_dlm 0 %endif @@ -38,12 +36,6 @@ %endif %endif -%if %{enable_cluster} - %global configure_cluster --with-cluster=internal -%else - %global configure_cluster --with-cluster=internal -%endif - %global from_snapshot 0 %if 0%{?from_snapshot} %global commit 4a1f6173d29a7d7ecab14a9313000aa5f81170d0 @@ -58,12 +50,11 @@ Name: lvm2 %if 0%{?rhel} Epoch: %{rhel} %endif -Version: 2.03.17 +Version: 2.03.21 %if 0%{?from_snapshot} -#Release: 0.1.20211115git%{shortcommit}%{?dist}%{?rel_suffix} -Release: 4%{?dist}%{?rel_suffix} +Release: 0.1.20211115git%{shortcommit}%{?dist}%{?rel_suffix} %else -Release: 7%{?dist}%{?rel_suffix} +Release: 3%{?dist}%{?rel_suffix} %endif License: GPLv2 URL: http://sourceware.org/lvm2 @@ -72,26 +63,30 @@ Source0: lvm2-%{shortcommit}.tgz %else Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz %endif -# BZ 2150348: -Patch1: 0001-device_id-fix-segfault-verifying-serial-for-non-pv.patch -# BZ 2151601: -Patch2: 0002-lvextend-fix-overprovisioning-check-for-thin-lvs.patch -# BZ 2157591: -Patch3: 0003-lvresize-fix-cryptsetup-resize-in-helper.patch -# BZ 2158619: -Patch4: 0004-vgimportclone-fix-importing-PV-without-metadata.patch -# BZ 2164044: -Patch5: 0005-lvmdbusd-Move-get_error_msg-to-utils.patch -Patch6: 0006-lvmdbusd-Add-command_log_selection-to-command-line.patch -# BZ 2162144: -Patch7: 0007-tests-lvresize-fs-crypt-using-helper-only-for-crypt-.patch -Patch8: 0008-lvresize-only-resize-crypt-when-fs-resize-is-enabled.patch -# BZ 2164226: -Patch9: 0009-lvresize-fail-early-if-mounted-LV-was-renamed.patch -# BZ 2158628: -Patch10: 0010-udev-import-previous-results-of-blkid-when-in-suspen.patch -# BZ 2164226: -Patch11: 0011-filesystem-use-PATH_MAX-for-linux-paths.patch +# BZ 2179430: +Patch1: 0001-fix-dev_name-use-in-add_areas_line.patch +Patch2: 0002-raidintegrity-allow-snapshots.patch +Patch3: 0003-lvmdbus-preserve-PATH-envvar.patch +Patch4: 0004-lvmcache-fix-valgrind-error-when-dropping-md-duplica.patch +# BZ 2188718 +Patch5: 0005-pvck-improve-error-for-write-to-existing-file.patch +# BZ 2191683: +Patch6: 0006-lvreduce-make-_lvseg_get_stripes-handle-integrity-la.patch +# BZ 2188480: +#Patch7: 0007-toollib-provide-proper-hint-for-referencing-VG-uuid-.patch +# BZ 2179430: +Patch8: 0008-tests-integrity-snapshots-now-work-on-raid-integrity.patch +# BZ 2212295: +Patch9: 0009-lvresize-fix-multiple-mounts.patch +# BZ 2208039: +Patch10: 0010-device_id-ignore-trailing-underscores-in-t10-wwid-fr.patch +# - 2212968: +Patch11: 0011-device_id-fix-handling-of-non-PV-with-duplicate-seri.patch +# - 2213653: +Patch12: 0012-device_id-ignore-leading-and-trailing-spaces-for-sys.patch +# BZ 2204467: +Patch13: 0013-Fix-multisegment-RAID1-allocator-uses-one-disk-for-b.patch +Patch14: 0014-tests-integrity-caching-ensure-raid-redundancy.patch BuildRequires: make BuildRequires: gcc @@ -103,10 +98,7 @@ BuildRequires: libblkid-devel >= %{util_linux_version} BuildRequires: ncurses-devel BuildRequires: libedit-devel BuildRequires: libaio-devel -%if %{enable_cluster} -BuildRequires: corosynclib-devel >= %{corosync_version} -%endif -%if %{enable_cluster} || %{enable_lockd_dlm} +%if %{enable_lockd_dlm} BuildRequires: dlm-devel >= %{dlm_version} %endif BuildRequires: module-init-tools @@ -127,7 +119,7 @@ BuildRequires: sanlock-devel >= %{sanlock_version} %endif Requires: %{name}-libs = %{?epoch}:%{version}-%{release} %if 0%{?fedora} -Requires: system-release >= %{system_release_version} +Requires(post): (system-release >= %{system_release_version} if system-release) %endif Requires: bash >= %{bash_version} Requires(post): systemd-units >= %{systemd_version}, systemd-sysv @@ -150,19 +142,8 @@ or more physical volumes and creating one or more logical volumes %if 0%{?from_snapshot} %setup -q -n lvm2-%{commit} %else -%setup -q -n LVM2.%{version} +%autosetup -p1 -n LVM2.%{version} %endif -%patch1 -p1 -b .backup1 -%patch2 -p1 -b .backup2 -%patch3 -p1 -b .backup3 -%patch4 -p1 -b .backup4 -%patch5 -p1 -b .backup5 -%patch6 -p1 -b .backup6 -%patch7 -p1 -b .backup7 -%patch8 -p1 -b .backup8 -%patch9 -p1 -b .backup9 -%patch10 -p1 -b .backup10 -%patch11 -p1 -b .backup11 %build %global _default_pid_dir /run @@ -189,7 +170,6 @@ or more physical volumes and creating one or more logical volumes --enable-cmdlib \ --enable-dmeventd \ --enable-blkid_wiping \ - %{?configure_cluster} \ --with-udevdir=%{_udevdir} --enable-udev_sync \ %if %{enable_thin} --with-thin=internal \ @@ -582,7 +562,7 @@ Version: %{device_mapper_version} License: GPLv2 URL: http://sources.redhat.com/dm Requires: device-mapper-libs = %{?epoch}:%{device_mapper_version}-%{release} -Requires: util-linux >= %{util_linux_version} +Requires: util-linux-core >= %{util_linux_version} Requires: systemd >= %{systemd_version} # We need dracut to install required udev rules if udev_sync # feature is turned on so we don't lose required notifications. @@ -734,6 +714,28 @@ An extensive functional testsuite for LVM2. %endif %changelog +* Thu Jul 13 2023 Marian Csontos - 2.03.21-3 +- Fix lvresize fail in case of multiple mountpoints. +- Fix allocator for RAID LVs allocating multiple legs on single device. +- Fix device id handling of WWIDs with trailing spaces. + +* Wed May 24 2023 Marian Csontos - 2.03.21-2 +- Allow snapshots over raid+integrity LV. + +* Fri Apr 21 2023 Marian Csontos - 2.03.21-1 +- Update to upstream version 2.03.21. +- Allow (write)cache over raid+integrity LV. + +* Wed Apr 05 2023 Marian Csontos - 2.03.20-2 +- Fix ModuleNotFoundError: No module named 'utils' in lvmdbusd. + +* Tue Mar 21 2023 Marian Csontos - 2.03.20-1 +- Update to upstream version 2.03.20. + +* Tue Mar 07 2023 Marian Csontos - 2.03.19-1 +- Update to upstream version 2.03.19. +- See WHATS_NEW and WHATS_NEW_DM for more information. + * Thu Feb 16 2023 Marian Csontos - 2.03.17-7 - Fix segfault in previous build.