diff --git a/0053-lvresize-fix-xfs-size-checks.patch b/0053-lvresize-fix-xfs-size-checks.patch new file mode 100644 index 0000000..0a6b565 --- /dev/null +++ b/0053-lvresize-fix-xfs-size-checks.patch @@ -0,0 +1,350 @@ +From dcda3b48c2f6ca9841d53911d10fe8825f4e1d19 Mon Sep 17 00:00:00 2001 +From: David Teigland +Date: Thu, 11 Dec 2025 14:48:42 -0600 +Subject: [PATCH 53/57] lvresize: fix xfs size checks + +After lvextend with xfs_growfs on a mounted xfs file system, +libblkid FSLASTBLOCK continues to return the original value, +and does not reflect the grown size of the fs. + +If that was followed by lvreduce back to the original LV size, +lvm saw the original fs size in FSLASTBLOCK, and allowed the LV +to shrink back to the original size, even though xfs had grown +and was now using the space. + +Fix this by using the XFS_IOC_FSGEOMETRY ioctl to get the +correct size value for mounted xfs. + +(cherry picked from commit 0b231e3f4e3e60b8ec7bb7e4443583a06f42614e) +--- + lib/device/filesystem.c | 53 +++++++++++++++++++++++--- + lib/device/filesystem.h | 3 +- + lib/metadata/lv_manip.c | 6 +-- + test/shell/lvresize-fs-crypt.sh | 18 +++++++++ + test/shell/lvresize-fs.sh | 67 +++++++++++++++++++++++++++++++++ + test/shell/lvresize-xfs.sh | 67 ++++++++++++++++++++++++++++++++- + 6 files changed, 203 insertions(+), 11 deletions(-) + +diff --git a/lib/device/filesystem.c b/lib/device/filesystem.c +index 6d53ebd24..64e1d9422 100644 +--- a/lib/device/filesystem.c ++++ b/lib/device/filesystem.c +@@ -22,7 +22,21 @@ + + #include + #include ++#include + #include ++#include ++/* including xfs/linux.h causes uuid_t conflicts, so define some types that are needed */ ++/* #include */ ++typedef off_t xfs_off_t; ++typedef uint64_t xfs_ino_t; ++typedef uint32_t xfs_dev_t; ++typedef int64_t xfs_daddr_t; ++typedef __u32 xfs_nlink_t; ++#include ++#ifndef __user ++#define __user ++#endif ++#include + + static const char *_lvresize_fs_helper_path; + +@@ -253,8 +267,36 @@ static int _btrfs_get_mnt(struct fs_info *fsi, dev_t lv_devt) + return ret; + } + +-int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, +- struct fs_info *fsi, int include_mount) ++static int _xfs_update_size_mounted(struct cmd_context *cmd, struct logical_volume *lv, ++ char *lv_path, struct fs_info *fsi) ++{ ++ struct xfs_fsop_geom geo = { 0 }; ++ int fd; ++ int ret = 0; ++ ++ if ((fd = open(fsi->mount_dir, O_RDONLY)) < 0) { ++ log_error("XFS geometry open error %d for %s %s", errno, lv_path, fsi->mount_dir); ++ return 0; ++ } ++ ++ if (ioctl(fd, XFS_IOC_FSGEOMETRY, &geo)) { ++ log_error("XFS geometry ioctl error %d for %s %s", errno, lv_path, fsi->mount_dir); ++ goto out; ++ } ++ ++ /* replace the potentially wrong value from blkid_probe_lookup_value FSLASTBLOCK */ ++ fsi->fs_last_byte = geo.blocksize * geo.datablocks; ++ ret = 1; ++ ++ log_debug("xfs geometry blocksize %llu datablocks %llu fs_last_byte %llu from %s %s", ++ (unsigned long long)geo.blocksize, (unsigned long long)geo.datablocks, ++ (unsigned long long)fsi->fs_last_byte, lv_path, fsi->mount_dir); ++out: ++ (void)close(fd); ++ return ret; ++} ++ ++int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi) + { + char lv_path[PATH_MAX]; + char crypt_path[PATH_MAX] = { 0 }; +@@ -340,14 +382,15 @@ int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, + st_top = st_lv; + } + +- if (!include_mount) +- return 1; +- + if (!strcmp(fsi->fstype, "btrfs")) + ret = _btrfs_get_mnt(fsi, st_lv.st_rdev); + else + ret = _fs_get_mnt(fsi, st_top.st_rdev); + ++ /* blkid FSLASTBLOCK may be incorrect for mounted xfs */ ++ if (fsi->mounted && !strcmp(fsi->fstype, "xfs")) ++ ret = _xfs_update_size_mounted(cmd, lv, lv_path, fsi); ++ + fsi->unmounted = !fsi->mounted; + return ret; + } +diff --git a/lib/device/filesystem.h b/lib/device/filesystem.h +index 4ba6f0db9..bb43f9a96 100644 +--- a/lib/device/filesystem.h ++++ b/lib/device/filesystem.h +@@ -45,8 +45,7 @@ struct fs_info { + unsigned needs_crypt:1; + }; + +-int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, +- struct fs_info *fsi, int include_mount); ++int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi); + + int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, char *fsmode); + int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, char *fsmode); +diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c +index e7405f1dc..7296f5e66 100644 +--- a/lib/metadata/lv_manip.c ++++ b/lib/metadata/lv_manip.c +@@ -6459,7 +6459,7 @@ static int _fs_reduce(struct cmd_context *cmd, struct logical_volume *lv, + memset(&fsinfo, 0, sizeof(fsinfo)); + memset(&fsinfo2, 0, sizeof(fsinfo)); + +- if (!fs_get_info(cmd, lv, &fsinfo, 1)) ++ if (!fs_get_info(cmd, lv, &fsinfo)) + goto_out; + + if (fsinfo.nofs) { +@@ -6578,7 +6578,7 @@ static int _fs_reduce(struct cmd_context *cmd, struct logical_volume *lv, + * Re-check the fs last block which should now be less than the + * requested (reduced) LV size. + */ +- if (!fs_get_info(cmd, lv, &fsinfo2, 0)) ++ if (!fs_get_info(cmd, lv, &fsinfo2)) + goto_out; + + if (fsinfo.fs_last_byte && (fsinfo2.fs_last_byte > fsinfo.new_size_bytes)) { +@@ -6600,7 +6600,7 @@ static int _fs_extend_check_fsinfo(struct cmd_context *cmd, struct logical_volum + + memset(fsinfo, 0, sizeof(*fsinfo)); + +- if (!fs_get_info(cmd, lv, fsinfo, 1)) ++ if (!fs_get_info(cmd, lv, fsinfo)) + return 0; + + if (fsinfo->nofs) +diff --git a/test/shell/lvresize-fs-crypt.sh b/test/shell/lvresize-fs-crypt.sh +index a56bf6a3e..d4f9de1e0 100644 +--- a/test/shell/lvresize-fs-crypt.sh ++++ b/test/shell/lvresize-fs-crypt.sh +@@ -97,6 +97,24 @@ umount "$mount_dir" + cryptsetup close $cr + lvremove -f $vg/$lv + ++# lvextend+lvreduce xfs on LUKS1 ++lvcreate -n $lv -L 320M $vg ++echo 93R4P4pIqAH8 | cryptsetup luksFormat -i1 --type luks1 "$DM_DEV_DIR/$vg/$lv" ++echo 93R4P4pIqAH8 | cryptsetup luksOpen "$DM_DEV_DIR/$vg/$lv" $cr ++mkfs.xfs /dev/mapper/$cr ++mount /dev/mapper/$cr "$mount_dir" ++dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct ++df --output=size "$mount_dir" |tee df1 ++lvextend -L+136M --fs resize $vg/$lv ++check lv_field $vg/$lv lv_size "456.00m" ++df --output=size "$mount_dir" |tee df2 ++not diff df1 df2 ++not lvresize -L 320M $vg/$lv ++not lvresize -r -L 320M $vg/$lv ++umount "$mount_dir" ++cryptsetup close $cr ++lvremove -f $vg/$lv ++ + # lvextend ext4 on plain crypt (no header) + lvcreate -n $lv -L 256M $vg + echo 93R4P4pIqAH8 | cryptsetup create $cr "$DM_DEV_DIR/$vg/$lv" +diff --git a/test/shell/lvresize-fs.sh b/test/shell/lvresize-fs.sh +index 4bcbb9ca2..266f18bc1 100644 +--- a/test/shell/lvresize-fs.sh ++++ b/test/shell/lvresize-fs.sh +@@ -700,5 +700,72 @@ blkid -p "$DM_DEV_DIR/$vg/$lv" | grep FSSIZE && { + lvreduce -L16m $vg/$lv + check lv_field $vg/$lv lv_size "16.00m" + } ++lvremove -y $vg/$lv ++ ++############################### ++# ++# lvextend followed by lvreduce ++# ++############################### ++ ++# mounted, fs resized ++lvcreate -n $lv -L 40M $vg ++mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct ++lvresize --yes -r -L 50M $vg/$lv ++not lvresize --yes -L 40M $vg/$lv ++lvresize --yes -r -L 40M $vg/$lv ++umount "$mount_dir" ++lvchange -an $vg/$lv ++lvremove $vg/$lv ++ ++# unmounted, fs resized ++lvcreate -n $lv -L 40M $vg ++mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct ++umount "$mount_dir" ++lvresize --yes -r -L 50M $vg/$lv ++not lvresize --yes -L 40M $vg/$lv ++lvresize --yes -r -L 40M $vg/$lv ++lvchange -an $vg/$lv ++lvremove $vg/$lv ++ ++# mounted, fs not resized ++lvcreate -n $lv -L 40M $vg ++mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct ++df --output=size "$mount_dir" |tee df1 ++lvresize --yes -L 50M $vg/$lv ++check lv_field $vg/$lv lv_size "50.00m" ++lvresize --yes -L 40M $vg/$lv ++check lv_field $vg/$lv lv_size "40.00m" ++df --output=size "$mount_dir" |tee df2 ++# fs size unchanged ++diff df1 df2 ++umount "$mount_dir" ++lvchange -an $vg/$lv ++lvremove $vg/$lv ++ ++# unmounted, fs not resized ++lvcreate -n $lv -L 40M $vg ++mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct ++df --output=size "$mount_dir" |tee df1 ++umount "$mount_dir" ++lvresize --yes -L 50M $vg/$lv ++check lv_field $vg/$lv lv_size "50.00m" ++lvresize --yes -L 40M $vg/$lv ++check lv_field $vg/$lv lv_size "40.00m" ++# fs size unchanged ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++df --output=size "$mount_dir" |tee df2 ++diff df1 df2 ++umount "$mount_dir" ++lvchange -an $vg/$lv ++lvremove $vg/$lv + + vgremove -ff $vg +diff --git a/test/shell/lvresize-xfs.sh b/test/shell/lvresize-xfs.sh +index 4c4ed15e7..ef87b1b3a 100644 +--- a/test/shell/lvresize-xfs.sh ++++ b/test/shell/lvresize-xfs.sh +@@ -19,7 +19,7 @@ which xfs_growfs || skip + + aux have_fsinfo || skip "Test needs --fs checksize support" + +-aux prepare_vg 1 500 ++aux prepare_vg 1 600 + + mount_dir="mnt_lvresize_fs" + mkdir -p "$mount_dir" +@@ -242,6 +242,71 @@ umount "$mount_dir" + + lvremove -f $vg/$lv + ++############################### ++# ++# lvextend followed by lvreduce ++# ++############################### ++ ++# mounted, fs resized ++lvcreate -n $lv -L 400M $vg ++mkfs.xfs "$DM_DEV_DIR/$vg/$lv" ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct ++lvresize --yes -r -L 500M $vg/$lv ++not lvresize --yes -r -L 400M $vg/$lv ++not lvresize --yes -L 400M $vg/$lv ++umount "$mount_dir" ++lvchange -an $vg/$lv ++lvremove $vg/$lv ++ ++# unmounted, fs resized ++lvcreate -n $lv -L 400M $vg ++mkfs.xfs "$DM_DEV_DIR/$vg/$lv" ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct ++umount "$mount_dir" ++lvresize --yes -r -L 500M $vg/$lv ++not lvresize --yes -r -L 400M $vg/$lv ++not lvresize --yes -L 400M $vg/$lv ++lvchange -an $vg/$lv ++lvremove $vg/$lv ++ ++# mounted, fs not resized ++lvcreate -n $lv -L 400M $vg ++mkfs.xfs "$DM_DEV_DIR/$vg/$lv" ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct ++df --output=size "$mount_dir" |tee df1 ++lvresize --yes -L 500M $vg/$lv ++check lv_field $vg/$lv lv_size "500.00m" ++lvresize --yes -L 400M $vg/$lv ++check lv_field $vg/$lv lv_size "400.00m" ++df --output=size "$mount_dir" |tee df2 ++# fs size unchanged ++diff df1 df2 ++umount "$mount_dir" ++lvchange -an $vg/$lv ++lvremove $vg/$lv ++ ++# unmounted, fs not resized ++lvcreate -n $lv -L 400M $vg ++mkfs.xfs "$DM_DEV_DIR/$vg/$lv" ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct ++df --output=size "$mount_dir" |tee df1 ++umount "$mount_dir" ++lvresize --yes -L 500M $vg/$lv ++check lv_field $vg/$lv lv_size "500.00m" ++lvresize --yes -L 400M $vg/$lv ++check lv_field $vg/$lv lv_size "400.00m" ++# fs size unchanged ++mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" ++df --output=size "$mount_dir" |tee df2 ++diff df1 df2 ++umount "$mount_dir" ++lvchange -an $vg/$lv ++lvremove $vg/$lv + + ########################################################## + # +-- +2.52.0 + diff --git a/0054-configure-check-for-xfs-header-file.patch b/0054-configure-check-for-xfs-header-file.patch new file mode 100644 index 0000000..d2cd5a6 --- /dev/null +++ b/0054-configure-check-for-xfs-header-file.patch @@ -0,0 +1,37 @@ +From f533eab471f78f27c86d9b88cf2ba66df924f3ea Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Sun, 14 Dec 2025 17:15:37 +0100 +Subject: [PATCH 54/57] configure: check for xfs header file + +Check if xfs/xfs.h is available. + +(cherry picked from commit 127774ff1bf1a471017b1ae91786eb4e1c2edd82) +--- + configure.ac | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 11a735af5..89ec0ea9c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -101,6 +101,7 @@ AC_CHECK_HEADERS([assert.h ctype.h dirent.h errno.h fcntl.h float.h \ + unistd.h], , [AC_MSG_ERROR(bailing out)]) + + AC_CHECK_HEADERS(termios.h sys/statvfs.h sys/timerfd.h sys/vfs.h linux/magic.h linux/fiemap.h) ++AC_CHECK_HEADERS(xfs/xfs.h, LVM_NO_XFS_WARN=, LVM_NO_XFS_WARN=y, [#define _GNU_SOURCE 1]) + AC_CHECK_HEADERS(libaio.h,LVM_NEEDS_LIBAIO_WARN=,LVM_NEEDS_LIBAIO_WARN=y) + AS_CASE(["$host_os"], + [linux*], [AC_CHECK_HEADERS([asm/byteorder.h linux/fs.h malloc.h], [], [AC_MSG_ERROR(bailing out)])], +@@ -2126,6 +2127,9 @@ AS_IF([test -n "$VDO_CONFIGURE_WARN"], + AS_IF([test -n "$LVM_NEEDS_LIBAIO_WARN"], + [AC_MSG_WARN([Only libdm part can be build without libaio: make [[install_]]device-mapper])]) + ++AS_IF([test -n "$LVM_NO_XFS_WARN"], ++ [AC_MSG_WARN(['lvextend --resizefs' is less capable without xfs/xfs.h (see package: xfsprogs devel)])]) ++ + AS_IF([test "$ODIRECT" != "yes"], + [AC_MSG_WARN([O_DIRECT disabled: low-memory pvmove may lock up])]) + +-- +2.52.0 + diff --git a/0055-log-add-string.h.patch b/0055-log-add-string.h.patch new file mode 100644 index 0000000..edb6ee7 --- /dev/null +++ b/0055-log-add-string.h.patch @@ -0,0 +1,27 @@ +From 9248e4fa05534a0865a7fad4b0bb76ca85c4dd55 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Sun, 14 Dec 2025 21:54:29 +0100 +Subject: [PATCH 55/57] log: add string.h + +Header file is using strerror() from . + +(cherry picked from commit e8d744e8bdb8386ab5754015e6511d0431d76f04) +--- + lib/log/log.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/log/log.h b/lib/log/log.h +index 6efe5a66b..287db00e5 100644 +--- a/lib/log/log.h ++++ b/lib/log/log.h +@@ -38,6 +38,7 @@ + */ + + #include ++#include + + #define EUNCLASSIFIED -1 /* Generic error code */ + +-- +2.52.0 + diff --git a/0056-filesystem-refactor-code-working-with-xfs.patch b/0056-filesystem-refactor-code-working-with-xfs.patch new file mode 100644 index 0000000..fb3f4ea --- /dev/null +++ b/0056-filesystem-refactor-code-working-with-xfs.patch @@ -0,0 +1,208 @@ +From 077eaef48b2d257e94feb1caa3825fa5a5da14e6 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Sun, 14 Dec 2025 17:14:08 +0100 +Subject: [PATCH 56/57] filesystem: refactor code working with xfs + +Move XFS ioctl code to separate filesystem_xfs.c file. +Remove hackish way of including xfs headers. + +When xfs/xfs.h is missing, continue running without checking +mounted filesystem size. + +(cherry picked from commit 1e9efc72cfed277e6885e201affbc47a2edbf576) +--- + lib/Makefile.in | 1 + + lib/device/filesystem.c | 48 +++-------------------------- + lib/device/filesystem.h | 10 +++++- + lib/device/filesystem_xfs.c | 61 +++++++++++++++++++++++++++++++++++++ + 4 files changed, 76 insertions(+), 44 deletions(-) + create mode 100644 lib/device/filesystem_xfs.c + +diff --git a/lib/Makefile.in b/lib/Makefile.in +index 8424ac952..8620eaaff 100644 +--- a/lib/Makefile.in ++++ b/lib/Makefile.in +@@ -40,6 +40,7 @@ SOURCES =\ + device/dev-luks.c \ + device/dev-dasd.c \ + device/dev-lvm1-pool.c \ ++ device/filesystem_xfs.c \ + device/filesystem.c \ + device/online.c \ + device/parse_vpd.c \ +diff --git a/lib/device/filesystem.c b/lib/device/filesystem.c +index 64e1d9422..f1add62f9 100644 +--- a/lib/device/filesystem.c ++++ b/lib/device/filesystem.c +@@ -19,24 +19,12 @@ + #include "lib/display/display.h" + #include "lib/misc/lvm-exec.h" + #include "lib/activate/dev_manager.h" ++#include "lib/commands/toolcontext.h" + + #include + #include +-#include + #include + #include +-/* including xfs/linux.h causes uuid_t conflicts, so define some types that are needed */ +-/* #include */ +-typedef off_t xfs_off_t; +-typedef uint64_t xfs_ino_t; +-typedef uint32_t xfs_dev_t; +-typedef int64_t xfs_daddr_t; +-typedef __u32 xfs_nlink_t; +-#include +-#ifndef __user +-#define __user +-#endif +-#include + + static const char *_lvresize_fs_helper_path; + +@@ -267,34 +255,6 @@ static int _btrfs_get_mnt(struct fs_info *fsi, dev_t lv_devt) + return ret; + } + +-static int _xfs_update_size_mounted(struct cmd_context *cmd, struct logical_volume *lv, +- char *lv_path, struct fs_info *fsi) +-{ +- struct xfs_fsop_geom geo = { 0 }; +- int fd; +- int ret = 0; +- +- if ((fd = open(fsi->mount_dir, O_RDONLY)) < 0) { +- log_error("XFS geometry open error %d for %s %s", errno, lv_path, fsi->mount_dir); +- return 0; +- } +- +- if (ioctl(fd, XFS_IOC_FSGEOMETRY, &geo)) { +- log_error("XFS geometry ioctl error %d for %s %s", errno, lv_path, fsi->mount_dir); +- goto out; +- } +- +- /* replace the potentially wrong value from blkid_probe_lookup_value FSLASTBLOCK */ +- fsi->fs_last_byte = geo.blocksize * geo.datablocks; +- ret = 1; +- +- log_debug("xfs geometry blocksize %llu datablocks %llu fs_last_byte %llu from %s %s", +- (unsigned long long)geo.blocksize, (unsigned long long)geo.datablocks, +- (unsigned long long)fsi->fs_last_byte, lv_path, fsi->mount_dir); +-out: +- (void)close(fd); +- return ret; +-} + + int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi) + { +@@ -388,8 +348,10 @@ int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv, struct fs_in + ret = _fs_get_mnt(fsi, st_top.st_rdev); + + /* blkid FSLASTBLOCK may be incorrect for mounted xfs */ +- if (fsi->mounted && !strcmp(fsi->fstype, "xfs")) +- ret = _xfs_update_size_mounted(cmd, lv, lv_path, fsi); ++ if (fsi->mounted && !strcmp(fsi->fstype, "xfs")) { ++ if (!(ret = fs_xfs_update_size_mounted(cmd, lv, lv_path, fsi))) ++ stack; ++ } + + fsi->unmounted = !fsi->mounted; + return ret; +diff --git a/lib/device/filesystem.h b/lib/device/filesystem.h +index bb43f9a96..c66b47995 100644 +--- a/lib/device/filesystem.h ++++ b/lib/device/filesystem.h +@@ -15,9 +15,13 @@ + #ifndef _FILESYSTEM_H + #define _FILESYSTEM_H + +-#include "lib/commands/toolcontext.h" + #include "lib/device/device.h" + ++#include /* PATH_MAX */ ++ ++struct cmd_context; ++struct logical_volume; ++ + #define FSTYPE_MAX 16 + #define UUID_LEN 37 + +@@ -54,4 +58,8 @@ int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, stru + int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *lv, char *lv_path, char *fstype); + int lv_crypt_is_active(struct cmd_context *cmd, char *lv_path); + ++/* filesystem_xfs.c */ ++int fs_xfs_update_size_mounted(struct cmd_context *cmd, struct logical_volume *lv, ++ char *lv_path, struct fs_info *fsi); ++ + #endif +diff --git a/lib/device/filesystem_xfs.c b/lib/device/filesystem_xfs.c +new file mode 100644 +index 000000000..61252fe16 +--- /dev/null ++++ b/lib/device/filesystem_xfs.c +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2025 Red Hat, Inc. All rights reserved. ++ * ++ * This file is part of LVM2. ++ * ++ * 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 Lesser General Public License v.2.1. ++ * ++ * You should have received a copy of the GNU Lesser 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 ++ */ ++ ++#include "filesystem.h" ++#include "lib/log/lvm-logging.h" ++ ++#ifdef HAVE_XFS_XFS_H ++ ++#include ++ ++int fs_xfs_update_size_mounted(struct cmd_context *cmd, struct logical_volume *lv, ++ char *lv_path, struct fs_info *fsi) ++{ ++ struct xfs_fsop_geom geo = { 0 }; ++ int ret = 0; ++ int fd; ++ ++ if ((fd = open(fsi->mount_dir, O_RDONLY)) < 0) { ++ log_sys_error("XFS geometry open", fsi->mount_dir); ++ return 0; ++ } ++ ++ if (ioctl(fd, XFS_IOC_FSGEOMETRY, &geo)) { ++ log_sys_error("XFS geometry ioctl", fsi->mount_dir); ++ goto out; ++ } ++ ++ /* replace the potentially wrong value from blkid_probe_lookup_value FSLASTBLOCK */ ++ fsi->fs_last_byte = geo.blocksize * geo.datablocks; ++ ret = 1; ++ ++ log_debug("xfs geometry blocksize %llu datablocks %llu fs_last_byte %llu from %s %s", ++ (unsigned long long)geo.blocksize, (unsigned long long)geo.datablocks, ++ (unsigned long long)fsi->fs_last_byte, lv_path, fsi->mount_dir); ++out: ++ (void)close(fd); ++ ++ return ret; ++} ++ ++#else /* !HAVE_XFS_XFS_H */ ++ ++int fs_xfs_update_size_mounted(struct cmd_context *cmd, struct logical_volume *lv, ++ char *lv_path, struct fs_info *fsi) ++{ ++ log_debug("No XFS support, continuing WITHOUT reading XFS geometry."); ++ return 1; ++} ++ ++#endif +-- +2.52.0 + diff --git a/0057-lib-rename-uuid.c-to-id.c.patch b/0057-lib-rename-uuid.c-to-id.c.patch new file mode 100644 index 0000000..db237d4 --- /dev/null +++ b/0057-lib-rename-uuid.c-to-id.c.patch @@ -0,0 +1,210 @@ +From 86812cc39d76f615af43d165c0117cae0c844129 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Sun, 14 Dec 2025 17:13:54 +0100 +Subject: [PATCH 1/2] lib: rename uuid.c to id.c + +Use id.c to better match function naming in id.h. +uuid/uuid.h is public header file, so using lib/id/id.c +avoids potential naming collision with system uuid.h file. + +(cherry picked from commit fe90043412f010957b6c09352a64e56a64c9b2c5) +--- + lib/Makefile.in | 2 +- + lib/cache/lvmcache.h | 2 +- + lib/device/device.h | 2 +- + lib/format_text/format-text.c | 2 +- + lib/format_text/layout.h | 2 +- + lib/{uuid/uuid.c => id/id.c} | 2 +- + lib/{uuid/uuid.h => id/id.h} | 6 +++--- + lib/label/label.h | 2 +- + lib/locking/locking.h | 2 +- + lib/metadata/metadata-exported.h | 2 +- + lib/metadata/pv.h | 2 +- + lib/metadata/vg.h | 2 +- + 12 files changed, 14 insertions(+), 14 deletions(-) + rename lib/{uuid/uuid.c => id/id.c} (99%) + rename lib/{uuid/uuid.h => id/id.h} (93%) + +diff --git a/lib/Makefile.in b/lib/Makefile.in +index 8620eaaff..002a9ec46 100644 +--- a/lib/Makefile.in ++++ b/lib/Makefile.in +@@ -70,6 +70,7 @@ SOURCES =\ + format_text/import_vsn1.c \ + format_text/text_label.c \ + freeseg/freeseg.c \ ++ id/id.c \ + label/label.c \ + label/hints.c \ + locking/file_locking.c \ +@@ -115,7 +116,6 @@ SOURCES =\ + snapshot/snapshot.c \ + striped/striped.c \ + thin/thin.c \ +- uuid/uuid.c \ + zero/zero.c + + ifeq ("@DEVMAPPER@", "yes") +diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h +index 9db5268dd..0468a6318 100644 +--- a/lib/cache/lvmcache.h ++++ b/lib/cache/lvmcache.h +@@ -18,7 +18,7 @@ + + #include "lib/device/dev-cache.h" + #include "lib/device/dev-type.h" +-#include "lib/uuid/uuid.h" ++#include "lib/id/id.h" + #include "lib/label/label.h" + #include "lib/locking/locking.h" + +diff --git a/lib/device/device.h b/lib/device/device.h +index 8c3cb53b0..35ec3712c 100644 +--- a/lib/device/device.h ++++ b/lib/device/device.h +@@ -17,7 +17,7 @@ + #define _LVM_DEVICE_H + + #include "base/data-struct/list.h" +-#include "lib/uuid/uuid.h" ++#include "lib/id/id.h" + + #include + #include +diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c +index d2c99f6bb..615b92df9 100644 +--- a/lib/format_text/format-text.c ++++ b/lib/format_text/format-text.c +@@ -23,7 +23,7 @@ + #include "lib/display/display.h" + #include "lib/commands/toolcontext.h" + #include "lib/misc/lvm-string.h" +-#include "lib/uuid/uuid.h" ++#include "lib/id/id.h" + #include "lib/misc/crc.h" + #include "lib/mm/xlate.h" + #include "lib/label/label.h" +diff --git a/lib/format_text/layout.h b/lib/format_text/layout.h +index 2ef35b3af..2858f39c2 100644 +--- a/lib/format_text/layout.h ++++ b/lib/format_text/layout.h +@@ -20,7 +20,7 @@ + #include "lib/metadata/metadata.h" + #include "lib/format_text/format-text.h" + #include "lib/cache/lvmcache.h" +-#include "lib/uuid/uuid.h" ++#include "lib/id/id.h" + + /* + * PV header extension versions: +diff --git a/lib/uuid/uuid.c b/lib/id/id.c +similarity index 99% +rename from lib/uuid/uuid.c +rename to lib/id/id.c +index 6f7acd2bd..b52121cd9 100644 +--- a/lib/uuid/uuid.c ++++ b/lib/id/id.c +@@ -13,8 +13,8 @@ + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#include "lib/id/id.h" + #include "lib/misc/lib.h" +-#include "lib/uuid/uuid.h" + #include "lib/misc/lvm-wrappers.h" + + #include +diff --git a/lib/uuid/uuid.h b/lib/id/id.h +similarity index 93% +rename from lib/uuid/uuid.h +rename to lib/id/id.h +index 5dad2548a..8e19dff0f 100644 +--- a/lib/uuid/uuid.h ++++ b/lib/id/id.h +@@ -1,6 +1,6 @@ + /* + * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. +- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. ++ * Copyright (C) 2004-2025 Red Hat, Inc. All rights reserved. + * + * This file is part of LVM2. + * +@@ -13,8 +13,8 @@ + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#ifndef _LVM_UUID_H +-#define _LVM_UUID_H ++#ifndef _LVM_ID_H ++#define _LVM_ID_H + + #define ID_LEN 32 + +diff --git a/lib/label/label.h b/lib/label/label.h +index 4c224dc50..e17f8c8ed 100644 +--- a/lib/label/label.h ++++ b/lib/label/label.h +@@ -16,7 +16,7 @@ + #ifndef _LVM_LABEL_H + #define _LVM_LABEL_H + +-#include "lib/uuid/uuid.h" ++#include "lib/id/id.h" + #include "lib/device/device.h" + #include "lib/device/bcache.h" + +diff --git a/lib/locking/locking.h b/lib/locking/locking.h +index a60935d52..487139a06 100644 +--- a/lib/locking/locking.h ++++ b/lib/locking/locking.h +@@ -16,7 +16,7 @@ + #ifndef _LVM_LOCKING_H + #define _LVM_LOCKING_H + +-#include "lib/uuid/uuid.h" ++#include "lib/id/id.h" + #include "lib/config/config.h" + + struct logical_volume; +diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h +index 3752caf1e..7ec81f27d 100644 +--- a/lib/metadata/metadata-exported.h ++++ b/lib/metadata/metadata-exported.h +@@ -21,7 +21,7 @@ + #ifndef _LVM_METADATA_EXPORTED_H + #define _LVM_METADATA_EXPORTED_H + +-#include "lib/uuid/uuid.h" ++#include "lib/id/id.h" + #include "lib/metadata/pv.h" + #include "lib/metadata/vg.h" + #include "lib/metadata/lv.h" +diff --git a/lib/metadata/pv.h b/lib/metadata/pv.h +index ee2bd853b..7195f9a2d 100644 +--- a/lib/metadata/pv.h ++++ b/lib/metadata/pv.h +@@ -15,7 +15,7 @@ + #ifndef _LVM_PV_H + #define _LVM_PV_H + +-#include "lib/uuid/uuid.h" ++#include "lib/id/id.h" + #include "device_mapper/all.h" + + struct device; +diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h +index 92a15ef2f..0f5adb6ee 100644 +--- a/lib/metadata/vg.h ++++ b/lib/metadata/vg.h +@@ -15,7 +15,7 @@ + #ifndef _LVM_VG_H + #define _LVM_VG_H + +-#include "lib/uuid/uuid.h" ++#include "lib/id/id.h" + #include "device_mapper/all.h" + + struct cmd_context; +-- +2.52.0 + diff --git a/0058-autoreconf-reconfigure.patch b/0058-autoreconf-reconfigure.patch new file mode 100644 index 0000000..578185f --- /dev/null +++ b/0058-autoreconf-reconfigure.patch @@ -0,0 +1,113 @@ +From 5c44e8301451e0bace56c5f1400f11f4758d2aed Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Sun, 14 Dec 2025 17:16:22 +0100 +Subject: [PATCH 2/2] autoreconf: reconfigure + +Regenerate configure and configure.h.in after adding XFS header check. +--- + aclocal.m4 | 8 ++++---- + configure | 28 ++++++++++++++++++++++++++++ + include/configure.h.in | 3 +++ + 3 files changed, 35 insertions(+), 4 deletions(-) + +diff --git a/aclocal.m4 b/aclocal.m4 +index 5f3a3e9c4..fa488e1f8 100644 +--- a/aclocal.m4 ++++ b/aclocal.m4 +@@ -1,6 +1,6 @@ +-# generated automatically by aclocal 1.17 -*- Autoconf -*- ++# generated automatically by aclocal 1.18.1 -*- Autoconf -*- + +-# Copyright (C) 1996-2024 Free Software Foundation, Inc. ++# Copyright (C) 1996-2025 Free Software Foundation, Inc. + + # This file is free software; the Free Software Foundation + # gives unlimited permission to copy and/or distribute it, +@@ -422,7 +422,7 @@ AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], + [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) + ])dnl PKG_HAVE_DEFINE_WITH_MODULES + +-# Copyright (C) 1999-2024 Free Software Foundation, Inc. ++# Copyright (C) 1999-2025 Free Software Foundation, Inc. + # + # This file is free software; the Free Software Foundation + # gives unlimited permission to copy and/or distribute it, +@@ -792,7 +792,7 @@ for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] + sys.exit(sys.hexversion < minverhex)" + AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) + +-# Copyright (C) 2001-2024 Free Software Foundation, Inc. ++# Copyright (C) 2001-2025 Free Software Foundation, Inc. + # + # This file is free software; the Free Software Foundation + # gives unlimited permission to copy and/or distribute it, +diff --git a/configure b/configure +index 342bd0047..e3eb37ff6 100755 +--- a/configure ++++ b/configure +@@ -6921,6 +6921,20 @@ then : + + fi + ++ for ac_header in xfs/xfs.h ++do : ++ ac_fn_c_check_header_compile "$LINENO" "xfs/xfs.h" "ac_cv_header_xfs_xfs_h" "#define _GNU_SOURCE 1 ++" ++if test "x$ac_cv_header_xfs_xfs_h" = xyes ++then : ++ printf "%s\n" "#define HAVE_XFS_XFS_H 1" >>confdefs.h ++ LVM_NO_XFS_WARN= ++else case e in #( ++ e) LVM_NO_XFS_WARN=y ;; ++esac ++fi ++ ++done + for ac_header in libaio.h + do : + ac_fn_c_check_header_compile "$LINENO" "libaio.h" "ac_cv_header_libaio_h" "$ac_includes_default" +@@ -12183,6 +12197,14 @@ then : + test $ac_status = 0; }; then + LOCKDSANLOCK_SUPPORT=400 + fi ++ if test -n "$PKG_CONFIG" && \ ++ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.1.0\""; } >&5 ++ ($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.1.0") 2>&5 ++ ac_status=$? ++ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; then ++ LOCKDSANLOCK_SUPPORT=410 ++fi + + pkg_failed=no + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsanlock_client >= 3.7.0" >&5 +@@ -18224,6 +18246,12 @@ then : + printf "%s\n" "$as_me: WARNING: Only libdm part can be build without libaio: make [install_]device-mapper" >&2;} + fi + ++if test -n "$LVM_NO_XFS_WARN" ++then : ++ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'lvextend --resizefs' is less capable without xfs/xfs.h (see package: xfsprogs devel)" >&5 ++printf "%s\n" "$as_me: WARNING: 'lvextend --resizefs' is less capable without xfs/xfs.h (see package: xfsprogs devel)" >&2;} ++fi ++ + if test "$ODIRECT" != "yes" + then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: O_DIRECT disabled: low-memory pvmove may lock up" >&5 +diff --git a/include/configure.h.in b/include/configure.h.in +index 3fe1dc85b..eee47a36d 100644 +--- a/include/configure.h.in ++++ b/include/configure.h.in +@@ -549,6 +549,9 @@ + /* Define to 1 if 'vfork' works. */ + #undef HAVE_WORKING_VFORK + ++/* Define to 1 if you have the header file. */ ++#undef HAVE_XFS_XFS_H ++ + /* Define to 1 if the system has the type '_Bool'. */ + #undef HAVE__BOOL + +-- +2.52.0 + diff --git a/lvm2.spec b/lvm2.spec index fa9835d..6dfe8dd 100644 --- a/lvm2.spec +++ b/lvm2.spec @@ -54,7 +54,7 @@ Version: 2.03.33 %if 0%{?from_snapshot} Release: 0.1.20211115git%{shortcommit}%{?dist}%{?rel_suffix} %else -Release: 3%{?dist}%{?rel_suffix} +Release: 4%{?dist}%{?rel_suffix} %endif License: GPL-2.0-only URL: https://sourceware.org/lvm2 @@ -116,6 +116,13 @@ Patch50: 0050-test-add-new-test-for-snapshot-on-raid-creation-acti.patch Patch51: 0051-WHATS_NEW-update.patch # RHEL-135072: Patch52: 0052-integrity-allow-creating-imeta-with-more-than-one-se.patch +# RHEL-116883: +Patch53: 0053-lvresize-fix-xfs-size-checks.patch +Patch54: 0054-configure-check-for-xfs-header-file.patch +Patch55: 0055-log-add-string.h.patch +Patch56: 0056-filesystem-refactor-code-working-with-xfs.patch +Patch57: 0057-lib-rename-uuid.c-to-id.c.patch +Patch58: 0058-autoreconf-reconfigure.patch BuildRequires: make BuildRequires: gcc @@ -128,6 +135,8 @@ BuildRequires: ncurses-devel BuildRequires: libedit-devel BuildRequires: libaio-devel BuildRequires: libnvme-devel +BuildRequires: xfsprogs-devel +#BuildRequires: libuuid-devel %if %{enable_lockd_dlm} BuildRequires: dlm-devel >= %{dlm_version} %endif @@ -747,6 +756,9 @@ An extensive functional testsuite for LVM2. %endif %changelog +* Thu Jan 15 2026 Marian Csontos - 2.03.33-4 +- Handle wrong XFS reported size when shrinking LV immediately after growing. + * Tue Jan 06 2026 Marian Csontos - 2.03.33-3 - Allow integrity to use multiple segments for metadata.