main - vgremove: remove online files in run dir
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=0887896847807e159a7...
Commit: 0887896847807e159a70edc5ac92a4030c13923a
Parent: a2d33cdfc516d946d390645cc694e745008b6fc0
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Sep 14 09:13:58 2022 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Sep 14 14:19:29 2022 -0500
vgremove: remove online files in run dir
These files are automatically cleared on reboot given
that /run is tmpfs, and that remains the primary way
of clearing online files.
But, if there's extreme use of vgcreate+pvscan+vgremove
between reboots, then removing online files in vgremove
will limit the number of unused online files using space
in /run.
---
lib/device/online.c | 56 +++++++++++++++++++++++++++++++++++++++
lib/device/online.h | 2 ++
test/shell/vgchange-pvs-online.sh | 39 +++++++++++++++++++++++++--
tools/pvscan.c | 17 +-----------
tools/vgremove.c | 3 +++
5 files changed, 99 insertions(+), 18 deletions(-)
diff --git a/lib/device/online.c b/lib/device/online.c
index 79652d990..7ffe14b18 100644
--- a/lib/device/online.c
+++ b/lib/device/online.c
@@ -17,6 +17,7 @@
#include "lib/commands/toolcontext.h"
#include "lib/device/device.h"
#include "lib/device/online.h"
+#include "lib/metadata/metadata.h"
#include <dirent.h>
@@ -504,3 +505,58 @@ do_lookup:
if ((rv < 0) && stat(PVS_LOOKUP_DIR, &st))
log_error_pvscan(cmd, "Failed to create %s %d", PVS_LOOKUP_DIR, errno);
}
+
+void online_lookup_file_remove(const char *vgname)
+{
+ char path[PATH_MAX];
+
+ if (dm_snprintf(path, sizeof(path), "%s/%s", PVS_LOOKUP_DIR, vgname) < 0) {
+ log_error("Path %s/%s is too long.", PVS_LOOKUP_DIR, vgname);
+ return;
+ }
+
+ log_debug("Unlink pvs_lookup: %s", path);
+
+ if (unlink(path) && (errno != ENOENT))
+ log_sys_debug("unlink", path);
+}
+
+static int _online_pvid_file_remove(char *pvid)
+{
+ char path[PATH_MAX];
+
+ if (dm_snprintf(path, sizeof(path), "%s/%s", PVS_ONLINE_DIR, pvid) < 0)
+ return_0;
+ if (!unlink(path))
+ return 1;
+ return 0;
+}
+
+/*
+ * Reboot automatically clearing tmpfs on /run is the main method of removing
+ * online files. It's important to note that removing the online files for a
+ * VG is not a technical requirement for anything and could easily be skipped
+ * if it had any downside. It's only done to clean up the space used in /run
+ * by the online files, e.g. if there happens to be an extreme amount of
+ * vgcreate/pvscan/vgremove between reboots that are leaving a large number of
+ * useless online files consuming tmpfs space.
+ */
+void online_vgremove(struct volume_group *vg)
+{
+ char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
+ struct pv_list *pvl;
+
+ /*
+ * online files may not exist for the vg if there has been no
+ * pvscans or autoactivation.
+ */
+
+ online_vg_file_remove(vg->name);
+ online_lookup_file_remove(vg->name);
+
+ dm_list_iterate_items(pvl, &vg->pvs) {
+ memcpy(pvid, &pvl->pv->id.uuid, ID_LEN);
+ _online_pvid_file_remove(pvid);
+ }
+}
+
diff --git a/lib/device/online.h b/lib/device/online.h
index 850b03db8..488129e3f 100644
--- a/lib/device/online.h
+++ b/lib/device/online.h
@@ -54,5 +54,7 @@ void online_dir_setup(struct cmd_context *cmd);
int get_pvs_online(struct dm_list *pvs_online, const char *vgname);
int get_pvs_lookup(struct dm_list *pvs_online, const char *vgname);
void free_po_list(struct dm_list *list);
+void online_lookup_file_remove(const char *vgname);
+void online_vgremove(struct volume_group *vg);
#endif
diff --git a/test/shell/vgchange-pvs-online.sh b/test/shell/vgchange-pvs-online.sh
index 8812de1a3..a1fc3a427 100644
--- a/test/shell/vgchange-pvs-online.sh
+++ b/test/shell/vgchange-pvs-online.sh
@@ -192,6 +192,41 @@ check lv_field $vg2/$lv1 lv_active "active"
vgchange -an $vg1
vgchange -an $vg2
-vgremove -f $vg1
-vgremove -f $vg2
+# vgremove clears online files
+
+PVID1=$(pvs "$bd1" --noheading -o uuid | tr -d - | awk '{print $1}')
+PVID2=$(pvs "$bd2" --noheading -o uuid | tr -d - | awk '{print $1}')
+PVID3=$(pvs "$bd3" --noheading -o uuid | tr -d - | awk '{print $1}')
+
+_clear_online_files
+
+pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$bd1"
+pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$bd2"
+vgchange -aay --autoactivation event $vg1
+check lv_field $vg1/$lv1 lv_active "active"
+check lv_field $vg1/$lv2 lv_active "active"
+check lv_field $vg2/$lv1 lv_active ""
+
+pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$bd3"
+vgchange -aay --autoactivation event $vg2
+check lv_field $vg2/$lv1 lv_active "active"
+
+ls "$RUNDIR/lvm/pvs_online/$PVID1"
+ls "$RUNDIR/lvm/pvs_online/$PVID2"
+ls "$RUNDIR/lvm/pvs_online/$PVID3"
+ls "$RUNDIR/lvm/pvs_lookup/$vg1"
+ls "$RUNDIR/lvm/vgs_online/$vg1"
+ls "$RUNDIR/lvm/vgs_online/$vg2"
+
+vgremove -y $vg1
+
+not ls "$RUNDIR/lvm/pvs_online/$PVID1"
+not ls "$RUNDIR/lvm/pvs_online/$PVID2"
+not ls "$RUNDIR/lvm/pvs_lookup/$vg1"
+not ls "$RUNDIR/lvm/vgs_online/$vg1"
+
+vgremove -y $vg2
+
+not ls "$RUNDIR/lvm/pvs_online/$PVID3"
+not ls "$RUNDIR/lvm/vgs_online/$vg2"
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 72c3279c3..1c58e4a5b 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -177,21 +177,6 @@ out:
return ret;
}
-static void _lookup_file_remove(char *vgname)
-{
- char path[PATH_MAX];
-
- if (dm_snprintf(path, sizeof(path), "%s/%s", PVS_LOOKUP_DIR, vgname) < 0) {
- log_error("Path %s/%s is too long.", PVS_LOOKUP_DIR, vgname);
- return;
- }
-
- log_debug("Unlink pvs_lookup: %s", path);
-
- if (unlink(path) && (errno != ENOENT))
- log_sys_debug("unlink", path);
-}
-
/*
* When a device goes offline we only know its major:minor, not its PVID.
* Since the dev isn't around, we can't read it to get its PVID, so we have to
@@ -233,7 +218,7 @@ static void _online_pvid_file_remove_devno(int major, int minor)
if (file_vgname[0]) {
online_vg_file_remove(file_vgname);
- _lookup_file_remove(file_vgname);
+ online_lookup_file_remove(file_vgname);
}
}
}
diff --git a/tools/vgremove.c b/tools/vgremove.c
index b6685ae2a..a3252ae80 100644
--- a/tools/vgremove.c
+++ b/tools/vgremove.c
@@ -14,6 +14,7 @@
*/
#include "tools.h"
+#include "lib/device/online.h"
static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg,
@@ -75,6 +76,8 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
if (!force && !vg_remove_check(vg))
return_ECMD_FAILED;
+ online_vgremove(vg);
+
vg_remove_pvs(vg);
if (!vg_remove(vg))
8 months, 3 weeks
master - configure: update
by Marian Csontos
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=a2d33cdfc516d946d39...
Commit: a2d33cdfc516d946d390645cc694e745008b6fc0
Parent: bf386411b87047e37e394b3c46c336507c80bd68
Author: Marian Csontos <mcsontos(a)redhat.com>
AuthorDate: Wed Sep 14 15:16:30 2022 +0200
Committer: Marian Csontos <mcsontos(a)redhat.com>
CommitterDate: Wed Sep 14 15:16:30 2022 +0200
configure: update
---
configure | 22 ++++++++++++++++++++++
include/configure.h.in | 6 ++++--
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/configure b/configure
index 2dbcf1c40..742012569 100755
--- a/configure
+++ b/configure
@@ -735,6 +735,7 @@ HAVE_VALGRIND
HAVE_REALTIME
HAVE_LIBDL
BLKDEACTIVATE
+LVRESIZE_FS_HELPER_PATH
FSADM_PATH
FSADM
ELDFLAGS
@@ -1012,6 +1013,7 @@ with_confdir
with_staticdir
with_usrlibdir
with_usrsbindir
+with_libexecdir
with_udev_prefix
with_udevdir
with_systemdsystemunitdir
@@ -1813,6 +1815,7 @@ Optional Packages:
--with-staticdir=DIR static binaries in DIR [EPREFIX/sbin]
--with-usrlibdir=DIR usrlib in DIR [PREFIX/lib]
--with-usrsbindir=DIR usrsbin executables in DIR [PREFIX/sbin]
+ --with-libexecdir=DIR libexec executables in DIR [PREFIX/libexec]
--with-udev-prefix=UPREFIX
install udev rule files in UPREFIX [EPREFIX]
--with-udevdir=DIR udev rules in DIR [UPREFIX/lib/udev/rules.d]
@@ -14652,6 +14655,16 @@ else $as_nop
fi
+
+# Check whether --with-libexecdir was given.
+if test ${with_libexecdir+y}
+then :
+ withval=$with_libexecdir; libexecdir=$withval
+else $as_nop
+ libexecdir='${prefix}/libexec'
+fi
+
+
################################################################################
# Check whether --with-udev_prefix was given.
@@ -15155,6 +15168,13 @@ LVMIMPORTVDO_PATH="$SBINDIR/lvm_import_vdo"
printf "%s\n" "#define LVMIMPORTVDO_PATH \"$LVMIMPORTVDO_PATH\"" >>confdefs.h
+LIBEXECDIR="$(eval echo $(eval echo $libexecdir))"
+
+LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
+
+printf "%s\n" "#define LVRESIZE_FS_HELPER_PATH \"$LVRESIZE_FS_HELPER_PATH\"" >>confdefs.h
+
+
################################################################################
if test "$BUILD_DMEVENTD" = yes; then
@@ -15474,6 +15494,8 @@ printf "%s\n" "#define LVM_CONFIGURE_LINE \"$CONFIGURE_LINE\"" >>confdefs.h
+
+
diff --git a/include/configure.h.in b/include/configure.h.in
index 584c2b4f1..e7abca2f1 100644
--- a/include/configure.h.in
+++ b/include/configure.h.in
@@ -127,9 +127,8 @@
/* Define to 1 to include the LVM editline shell. */
#undef EDITLINE_SUPPORT
-/* Paths to binaries. */
+/* Path to fsadm binary. */
#undef FSADM_PATH
-#undef LVRESIZE_FS_HELPER_PATH
/* Define to use GNU versioning in the shared library. */
#undef GNU_SYMVER
@@ -599,6 +598,9 @@
/* Path to lvm binary. */
#undef LVM_PATH
+/* Path to lvresize_fs_helper script. */
+#undef LVRESIZE_FS_HELPER_PATH
+
/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
*/
#undef MAJOR_IN_MKDEV
8 months, 3 weeks
main - tests: skip new lvresize tests when missing new libblkid
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=bf386411b87047e37e3...
Commit: bf386411b87047e37e394b3c46c336507c80bd68
Parent: 264827cb98458f7100456eeebf7fdde8dcbc0ad4
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Sep 13 15:37:10 2022 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Sep 13 15:37:10 2022 -0500
tests: skip new lvresize tests when missing new libblkid
---
test/shell/fsadm-crypt-fsresize.sh | 7 +++++++
test/shell/lvresize-fs-crypt.sh | 7 +++++++
test/shell/lvresize-fs.sh | 6 ++++++
3 files changed, 20 insertions(+)
diff --git a/test/shell/fsadm-crypt-fsresize.sh b/test/shell/fsadm-crypt-fsresize.sh
index 009350800..65f555b29 100644
--- a/test/shell/fsadm-crypt-fsresize.sh
+++ b/test/shell/fsadm-crypt-fsresize.sh
@@ -22,6 +22,13 @@ export LVM_TEST_PREFER_BRD=0
aux prepare_vg 1 300
+# Tests require a libblkid version that shows FSLASTBLOCK
+lvcreate -n $lv1 -L 100 $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1"
+blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep FSLASTBLOCK || skip
+lvchange -an $vg
+lvremove $vg/$lv1
+
# set to "skip" to avoid testing given fs and test warning result
# i.e. check_reiserfs=skip
check_ext2=
diff --git a/test/shell/lvresize-fs-crypt.sh b/test/shell/lvresize-fs-crypt.sh
index 19c4e7d8e..0fbb2716e 100644
--- a/test/shell/lvresize-fs-crypt.sh
+++ b/test/shell/lvresize-fs-crypt.sh
@@ -17,6 +17,13 @@ SKIP_WITH_LVMPOLLD=1
aux prepare_vg 3 256
+# Tests require a libblkid version that shows FSLASTBLOCK
+lvcreate -n $lv1 -L 300 $vg
+mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
+blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep FSLASTBLOCK || skip
+lvchange -an $vg
+lvremove $vg/$lv1
+
mount_dir="mnt_lvresize_cr"
mkdir -p "$mount_dir"
diff --git a/test/shell/lvresize-fs.sh b/test/shell/lvresize-fs.sh
index b65e980b7..e4d315b95 100644
--- a/test/shell/lvresize-fs.sh
+++ b/test/shell/lvresize-fs.sh
@@ -28,6 +28,12 @@ aux prepare_vg 3 256
mount_dir="mnt_lvresize_fs"
mkdir -p "$mount_dir"
+# Tests require a libblkid version that shows FSLASTBLOCK
+lvcreate -n $lv1 -L 300 $vg
+mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
+blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep FSLASTBLOCK || skip
+lvchange -an $vg
+lvremove $vg/$lv1
#
# lvextend, no fs
8 months, 3 weeks
main - lvresize: add new options and defaults for fs handling
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=264827cb98458f71004...
Commit: 264827cb98458f7100456eeebf7fdde8dcbc0ad4
Parent: 18722dfdf4d3e6f172d0b2af8bbdc4a154ea1dc0
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Jun 14 15:20:21 2022 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Sep 13 15:15:05 2022 -0500
lvresize: add new options and defaults for fs handling
The new option "--fs String" for lvresize/lvreduce/lvextend
controls the handling of file systems before/after resizing
the LV. --resizefs is the same as --fs resize.
The new option "--fsmode String" can be used to control
mounting and unmounting of the fs during resizing.
Possible --fs values:
checksize
Only applies to reducing size; does nothing for extend.
Check the fs size and reduce the LV if the fs is not using
the affected space, i.e. the fs does not need to be shrunk.
Fail the command without reducing the fs or LV if the fs is
using the affected space.
resize
Resize the fs using the fs-specific resize command.
This may include mounting, unmounting, or running fsck.
See --fsmode to control mounting behavior, and --nofsck to
disable fsck.
resize_fsadm
Use the old method of calling fsadm to handle the fs
(deprecated.) Warning: this option does not prevent lvreduce
from destroying file systems that are unmounted (or mounted
if prompts are skipped.)
ignore
Resize the LV without checking for or handling a file system.
Warning: using ignore when reducing the LV size may destroy the
file system.
Possible --fsmode values:
manage
Mount or unmount the fs as needed to resize the fs,
and attempt to restore the original mount state at the end.
nochange
Do not mount or unmount the fs. If mounting or unmounting
is required to resize the fs, then do not resize the fs or
the LV and fail the command.
offline
Unmount the fs if it is mounted, and resize the fs while it
is unmounted. If mounting is required to resize the fs,
then do not resize the fs or the LV and fail the command.
Notes on lvreduce:
When no --fs or --resizefs option is specified:
. lvextend default behavior is fs ignore.
. lvreduce default behavior is fs checksize
(includes activating the LV.)
With the exception of --fs resize_fsadm|ignore, lvreduce requires
the recent libblkid fields FSLASTBLOCK and FSBLOCKSIZE.
FSLASTBLOCK*FSBLOCKSIZE is the last byte used by the fs on the LV,
which determines if reducing the fs is necessary.
---
configure.ac | 12 +
include/configure.h.in | 3 +-
lib/Makefile.in | 1 +
lib/activate/dev_manager.c | 75 +++
lib/activate/dev_manager.h | 2 +
lib/device/dev-type.c | 91 +++
lib/device/dev-type.h | 2 +
lib/device/filesystem.c | 400 ++++++++++++
lib/device/filesystem.h | 50 ++
lib/metadata/lv_manip.c | 763 ++++++++++++++++++++--
lib/metadata/metadata-exported.h | 7 +-
lib/metadata/metadata.c | 4 +-
lib/metadata/metadata.h | 2 +
scripts/Makefile.in | 6 +-
scripts/fsadm.sh | 2 +-
scripts/lvresize_fs_helper.sh | 466 ++++++++++++++
spec/packages.inc | 1 +
test/shell/fsadm-crypt-fsresize.sh | 612 ++++++++++++++++++
test/shell/fsadm-crypt.sh | 130 ++--
test/shell/fsadm.sh | 37 +-
test/shell/hints.sh | 4 +-
test/shell/lvresize-fs-crypt.sh | 131 ++++
test/shell/lvresize-fs.sh | 1186 +++++++++++++++++++++++++++++++++++
test/shell/lvresize-full.sh | 7 +-
test/shell/lvresize-mirror.sh | 2 +-
test/shell/lvresize-rounding.sh | 10 +-
test/shell/relative-sign-options.sh | 16 +-
tools/args.h | 35 +-
tools/command-lines.in | 12 +-
tools/lvresize.c | 115 +++-
30 files changed, 3987 insertions(+), 197 deletions(-)
diff --git a/configure.ac b/configure.ac
index 39bbc4fef..e0593aba0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1605,6 +1605,11 @@ AC_ARG_WITH(usrsbindir,
[usrsbin executables in DIR [PREFIX/sbin]]),
usrsbindir=$withval, usrsbindir='${prefix}/sbin')
+AC_ARG_WITH(libexecdir,
+ AS_HELP_STRING([--with-libexecdir=DIR],
+ [libexec executables in DIR [PREFIX/libexec]]),
+ libexecdir=$withval, libexecdir='${prefix}/libexec')
+
################################################################################
AC_ARG_WITH(udev_prefix,
AS_HELP_STRING([--with-udev-prefix=UPREFIX],
@@ -1709,6 +1714,11 @@ AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
LVMIMPORTVDO_PATH="$SBINDIR/lvm_import_vdo"
AC_DEFINE_UNQUOTED(LVMIMPORTVDO_PATH, ["$LVMIMPORTVDO_PATH"], [Path to lvm_import_vdo script.])
+LIBEXECDIR="$(eval echo $(eval echo $libexecdir))"
+
+LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
+AC_DEFINE_UNQUOTED(LVRESIZE_FS_HELPER_PATH, ["$LVRESIZE_FS_HELPER_PATH"], [Path to lvresize_fs_helper script.])
+
################################################################################
dnl -- dmeventd pidfile and executable path
if test "$BUILD_DMEVENTD" = yes; then
@@ -1878,6 +1888,7 @@ AC_SUBST(DM_LIB_PATCHLEVEL)
AC_SUBST(ELDFLAGS)
AC_SUBST(FSADM)
AC_SUBST(FSADM_PATH)
+AC_SUBST(LVRESIZE_FS_HELPER_PATH)
AC_SUBST(BLKDEACTIVATE)
AC_SUBST(HAVE_LIBDL)
AC_SUBST(HAVE_REALTIME)
@@ -1976,6 +1987,7 @@ AC_SUBST(systemdutildir)
AC_SUBST(tmpfilesdir)
AC_SUBST(usrlibdir)
AC_SUBST(usrsbindir)
+AC_SUBST(libexecdir)
################################################################################
dnl -- First and last lines should not contain files to generate in order to
diff --git a/include/configure.h.in b/include/configure.h.in
index 230658f7b..584c2b4f1 100644
--- a/include/configure.h.in
+++ b/include/configure.h.in
@@ -127,8 +127,9 @@
/* Define to 1 to include the LVM editline shell. */
#undef EDITLINE_SUPPORT
-/* Path to fsadm binary. */
+/* Paths to binaries. */
#undef FSADM_PATH
+#undef LVRESIZE_FS_HELPER_PATH
/* Define to use GNU versioning in the shared library. */
#undef GNU_SYMVER
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 3ab5cb2f1..3380b28fb 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.c \
device/online.c \
device/parse_vpd.c \
display/display.c \
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 2bfd275fd..5fec52a2a 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -4028,3 +4028,78 @@ out:
return r;
}
+
+/*
+ * crypt offset is usually the LUKS header size but can be larger.
+ * The LUKS header is usually 2MB for LUKS1 and 16MB for LUKS2.
+ * The offset needs to be subtracted from the LV size to get the
+ * size used to resize the crypt device.
+ */
+int get_crypt_table_offset(dev_t crypt_devt, uint32_t *offset_bytes)
+{
+ struct dm_task *dmt = dm_task_create(DM_DEVICE_TABLE);
+ uint64_t start, length;
+ char *target_type = NULL;
+ void *next = NULL;
+ char *params = NULL;
+ char offset_str[32] = { 0 };
+ int copy_offset = 0;
+ int spaces = 0;
+ int i, i_off = 0;
+
+ if (!dmt)
+ return_0;
+
+ if (!dm_task_set_major_minor(dmt, (int)MAJOR(crypt_devt), (int)MINOR(crypt_devt), 0)) {
+ dm_task_destroy(dmt);
+ return_0;
+ }
+
+ /* Non-blocking status read */
+ if (!dm_task_no_flush(dmt))
+ log_warn("WARNING: Can't set no_flush for dm status.");
+
+ if (!dm_task_run(dmt)) {
+ dm_task_destroy(dmt);
+ return_0;
+ }
+
+ next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
+
+ if (!target_type || !params || strcmp(target_type, "crypt")) {
+ dm_task_destroy(dmt);
+ return_0;
+ }
+
+ /*
+ * get offset from params string:
+ * <cipher> <key> <iv_offset> <device> <offset> [<#opt_params> <opt_params>]
+ * <offset> is reported in 512 byte sectors.
+ */
+ for (i = 0; i < strlen(params); i++) {
+ if (params[i] == ' ') {
+ spaces++;
+ if (spaces == 4)
+ copy_offset = 1;
+ if (spaces == 5)
+ break;
+ continue;
+ }
+ if (!copy_offset)
+ continue;
+
+ offset_str[i_off++] = params[i];
+
+ if (i_off == sizeof(offset_str)) {
+ offset_str[0] = '\0';
+ break;
+ }
+ }
+ dm_task_destroy(dmt);
+
+ if (!offset_str[0])
+ return_0;
+
+ *offset_bytes = ((uint32_t)strtoul(offset_str, NULL, 0) * 512);
+ return 1;
+}
diff --git a/lib/activate/dev_manager.h b/lib/activate/dev_manager.h
index 9980e1647..b494e3eaf 100644
--- a/lib/activate/dev_manager.h
+++ b/lib/activate/dev_manager.h
@@ -29,6 +29,8 @@ struct lv_seg_status;
int read_only_lv(const struct logical_volume *lv, const struct lv_activate_opts *laopts, const char *layer);
+int get_crypt_table_offset(dev_t crypt_devt, uint32_t *offset_bytes);
+
/*
* Constructor and destructor.
*/
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index b1cf5b431..fb6e9a444 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -26,6 +26,11 @@
#ifdef BLKID_WIPING_SUPPORT
#include <blkid.h>
+/*
+ * FIXME: recent addition to blkid.h copied here.
+ * Remove this and require a recent libblkid version from configure.
+ */
+#define BLKID_SUBLKS_FSINFO (1 << 11) /* read and define fs properties from superblock */
#endif
#ifdef UDEV_SYNC_SUPPORT
@@ -880,12 +885,98 @@ out:
blkid_free_probe(probe);
return ret;
}
+
+int fs_get_blkid(const char *pathname, struct fs_info *fsi)
+{
+ blkid_probe probe = NULL;
+ const char *str;
+ size_t len;
+ uint64_t fslastblock = 0;
+ unsigned int fsblocksize = 0;
+ int no_block_size = 0, no_fslastblock = 0, no_fsblocksize = 0;
+ int rc;
+
+ if (!(probe = blkid_new_probe_from_filename(pathname))) {
+ log_error("Failed libblkid probe setup for %s", pathname);
+ return 0;
+ }
+
+ blkid_probe_enable_superblocks(probe, 1);
+ blkid_probe_set_superblocks_flags(probe,
+ BLKID_SUBLKS_LABEL | BLKID_SUBLKS_LABELRAW |
+ BLKID_SUBLKS_UUID | BLKID_SUBLKS_UUIDRAW |
+ BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE |
+ BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION |
+ BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_FSINFO);
+ rc = blkid_do_safeprobe(probe);
+ if (rc < 0) {
+ log_error("Failed libblkid probe for %s", pathname);
+ blkid_free_probe(probe);
+ return 0;
+ } else if (rc == 1) {
+ /* no file system on the device */
+ log_print("No file system found on %s.", pathname);
+ fsi->nofs = 1;
+ blkid_free_probe(probe);
+ return 1;
+ }
+
+ if (!blkid_probe_lookup_value(probe, "TYPE", &str, &len) && len)
+ strncpy(fsi->fstype, str, sizeof(fsi->fstype)-1);
+ else {
+ /* any difference from blkid_do_safeprobe rc=1? */
+ log_print("No file system type on %s.", pathname);
+ fsi->nofs = 1;
+ blkid_free_probe(probe);
+ return 1;
+ }
+
+ if (!blkid_probe_lookup_value(probe, "BLOCK_SIZE", &str, &len) && len)
+ fsi->fs_block_size_bytes = atoi(str);
+ else
+ no_block_size = 1;
+
+ if (!blkid_probe_lookup_value(probe, "FSLASTBLOCK", &str, &len) && len)
+ fslastblock = strtoull(str, NULL, 0);
+ else
+ no_fslastblock = 1;
+
+ if (!blkid_probe_lookup_value(probe, "FSBLOCKSIZE", &str, &len) && len)
+ fsblocksize = (unsigned int)atoi(str);
+ else
+ no_fsblocksize = 1;
+
+ blkid_free_probe(probe);
+
+ /* We don't expect to get this info for luks */
+ if (strcmp(fsi->fstype, "crypto_LUKS") && (no_block_size || no_fslastblock || no_fsblocksize)) {
+ log_print("Missing libblkid %s%s%sfor %s",
+ no_block_size ? "BLOCK_SIZE " : "",
+ no_fslastblock ? "FSLASTBLOCK " : "",
+ no_fsblocksize ? "FSBLOCKSIZE " : "",
+ pathname);
+ }
+
+ if (fslastblock && fsblocksize)
+ fsi->fs_last_byte = fslastblock * fsblocksize;
+
+ log_debug("libblkid TYPE %s BLOCK_SIZE %d FSLASTBLOCK %llu FSBLOCKSIZE %u fs_last_byte %llu",
+ fsi->fstype, fsi->fs_block_size_bytes, (unsigned long long)fslastblock, fsblocksize,
+ (unsigned long long)fsi->fs_last_byte);
+ return 1;
+}
+
#else
int fs_block_size_and_type(const char *pathname, uint32_t *fs_block_size_bytes, char *fstype, int *nofs)
{
log_debug("Disabled blkid BLOCK_SIZE for fs.");
return 0;
}
+int fs_get_blkid(const char *pathname, struct fs_info *fsi)
+{
+ log_debug("Disabled blkid for fs info.");
+ return 0;
+}
#endif
#ifdef BLKID_WIPING_SUPPORT
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
index 4f793b0e0..efbf995c2 100644
--- a/lib/device/dev-type.h
+++ b/lib/device/dev-type.h
@@ -18,6 +18,7 @@
#include "lib/device/device.h"
#include "lib/display/display.h"
#include "lib/label/label.h"
+#include "lib/device/filesystem.h"
#define NUMBER_OF_MAJORS 4096
@@ -103,6 +104,7 @@ int dev_is_lv(struct device *dev);
#define FSTYPE_MAX 16
int fs_block_size_and_type(const char *pathname, uint32_t *fs_block_size_bytes, char *fstype, int *nofs);
+int fs_get_blkid(const char *pathname, struct fs_info *fsi);
int dev_is_used_by_active_lv(struct cmd_context *cmd, struct device *dev, int *used_by_lv_count,
char **used_by_dm_name, char **used_by_vg_uuid, char **used_by_lv_uuid);
diff --git a/lib/device/filesystem.c b/lib/device/filesystem.c
new file mode 100644
index 000000000..c53a377ea
--- /dev/null
+++ b/lib/device/filesystem.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2022 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 "base/memory/zalloc.h"
+#include "lib/misc/lib.h"
+#include "lib/commands/toolcontext.h"
+#include "lib/device/device.h"
+#include "lib/device/dev-type.h"
+#include "lib/misc/lvm-exec.h"
+#include "lib/activate/dev_manager.h"
+
+#include <dirent.h>
+#include <mntent.h>
+#include <sys/ioctl.h>
+
+/*
+ * Set the path of the dm-crypt device, i.e. /dev/dm-N, that is using the LV.
+ */
+static int _get_crypt_path(dev_t lv_devt, char *lv_path, char *crypt_path)
+{
+ char holders_path[PATH_MAX];
+ char *holder_name;
+ DIR *dr;
+ struct stat st;
+ struct dirent *de;
+ int ret = 0;
+
+ if (dm_snprintf(holders_path, sizeof(holders_path), "%sdev/block/%d:%d/holders",
+ dm_sysfs_dir(), (int)MAJOR(lv_devt), (int)MINOR(lv_devt)) < 0)
+ return_0;
+
+ /* If the crypt dev is not active, there will be no LV holder. */
+ if (stat(holders_path, &st)) {
+ log_error("Missing %s for %s", crypt_path, lv_path);
+ return 0;
+ }
+
+ if (!(dr = opendir(holders_path))) {
+ log_error("Cannot open %s", holders_path);
+ return 0;
+ }
+
+ while ((de = readdir(dr))) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+ continue;
+
+ holder_name = de->d_name;
+
+ if (strncmp(holder_name, "dm", 2)) {
+ log_error("Unrecognized holder %s of %s", holder_name, lv_path);
+ ret = 0;
+ break;
+ }
+
+ /* We could read the holder's dm uuid to verify it's a crypt dev. */
+
+ if (dm_snprintf(crypt_path, PATH_MAX, "/dev/%s", holder_name) < 0) {
+ ret = 0;
+ stack;
+ break;
+ }
+ ret = 1;
+ break;
+ }
+ closedir(dr);
+ if (ret)
+ log_debug("Found holder %s of %s.", crypt_path, lv_path);
+ else
+ log_debug("No holder in %s", holders_path);
+ return ret;
+}
+
+int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv,
+ struct fs_info *fsi, int include_mount)
+{
+ char lv_path[PATH_MAX];
+ char crypt_path[PATH_MAX];
+ struct stat st_lv;
+ struct stat st_crypt;
+ struct stat st_top;
+ struct stat stme;
+ struct fs_info info;
+ FILE *fme = NULL;
+ struct mntent *me;
+ int ret;
+
+ if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", lv->vg->cmd->dev_dir,
+ lv->vg->name, lv->name) < 0) {
+ log_error("Couldn't create LV path for %s.", display_lvname(lv));
+ return 0;
+ }
+
+ if (stat(lv_path, &st_lv) < 0) {
+ log_error("Failed to get LV path %s", lv_path);
+ return 0;
+ }
+
+ memset(&info, 0, sizeof(info));
+
+ if (!fs_get_blkid(lv_path, &info)) {
+ log_error("No file system info from blkid for %s", display_lvname(lv));
+ return 0;
+ }
+
+ if (fsi->nofs)
+ return 1;
+
+ /*
+ * If there's a LUKS dm-crypt layer over the LV, then
+ * return fs info from that layer, setting needs_crypt
+ * to indicate a crypt layer between the fs and LV.
+ */
+ if (!strcmp(info.fstype, "crypto_LUKS")) {
+ if (!_get_crypt_path(st_lv.st_rdev, lv_path, crypt_path)) {
+ log_error("Cannot find active LUKS dm-crypt device using %s.",
+ display_lvname(lv));
+ return 0;
+ }
+
+ if (stat(crypt_path, &st_crypt) < 0) {
+ log_error("Failed to get crypt path %s", crypt_path);
+ return 0;
+ }
+
+ memset(&info, 0, sizeof(info));
+
+ log_print("File system found on crypt device %s on LV %s.",
+ crypt_path, display_lvname(lv));
+
+ 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));
+ return 0;
+ }
+ *fsi = info;
+ fsi->needs_crypt = 1;
+ fsi->crypt_devt = st_crypt.st_rdev;
+ memcpy(fsi->fs_dev_path, crypt_path, PATH_MAX);
+ st_top = st_crypt;
+
+ if (!get_crypt_table_offset(st_crypt.st_rdev, &fsi->crypt_offset_bytes)) {
+ log_error("Failed to get crypt data offset.");
+ return 0;
+ }
+ } else {
+ *fsi = info;
+ memcpy(fsi->fs_dev_path, lv_path, PATH_MAX);
+ st_top = st_lv;
+ }
+
+ if (!include_mount)
+ return 1;
+
+ if (!(fme = setmntent("/etc/mtab", "r")))
+ return_0;
+
+ ret = 1;
+
+ while ((me = getmntent(fme))) {
+ if (strcmp(me->mnt_type, fsi->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_top.st_rdev)
+ continue;
+
+ log_debug("fs_get_info %s is mounted \"%s\"", fsi->fs_dev_path, me->mnt_dir);
+ fsi->mounted = 1;
+ strncpy(fsi->mount_dir, me->mnt_dir, PATH_MAX-1);
+ }
+ endmntent(fme);
+
+ fsi->unmounted = !fsi->mounted;
+ return ret;
+}
+
+#define FS_CMD_MAX_ARGS 16
+
+int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
+ uint64_t newsize_bytes_fs)
+{
+ char crypt_path[PATH_MAX];
+ char newsize_str[16] = { 0 };
+ const char *argv[FS_CMD_MAX_ARGS + 4];
+ int args = 0;
+ int status;
+
+ if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)newsize_bytes_fs) < 0)
+ return_0;
+
+ if (dm_snprintf(crypt_path, sizeof(crypt_path), "/dev/dm-%d", (int)MINOR(fsi->crypt_devt)) < 0)
+ return_0;
+
+ argv[0] = LVRESIZE_FS_HELPER_PATH; /* from configure, usually in /usr/libexec */
+ argv[++args] = "--cryptresize";
+ argv[++args] = "--cryptpath";
+ argv[++args] = crypt_path;
+ argv[++args] = "--newsizebytes";
+ argv[++args] = newsize_str;
+ argv[++args] = NULL;
+
+ if (!exec_cmd(cmd, argv, &status, 1)) {
+ log_error("Failed to resize crypt dev with lvresize_fs_helper.");
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * The helper script does the following steps for reduce:
+ * devpath = $cryptpath ? $cryptpath : $lvpath
+ * if needs_unmount
+ * umount $mountdir
+ * if needs_fsck
+ * e2fsck -f -p $devpath
+ * if needs_mount
+ * mount $devpath $tmpdir
+ * if $fstype == "ext"
+ * resize2fs $devpath $newsize_kb
+ * if needs_crypt
+ * cryptsetup resize --size $newsize_sectors $cryptpath
+ *
+ * Note: when a crypt layer is included, newsize_bytes_fs is smaller
+ * than newsize_bytes_lv because of the crypt header.
+ */
+
+int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
+ uint64_t newsize_bytes_fs, char *fsmode)
+{
+ char lv_path[PATH_MAX];
+ char crypt_path[PATH_MAX];
+ char newsize_str[16] = { 0 };
+ const char *argv[FS_CMD_MAX_ARGS + 4];
+ char *devpath;
+ int args = 0;
+ int status;
+
+ if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)newsize_bytes_fs) < 0)
+ return_0;
+
+ if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", lv->vg->cmd->dev_dir, lv->vg->name, lv->name) < 0)
+ return_0;
+
+ argv[0] = LVRESIZE_FS_HELPER_PATH; /* from configure, usually in /usr/libexec */
+ argv[++args] = "--fsreduce";
+ argv[++args] = "--fstype";
+ argv[++args] = fsi->fstype;
+ argv[++args] = "--lvpath";
+ argv[++args] = lv_path;
+
+ if (newsize_bytes_fs) {
+ argv[++args] = "--newsizebytes";
+ argv[++args] = newsize_str;
+ }
+ if (fsi->mounted) {
+ argv[++args] = "--mountdir";
+ argv[++args] = fsi->mount_dir;
+ }
+
+ if (fsi->needs_unmount)
+ argv[++args] = "--unmount";
+ if (fsi->needs_mount)
+ argv[++args] = "--mount";
+ if (fsi->needs_fsck)
+ argv[++args] = "--fsck";
+
+ if (fsi->needs_crypt) {
+ if (dm_snprintf(crypt_path, sizeof(crypt_path), "/dev/dm-%d", (int)MINOR(fsi->crypt_devt)) < 0)
+ return_0;
+ argv[++args] = "--cryptresize";
+ argv[++args] = "--cryptpath";
+ argv[++args] = crypt_path;
+ }
+
+ /*
+ * fsmode manage means the fs should be remounted after
+ * resizing if it was unmounted.
+ */
+ if (fsi->needs_unmount && !strcmp(fsmode, "manage"))
+ argv[++args] = "--remount";
+
+ argv[++args] = NULL;
+
+ devpath = fsi->needs_crypt ? crypt_path : (char *)display_lvname(lv);
+
+ log_print("Reducing file system %s to %s (%llu bytes) on %s...",
+ fsi->fstype, display_size(cmd, newsize_bytes_fs/512),
+ (unsigned long long)newsize_bytes_fs, devpath);
+
+ if (!exec_cmd(cmd, argv, &status, 1)) {
+ log_error("Failed to reduce file system with lvresize_fs_helper.");
+ return 0;
+ }
+
+ log_print("Reduced file system %s on %s.", fsi->fstype, devpath);
+
+ return 1;
+}
+
+/*
+ * The helper script does the following steps for extend:
+ * devpath = $cryptpath ? $cryptpath : $lvpath
+ * if needs_unmount
+ * umount $mountdir
+ * if needs_fsck
+ * e2fsck -f -p $devpath
+ * if needs_crypt
+ * cryptsetup resize $cryptpath
+ * if needs_mount
+ * mount $devpath $tmpdir
+ * if $fstype == "ext"
+ * resize2fs $devpath
+ * if $fstype == "xfs"
+ * xfs_growfs $devpath
+ *
+ * Note: when a crypt layer is included, newsize_bytes_fs is smaller
+ * than newsize_bytes_lv because of the crypt header.
+ */
+
+int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
+ uint64_t newsize_bytes_fs, char *fsmode)
+{
+ char lv_path[PATH_MAX];
+ char crypt_path[PATH_MAX];
+ const char *argv[FS_CMD_MAX_ARGS + 4];
+ char *devpath;
+ int args = 0;
+ int status;
+
+ if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", lv->vg->cmd->dev_dir, lv->vg->name, lv->name) < 0)
+ return_0;
+
+ argv[0] = LVRESIZE_FS_HELPER_PATH; /* from configure, usually in /usr/libexec */
+ argv[++args] = "--fsextend";
+ argv[++args] = "--fstype";
+ argv[++args] = fsi->fstype;
+ argv[++args] = "--lvpath";
+ argv[++args] = lv_path;
+
+ if (fsi->mounted) {
+ argv[++args] = "--mountdir";
+ argv[++args] = fsi->mount_dir;
+ }
+
+ if (fsi->needs_unmount)
+ argv[++args] = "--unmount";
+ if (fsi->needs_mount)
+ argv[++args] = "--mount";
+ if (fsi->needs_fsck)
+ argv[++args] = "--fsck";
+
+ if (fsi->needs_crypt) {
+ if (dm_snprintf(crypt_path, sizeof(crypt_path), "/dev/dm-%d", (int)MINOR(fsi->crypt_devt)) < 0)
+ return_0;
+ argv[++args] = "--cryptresize";
+ argv[++args] = "--cryptpath";
+ argv[++args] = crypt_path;
+ }
+
+ /*
+ * fsmode manage means the fs should be remounted after
+ * resizing if it was unmounted.
+ */
+ if (fsi->needs_unmount && !strcmp(fsmode, "manage"))
+ argv[++args] = "--remount";
+
+ argv[++args] = NULL;
+
+ devpath = fsi->needs_crypt ? crypt_path : (char *)display_lvname(lv);
+
+ log_print("Extending file system %s to %s (%llu bytes) on %s...",
+ fsi->fstype, display_size(cmd, newsize_bytes_fs/512),
+ (unsigned long long)newsize_bytes_fs, devpath);
+
+ if (!exec_cmd(cmd, argv, &status, 1)) {
+ log_error("Failed to extend file system with lvresize_fs_helper.");
+ return 0;
+ }
+
+ log_print("Extended file system %s on %s.", fsi->fstype, devpath);
+
+ return 1;
+}
+
diff --git a/lib/device/filesystem.h b/lib/device/filesystem.h
new file mode 100644
index 000000000..7a34d2ae0
--- /dev/null
+++ b/lib/device/filesystem.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 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
+ */
+
+#ifndef _FILESYSTEM_H
+#define _FILESYSTEM_H
+
+#define FSTYPE_MAX 16
+
+struct fs_info {
+ char fstype[FSTYPE_MAX];
+ char mount_dir[PATH_MAX];
+ char fs_dev_path[PATH_MAX]; /* usually lv dev, can be crypt dev */
+ unsigned int fs_block_size_bytes; /* 512 or 4k */
+ 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 */
+
+ unsigned nofs:1;
+ unsigned unmounted:1;
+ unsigned mounted:1;
+ /* for resizing */
+ unsigned needs_reduce:1;
+ unsigned needs_extend:1;
+ unsigned needs_fsck:1;
+ unsigned needs_unmount:1;
+ unsigned needs_mount:1;
+ 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_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
+ uint64_t newsize_bytes, char *fsmode);
+int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
+ 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);
+#endif
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index e819db8d5..71aee7fb7 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -31,6 +31,7 @@
#include "lib/locking/lvmlockd.h"
#include "lib/label/label.h"
#include "lib/misc/lvm-signal.h"
+#include "lib/device/filesystem.h"
#ifdef HAVE_BLKZEROOUT
#include <sys/ioctl.h>
@@ -4946,13 +4947,6 @@ static int _lv_reduce_confirmation(struct logical_volume *lv,
return 0;
}
- if (lv_is_vdo(lv) && !info.exists) {
- log_error("Logical volume %s must be activated "
- "before reducing device size.",
- display_lvname(lv));
- return 0;
- }
-
if (!info.exists)
return 1;
@@ -5565,10 +5559,8 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
if (!(seg_size = lp->extents - existing_logical_extents))
return 1; /* No change in metadata size */
}
- } else { /* If reducing, find stripes, stripesize & size of last segment */
- if (lp->stripes || lp->stripe_size || lp->mirrors)
- log_print_unless_silent("Ignoring stripes, stripesize and mirrors "
- "arguments when reducing.");
+ } else {
+ /* If reducing, find stripes, stripesize & size of last segment */
if (lp->sign == SIGN_MINUS) {
if (lp->extents >= existing_extents) {
@@ -5933,7 +5925,7 @@ static void _setup_params_for_extend_metadata(struct logical_volume *lv,
lp->percent = PERCENT_NONE;
lp->segtype = mseg->segtype;
lp->mirrors = seg_is_mirrored(mseg) ? lv_mirror_count(lv) : 0;
- lp->resizefs = 0;
+ lp->fsopt[0] = '\0';
lp->stripes = lp->mirrors ? mseg->area_count / lp->mirrors : 0;
lp->stripe_size = mseg->stripe_size;
}
@@ -5974,6 +5966,581 @@ static int _lv_resize_check_used(struct logical_volume *lv)
return 1;
}
+/*
+ * --fs checksize: check fs size and allow the lv to reduce if the fs is not
+ * using the affected space, i.e. the fs does not need to be
+ * resized. fail the command without reducing the fs or lv if
+ * the fs is using the affected space.
+ *
+ * --fs resize --fsmode manage: resize the fs, mounting/unmounting the fs
+ * as needed, but avoiding mounting/unmounted when possible.
+ *
+ * --fs resize --fsmode nochange: resize the fs without changing the current
+ * mount/unmount state. fail the command without reducing the
+ * fs or lv if the fs resize would require mounting or unmounting.
+ *
+ * --fs resize --fsmode offline: resize the fs only while it's unmounted
+ * unmounting the fs if needed. fail the commandn without
+ * reducing the fs or lv if the fs resize would require having
+ * the fs mounted.
+ *
+ * --fs resize_fsadm: old method using fsadm script to do everything
+ */
+static int _fs_reduce_allow(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvresize_params *lp, uint64_t newsize_bytes_lv,
+ uint64_t newsize_bytes_fs, struct fs_info *fsi)
+{
+ const char *fs_reduce_cmd = "";
+ const char *cmp_desc = "";
+ int equal = 0, smaller = 0, larger = 0;
+ int is_ext_fstype = 0;
+ int confirm_mount_change = 0;
+
+ /*
+ * Allow reducing the LV for other fs types if the fs is not using
+ * space that's being reduced.
+ */
+ if (!strcmp(fsi->fstype, "ext2") ||
+ !strcmp(fsi->fstype, "ext3") ||
+ !strcmp(fsi->fstype, "ext4") ||
+ !strcmp(fsi->fstype, "xfs")) {
+ log_debug("Found fs %s last_byte %llu newsize_bytes_fs %llu",
+ fsi->fstype,
+ (unsigned long long)fsi->fs_last_byte,
+ (unsigned long long)newsize_bytes_fs);
+ if (!strncmp(fsi->fstype, "ext", 3)) {
+ is_ext_fstype = 1;
+ fs_reduce_cmd = " resize2fs";
+ }
+ }
+
+ if (!fsi->mounted)
+ log_print("File system %s%s found on %s.",
+ fsi->fstype, fsi->needs_crypt ? "+crypto_LUKS" : "",
+ display_lvname(lv));
+ else
+ log_print("File system %s%s found on %s mounted at %s.",
+ fsi->fstype, fsi->needs_crypt ? "+crypto_LUKS" : "",
+ display_lvname(lv), fsi->mount_dir);
+
+ if (!fsi->fs_last_byte) {
+ log_error("File system size unknown: update libblkid for FSLASTBLOCK, or see --fs resize_fsadm.");
+ return 0;
+ }
+
+ if ((equal = (fsi->fs_last_byte == newsize_bytes_fs)))
+ cmp_desc = "equal to";
+ else if ((smaller = (fsi->fs_last_byte < newsize_bytes_fs)))
+ cmp_desc = "smaller than";
+ else if ((larger = (fsi->fs_last_byte > newsize_bytes_fs)))
+ cmp_desc = "larger than";
+
+ log_print("File system size (%s) is %s the requested size (%s).",
+ display_size(cmd, fsi->fs_last_byte/512), cmp_desc,
+ display_size(cmd, newsize_bytes_fs/512));
+
+ /*
+ * FS reduce is not needed, it's not using the affected space.
+ */
+ if (smaller || equal) {
+ log_print("File system reduce is not needed, skipping.");
+ fsi->needs_reduce = 0;
+ return 1;
+ }
+
+ /*
+ * FS reduce is required, but checksize does not allow it.
+ */
+ if (!strcmp(lp->fsopt, "checksize")) {
+ if (is_ext_fstype)
+ log_error("File system reduce is required (see resize2fs or --resizefs.)");
+ else
+ log_error("File system reduce is required and not supported (%s).", fsi->fstype);
+ return 0;
+ }
+
+ /*
+ * FS reduce required, ext* supports it, xfs does not.
+ */
+ if (is_ext_fstype) {
+ log_print("File system reduce is required using resize2fs.");
+ } else {
+ log_error("File system reduce is required and not supported (%s).", fsi->fstype);
+ return 0;
+ }
+
+ /*
+ * Set fstype-specific requirements for running fs resize command.
+ * ext2,3,4 require the fs to be unmounted to shrink with resize2fs,
+ * and they require e2fsck to be run first, unless resize2fs -f is used.
+ */
+ if (is_ext_fstype) {
+ /* it's traditional to run fsck before shrink */
+ if (!lp->nofsck)
+ fsi->needs_fsck = 1;
+
+ /* ext2,3,4 require fs to be unmounted to shrink */
+ if (fsi->mounted)
+ fsi->needs_unmount = 1;
+
+ fsi->needs_reduce = 1;
+ } else {
+ /*
+ * Shouldn't reach here since no other fs types get this far.
+ * A future fs supporting shrink may require the fs to be
+ * mounted or unmounted to run the fs shrink command.
+ * set fsi->needs_unmount or fs->needs_mount according to
+ * the fs-specific shrink command's requirement.
+ */
+ log_error("File system %s: fs reduce not implemented.", fsi->fstype);
+ return 0;
+ }
+
+ /*
+ * FS reduce may require mounting or unmounting, check the fsopt value
+ * from the user, and the current mount state to decide if fs resize
+ * can be done.
+ */
+ if (!strcmp(lp->fsopt, "resize") && !strcmp(lp->fsmode, "nochange")) {
+ /* can't mount|unmount to run fs resize */
+ if (fsi->needs_mount) {
+ log_error("File system needs to be mounted to reduce fs (see --fsmode).");
+ return 0;
+ }
+ if (fsi->needs_unmount) {
+ log_error("File system needs to be unmounted to reduce fs (see --fsmode).");
+ return 0;
+ }
+ } else if (!strcmp(lp->fsopt, "resize") && !strcmp(lp->fsmode, "offline")) {
+ /* we can unmount if needed to run fs resize */
+ if (fsi->needs_mount) {
+ log_error("File system needs to be mounted to reduce fs (see --fsmode).");
+ return 0;
+ }
+ } else if (!strcmp(lp->fsopt, "resize") && !strcmp(lp->fsmode, "manage")) {
+ /* we can mount|unmount as needed to run fs resize */
+ /* confirm mount change unless --fsmode manage is set explicitly */
+
+ if (fsi->needs_mount || fsi->needs_unmount)
+ confirm_mount_change = 1;
+
+ if (lp->user_set_fsmode)
+ confirm_mount_change = 0;
+ } else {
+ log_error("Unknown file system resize options: --fs %s --fsmode %s", lp->fsopt, lp->fsmode);
+ return 0;
+ }
+
+ /*
+ * If future file systems can be reduced while mounted, then suppress
+ * needs_fsck here if the fs is already mounted.
+ */
+
+ if (fsi->needs_unmount)
+ log_print("File system unmount is needed for reduce.");
+ if (fsi->needs_fsck)
+ log_print("File system fsck will be run before reduce.");
+ if (fsi->needs_mount)
+ log_print("File system mount is needed for reduce.");
+ if (fsi->needs_crypt)
+ log_print("cryptsetup resize is needed for reduce.");
+
+ /*
+ * Use a confirmation prompt because mount|unmount is needed, and
+ * no specific --fsmode was set (i.e. the user did not give specific
+ * direction about how to handle mounting|unmounting with --fsmode.)
+ */
+ if (!lp->yes && confirm_mount_change) {
+ if (yes_no_prompt("Continue with %s file system reduce steps:%s%s%s%s%s? [y/n]:",
+ fsi->fstype,
+ fsi->needs_unmount ? " unmount," : "",
+ fsi->needs_fsck ? " fsck," : "",
+ fsi->needs_mount ? " mount," : "",
+ fsi->needs_crypt ? " cryptsetup," : "",
+ fsi->needs_reduce ? fs_reduce_cmd : "") == 'n') {
+ log_error("File system not reduced.");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int _fs_extend_allow(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvresize_params *lp, struct fs_info *fsi)
+{
+ const char *fs_extend_cmd = "";
+ int is_ext_fstype = 0;
+ int confirm_mount_change = 0;
+
+ if (!strcmp(fsi->fstype, "ext2") ||
+ !strcmp(fsi->fstype, "ext3") ||
+ !strcmp(fsi->fstype, "ext4") ||
+ !strcmp(fsi->fstype, "xfs")) {
+ log_debug("Found fs %s last_byte %llu",
+ fsi->fstype, (unsigned long long)fsi->fs_last_byte);
+ if (!strncmp(fsi->fstype, "ext", 3))
+ is_ext_fstype = 1;
+ } else {
+ log_error("File system extend is not supported (%s).", fsi->fstype);
+ return 0;
+ }
+
+ if (!fsi->mounted)
+ log_print("File system %s%s found on %s.",
+ fsi->fstype, fsi->needs_crypt ? "+crypto_LUKS" : "",
+ display_lvname(lv));
+ else
+ log_print("File system %s%s found on %s mounted at %s.",
+ fsi->fstype, fsi->needs_crypt ? "+crypto_LUKS" : "",
+ display_lvname(lv), fsi->mount_dir);
+
+ /*
+ * FS extend may require mounting or unmounting, check the fsopt value
+ * from the user, and the current mount state to decide if fs extend
+ * can be done.
+ */
+
+ if (is_ext_fstype) {
+ fs_extend_cmd = " resize2fs";
+
+ /*
+ * ext* can be extended while it's mounted or unmounted. If
+ * the fs is unmounted, it's traditional to run fsck before
+ * running the fs extend.
+ *
+ * --fs resize --fsmode nochange: don't change mount condition.
+ * if mounted: fs_extend
+ * if unmounted: fsck, fs_extend
+ *
+ * --fs resize --fsmode offline: extend offline, so unmount first if mounted.
+ * if mounted: unmount, fsck, fs_extend
+ * if unmounted: fsck, fs_extend
+ *
+ * --fs resize --fsmode manage: do any mount or unmount that's necessary,
+ * avoiding unnecessary mounting/unmounting.
+ * if mounted: fs_extend
+ * if unmounted: fsck, fs_extend
+ */
+ if (!strcmp(lp->fsopt, "resize") && !strcmp(lp->fsmode, "nochange")) {
+ if (fsi->mounted)
+ fsi->needs_extend = 1;
+ else if (fsi->unmounted) {
+ fsi->needs_fsck = 1;
+ fsi->needs_extend = 1;
+ }
+ } else if (!strcmp(lp->fsopt, "resize") && !strcmp(lp->fsmode, "offline")) {
+ if (fsi->mounted) {
+ fsi->needs_unmount = 1;
+ fsi->needs_fsck = 1;
+ fsi->needs_extend = 1;
+ } else if (fsi->unmounted) {
+ fsi->needs_fsck = 1;
+ fsi->needs_extend = 1;
+ }
+ } else if (!strcmp(lp->fsopt, "resize") && !strcmp(lp->fsmode, "manage")) {
+ if (fsi->mounted)
+ fsi->needs_extend = 1;
+ else if (fsi->unmounted) {
+ fsi->needs_fsck = 1;
+ fsi->needs_extend = 1;
+ }
+ }
+
+ if (lp->nofsck)
+ fsi->needs_fsck = 0;
+
+ } else if (!strcmp(fsi->fstype, "xfs")) {
+ fs_extend_cmd = " xfs_growfs";
+
+ /*
+ * xfs must be mounted to extend.
+ *
+ * --fs resize --fsmode nochange: don't change mount condition.
+ * if mounted: fs_extend
+ * if unmounted: fail
+ *
+ * --fs resize --fsmode offline: extend offline, so unmount first if mounted.
+ * if mounted: fail
+ * if unmounted: fail
+ *
+ * --fs resize --fsmode manage: do any mount or unmount that's necessary,
+ * avoiding unnecessary mounting/unmounting.
+ * if mounted: fs_extend
+ * if unmounted: mount, fs_extend
+ */
+ if (!strcmp(lp->fsopt, "resize") && !strcmp(lp->fsmode, "nochange")) {
+ if (fsi->mounted)
+ fsi->needs_extend = 1;
+ else if (fsi->unmounted) {
+ log_error("File system must be mounted to extend (see --fsmode).");
+ return 0;
+ }
+ } else if (!strcmp(lp->fsopt, "resize") && !strcmp(lp->fsmode, "offline")) {
+ log_error("File system must be mounted to extend (see --fsmode).");
+ return 0;
+ } else if (!strcmp(lp->fsopt, "resize") && !strcmp(lp->fsmode, "manage")) {
+ if (fsi->mounted)
+ fsi->needs_extend = 1;
+ else if (fsi->unmounted) {
+ fsi->needs_mount = 1;
+ fsi->needs_extend = 1;
+ }
+ }
+
+ } else {
+ /* shouldn't reach here */
+ log_error("File system type %s not handled.", fsi->fstype);
+ return 0;
+ }
+
+ /*
+ * Skip needs_fsck if the fs is mounted and we can extend the fs while
+ * it's mounted.
+ */
+ if (fsi->mounted && !fsi->needs_unmount && fsi->needs_fsck) {
+ log_print("File system fsck skipped for extending mounted fs.");
+ fsi->needs_fsck = 0;
+ }
+
+ if (fsi->needs_unmount)
+ log_print("File system unmount is needed for extend.");
+ if (fsi->needs_fsck)
+ log_print("File system fsck will be run before extend.");
+ if (fsi->needs_mount)
+ log_print("File system mount is needed for extend.");
+ if (fsi->needs_crypt)
+ log_print("cryptsetup resize is needed for extend.");
+
+ /*
+ * Use a confirmation prompt when mount|unmount is needed if
+ * the user did not give specific direction about how to handle
+ * mounting|unmounting with --fsmode.
+ */
+ if (!strcmp(lp->fsopt, "resize") && !lp->user_set_fsmode &&
+ (fsi->needs_mount || fsi->needs_unmount))
+ confirm_mount_change = 1;
+
+ if (!lp->yes && confirm_mount_change) {
+ if (yes_no_prompt("Continue with %s file system extend steps:%s%s%s%s%s? [y/n]:",
+ fsi->fstype,
+ fsi->needs_unmount ? " unmount," : "",
+ fsi->needs_fsck ? " fsck," : "",
+ fsi->needs_mount ? " mount," : "",
+ fsi->needs_crypt ? " cryptsetup," : "",
+ fsi->needs_extend ? fs_extend_cmd : "") == 'n') {
+ log_error("File system not extended.");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int _fs_reduce(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvresize_params *lp)
+{
+ struct fs_info fsinfo;
+ struct fs_info fsinfo2;
+ uint64_t newsize_bytes_lv;
+ uint64_t newsize_bytes_fs;
+ int ret = 0;
+
+ memset(&fsinfo, 0, sizeof(fsinfo));
+ memset(&fsinfo2, 0, sizeof(fsinfo));
+
+ if (!fs_get_info(cmd, lv, &fsinfo, 1))
+ goto_out;
+
+ if (fsinfo.nofs) {
+ ret = 1;
+ goto_out;
+ }
+
+ /* extent_size units is SECTOR_SIZE (512) */
+ newsize_bytes_lv = lp->extents * lv->vg->extent_size * SECTOR_SIZE;
+ newsize_bytes_fs = newsize_bytes_lv;
+
+ /*
+ * If needs_crypt, then newsize_bytes passed to fs_reduce_script() and
+ * crypt_resize_script() needs to be decreased by the offset of crypt
+ * data on the LV (usually the size of the LUKS header which is usually
+ * 2MB for LUKS1 and 16MB for LUKS2.)
+ */
+ if (fsinfo.needs_crypt) {
+ newsize_bytes_fs -= fsinfo.crypt_offset_bytes;
+ log_print("File system size %llub is adjusted for crypt data offset %ub.",
+ (unsigned long long)newsize_bytes_fs, fsinfo.crypt_offset_bytes);
+ }
+
+ /*
+ * Based on the --fs command option, the fs type, the last block used,
+ * and the mount state, determine if LV reduce is allowed. If not
+ * returns 0 and lvreduce should fail. If allowed, returns 1 and sets
+ * fsinfo.needs_* for any steps that are required to reduce the LV.
+ */
+ if (!_fs_reduce_allow(cmd, lv, lp, newsize_bytes_lv, newsize_bytes_fs, &fsinfo))
+ goto_out;
+
+ /*
+ * Uncommon special case in which the FS does not need to be shrunk,
+ * 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()) {
+ ret = crypt_resize_script(cmd, lv, &fsinfo, newsize_bytes_fs);
+ goto out;
+ }
+
+ /*
+ * fs reduce is not needed to reduce the LV.
+ */
+ if (!fsinfo.needs_reduce) {
+ ret = 1;
+ goto_out;
+ }
+
+ if (test_mode()) {
+ if (fsinfo.needs_unmount)
+ log_print("Skip unmount in test mode.");
+ if (fsinfo.needs_fsck)
+ log_print("Skip fsck in test mode.");
+ if (fsinfo.needs_mount)
+ log_print("Skip mount in test mode.");
+ if (fsinfo.needs_crypt)
+ log_print("Skip cryptsetup in test mode.");
+ log_print("Skip fs reduce in test mode.");
+ ret = 1;
+ goto out;
+ }
+
+ /*
+ * mounting, unmounting, fsck, and shrink command can all take a long
+ * time to run, and this lvm command should not block other lvm
+ * commands from running during that time, so release the vg lock
+ * around the long-running steps, and reacquire after.
+ */
+ unlock_vg(cmd, lv->vg, lv->vg->name);
+
+ if (!fs_reduce_script(cmd, lv, &fsinfo, newsize_bytes_fs, lp->fsmode))
+ goto_out;
+
+ if (!lock_vol(cmd, lv->vg->name, LCK_VG_WRITE, NULL)) {
+ log_error("Failed to lock VG, cannot reduce LV.");
+ ret = 0;
+ goto out;
+ }
+
+ /*
+ * Check that the vg wasn't changed while it was unlocked.
+ * (can_use_one_scan: check just one mda in the vg for changes)
+ */
+ cmd->can_use_one_scan = 1;
+ if (scan_text_mismatch(cmd, lv->vg->name, NULL)) {
+ log_print("VG was changed during fs operations, restarting.");
+ lp->vg_changed_error = 1;
+ ret = 0;
+ goto out;
+ }
+
+ /*
+ * 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))
+ goto_out;
+
+ if (fsinfo.fs_last_byte && (fsinfo2.fs_last_byte > newsize_bytes_fs)) {
+ log_error("File system last byte %llu is greater than new size %llu bytes.",
+ (unsigned long long)fsinfo2.fs_last_byte,
+ (unsigned long long)newsize_bytes_fs);
+ goto_out;
+ }
+
+ ret = 1;
+ out:
+ return ret;
+}
+
+static int _fs_extend(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvresize_params *lp)
+{
+ struct fs_info fsinfo;
+ uint64_t newsize_bytes_lv;
+ uint64_t newsize_bytes_fs;
+ int ret = 0;
+
+ memset(&fsinfo, 0, sizeof(fsinfo));
+
+ if (!fs_get_info(cmd, lv, &fsinfo, 1))
+ goto_out;
+
+ if (fsinfo.nofs) {
+ ret = 1;
+ goto_out;
+ }
+
+ /*
+ * Note: here in the case of extend, newsize_bytes_lv/newsize_bytes_fs
+ * are only calculated and used for log messages. The extend commands
+ * do not use these values, they just extend to the new LV size that
+ * is visible to them.
+ */
+
+ /* extent_size units is SECTOR_SIZE (512) */
+ newsize_bytes_lv = lp->extents * lv->vg->extent_size * SECTOR_SIZE;
+ newsize_bytes_fs = newsize_bytes_lv;
+ if (fsinfo.needs_crypt) {
+ newsize_bytes_fs -= fsinfo.crypt_offset_bytes;
+ log_print("File system size %llub is adjusted for crypt data offset %ub.",
+ (unsigned long long)newsize_bytes_fs, fsinfo.crypt_offset_bytes);
+ }
+
+ /*
+ * Decide if fs should be extended based on the --fs option,
+ * the fs type and the mount state.
+ */
+ if (!_fs_extend_allow(cmd, lv, lp, &fsinfo))
+ goto_out;
+
+ /*
+ * fs extend is not needed
+ */
+ if (!fsinfo.needs_extend) {
+ ret = 1;
+ goto_out;
+ }
+
+ if (test_mode()) {
+ if (fsinfo.needs_unmount)
+ log_print("Skip unmount in test mode.");
+ if (fsinfo.needs_fsck)
+ log_print("Skip fsck in test mode.");
+ if (fsinfo.needs_mount)
+ log_print("Skip mount in test mode.");
+ if (fsinfo.needs_crypt)
+ log_print("Skip cryptsetup in test mode.");
+ log_print("Skip fs extend in test mode.");
+ ret = 1;
+ goto out;
+ }
+
+ /*
+ * mounting, unmounting and extend command can all take a long
+ * time to run, and this lvm command should not block other lvm
+ * commands from running during that time, so release the vg
+ * lock around the long-running steps.
+ */
+ unlock_vg(cmd, lv->vg, lv->vg->name);
+
+ if (!fs_extend_script(cmd, lv, &fsinfo, newsize_bytes_fs, lp->fsmode))
+ goto_out;
+
+ ret = 1;
+ out:
+ return ret;
+}
+
int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
struct lvresize_params *lp)
{
@@ -5989,7 +6556,9 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
int meta_size_matches = 0;
int is_extend = (lp->resize == LV_EXTEND);
int is_reduce = (lp->resize == LV_REDUCE);
+ int is_active = 0;
int activated = 0;
+ int activated_checksize = 0;
int status;
int ret = 0;
@@ -6018,26 +6587,6 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
- /*
- * resizefs applies to the LV command arg, not to the top LV or lower
- * resizable LV.
- */
- if (lp->resizefs) {
- if (!lv_is_active(lv)) {
- log_error("Logical volume %s must be activated before resizing filesystem.",
- display_lvname(lv));
- return 0;
- }
- /* types of LVs that can hold a file system */
- if (!(lv_is_linear(lv) || lv_is_striped(lv) || lv_is_raid(lv) ||
- lv_is_mirror(lv) || lv_is_thin_volume(lv) || lv_is_vdo(lv) ||
- lv_is_cache(lv) || lv_is_writecache(lv))) {
- log_print_unless_silent("Ignoring --resizefs for LV type %s.",
- seg ? seg->segtype->name : "unknown");
- lp->resizefs = 0;
- }
- }
-
/*
* Figure out which LVs are going to be extended, and set params
* to the requested extents/size for each. Some LVs are extended
@@ -6197,10 +6746,6 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
if (!_lv_resize_check_type(lv_main, lp))
return_0;
-
- if (is_reduce && !main_size_matches && !lp->resizefs &&
- !_lv_reduce_confirmation(lv, lp))
- return_0;
}
/*
@@ -6265,20 +6810,93 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
* So active temporarily pool LV (with on disk metadata) then use
* suspend and resume and deactivate pool LV, instead of searching for
* an active thin volume.
+ *
+ * FIXME: why are thin pools activated where other LV types return
+ * error if inactive?
*/
if (lv_is_thin_pool(lv_top) && !lv_is_active(lv_top)) {
- if (!activation()) {
- log_error("Cannot resize %s without using device-mapper kernel driver.",
- display_lvname(lv_top));
- return_0;
+ if (!activation()) {
+ log_error("Cannot activate to resize %s without using device-mapper kernel driver.",
+ display_lvname(lv_top));
+ return 0;
}
if (!activate_lv(cmd, lv_top)) {
log_error("Failed to activate %s.", display_lvname(lv_top));
- return_0;
+ return 0;
}
+ if (!sync_local_dev_names(cmd))
+ stack;
activated = 1;
}
+ /*
+ * Disable fsopt checksize for lvextend.
+ */
+ if (is_extend && !strcmp(lp->fsopt, "checksize"))
+ lp->fsopt[0] = '\0';
+
+ /*
+ * Disable fsopt if LV type cannot hold a file system.
+ */
+ if (lp->fsopt[0] &&
+ !(lv_is_linear(lv) || lv_is_striped(lv) || lv_is_raid(lv) ||
+ lv_is_mirror(lv) || lv_is_thin_volume(lv) || lv_is_vdo(lv) ||
+ lv_is_cache(lv) || lv_is_writecache(lv))) {
+ log_print_unless_silent("Ignoring fs resizing options for LV type %s.",
+ seg ? seg->segtype->name : "unknown");
+ lp->fsopt[0] = '\0';
+ }
+
+ /*
+ * Using an option to resize the fs has always/traditionally required
+ * the LV to already be active, so keep that behavior. Reducing an
+ * inactive LV will activate the LV to look for a fs that would be
+ * damaged.
+ */
+ is_active = lv_is_active(lv_top);
+
+ if (is_reduce && !is_active && !strcmp(lp->fsopt, "checksize")) {
+ if (!activate_lv(cmd, lv_top)) {
+ log_error("Failed to activate %s to check for fs.", display_lvname(lv_top));
+ goto out;
+ }
+ if (!sync_local_dev_names(cmd))
+ stack;
+ activated_checksize = 1;
+
+ } else if (lp->fsopt[0] && !is_active) {
+ log_error("Logical volume %s must be active for file system %s.",
+ display_lvname(lv_top), lp->fsopt);
+ goto out;
+ }
+
+ /*
+ * Return an error without resizing the LV if the user requested
+ * a file system resize when no file system exists on the LV.
+ * (fs checksize does not require a fs to exist.)
+ */
+ if (lp->fsopt[0] && strcmp(lp->fsopt, "checksize") && lp->user_set_fs) {
+ char lv_path[PATH_MAX];
+ char fstype[FSTYPE_MAX];
+ int nofs = 0;
+
+ if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s", cmd->dev_dir,
+ lv_top->vg->name, lv_top->name) < 0) {
+ log_error("Couldn't create LV path for %s.", display_lvname(lv_top));
+ goto out;
+ }
+ if (!fs_block_size_and_type(lv_path, NULL, fstype, &nofs) || nofs) {
+ log_error("File system not found for --resizefs or --fs options.");
+ goto out;
+ }
+ }
+
+ /*
+ * Warn and confirm if checksize has been disabled for reduce.
+ */
+ if (is_reduce && !lp->fsopt[0] && !_lv_reduce_confirmation(lv_top, lp))
+ goto_out;
+
/*
* If the LV is locked due to being active, this lock call is a no-op.
* Otherwise, this acquires a transient lock on the lv (not PERSISTENT)
@@ -6286,25 +6904,30 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
if (!lockd_lv_resize(cmd, lv_top, "ex", 0, lp))
goto_out;
- /*
- * Check the file system, and shrink the fs before reducing lv.
- * TODO: libblkid fs type, fs last_block, mount state,
- * unlock vg, mount|unmount if needed, fork fs shrink,
- * lock vg, rescan devs, recheck fs type last_block.
- * (at end mount|unmount if needed to restore initial state.)
- */
- if (lp->resizefs && !lp->nofsck &&
+ /* Part of old approach to fs handling using fsadm. */
+ if (!strcmp(lp->fsopt, "resize_fsadm") && !lp->nofsck &&
!_fsadm_cmd(FSADM_CMD_CHECK, lv_top, 0, lp->yes, lp->force, &status)) {
if (status != FSADM_CHECK_FAILS_FOR_MOUNTED) {
log_error("Filesystem check failed.");
goto out;
}
- /* some filesystems support online resize */
}
- if (lp->resizefs && is_reduce &&
- !_fsadm_cmd(FSADM_CMD_RESIZE, lv_top, lp->extents, lp->yes, lp->force, NULL)) {
- log_error("Filesystem resize failed.");
- goto out;
+
+ if (is_reduce && lp->fsopt[0]) {
+ if (!strcmp(lp->fsopt, "resize_fsadm")) {
+ /* Old approach to fs handling using fsadm. */
+ if (!_fsadm_cmd(FSADM_CMD_RESIZE, lv_top, lp->extents, lp->yes, lp->force, NULL)) {
+ log_error("Filesystem resize failed.");
+ goto out;
+ }
+ } else {
+ /* New approach to fs handling using fs info. */
+ if (!_fs_reduce(cmd, lv_top, lp))
+ goto_out;
+ }
+
+ if (activated_checksize && !deactivate_lv(cmd, lv_top))
+ log_warn("Problem deactivating %s.", display_lvname(lv_top));
}
/*
@@ -6319,9 +6942,9 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
* Remove any striped raid reshape space for LV resizing (not common).
*/
if (lv_meta && first_seg(lv_meta)->reshape_len && !lv_raid_free_reshape_space(lv_meta))
- return_0;
+ goto_out;
if (lv_main && first_seg(lv_main)->reshape_len && !lv_raid_free_reshape_space(lv_main))
- return_0;
+ goto_out;
/*
* The core of the actual lv resizing.
@@ -6376,22 +6999,28 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
stack;
}
- /*
- * Extend the file system.
- * TODO: libblkid fs type, mount state,
- * unlock vg, mount|unmount if needed, fork fs grow,
- * mount|unmount if needed to restore initial state.
- */
- if (lp->resizefs && is_extend &&
- !_fsadm_cmd(FSADM_CMD_RESIZE, lv_top, lp->extents, lp->yes, lp->force, NULL)) {
- log_warn("Filesystem resize failed.");
- goto out;
+ if (is_extend && lp->fsopt[0]) {
+ if (!strcmp(lp->fsopt, "resize_fsadm")) {
+ /* Old approach to fs handling using fsadm. */
+ if (!_fsadm_cmd(FSADM_CMD_RESIZE, lv_top, lp->extents, lp->yes, lp->force, NULL)) {
+ log_error("File system extend error.");
+ lp->extend_fs_error = 1;
+ goto out;
+ }
+ } else {
+ /* New approach to fs handling using fs info. */
+ if (!_fs_extend(cmd, lv_top, lp)) {
+ log_error("File system extend error.");
+ lp->extend_fs_error = 1;
+ goto out;
+ }
+ }
}
ret = 1;
out:
- if (activated) {
+ if (activated || activated_checksize) {
if (!sync_local_dev_names(cmd))
stack;
if (!deactivate_lv(cmd, lv_top))
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 048b7553f..04f32cace 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -674,8 +674,11 @@ struct lvresize_params {
int force;
int nosync;
int nofsck;
- int resizefs;
int use_policies;
+ int user_set_fs;
+ int user_set_fsmode;
+ char fsopt[16]; /* set by --resizefs|--fs, empty for --fs ignore */
+ char fsmode[16]; /* set by --fsmode */
const struct segment_type *segtype;
unsigned mirrors;
@@ -695,6 +698,8 @@ struct lvresize_params {
int approx_alloc;
int extents_are_pes; /* Is 'extents' counting PEs or LEs? */
int size_changed; /* Was there actually a size change */
+ int extend_fs_error; /* FS extend error after LV extend success */
+ int vg_changed_error; /* VG metadata was modified during fs resize */
const char *lockopt;
char *lockd_lv_refresh_path; /* set during resize to use for refresh at the end */
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 95f25eef8..30b2c1779 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -4533,7 +4533,7 @@ void vg_write_commit_bad_mdas(struct cmd_context *cmd, struct volume_group *vg)
* reread metadata.
*/
-static bool _scan_text_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid)
+bool scan_text_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid)
{
DM_LIST_INIT(mda_list);
struct mda_list *mdal, *safe;
@@ -4706,7 +4706,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
* probably unnecessary; all commands could likely just check a single mda.
*/
- if (lvmcache_scan_mismatch(cmd, vgname, vgid) || _scan_text_mismatch(cmd, vgname, vgid)) {
+ if (lvmcache_scan_mismatch(cmd, vgname, vgid) || scan_text_mismatch(cmd, vgname, vgid)) {
log_debug_metadata("Rescanning devices for %s %s", vgname, writing ? "rw" : "");
if (writing)
lvmcache_label_rescan_vg_rw(cmd, vgname, vgid);
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 7f3cf9d29..95fd359c7 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -541,5 +541,7 @@ void set_pv_devices(struct format_instance *fid, struct volume_group *vg);
int get_visible_lvs_using_pv(struct cmd_context *cmd, struct volume_group *vg, struct device *dev,
struct dm_list *lvs_list);
+bool scan_text_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
+
#endif
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index ebcea92f9..9fcff37b0 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -56,7 +56,11 @@ install_device-mapper: $(DM_SCRIPTS:.sh=_install)
install_ocf: $(OCF_SCRIPTS:.ocf=_install)
-install: install_lvm2 install_ocf install_device-mapper
+install_libexec:
+ $(Q) $(INSTALL_SCRIPT) lvresize_fs_helper.sh $(libexecdir)/lvresize_fs_helper
+
+install: install_lvm2 install_ocf install_device-mapper install_libexec
+
# FIXME Customise for other distributions
install_initscripts:
diff --git a/scripts/fsadm.sh b/scripts/fsadm.sh
index 9ae422f55..d22c7d0a6 100755
--- a/scripts/fsadm.sh
+++ b/scripts/fsadm.sh
@@ -164,7 +164,7 @@ cleanup() {
export _FSADM_YES _FSADM_EXTOFF
unset FSADM_RUNNING
test -n "${LVM_BINARY-}" && PATH=$_SAVEPATH
- dry exec "$LVM" lvresize $VERB $FORCE -r -L"${NEWSIZE_ORIG}b" "$VOLUME_ORIG"
+ dry exec "$LVM" lvresize $VERB $FORCE $YES --fs resize_fsadm -L"${NEWSIZE_ORIG}b" "$VOLUME_ORIG"
fi
# error exit status for break
diff --git a/scripts/lvresize_fs_helper.sh b/scripts/lvresize_fs_helper.sh
new file mode 100755
index 000000000..031b8453b
--- /dev/null
+++ b/scripts/lvresize_fs_helper.sh
@@ -0,0 +1,466 @@
+#!/bin/bash
+#
+# Copyright (C) 2022 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 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
+
+errorexit() {
+ echo "$1" >&2
+ exit 1
+}
+
+logmsg() {
+ echo "$1"
+ logger "${SCRIPTNAME}: $1"
+}
+
+# Set to 1 while the fs is temporarily mounted on $TMPDIR
+TMP_MOUNT_DONE=0
+# Set to 1 if the fs resize command fails
+RESIZEFS_FAILED=0
+
+fsextend() {
+ if [ "$DO_UNMOUNT" -eq 1 ]; then
+ logmsg "unmount ${MOUNTDIR}"
+ umount "$MOUNTDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "unmount done"
+ else
+ logmsg "unmount failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_FSCK" -eq 1 ]; then
+ logmsg "e2fsck ${DEVPATH}"
+ e2fsck -f -p "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "e2fsck done"
+ else
+ logmsg "e2fsck failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_CRYPTRESIZE" -eq 1 ]; then
+ logmsg "cryptsetup resize ${DEVPATH}"
+ cryptsetup resize "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "cryptsetup done"
+ else
+ logmsg "cryptsetup failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_MOUNT" -eq 1 ]; then
+ logmsg "mount ${DEVPATH} ${TMPDIR}"
+ mount -t "$FSTYPE" "$DEVPATH" "$TMPDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "mount done"
+ TMP_MOUNT_DONE=1
+ else
+ logmsg "mount failed"
+ exit 1
+ fi
+ fi
+
+ if [[ "$FSTYPE" == "ext"* ]]; then
+ logmsg "resize2fs ${DEVPATH}"
+ resize2fs "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "resize2fs done"
+ else
+ logmsg "resize2fs failed"
+ RESIZEFS_FAILED=1
+ fi
+ elif [[ "$FSTYPE" == "xfs" ]]; then
+ logmsg "xfs_growfs ${DEVPATH}"
+ xfs_growfs "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "xfs_growfs done"
+ else
+ logmsg "xfs_growfs failed"
+ RESIZEFS_FAILED=1
+ fi
+ fi
+
+ # If the fs was temporarily mounted, now unmount it.
+ if [ $TMP_MOUNT_DONE -eq 1 ]; then
+ logmsg "cleanup unmount ${TMPDIR}"
+ umount "$TMPDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "cleanup unmount done"
+ TMP_MOUNT_DONE=0
+ rmdir "$TMPDIR"
+ else
+ logmsg "cleanup unmount failed"
+ exit 1
+ fi
+ fi
+
+ # If the fs was temporarily unmounted, now remount it.
+ # Not considered a command failure if this fails.
+ if [[ $DO_UNMOUNT -eq 1 && $REMOUNT -eq 1 ]]; then
+ logmsg "remount ${DEVPATH} ${MOUNTDIR}"
+ mount -t "$FSTYPE" "$DEVPATH" "$MOUNTDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "remount done"
+ else
+ logmsg "remount failed"
+ fi
+ fi
+
+ if [ $RESIZEFS_FAILED -eq 1 ]; then
+ logmsg "File system extend failed."
+ exit 1
+ fi
+
+ exit 0
+}
+
+fsreduce() {
+ if [ "$DO_UNMOUNT" -eq 1 ]; then
+ logmsg "unmount ${MOUNTDIR}"
+ umount "$MOUNTDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "unmount done"
+ else
+ logmsg "unmount failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_FSCK" -eq 1 ]; then
+ logmsg "e2fsck ${DEVPATH}"
+ e2fsck -f -p "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "e2fsck done"
+ else
+ logmsg "e2fsck failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_MOUNT" -eq 1 ]; then
+ logmsg "mount ${DEVPATH} ${TMPDIR}"
+ mount -t "$FSTYPE" "$DEVPATH" "$TMPDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "mount done"
+ TMP_MOUNT_DONE=1
+ else
+ logmsg "mount failed"
+ exit 1
+ fi
+ fi
+
+ if [[ "$FSTYPE" == "ext"* ]]; then
+ NEWSIZEKB=$(($NEWSIZEBYTES/1024))
+ logmsg "resize2fs ${DEVPATH} ${NEWSIZEKB}k"
+ resize2fs "$DEVPATH" "$NEWSIZEKB"k
+ if [ $? -eq 0 ]; then
+ logmsg "resize2fs done"
+ else
+ logmsg "resize2fs failed"
+ # will exit after cleanup unmount
+ RESIZEFS_FAILED=1
+ fi
+ fi
+
+ # If the fs was temporarily mounted, now unmount it.
+ if [ $TMP_MOUNT_DONE -eq 1 ]; then
+ logmsg "cleanup unmount ${TMPDIR}"
+ umount "$TMPDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "cleanup unmount done"
+ TMP_MOUNT_DONE=0
+ rmdir "$TMPDIR"
+ else
+ logmsg "cleanup unmount failed"
+ exit 1
+ fi
+ fi
+
+ if [ $RESIZEFS_FAILED -eq 1 ]; then
+ logmsg "File system reduce failed."
+ exit 1
+ fi
+
+ if [ "$DO_CRYPTRESIZE" -eq 1 ]; then
+ NEWSIZESECTORS=$(($NEWSIZEBYTES/512))
+ logmsg "cryptsetup resize ${NEWSIZESECTORS} sectors ${DEVPATH}"
+ cryptsetup resize --size "$NEWSIZESECTORS" "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "cryptsetup done"
+ else
+ logmsg "cryptsetup failed"
+ exit 1
+ fi
+ fi
+
+ # If the fs was temporarily unmounted, now remount it.
+ # Not considered a command failure if this fails.
+ if [[ $DO_UNMOUNT -eq 1 && $REMOUNT -eq 1 ]]; then
+ logmsg "remount ${DEVPATH} ${MOUNTDIR}"
+ mount -t "$FSTYPE" "$DEVPATH" "$MOUNTDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "remount done"
+ else
+ logmsg "remount failed"
+ fi
+ fi
+
+ exit 0
+}
+
+cryptresize() {
+ NEWSIZESECTORS=$(($NEWSIZEBYTES/512))
+ logmsg "cryptsetup resize ${NEWSIZESECTORS} sectors ${DEVPATH}"
+ cryptresize resize --size "$NEWSIZESECTORS" "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "cryptsetup done"
+ else
+ logmsg "cryptsetup failed"
+ exit 1
+ fi
+
+ exit 0
+}
+
+usage() {
+ echo "${SCRIPTNAME}: helper script called by lvresize to resize file systems."
+ echo ""
+ echo "${SCRIPTNAME} --fsextend --fstype name --lvpath path"
+ echo " [ --mountdir path ]"
+ echo " [ --mount ]"
+ echo " [ --unmount ]"
+ echo " [ --remount ]"
+ echo " [ --fsck ]"
+ echo " [ --cryptresize ]"
+ echo " [ --cryptpath path ]"
+ echo ""
+ echo "${SCRIPTNAME} --fsreduce --fstype name --lvpath path"
+ echo " [ --newsizebytes num ]"
+ echo " [ --mountdir path ]"
+ echo " [ --mount ]"
+ echo " [ --unmount ]"
+ echo " [ --remount ]"
+ echo " [ --fsck ]"
+ echo " [ --cryptresize ]"
+ echo " [ --cryptpath path ]"
+ echo ""
+ echo "${SCRIPTNAME} --cryptresize --cryptpath path --newsizebytes num"
+ echo ""
+ echo "Options:"
+ echo " --fsextend"
+ echo " Extend the file system."
+ echo " --fsreduce"
+ echo " Reduce the file system."
+ echo " --fstype name"
+ echo " The type of file system (ext*, xfs)."
+ echo " --lvpath path"
+ echo " The path to the LV being resized."
+ echo " --mountdir path"
+ echo " The file system is currently mounted here."
+ echo " --mount"
+ echo " Mount the file system on a temporary directory before resizing."
+ echo " --unmount"
+ echo " Unmount the file system before resizing."
+ echo " --remount"
+ echo " Remount the file system after resizing if unmounted."
+ echo " --fsck"
+ echo " Run fsck on the file system before resizing (only with ext*)."
+ echo " --newsizebytes num"
+ echo " The new size of the file system."
+ echo " --cryptresize"
+ echo " Resize the crypt device between the LV and file system."
+ echo " --cryptpath path"
+ echo " The path to the crypt device."
+ echo ""
+}
+
+#
+# BEGIN SCRIPT
+#
+PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH"
+SCRIPTNAME=$(basename "$0")
+
+# These are the only commands that this script will run.
+# Each is enabled (1) by the corresponding command options:
+# --fsextend, --fsreduce, --cryptresize, --mount, --unmount, --fsck
+DO_FSEXTEND=0
+DO_FSREDUCE=0
+DO_CRYPTRESIZE=0
+DO_MOUNT=0
+DO_UNMOUNT=0
+DO_FSCK=0
+
+# --remount: attempt to remount the fs if it was originally
+# mounted and the script unmounted it.
+REMOUNT=0
+
+if [ "$UID" != 0 ] && [ "$EUID" != 0 ]; then
+ errorexit "${SCRIPTNAME} must be run as root."
+fi
+
+GETOPT="getopt"
+
+OPTIONS=$("$GETOPT" -o h -l help,fsextend,fsreduce,cryptresize,mount,unmount,remount,fsck,fstype:,lvpath:,newsizebytes:,mountdir:,cryptpath: -n "${SCRIPTNAME}" -- "$@")
+eval set -- "$OPTIONS"
+
+while true
+do
+ case $1 in
+ --fsextend)
+ DO_FSEXTEND=1
+ shift
+ ;;
+ --fsreduce)
+ DO_FSREDUCE=1
+ shift
+ ;;
+ --cryptresize)
+ DO_CRYPTRESIZE=1
+ shift
+ ;;
+ --mount)
+ DO_MOUNT=1
+ shift
+ ;;
+ --unmount)
+ DO_UNMOUNT=1
+ shift
+ ;;
+ --fsck)
+ DO_FSCK=1
+ shift
+ ;;
+ --remount)
+ REMOUNT=1
+ shift
+ ;;
+ --fstype)
+ FSTYPE=$2;
+ shift; shift
+ ;;
+ --lvpath)
+ LVPATH=$2;
+ shift; shift
+ ;;
+ --newsizebytes)
+ NEWSIZEBYTES=$2;
+ shift; shift
+ ;;
+ --mountdir)
+ MOUNTDIR=$2;
+ shift; shift
+ ;;
+ --cryptpath)
+ CRYPTPATH=$2;
+ shift; shift
+ ;;
+ -h|--help)
+ usage
+ shift
+ exit 0
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ errorexit "Unknown option \"$1\."
+ exit 1
+ ;;
+ esac
+done
+
+#
+# Input arg checking
+#
+
+# There are three top level commands: --fsextend, --fsreduce, --cryptresize.
+if [[ "$DO_FSEXTEND" -eq 0 && "$DO_FSREDUCE" -eq 0 && "$DO_CRYPTRESIZE" -eq 0 ]]; then
+ errorexit "Missing --fsextend|--fsreduce|--cryptresize."
+fi
+
+if [[ "$DO_FSEXTEND" -eq 1 || "$DO_FSREDUCE" -eq 1 ]]; then
+ case "$FSTYPE" in
+ ext[234]) ;;
+ "xfs") ;;
+ *) errorexit "Cannot resize --fstype \"$FSTYPE\"."
+ esac
+
+ if [ -z "$LVPATH" ]; then
+ errorexit "Missing required --lvpath."
+ fi
+fi
+
+if [[ "$DO_CRYPTRESIZE" -eq 1 && -z "$CRYPTPATH" ]]; then
+ errorexit "Missing required --cryptpath for --cryptresize."
+fi
+
+if [ "$DO_CRYPTRESIZE" -eq 1 ]; then
+ DEVPATH=$CRYPTPATH
+else
+ DEVPATH=$LVPATH
+fi
+
+if [ -z "$DEVPATH" ]; then
+ errorexit "Missing path to device."
+fi
+
+if [ ! -e "$DEVPATH" ]; then
+ errorexit "Device does not exist \"$DEVPATH\"."
+fi
+
+if [[ "$DO_UNMOUNT" -eq 1 && -z "$MOUNTDIR" ]]; then
+ errorexit "Missing required --mountdir for --unmount."
+fi
+
+if [[ "$DO_FSREDUCE" -eq 1 && "$FSTYPE" == "xfs" ]]; then
+ errorexit "Cannot reduce xfs."
+fi
+
+if [[ "$DO_FSCK" -eq 1 && "$FSTYPE" == "xfs" ]]; then
+ errorexit "Cannot use --fsck with xfs."
+fi
+
+if [ "$DO_MOUNT" -eq 1 ]; then
+ TMPDIR=$(mktemp --suffix _lvresize_$$ -d -p /tmp)
+ if [ ! -e "$TMPDIR" ]; then
+ errorexit "Failed to create temp dir."
+ fi
+ # In case the script terminates without doing cleanup
+ function finish {
+ if [ "$TMP_MOUNT_DONE" -eq 1 ]; then
+ logmsg "exit unmount ${TMPDIR}"
+ umount "$TMPDIR"
+ rmdir "$TMPDIR"
+ fi
+ }
+ trap finish EXIT
+fi
+
+#
+# Main program function:
+# - the two main functions are fsextend and fsreduce.
+# - one special case function is cryptresize.
+#
+
+if [ "$DO_FSEXTEND" -eq 1 ]; then
+ fsextend
+elif [ "$DO_FSREDUCE" -eq 1 ]; then
+ fsreduce
+elif [ "$DO_CRYPTRESIZE" -eq 1 ]; then
+ cryptresize
+fi
+
diff --git a/spec/packages.inc b/spec/packages.inc
index f8271533a..cc1655ece 100644
--- a/spec/packages.inc
+++ b/spec/packages.inc
@@ -34,6 +34,7 @@ fi
%doc COPYING COPYING.LIB INSTALL README VERSION WHATS_NEW
%doc doc/lvm_fault_handling.txt
%{_sbindir}/fsadm
+%{_libexecdir}/lvresize_fs_helper
%{_sbindir}/lvchange
%{_sbindir}/lvconvert
%{_sbindir}/lvcreate
diff --git a/test/shell/fsadm-crypt-fsresize.sh b/test/shell/fsadm-crypt-fsresize.sh
new file mode 100644
index 000000000..009350800
--- /dev/null
+++ b/test/shell/fsadm-crypt-fsresize.sh
@@ -0,0 +1,612 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2008-2017 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_description='Exercise fsadm filesystem resize on crypt devices'
+
+SKIP_WITH_LVMPOLLD=1
+
+# FIXME: cannot use brd (ramdisk) - lsblk is NOT listing it
+# so lsblk usage should be replaced
+export LVM_TEST_PREFER_BRD=0
+
+. lib/inittest
+
+aux prepare_vg 1 300
+
+# set to "skip" to avoid testing given fs and test warning result
+# i.e. check_reiserfs=skip
+check_ext2=
+check_ext3=
+check_xfs=
+check_reiserfs=
+check_cryptsetup=
+DROP_SYMLINK=
+
+CRYPT_NAME="$PREFIX-tcrypt"
+CRYPT_DEV="$DM_DEV_DIR/mapper/$CRYPT_NAME"
+
+CRYPT_NAME2="$PREFIX-tcrypt2"
+CRYPT_DEV2="$DM_DEV_DIR/mapper/$CRYPT_NAME2"
+
+CRYPT_NAME_PLAIN="$PREFIX-tcryptp"
+CRYPT_DEV_PLAIN="$DM_DEV_DIR/mapper/$CRYPT_NAME_PLAIN"
+
+FORMAT_PARAMS="-i1"
+PWD1="93R4P4pIqAH8"
+PWD2="mymJeD8ivEhE"
+PWD3="ocMakf3fAcQO"
+SKIP_DETACHED=
+
+if which cryptsetup ; then
+ # use older format luks1 - otherwise the test would need to pass password everywhere...
+ case $(cryptsetup --version) in
+ "cryptsetup 2"*) FORMAT_PARAMS="$FORMAT_PARAMS --type luks1" ;;
+ esac
+else
+ check_cryptsetup=${check_cryptsetup:-cryptsetup}
+fi
+
+which mkfs.ext2 || check_ext2=${check_ext2:-mkfs.ext2}
+which mkfs.ext3 || check_ext3=${check_ext3:-mkfs.ext3}
+which fsck.ext3 || check_ext3=${check_ext3:-fsck.ext3}
+which mkfs.xfs || check_xfs=${check_xfs:-mkfs.xfs}
+which xfs_check || {
+ which xfs_repair || check_xfs=${check_xfs:-xfs_repair}
+}
+grep xfs /proc/filesystems || check_xfs=${check_xfs:-no_xfs}
+
+which mkfs.reiserfs || check_reiserfs=${check_reiserfs:-mkfs.reiserfs}
+which reiserfsck || check_reiserfs=${check_reiserfs:-reiserfsck}
+modprobe reiserfs || true
+grep reiserfs /proc/filesystems || check_reiserfs=${check_reiserfs:-no_reiserfs}
+
+vg_lv=$vg/$lv1
+vg_lv2=$vg/${lv1}bar
+vg_lv3=$vg/${lv1}plain
+dev_vg_lv="$DM_DEV_DIR/$vg_lv"
+dev_vg_lv2="$DM_DEV_DIR/$vg_lv2"
+dev_vg_lv3="$DM_DEV_DIR/$vg_lv3"
+mount_dir="mnt"
+
+test ! -d "$mount_dir" && mkdir "$mount_dir"
+
+crypt_close() {
+ aux udev_wait
+ cryptsetup remove "$1"
+ if [ "$?" -eq 0 -a -n "$DROP_SYMLINK" ]; then
+ rm -f "$DM_DEV_DIR/mapper/$1"
+ fi
+}
+
+cleanup_mounted_and_teardown()
+{
+ umount "$mount_dir" || true
+ crypt_close $CRYPT_NAME > /dev/null 2>&1 || true
+ crypt_close $CRYPT_NAME2 > /dev/null 2>&1 || true
+ crypt_close $CRYPT_NAME_PLAIN > /dev/null 2>&1 || true
+ aux teardown
+}
+
+fscheck_ext3()
+{
+ fsck.ext3 -p -F -f "$1"
+}
+
+fscheck_xfs()
+{
+ if which xfs_repair ; then
+ xfs_repair -n "$1"
+ else
+ xfs_check "$1"
+ fi
+}
+
+fscheck_reiserfs()
+{
+ reiserfsck --check -p -f "$1" </dev/null
+}
+
+check_missing()
+{
+ local t
+ eval "t=\$check_$1"
+ test -z "$t" && return 0
+ test "$t" = skip && return 1
+ echo "WARNING: fsadm test skipped $1 tests, $t tool is missing."
+ # trick to get test listed with warning
+ # should false;
+ return 1
+}
+
+get_crypt_kname() {
+ lsblk -r -n -o KNAME,NAME | grep "$1" | cut -d ' ' -f 1
+}
+
+
+# $1 device
+# $2 pass
+crypt_format() {
+ echo "$2" | cryptsetup luksFormat $FORMAT_PARAMS "$1"
+}
+
+
+# $1 device
+# $2 pass
+# $3 name
+crypt_open() {
+ local kname=
+ echo "$2" | cryptsetup luksOpen "$1" "$3"
+ test -L "$DM_DEV_DIR/mapper/$3" || {
+ kname=$(get_crypt_kname $3)
+ ln -s "/dev/$kname" "$DM_DEV_DIR/mapper/$3"
+ DROP_SYMLINK=1
+ }
+}
+
+# $1 data device
+# $2 pass
+# $3 name
+# $4 header
+crypt_open_detached() {
+ local kname=
+ echo "$2" | cryptsetup luksOpen --header "$4" "$1" "$3" || return $?
+ test -L "$DM_DEV_DIR/mapper/$3" || {
+ kname=$(get_crypt_kname $3)
+ ln -s "/dev/$kname" "$DM_DEV_DIR/mapper/$3"
+ DROP_SYMLINK=1
+ }
+}
+
+# $1 device
+# $2 pass
+# $3 name
+crypt_open_plain() {
+ local kname=
+ echo "$2" | cryptsetup create "$3" "$1"
+ test -L "$DM_DEV_DIR/mapper/$3" || {
+ kname=$(get_crypt_kname $3)
+ ln -s "/dev/$kname" "$DM_DEV_DIR/mapper/$3"
+ DROP_SYMLINK=1
+ }
+}
+
+# $1 device
+# $2 type
+create_crypt_device()
+{
+ crypt_format "$dev_vg_lv" $PWD1
+ crypt_open "$dev_vg_lv" $PWD1 "$CRYPT_NAME"
+
+ crypt_format "$dev_vg_lv2" $PWD2
+
+ if crypt_open_detached "$dev_vg_lv3" "$PWD2" "$PREFIX-test" "$dev_vg_lv2"; then
+ crypt_close "$PREFIX-test"
+ else
+ SKIP_DETACHED=1
+ fi
+}
+
+which lsblk > /dev/null || skip
+check_missing cryptsetup || skip
+
+vgchange -s 128k
+lvcreate -n $lv1 -L25M $vg
+lvcreate -n ${lv1}bar -L35M $vg
+lvcreate -n ${lv1}plain -L35M $vg
+create_crypt_device
+trap 'cleanup_mounted_and_teardown' EXIT
+
+
+# $1 LVM backend (vg/lv name)
+# $2 LVM backend device (/dev/vg/lv)
+# $3 active dm-crypt device (/dev/mapper/some_name )
+test_ext2_resize() {
+ mkfs.ext2 -b4096 -j "$3"
+
+ fsadm --lvresize resize $1 30M
+ # Fails - not enough space for 4M fs
+ not fsadm -y --lvresize resize "$2" 4M
+ lvresize -L+10M --fs resize $1
+ lvreduce -L10M --fs resize $1
+
+ fscheck_ext3 "$3"
+ mount "$3" "$mount_dir"
+ not fsadm -y --lvresize resize $1 4M
+ echo n | not lvresize -L4M --fs resize -n $1
+ lvresize -L+20M --fs resize -n $1
+ umount "$mount_dir"
+ fscheck_ext3 "$3"
+}
+
+test_ext2_small_shrink() {
+ mkfs.ext2 "$3"
+
+ lvresize -L-1 --fs resize $1
+ lvresize -L-1 --fs resize $1
+
+ fscheck_ext3 "$3"
+}
+
+test_ext3_resize() {
+ mkfs.ext3 -b4096 -j "$3"
+
+ fsadm --lvresize resize $1 30M
+ # Fails - not enough space for 4M fs
+ not fsadm -y --lvresize resize "$2" 4M
+ lvresize -L+10M --fs resize $1
+ lvreduce -L10M --fs resize $1
+
+ fscheck_ext3 "$3"
+ mount "$3" "$mount_dir"
+ lvresize -L+10M --fs resize $1
+
+ not fsadm -y --lvresize resize $1 4M
+ echo n | not lvresize -L4M --fs resize -n $1
+ lvresize -L+20M --fs resize -n $1
+ lvresize -L-10M --fs resize -y $1
+ umount "$mount_dir"
+}
+
+test_ext3_small_shrink() {
+ mkfs.ext3 "$3"
+
+ lvresize -L-1 --fs resize $1
+ lvresize -L-1 --fs resize $1
+
+ fscheck_ext3 "$3"
+}
+
+test_xfs_resize() {
+ mkfs.xfs -l internal,size=1536b -f "$3"
+
+ fsadm --lvresize resize $1 30M
+ # Fails - not enough space for 4M fs
+ lvresize -L+10M -y --fs resize $1
+ not lvreduce -L10M --fs resize $1
+
+ fscheck_xfs "$3"
+ mount "$3" "$mount_dir"
+ lvresize -L+10M -y --fs resize -n $1
+ umount "$mount_dir"
+ fscheck_xfs "$3"
+}
+
+test_xfs_small_shrink() {
+ mkfs.xfs -l internal,size=1536b -f "$3"
+
+ not lvresize -L-1 --fs resize $1
+ fscheck_xfs "$3"
+}
+
+test_reiserfs_resize() {
+ mkfs.reiserfs -s 513 -f "$3"
+
+ fsadm --lvresize resize $1 30M
+ lvresize -L+10M --fs resize $1
+ fsadm --lvresize -y resize $1 10M
+
+ fscheck_reiserfs "$3"
+ mount "$3" "$mount_dir"
+
+ fsadm -y --lvresize resize $1 30M
+ umount "$mount_dir"
+ fscheck_reiserfs "$3"
+}
+
+test_reiserfs_small_shrink() {
+ mkfs.reiserfs -s 513 -f "$3"
+
+ lvresize -y -L-1 --fs resize $1
+ lvresize -y -L-1 --fs resize $1
+
+ fscheck_reiserfs "$3"
+}
+
+# $1 LVM backend (vg/lv name)
+# $2 LVM backend device (/dev/vg/lv)
+# $3 active dm-crypt device (/dev/mapper/some_name )
+# $4 active dm-crypt name ( some_name )
+test_ext2_inactive() {
+ crypt_open "$2" $PWD2 "$4"
+ mkfs.ext2 -b4096 -j "$3"
+ crypt_close "$4"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+
+ crypt_open "$2" $PWD2 "$4"
+ fscheck_ext3 "$3"
+ crypt_close "$4"
+}
+
+test_ext3_inactive() {
+ crypt_open "$2" $PWD2 "$4"
+ mkfs.ext3 -b4096 -j "$3"
+ crypt_close "$4"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+
+ crypt_open "$2" $PWD2 "$4"
+ fscheck_ext3 "$3"
+ crypt_close "$4"
+}
+
+test_xfs_inactive() {
+ crypt_open "$2" $PWD2 "$4"
+ mkfs.xfs -l internal,size=1536b -f "$3"
+ crypt_close "$4"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+
+ crypt_open "$2" $PWD2 "$4"
+ fscheck_xfs "$3"
+ crypt_close "$4"
+}
+
+test_reiserfs_inactive() {
+ crypt_open "$2" $PWD2 "$4"
+ mkfs.reiserfs -s 513 -f "$3"
+ crypt_close "$4"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+
+ crypt_open "$2" $PWD2 "$4"
+ fscheck_reiserfs "$3"
+ crypt_close "$4"
+}
+
+# $1 LVM backend (vg/lv name)
+# $2 LVM backend device (/dev/vg/lv)
+# $3 active dm-crypt device (/dev/mapper/some_name )
+# $4 active dm-crypt name ( some_name )
+test_ext2_plain() {
+ mkfs.ext2 -b4096 -j "$3"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+ fscheck_ext3 "$3"
+
+ fsadm --cryptresize resize $3 30M
+ fsadm --cryptresize resize $3 35M
+ fscheck_ext3 "$3"
+
+ mount "$3" "$mount_dir"
+ not fsadm -y --cryptresize resize $3 4M
+ umount "$mount_dir"
+ fscheck_ext3 "$3"
+
+ crypt_close "$4"
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+ crypt_open_plain "$2" $PWD3 "$4"
+ fscheck_ext3 "$3"
+}
+
+test_ext3_plain() {
+ mkfs.ext3 -b4096 -j "$3"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+ fscheck_ext3 "$3"
+
+ fsadm --cryptresize resize $3 30M
+ fsadm --cryptresize resize $3 35M
+ fscheck_ext3 "$3"
+
+ mount "$3" "$mount_dir"
+ not fsadm -y --cryptresize resize $3 4M
+ umount "$mount_dir"
+ fscheck_ext3 "$3"
+
+ crypt_close "$4"
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+ crypt_open_plain "$2" $PWD3 "$4"
+ fscheck_ext3 "$3"
+}
+
+test_xfs_plain() {
+ mkfs.xfs -l internal,size=1536b -f "$3"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+ fscheck_xfs "$3"
+
+ lvresize -f -L+10M $1
+ fsadm --cryptresize resize $3 40M
+ # no shrink support in xfs
+ not fsadm --cryptresize resize $3 35M
+ fscheck_xfs "$3"
+
+ crypt_close "$4"
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+ crypt_open_plain "$2" $PWD3 "$4"
+ fscheck_xfs "$3"
+
+ lvresize -f -L35M $1
+}
+
+test_reiserfs_plain() {
+ mkfs.reiserfs -s 513 -f "$3"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L-10M --fs resize $1
+ fscheck_reiserfs "$3"
+
+ fsadm -y --cryptresize resize $3 30M
+ fsadm -y --cryptresize resize $3 35M
+ fscheck_reiserfs "$3"
+
+ crypt_close "$4"
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+ crypt_open_plain "$2" $PWD3 "$4"
+ fscheck_reiserfs "$3"
+}
+
+# $1 LVM header backend (vg/lv name)
+# $2 LVM hedaer backend device (/dev/vg/lv)
+# $3 active dm-crypt device (/dev/mapper/some_name )
+# $4 active dm-crypt name ( some_name )a
+test_ext2_detached() {
+ mkfs.ext2 -b4096 -j "$3"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+ fscheck_ext3 "$3"
+}
+
+test_ext3_detached() {
+ mkfs.ext3 -b4096 -j "$3"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+ fscheck_ext3 "$3"
+}
+
+test_xfs_detached() {
+ mkfs.xfs -l internal,size=1536b -f "$3"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+
+ fscheck_xfs "$3"
+}
+
+test_reiserfs_detached() {
+ mkfs.reiserfs -s 513 -f "$3"
+
+ not fsadm --lvresize resize $1 30M
+ not lvresize -L+10M --fs resize $1
+ not lvreduce -L10M --fs resize $1
+
+ fscheck_reiserfs "$3"
+}
+
+if check_missing ext2; then
+ test_ext2_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
+ lvresize --fs ignore -y -L25M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+
+ test_ext2_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
+
+ crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN"
+ test_ext2_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN"
+ crypt_close "$CRYPT_NAME_PLAIN"
+
+ lvresize --fs ignore -y -L100M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+ test_ext2_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
+ lvresize --fs ignore -y -L25M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+
+ if [ -z "$SKIP_DETACHED" ]; then
+ crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2"
+ test_ext2_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
+ crypt_close "$CRYPT_NAME2"
+ fi
+fi
+
+if check_missing ext3; then
+ test_ext3_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
+ lvresize --fs ignore -y -L25M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+
+ test_ext3_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
+
+ crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN"
+ test_ext3_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN"
+ crypt_close "$CRYPT_NAME_PLAIN"
+
+ lvresize --fs ignore -y -L100M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+ test_ext3_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
+ lvresize --fs ignore -y -L25M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+
+ if [ -z "$SKIP_DETACHED" ]; then
+ crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2"
+ test_ext3_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
+ crypt_close "$CRYPT_NAME2"
+ fi
+fi
+
+if check_missing xfs; then
+ test_xfs_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
+ lvresize --fs ignore -y -L25M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+
+ test_xfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
+
+ crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN"
+ test_xfs_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN"
+ crypt_close "$CRYPT_NAME_PLAIN"
+
+ lvresize --fs ignore -y -L100M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+ test_xfs_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
+ lvresize --fs ignore -y -L25M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+
+ if [ -z "$SKIP_DETACHED" ]; then
+ crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2"
+ test_xfs_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
+ crypt_close "$CRYPT_NAME2"
+ fi
+fi
+
+if check_missing reiserfs; then
+ test_reiserfs_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
+ lvresize --fs ignore -y -L25M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+
+ test_reiserfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
+
+ crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN"
+ test_reiserfs_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN"
+ crypt_close "$CRYPT_NAME_PLAIN"
+
+ lvresize --fs ignore -y -L100M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+ test_reiserfs_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
+ lvresize --fs ignore -y -L25M $vg_lv
+ cryptsetup resize $CRYPT_NAME
+
+ if [ -z "$SKIP_DETACHED" ]; then
+ crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2"
+ test_reiserfs_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
+ crypt_close "$CRYPT_NAME2"
+ fi
+fi
+
+crypt_close "$CRYPT_NAME"
+
+vgremove -ff $vg
diff --git a/test/shell/fsadm-crypt.sh b/test/shell/fsadm-crypt.sh
index 3b0c46aca..4d6efbc63 100644
--- a/test/shell/fsadm-crypt.sh
+++ b/test/shell/fsadm-crypt.sh
@@ -215,14 +215,14 @@ test_ext2_resize() {
fsadm --lvresize resize $1 30M
# Fails - not enough space for 4M fs
not fsadm -y --lvresize resize "$2" 4M
- lvresize -L+10M -r $1
- lvreduce -L10M -r $1
+ lvresize -L+10M --fs resize_fsadm $1
+ lvreduce -L10M --fs resize_fsadm $1
fscheck_ext3 "$3"
mount "$3" "$mount_dir"
not fsadm -y --lvresize resize $1 4M
- echo n | not lvresize -L4M -r -n $1
- lvresize -L+20M -r -n $1
+ echo n | not lvresize -L4M --fs resize_fsadm -n $1
+ lvresize -L+20M --fs resize_fsadm -n $1
umount "$mount_dir"
fscheck_ext3 "$3"
}
@@ -230,8 +230,8 @@ test_ext2_resize() {
test_ext2_small_shrink() {
mkfs.ext2 "$3"
- lvresize -L-1 -r $1
- lvresize -L-1 -r $1
+ lvresize -L-1 --fs resize_fsadm $1
+ lvresize -L-1 --fs resize_fsadm $1
fscheck_ext3 "$3"
}
@@ -242,25 +242,25 @@ test_ext3_resize() {
fsadm --lvresize resize $1 30M
# Fails - not enough space for 4M fs
not fsadm -y --lvresize resize "$2" 4M
- lvresize -L+10M -r $1
- lvreduce -L10M -r $1
+ lvresize -L+10M --fs resize_fsadm $1
+ lvreduce -L10M --fs resize_fsadm $1
fscheck_ext3 "$3"
mount "$3" "$mount_dir"
- lvresize -L+10M -r $1
+ lvresize -L+10M --fs resize_fsadm $1
not fsadm -y --lvresize resize $1 4M
- echo n | not lvresize -L4M -r -n $1
- lvresize -L+20M -r -n $1
- lvresize -L-10M -r -y $1
+ echo n | not lvresize -L4M --fs resize_fsadm -n $1
+ lvresize -L+20M --fs resize_fsadm -n $1
+ lvresize -L-10M --fs resize_fsadm -y $1
umount "$mount_dir"
}
test_ext3_small_shrink() {
mkfs.ext3 "$3"
- lvresize -L-1 -r $1
- lvresize -L-1 -r $1
+ lvresize -L-1 --fs resize_fsadm $1
+ lvresize -L-1 --fs resize_fsadm $1
fscheck_ext3 "$3"
}
@@ -270,12 +270,12 @@ test_xfs_resize() {
fsadm --lvresize resize $1 330M
# Fails - not enough space for 4M fs
- lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
fscheck_xfs "$3"
mount "$3" "$mount_dir"
- lvresize -L+10M -r -n $1
+ lvresize -L+10M --fs resize_fsadm -n $1
umount "$mount_dir"
fscheck_xfs "$3"
}
@@ -283,7 +283,7 @@ test_xfs_resize() {
test_xfs_small_shrink() {
mkfs.xfs -f "$3"
- not lvresize -L-1 -r $1
+ not lvresize -L-1 --fs resize_fsadm $1
fscheck_xfs "$3"
}
@@ -291,7 +291,7 @@ test_reiserfs_resize() {
mkfs.reiserfs -s 513 -f "$3"
fsadm --lvresize resize $1 30M
- lvresize -L+10M -r $1
+ lvresize -L+10M --fs resize_fsadm $1
fsadm --lvresize -y resize $1 10M
fscheck_reiserfs "$3"
@@ -305,8 +305,8 @@ test_reiserfs_resize() {
test_reiserfs_small_shrink() {
mkfs.reiserfs -s 513 -f "$3"
- lvresize -y -L-1 -r $1
- lvresize -y -L-1 -r $1
+ lvresize -y -L-1 --fs resize_fsadm $1
+ lvresize -y -L-1 --fs resize_fsadm $1
fscheck_reiserfs "$3"
}
@@ -321,8 +321,8 @@ test_ext2_inactive() {
crypt_close "$4"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
crypt_open "$2" $PWD2 "$4"
fscheck_ext3 "$3"
@@ -335,8 +335,8 @@ test_ext3_inactive() {
crypt_close "$4"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
crypt_open "$2" $PWD2 "$4"
fscheck_ext3 "$3"
@@ -349,8 +349,8 @@ test_xfs_inactive() {
crypt_close "$4"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
crypt_open "$2" $PWD2 "$4"
fscheck_xfs "$3"
@@ -363,8 +363,8 @@ test_reiserfs_inactive() {
crypt_close "$4"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
crypt_open "$2" $PWD2 "$4"
fscheck_reiserfs "$3"
@@ -379,8 +379,8 @@ test_ext2_plain() {
mkfs.ext2 -b4096 -j "$3"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
fscheck_ext3 "$3"
fsadm --cryptresize resize $3 30M
@@ -394,8 +394,8 @@ test_ext2_plain() {
crypt_close "$4"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
crypt_open_plain "$2" $PWD3 "$4"
fscheck_ext3 "$3"
}
@@ -404,8 +404,8 @@ test_ext3_plain() {
mkfs.ext3 -b4096 -j "$3"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
fscheck_ext3 "$3"
fsadm --cryptresize resize $3 30M
@@ -419,8 +419,8 @@ test_ext3_plain() {
crypt_close "$4"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
crypt_open_plain "$2" $PWD3 "$4"
fscheck_ext3 "$3"
}
@@ -429,8 +429,8 @@ test_xfs_plain() {
mkfs.xfs -f "$3"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
fscheck_xfs "$3"
lvresize -f -L+10M $1
@@ -441,8 +441,8 @@ test_xfs_plain() {
crypt_close "$4"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
crypt_open_plain "$2" $PWD3 "$4"
fscheck_xfs "$3"
@@ -453,8 +453,8 @@ test_reiserfs_plain() {
mkfs.reiserfs -s 513 -f "$3"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L-10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L-10M --fs resize_fsadm $1
fscheck_reiserfs "$3"
fsadm -y --cryptresize resize $3 30M
@@ -463,8 +463,8 @@ test_reiserfs_plain() {
crypt_close "$4"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
crypt_open_plain "$2" $PWD3 "$4"
fscheck_reiserfs "$3"
}
@@ -477,8 +477,8 @@ test_ext2_detached() {
mkfs.ext2 -b4096 -j "$3"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
fscheck_ext3 "$3"
}
@@ -486,8 +486,8 @@ test_ext3_detached() {
mkfs.ext3 -b4096 -j "$3"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
fscheck_ext3 "$3"
}
@@ -495,8 +495,8 @@ test_xfs_detached() {
mkfs.xfs -f "$3"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
fscheck_xfs "$3"
}
@@ -505,15 +505,15 @@ test_reiserfs_detached() {
mkfs.reiserfs -s 513 -f "$3"
not fsadm --lvresize resize $1 30M
- not lvresize -L+10M -r $1
- not lvreduce -L10M -r $1
+ not lvresize -L+10M --fs resize_fsadm $1
+ not lvreduce -L10M --fs resize_fsadm $1
fscheck_reiserfs "$3"
}
if check_missing ext2; then
test_ext2_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
- lvresize -f -L25M $vg_lv
+ lvresize --fs ignore -y -L25M $vg_lv
cryptsetup resize $CRYPT_NAME
test_ext2_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
@@ -522,10 +522,10 @@ if check_missing ext2; then
test_ext2_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN"
crypt_close "$CRYPT_NAME_PLAIN"
- lvresize -f -L100M $vg_lv
+ lvresize --fs ignore -y -L100M $vg_lv
cryptsetup resize $CRYPT_NAME
test_ext2_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
- lvresize -f -L25M $vg_lv
+ lvresize --fs ignore -y -L25M $vg_lv
cryptsetup resize $CRYPT_NAME
if [ -z "$SKIP_DETACHED" ]; then
@@ -537,7 +537,7 @@ fi
if check_missing ext3; then
test_ext3_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
- lvresize -f -L25M $vg_lv
+ lvresize --fs ignore -y -L25M $vg_lv
cryptsetup resize $CRYPT_NAME
test_ext3_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
@@ -546,10 +546,10 @@ if check_missing ext3; then
test_ext3_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN"
crypt_close "$CRYPT_NAME_PLAIN"
- lvresize -f -L100M $vg_lv
+ lvresize --fs ignore -y -L100M $vg_lv
cryptsetup resize $CRYPT_NAME
test_ext3_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
- lvresize -f -L25M $vg_lv
+ lvresize --fs ignore -y -L25M $vg_lv
cryptsetup resize $CRYPT_NAME
if [ -z "$SKIP_DETACHED" ]; then
@@ -563,7 +563,7 @@ if check_missing xfs; then
lvresize -f -L310M $vg_lv
cryptsetup resize $CRYPT_NAME
test_xfs_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
- lvresize -f -L325M $vg_lv
+ lvresize --fs ignore -y -L325M $vg_lv
cryptsetup resize $CRYPT_NAME
test_xfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
@@ -572,10 +572,10 @@ if check_missing xfs; then
test_xfs_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN"
crypt_close "$CRYPT_NAME_PLAIN"
- lvresize -f -L310M $vg_lv
+ lvresize --fs ignore -y -L310M $vg_lv
cryptsetup resize $CRYPT_NAME
test_xfs_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
- lvresize -f -L25M $vg_lv
+ lvresize --fs ignore -y -L25M $vg_lv
cryptsetup resize $CRYPT_NAME
if [ -z "$SKIP_DETACHED" ]; then
@@ -587,7 +587,7 @@ fi
if check_missing reiserfs; then
test_reiserfs_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
- lvresize -f -L25M $vg_lv
+ lvresize --fs ignore -y -L25M $vg_lv
cryptsetup resize $CRYPT_NAME
test_reiserfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
@@ -596,10 +596,10 @@ if check_missing reiserfs; then
test_reiserfs_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN"
crypt_close "$CRYPT_NAME_PLAIN"
- lvresize -f -L100M $vg_lv
+ lvresize --fs ignore -y -L100M $vg_lv
cryptsetup resize $CRYPT_NAME
test_reiserfs_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
- lvresize -f -L25M $vg_lv
+ lvresize --fs ignore -y -L25M $vg_lv
cryptsetup resize $CRYPT_NAME
if [ -z "$SKIP_DETACHED" ]; then
diff --git a/test/shell/fsadm.sh b/test/shell/fsadm.sh
index fea86813d..7f155d707 100644
--- a/test/shell/fsadm.sh
+++ b/test/shell/fsadm.sh
@@ -113,18 +113,18 @@ if check_missing ext2; then
fsadm --lvresize resize $vg_lv 30M
# Fails - not enough space for 4M fs
not fsadm -y --lvresize resize "$dev_vg_lv" 4M
- lvresize -L+10M -r $vg_lv
- lvreduce -L10M -r $vg_lv
+ lvresize -L+10M --fs resize_fsadm $vg_lv
+ lvreduce -L10M --fs resize_fsadm $vg_lv
fscheck_ext3
mount "$dev_vg_lv" "$mount_dir"
not fsadm -y --lvresize resize $vg_lv 4M
- echo n | not lvresize -L4M -r -n $vg_lv
- lvresize -L+20M -r -n $vg_lv
+ echo n | not lvresize -L4M --fs resize_fsadm -n $vg_lv
+ lvresize -L+20M --fs resize_fsadm -n $vg_lv
umount "$mount_dir"
fscheck_ext3
- lvresize -f -L20M $vg_lv
+ lvresize --fs ignore -y -L20M $vg_lv
if which debugfs ; then
mkfs.ext2 -b4096 -j "$dev_vg_lv"
@@ -145,7 +145,7 @@ if check_missing ext2; then
mount "$dev_vg_lv" "$mount_dir"
fsadm -v -y --lvresize resize $vg_lv 10M
- lvresize -L+10M -y -r -n $vg_lv
+ lvresize -L+10M -y --fs resize_fsadm -n $vg_lv
umount "$mount_dir" 2>/dev/null || true
fscheck_ext3
fi
@@ -158,24 +158,24 @@ if check_missing ext3; then
fsadm --lvresize resize $vg_lv 30M
# Fails - not enough space for 4M fs
not fsadm -y --lvresize resize "$dev_vg_lv" 4M
- lvresize -L+10M -r $vg_lv
- lvreduce -L10M -r $vg_lv
+ lvresize -L+10M --fs resize_fsadm $vg_lv
+ lvreduce -L10M --fs resize_fsadm $vg_lv
fscheck_ext3
mount "$dev_vg_lv" "$mount_dir"
- lvresize -L+10M -r $vg_lv
+ lvresize -L+10M --fs resize_fsadm $vg_lv
mount "$dev_vg_lv2" "$mount_space_dir"
fsadm --lvresize -e -y resize $vg_lv2 25M
not fsadm -y --lvresize resize $vg_lv 4M
echo n | not lvresize -L4M -r -n $vg_lv
- lvresize -L+20M -r -n $vg_lv
- lvresize -L-10M -r -y $vg_lv
+ lvresize -L+20M --fs resize_fsadm -n $vg_lv
+ lvresize -L-10M --fs resize_fsadm -y $vg_lv
umount "$mount_dir"
umount "$mount_space_dir"
fscheck_ext3
- lvresize -f -L20M $vg_lv
+ lvresize --fs ignore -y -L20M $vg_lv
fi
if check_missing xfs; then
@@ -183,23 +183,24 @@ if check_missing xfs; then
mkfs.xfs -l internal -f "$dev_vg_lv"
fsadm --lvresize resize $vg_lv 320M
- lvresize -L+10M -r $vg_lv
- not lvreduce -L10M -r $vg_lv
+ # Fails - not enough space for 4M fs
+ lvresize -L+10M --fs resize_fsadm $vg_lv
+ not lvreduce -L10M --fs resize_fsadm $vg_lv
fscheck_xfs
mount "$dev_vg_lv" "$mount_dir"
- lvresize -L+10M -r -n $vg_lv
+ lvresize -L+10M --fs resize_fsadm -n $vg_lv
umount "$mount_dir"
fscheck_xfs
- lvresize -f -L20M $vg_lv
+ lvresize --fs ignore -y -L20M $vg_lv
fi
if check_missing reiserfs; then
mkfs.reiserfs -s 513 -f "$dev_vg_lv"
fsadm --lvresize resize $vg_lv 30M
- lvresize -L+10M -r $vg_lv
+ lvresize -L+10M --fs resize_fsadm $vg_lv
fsadm --lvresize -y resize $vg_lv 10M
fscheck_reiserfs
@@ -209,7 +210,7 @@ if check_missing reiserfs; then
umount "$mount_dir"
fscheck_reiserfs
- lvresize -f -L20M $vg_lv
+ lvresize --fs ignore -y -L20M $vg_lv
fi
vgremove -ff $vg
diff --git a/test/shell/hints.sh b/test/shell/hints.sh
index 506c005dd..68e61153d 100644
--- a/test/shell/hints.sh
+++ b/test/shell/hints.sh
@@ -264,8 +264,8 @@ lvcreate -l1 -n $lv2 $vg1
lvcreate -l1 -an -n $lv3 $vg1
lvchange -an $vg1
lvremove $vg1/$lv3
-lvresize -l+1 $vg1/$lv2
-lvresize -l-1 $vg1/$lv2
+lvresize --fs ignore -l+1 $vg1/$lv2
+lvresize --fs ignore -l-1 $vg1/$lv2
lvdisplay
pvdisplay
vgdisplay
diff --git a/test/shell/lvresize-fs-crypt.sh b/test/shell/lvresize-fs-crypt.sh
new file mode 100644
index 000000000..19c4e7d8e
--- /dev/null
+++ b/test/shell/lvresize-fs-crypt.sh
@@ -0,0 +1,131 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2007-2016 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
+
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux prepare_vg 3 256
+
+mount_dir="mnt_lvresize_cr"
+mkdir -p "$mount_dir"
+
+# dm-crypt device on lv
+cr="$PREFIX-$lv-cr"
+
+# lvextend ext4 on LUKS1
+lvcreate -n $lv -L 256M $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=200 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+lvextend -L+200M --fs resize $vg/$lv
+check lv_field $vg/$lv lv_size "456.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
+
+# lvreduce ext4 on LUKS1
+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=200 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+lvresize -L-100M --yes --fs resize $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
+
+# lvextend xfs on LUKS1
+lvcreate -n $lv -L 256M $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=200 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+lvextend -L+200M --fs resize $vg/$lv
+check lv_field $vg/$lv lv_size "456.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
+
+# lvreduce xfs on LUKS1
+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.xfs /dev/mapper/$cr
+mount /dev/mapper/$cr "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# xfs cannot be reduced
+not lvresize -L-100M --yes --fs resize $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+diff df1 df2
+umount "$mount_dir"
+cryptsetup close $cr
+lvchange -an $vg/$lv
+lvremove $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"
+mkfs.ext4 /dev/mapper/$cr
+mount /dev/mapper/$cr "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# fails when no fs is found for --fs resize
+not lvextend -L+200M --yes --fs resize $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+df --output=size "$mount_dir" |tee df2
+diff df1 df2
+umount "$mount_dir"
+cryptsetup close $cr
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce ext4 on plain crypt (no header)
+lvcreate -n $lv -L 456M $vg
+echo 93R4P4pIqAH8 | cryptsetup create $cr "$DM_DEV_DIR/$vg/$lv"
+mkfs.ext4 /dev/mapper/$cr
+mount /dev/mapper/$cr "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# fails when no fs is found for --fs resize
+not lvresize -L-100M --yes --fs resize $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+diff df1 df2
+umount "$mount_dir"
+cryptsetup close $cr
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# test with LUKS2?
+
+vgremove -ff $vg
diff --git a/test/shell/lvresize-fs.sh b/test/shell/lvresize-fs.sh
new file mode 100644
index 000000000..b65e980b7
--- /dev/null
+++ b/test/shell/lvresize-fs.sh
@@ -0,0 +1,1186 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2007-2016 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
+
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux prepare_vg 3 256
+
+# Test combinations of the following:
+# lvreduce / lvextend
+# no fs / ext4 / xfs
+# each --fs opt / no --fs opt / --resizefs
+# active / inactive
+# mounted / unmounted
+# fs size less than, equal to or greater than reduced lv size
+
+mount_dir="mnt_lvresize_fs"
+mkdir -p "$mount_dir"
+
+
+#
+# lvextend, no fs
+#
+
+# lvextend, no fs, active, no --fs
+lvcreate -n $lv -L 256M $vg
+aux wipefs_a "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, no fs, inactive, no --fs
+lvcreate -n $lv -L 256M $vg
+aux wipefs_a "$DM_DEV_DIR/$vg/$lv"
+lvchange -an $vg/$lv
+lvextend -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+lvremove $vg/$lv
+
+# lvextend, no fs, active, --fs resize fails with no fs found
+lvcreate -n $lv -L 256M $vg
+aux wipefs_a "$DM_DEV_DIR/$vg/$lv"
+not lvextend -L+200M --fs resize $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, no fs, inactive, --fs resize error requires active lv
+lvcreate -n $lv -L 256M $vg
+aux wipefs_a "$DM_DEV_DIR/$vg/$lv"
+lvchange -an $vg/$lv
+not lvextend -L+200M --fs resize $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+lvremove $vg/$lv
+
+#
+# lvextend, ext4
+#
+
+# lvextend, ext4, active, mounted, no --fs setting is same as --fs ignore
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+# with no --fs used, the fs size should be the same
+df --output=size "$mount_dir" |tee df2
+diff df1 df2
+resize2fs "$DM_DEV_DIR/$vg/$lv"
+df --output=size "$mount_dir" |tee df3
+not diff df2 df3
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, inactive, --fs ignore
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvchange -an $vg/$lv
+lvextend --fs ignore -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+lvremove $vg/$lv
+
+# lvextend, ext4, active, mounted, --fs ignore
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+lvextend --fs ignore -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, active, mounted, --fs resize
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --fs resize -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, active, mounted, --resizefs (same as --fs resize)
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --resizefs -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, active, mounted, --fs resize --fsmode manage (same as --fs resize)
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --fs resize --fsmode manage -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, active, mounted, --fs resize --fsmode offline
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --fs resize --fsmode offline -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+# fsmode offline leaves fs unmounted
+df -a | tee dfa
+not grep "$mount_dir" dfa
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, active, mounted, --fs resize --fsmode nochange
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --fs resize --fsmode nochange -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, active, mounted, --fs resize_fsadm
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --fs resize_fsadm -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, active, unmounted, --fs resize --fsmode nochange
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvextend --fs resize --fsmode nochange -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, active, unmounted, --fs resize
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvextend --fs resize -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, ext4, active, unmounted, --fs resize_fsadm
+lvcreate -n $lv -L 256M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvextend --fs resize_fsadm -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+
+#
+# lvextend, xfs
+#
+
+# lvextend, xfs, active, mounted, no --fs setting is same as --fs ignore
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+# with no --fs used, the fs size should be the same
+df --output=size "$mount_dir" |tee df2
+diff df1 df2
+xfs_growfs "$DM_DEV_DIR/$vg/$lv"
+df --output=size "$mount_dir" |tee df3
+not diff df2 df3
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, inactive, --fs ignore
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+lvchange -an $vg/$lv
+lvextend --fs ignore -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+lvremove $vg/$lv
+
+# lvextend, xfs, active, mounted, --fs ignore
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+lvextend --fs ignore -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, active, mounted, --fs resize
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --fs resize -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, active, mounted, --resizefs (same as --fs resize)
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --resizefs -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, active, mounted, --fs resize --fsmode manage (same as --fs resize)
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --fs resize --fsmode manage -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, active, mounted, --fs resize --fsmode offline
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+# xfs_growfs requires the fs to be mounted, so extending the lv is
+# succeeds, then the xfs extend fails because it cannot be done unmounted
+not lvextend --fs resize --fsmode offline -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df -a | tee dfa
+grep "$mount_dir" dfa
+df --output=size "$mount_dir" |tee df2
+# fs not extended so fs size not changed
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, active, mounted, --fs resize --fsmode nochange
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --fs resize --fsmode nochange -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, active, mounted, --fs resize_fsadm
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+lvextend --fs resize_fsadm -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, active, unmounted, --fs resize --fsmode nochange
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+# xfs_growfs requires the fs to be mounted to grow, so --fsmode nochange
+# with an unmounted fs fails
+not lvextend --fs resize --fsmode nochange -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs not extended so fs size not changed
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, active, unmounted, --fs resize
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+# --yes needed because mount changes are required and plain "resize"
+# fsopt did not specify if the user wants to change mount state
+lvextend --yes --fs resize -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvextend, xfs, active, unmounted, --fs resize_fsadm
+lvcreate -n $lv -L 256M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df1
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvextend --fs resize_fsadm -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+not diff df1 df2
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=200 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+
+#
+# lvreduce, no fs
+#
+
+# lvreduce, no fs, active, no --fs setting is same as --fs checksize
+lvcreate -n $lv -L 456M $vg
+aux wipefs_a "$DM_DEV_DIR/$vg/$lv"
+lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, no fs, inactive, no --fs setting is same as --fs checksize
+lvcreate -n $lv -L 456M $vg
+aux wipefs_a "$DM_DEV_DIR/$vg/$lv"
+lvchange -an $vg/$lv
+lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+lvremove $vg/$lv
+
+# lvreduce, no fs, active, --fs resize requires fs to be found
+lvcreate -n $lv -L 456M $vg
+aux wipefs_a "$DM_DEV_DIR/$vg/$lv"
+not lvreduce -L-200M --fs resize $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, no fs, inactive, --fs ignore
+lvcreate -n $lv -L 456M $vg
+aux wipefs_a "$DM_DEV_DIR/$vg/$lv"
+lvchange -an $vg/$lv
+lvreduce -L-200M --fs ignore $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+
+#
+# lvreduce, ext4, no --fs setting and the equivalent --fs checksize
+# i.e. fs is not resized
+#
+
+# lvreduce, ext4, active, mounted, no --fs setting is same as --fs checksize
+# fs smaller than the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# fs is 200M, reduced size is 216M, so no fs reduce is needed
+# todo: check that resize2fs was not run?
+lvreduce -L216M $vg/$lv
+check lv_field $vg/$lv lv_size "216.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, mounted, no --fs setting is same as --fs checksize
+# fs equal to the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# fs is 200M, reduced size is 200M, so no fs reduce is needed
+# todo: check that resize2fs was not run?
+lvreduce -L200M $vg/$lv
+check lv_field $vg/$lv lv_size "200.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, mounted, no --fs setting is same as --fs checksize
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce fails because fs needs to be reduced and checksize does not resize
+not lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, mounted, no --fs setting is same as --fs checksize
+# fs larger than the reduced size, fs is using reduced space
+lvcreate -n $lv -L 456M $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=300 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce fails because fs needs to be reduced and checksize does not resize
+not lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# repeat lvreduce tests with unmounted instead of mounted fs
+
+# lvreduce, ext4, active, unmounted, no --fs setting is same as --fs checksize
+# fs smaller than the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# fs is 200M, reduced size is 216M, so no fs reduce is needed
+lvreduce -L216M $vg/$lv
+check lv_field $vg/$lv lv_size "216.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, no --fs setting is same as --fs checksize
+# fs equal to the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# fs is 200M, reduced size is 200M, so no fs reduce is needed
+lvreduce -L200M $vg/$lv
+check lv_field $vg/$lv lv_size "200.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, no --fs setting is same as --fs checksize
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# lvreduce fails because fs needs to be reduced and checksize does not resize
+not lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, no --fs setting is same as --fs checksize
+# fs larger than the reduced size, fs is using reduced space
+lvcreate -n $lv -L 456M $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=300 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# lvreduce fails because fs needs to be reduced and checksize does not resize
+not lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# repeat a couple prev lvreduce that had no --fs setting,
+# now using --fs checksize to verify it's the same as using no --fs set
+
+# lvreduce, ext4, active, mounted, --fs checksize (same as no --fs set)
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce fails because fs needs to be reduced and checksize does not resize
+not lvreduce --fs checksize -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, --fs checksize (same as no --fs set)
+# fs smaller than the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# fs is 200M, reduced size is 216M, so no fs reduce is needed
+lvreduce --fs checksize -L216M $vg/$lv
+check lv_field $vg/$lv lv_size "216.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce with inactive and no --fs setting fails because
+# default behavior is fs checksize which activates the LV
+# and sees the fs
+
+# lvreduce, ext4, inactive, no --fs setting same as --fs checksize
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+lvchange -an $vg/$lv
+# lvreduce fails because default is --fs checksize which sees the fs
+not lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+lvremove $vg/$lv
+
+#
+# lvreduce, ext4, --fs resize*
+#
+
+# lvreduce, ext4, active, mounted, --fs resize
+# fs smaller than the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# fs is 200M, reduced size is 216M, so no fs reduce is needed
+lvreduce -L216M $vg/$lv
+check lv_field $vg/$lv lv_size "216.00m"
+ls -l $mount_dir/zeros1
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, mounted, --fs resize
+# fs equal to the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# fs is 200M, reduced size is 200M, so no fs reduce is needed
+lvreduce -L200M $vg/$lv
+check lv_field $vg/$lv lv_size "200.00m"
+ls -l $mount_dir/zeros1
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, mounted, --fs resize
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce runs resize2fs to shrink the fs
+lvreduce --yes --fs resize -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+ls -l $mount_dir/zeros1
+df --output=size "$mount_dir" |tee df2
+# fs size is changed
+not diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, mounted, --fs resize
+# fs larger than the reduced size, fs is using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=300 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce runs resize2fs to shrink the fs but resize2fs fails
+# the fs is not remounted after resize2fs fails because the
+# resize failure might leave the fs in an unknown state
+not lvreduce --yes --fs resize -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+ls -l $mount_dir/zeros1
+ls -l $mount_dir/zeros2
+df --output=size "$mount_dir" |tee df2
+# fs size is unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# repeat with unmounted instead of mounted
+
+# lvreduce, ext4, active, unmounted, --fs resize
+# fs smaller than the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# fs is 200M, reduced size is 216M, so no fs reduce is needed
+lvreduce -L216M $vg/$lv
+check lv_field $vg/$lv lv_size "216.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+ls -l $mount_dir/zeros1
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, --fs resize
+# fs equal to the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# fs is 200M, reduced size is 200M, so no fs reduce is needed
+lvreduce -L200M $vg/$lv
+check lv_field $vg/$lv lv_size "200.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+ls -l $mount_dir/zeros1
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, --fs resize
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# lvreduce runs resize2fs to shrink the fs
+lvreduce --fs resize -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+ls -l $mount_dir/zeros1
+df --output=size "$mount_dir" |tee df2
+# fs size is changed
+not diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, --fs resize
+# fs larger than the reduced size, fs is using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=300 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# lvreduce runs resize2fs to shrink the fs but resize2fs fails
+not lvreduce --yes --fs resize -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+ls -l $mount_dir/zeros1
+df --output=size "$mount_dir" |tee df2
+# fs size is unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# repeat resizes that shrink the fs, replacing --fs resize with
+# --fs resize --fsmode nochange|offline, --fs resize_fsadm.
+# while mounted and unmounted
+
+# lvreduce, ext4, active, mounted, --fs resize --fsmode nochange
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce needs to unmount to run resize2fs but fsmode nochange doesn't let it
+not lvreduce --fs resize --fsmode nochange -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size is unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, --fs resize --fsmode nochange
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# lvreduce runs resize2fs to shrink the fs
+lvreduce --fs resize --fsmode nochange -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size is changed
+not diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, mounted, --fs resize --fsmode offline
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce runs resize2fs to shrink the fs
+# fsmode offline leaves the fs unmounted
+lvreduce --fs resize --fsmode offline -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size is changed
+not diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, --fs resize --fsmode offline
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# lvreduce runs resize2fs to shrink the fs
+lvreduce --fs resize --fsmode offline -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size is changed
+not diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, mounted, --fs resize_fsadm
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce runs resize2fs to shrink the fs
+lvreduce --yes --fs resize_fsadm -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+ls -l $mount_dir/zeros1
+df --output=size "$mount_dir" |tee df2
+# fs size is changed
+not diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, ext4, active, unmounted, --fs resize_fsadm
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# lvreduce runs resize2fs to shrink the fs
+lvreduce --fs resize_fsadm -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "256.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size is changed
+not diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+#
+# lvreduce, xfs (xfs does not support shrinking)
+#
+
+# lvreduce, xfs, active, mounted, no --fs setting is same as --fs checksize
+# fs smaller than the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# fs is 200M, reduced size is 216M, so no fs reduce is needed
+lvreduce -L216M $vg/$lv
+check lv_field $vg/$lv lv_size "216.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, xfs, active, mounted, no --fs setting is same as --fs checksize
+# fs equal to the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# fs is 200M, reduced size is 200M, so no fs reduce is needed
+lvreduce -L200M $vg/$lv
+check lv_field $vg/$lv lv_size "200.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, xfs, active, mounted, no --fs setting is same as --fs checksize
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce fails because fs needs to be reduced
+not lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, xfs, active, unmounted, no --fs setting is same as --fs checksize
+# fs smaller than the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# fs is 200M, reduced size is 216M, so no fs reduce is needed
+lvreduce -L216M $vg/$lv
+check lv_field $vg/$lv lv_size "216.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, xfs, active, mounted, --fs resize
+# fs smaller than the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# fs is 200M, reduced size is 216M, so no fs reduce is needed
+lvreduce -L216M $vg/$lv
+check lv_field $vg/$lv lv_size "216.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, xfs, active, mounted, --fs resize
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+# lvreduce fails because xfs cannot shrink
+not lvreduce --yes --fs resize -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, xfs, active, unmounted, --fs resize*
+# fs larger than the reduced size, fs not using reduced space
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+# lvreduce fails because xfs cannot shrink
+not lvreduce --yes --fs resize -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+not lvreduce --yes --fs resize --fsmode manage -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+not lvreduce --yes --fs resize --fsmode nochange -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+not lvreduce --yes --fs resize --fsmode offline -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+not lvreduce --yes --fs resize_fsadm -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+not lvreduce --yes --resizefs -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, xfs, inactive, no --fs setting is same as --fs checksize
+# fs equal to the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+lvchange -an $vg/$lv
+# no fs reduce is needed
+lvreduce -L200M $vg/$lv
+check lv_field $vg/$lv lv_size "200.00m"
+lvchange -ay $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, xfs, inactive, no fs setting is same as --fs checksize
+# fs smaller than the reduced size
+lvcreate -n $lv -L 200M $vg
+mkfs.xfs "$DM_DEV_DIR/$vg/$lv"
+lvextend -L+256M $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=128 conv=fdatasync
+df --output=size "$mount_dir" |tee df1
+umount "$mount_dir"
+lvchange -an $vg/$lv
+# fs is 200M, reduced size is 216M, so no fs reduce is needed
+lvreduce -L216M $vg/$lv
+check lv_field $vg/$lv lv_size "216.00m"
+lvchange -ay $vg/$lv
+mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
+df --output=size "$mount_dir" |tee df2
+# fs size unchanged
+diff df1 df2
+umount "$mount_dir"
+lvchange -an $vg/$lv
+lvremove $vg/$lv
+
+# lvreduce, xfs, inactive, no --fs setting is same as --fs checksize
+# fs larger than the reduced size
+lvcreate -n $lv -L 456M $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=100 conv=fdatasync
+umount "$mount_dir"
+lvchange -an $vg/$lv
+# lvreduce fails because fs needs to be reduced
+not lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+lvremove $vg/$lv
+
+vgremove -ff $vg
diff --git a/test/shell/lvresize-full.sh b/test/shell/lvresize-full.sh
index 1ad9f32b1..fe39f45df 100644
--- a/test/shell/lvresize-full.sh
+++ b/test/shell/lvresize-full.sh
@@ -69,7 +69,10 @@ grep -v "20000 blocks" out
# Also check it fails when the user 'resize' volume without
# resizing fs and then retries with '-r'.
-lvreduce -f -l50%VG $vg/$lv1
-fail lvresize -r -f -l50%VG $vg/$lv1
+# The first lvreduce intentionally ignores the fs and intentionally
+# corrupts the fs so that the second lvresize will fail when it runs
+# fsck.
+lvreduce -f --fs ignore -l50%VG $vg/$lv1
+fail lvresize -r -f -l20%VG $vg/$lv1
lvremove -ff $vg
diff --git a/test/shell/lvresize-mirror.sh b/test/shell/lvresize-mirror.sh
index 61e4491bd..ee23f7f24 100644
--- a/test/shell/lvresize-mirror.sh
+++ b/test/shell/lvresize-mirror.sh
@@ -29,7 +29,7 @@ for deactivate in true false; do
check mirror_images_contiguous $vg $lv1
# reduce 2-way mirror
- lvreduce -f -l-2 $vg/$lv1
+ lvreduce -f --fs ignore -l-2 $vg/$lv1
check mirror $vg $lv1 "$dev3"
# extend 2-way mirror (cling if not contiguous)
diff --git a/test/shell/lvresize-rounding.sh b/test/shell/lvresize-rounding.sh
index 0cdce558f..c2251eb06 100644
--- a/test/shell/lvresize-rounding.sh
+++ b/test/shell/lvresize-rounding.sh
@@ -52,7 +52,7 @@ lvcreate -an -Zn -l1 -n $lv1 -i3 $vg
lvextend -l+100%FREE -i3 $vg/$lv1
check vg_field $vg vg_free_count 2
-lvreduce -f -l50%LV $vg/$lv1
+lvreduce -f --fs ignore -l50%LV $vg/$lv1
vgremove -f $vg
vgcreate $SHARED -s 4M $vg "$dev1" "$dev2" "$dev3"
@@ -72,21 +72,21 @@ lvextend -l+100%FREE $vg/lv
check vg_field $vg vg_free_count 0
# Rounds up and should reduce just by 3 extents
-lvreduce -f -l-4 $vg/lv
+lvreduce -f --fs ignore -l-4 $vg/lv
check vg_field $vg vg_free_count 3
# Should round up to 15 extents
lvextend -f -l+1 $vg/lv
check vg_field $vg vg_free_count 0
-lvreduce -f -l-4 $vg/lv
+lvreduce -f --fs ignore -l-4 $vg/lv
check vg_field $vg vg_free_count 3
lvextend -l90%VG $vg/lv
check vg_field $vg vg_free_count 0
-not lvreduce -f -l-10%LV $vg/lv
+not lvreduce -f --fs ignore -l-10%LV $vg/lv
check vg_field $vg vg_free_count 0
-lvreduce -f -l-20%LV $vg/lv
+lvreduce -f --fs ignore -l-20%LV $vg/lv
check vg_field $vg vg_free_count 3
diff --git a/test/shell/relative-sign-options.sh b/test/shell/relative-sign-options.sh
index ac6fe53b0..6be75259a 100644
--- a/test/shell/relative-sign-options.sh
+++ b/test/shell/relative-sign-options.sh
@@ -34,8 +34,8 @@ lvresize -y -l8 $vg/$lv1
lvresize -y -L16 $vg/$lv1
lvresize -y -l+1 $vg/$lv1
lvresize -y -L+1 $vg/$lv1
-lvresize -y -l-1 $vg/$lv1
-lvresize -y -L-1 $vg/$lv1
+lvresize -y --fs ignore -l-1 $vg/$lv1
+lvresize -y --fs ignore -L-1 $vg/$lv1
lvcreate -an -n $lv2 -l4 $vg
lvextend -y -l8 $vg/$lv2
@@ -46,12 +46,12 @@ not lvextend -y -l-1 $vg/$lv2
not lvextend -y -L-1 $vg/$lv2
lvcreate -an -n $lv3 -l64 $vg
-lvreduce -y -l32 $vg/$lv3
-lvreduce -y -L8 $vg/$lv3
-lvreduce -y -l-1 $vg/$lv3
-lvreduce -y -L-1 $vg/$lv3
-not lvreduce -y -l+1 $vg/$lv3
-not lvreduce -y -L+1 $vg/$lv3
+lvreduce -y --fs ignore -l32 $vg/$lv3
+lvreduce -y --fs ignore -L8 $vg/$lv3
+lvreduce -y --fs ignore -l-1 $vg/$lv3
+lvreduce -y --fs ignore -L-1 $vg/$lv3
+not lvreduce -y --fs ignore -l+1 $vg/$lv3
+not lvreduce -y --fs ignore -L+1 $vg/$lv3
# relative with percent extents
diff --git a/tools/args.h b/tools/args.h
index 85dd11aeb..a7a0dd3d9 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -301,6 +301,32 @@ arg(foreign_ARG, '\0', "foreign", 0, 0, 0,
"Report/display foreign VGs that would otherwise be skipped.\n"
"See \\fBlvmsystemid\\fP(7) for more information about foreign VGs.\n")
+arg(fs_ARG, '\0', "fs", string_VAL, 0, 0,
+ "Control file system resizing when resizing an LV.\n"
+ "\\fBchecksize\\fP: Check the fs size and reduce the LV if the fs is not\n"
+ "using the reduced space (fs reduce is not needed.) If the reduced space\n"
+ "is used by the fs, then do not resize the fs or LV, and return an error.\n"
+ "(checksize only applies when reducing, and does nothing for extend.)\n"
+ "\\fBresize\\fP: Resize the fs by calling the fs-specific resize command.\n"
+ "This may also include mounting, unmounting, or running fsck. See --fsmode to\n"
+ "control mounting behavior, and --nofsck to disable fsck.\n"
+ "\\fBresize_fsadm\\fP: Use the old method of calling fsadm to handle the fs\n"
+ "(deprecated.) Warning: this option does not prevent lvreduce from destroying\n"
+ "file systems that are unmounted (or mounted if prompts are skipped.)\n"
+ "\\fBignore\\fP: Resize the LV without checking for or handling a file system.\n"
+ "Warning: using ignore when reducing the LV size may destroy the file system.\n")
+
+arg(fsmode_ARG, '\0', "fsmode", string_VAL, 0, 0,
+ "Control file system mounting behavior for fs resize.\n"
+ "\\fBmanage\\fP: Mount or unmount the fs as needed to resize the fs,\n"
+ "and attempt to restore the original mount state at the end.\n"
+ "\\fBnochange\\fP: Do not mount or unmount the fs. If mounting or unmounting\n"
+ "is required to resize the fs, then do not resize the fs or the LV and fail\n"
+ "the command.\n"
+ "\\fBoffline\\fP: Unmount the fs if it is mounted, and resize the fs while it\n"
+ "is unmounted. If mounting is required to resize the fs, then do not resize\n"
+ "the fs or the LV and fail the command.\n")
+
arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", 0, 0, 0,
"Allows a polling operation to continue when PVs are missing,\n"
"e.g. for repairs due to faulty devices.\n")
@@ -1384,9 +1410,7 @@ arg(name_ARG, 'n', "name", string_VAL, 0, 0,
"Move only PVs used by the named LV.\n")
arg(nofsck_ARG, 'n', "nofsck", 0, 0, 0,
- "Do not perform fsck before resizing filesystem when filesystem\n"
- "requires it. You may need to use --force to proceed with\n"
- "this option.\n")
+ "Do not perform fsck when resizing the file system with --resizefs.\n")
arg(novolumegroup_ARG, 'n', "novolumegroup", 0, 0, 0,
"Only show PVs not belonging to any VG.\n")
@@ -1452,7 +1476,10 @@ arg(readahead_ARG, 'r', "readahead", readahead_VAL, 0, 0,
"\\fBnone\\fP is equivalent to zero.\n")
arg(resizefs_ARG, 'r', "resizefs", 0, 0, 0,
- "Resize underlying filesystem together with the LV using \\fBfsadm\\fP(8).\n")
+ "Resize the fs using the fs-specific resize command.\n"
+ "May include mounting, unmounting, or running fsck. See --fsmode to control\n"
+ "mounting behavior, and --nofsck to disable fsck. See --fs for more options\n"
+ "(--resizefs is equivalent to --fs resize.)\n")
/* Not used */
arg(reset_ARG, 'R', "reset", 0, 0, 0, NULL)
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 0cb9425c1..ec61d3b7d 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1380,7 +1380,7 @@ lvextend --size PSizeMB LV
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync, --reportformat ReportFmt, --resizefs,
--stripes Number, --stripesize SizeKB, --poolmetadatasize PSizeMB,
---type SegType
+--type SegType, --fs String, --fsmode String
OP: PV ...
ID: lvextend_size
DESC: Extend an LV by a specified size.
@@ -1389,7 +1389,7 @@ lvextend LV PV ...
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB,
---type SegType
+--type SegType, --fs String, --fsmode String
ID: lvextend_pv
DESC: Extend an LV by specified PV extents.
@@ -1406,7 +1406,7 @@ lvextend --usepolicies LV_snapshot_thinpool_vdopool
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs,
---type SegType
+--type SegType, --fs String, --fsmode String
OP: PV ...
ID: lvextend_policy
DESC: Extend an LV according to a predefined policy.
@@ -1455,7 +1455,7 @@ DESC: Remove the devices file entry for the given PVID.
lvreduce --size NSizeMB LV
OO: --autobackup Bool, --force, --nofsck, --noudevsync,
---reportformat ReportFmt, --resizefs
+--reportformat ReportFmt, --resizefs, --fs String, --fsmode String
ID: lvreduce_size
---
@@ -1485,7 +1485,7 @@ lvresize --size SSizeMB LV
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync, --reportformat ReportFmt, --resizefs,
--stripes Number, --stripesize SizeKB, --poolmetadatasize PSizeMB,
---type SegType
+--type SegType, --fs String, --fsmode String
OP: PV ...
ID: lvresize_size
DESC: Resize an LV by a specified size.
@@ -1494,7 +1494,7 @@ lvresize LV PV ...
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB,
---type SegType
+--type SegType, --fs String, --fsmode String
ID: lvresize_pv
DESC: Resize an LV by specified PV extents.
diff --git a/tools/lvresize.c b/tools/lvresize.c
index a7148e52c..bba8ee26c 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -19,6 +19,7 @@ static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
{
const char *type_str = arg_str_value(cmd, type_ARG, NULL);
int only_linear = 0;
+ int set_fsopt = 0;
int set_extents_and_size = 0;
memset(lp, 0, sizeof(struct lvresize_params));
@@ -54,35 +55,31 @@ static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
lp->percent = PERCENT_PVS;
lp->sign = SIGN_PLUS;
lp->poolmetadata_size = 0;
- lp->resizefs = arg_is_set(cmd, resizefs_ARG);
- lp->nofsck = arg_is_set(cmd, nofsck_ARG);
+ set_fsopt = 1;
break;
case lvextend_size_CMD:
lp->resize = LV_EXTEND;
- lp->resizefs = arg_is_set(cmd, resizefs_ARG);
- lp->nofsck = arg_is_set(cmd, nofsck_ARG);
if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0)))
lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
set_extents_and_size = 1;
+ set_fsopt = 1;
break;
case lvreduce_size_CMD:
lp->resize = LV_REDUCE;
lp->poolmetadata_size = 0;
- lp->resizefs = arg_is_set(cmd, resizefs_ARG);
- lp->nofsck = arg_is_set(cmd, nofsck_ARG);
set_extents_and_size = 1;
+ set_fsopt = 1;
break;
case lvresize_size_CMD:
lp->resize = LV_ANY;
lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0);
- lp->resizefs = arg_is_set(cmd, resizefs_ARG);
- lp->nofsck = arg_is_set(cmd, nofsck_ARG);
if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0)))
lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
set_extents_and_size = 1;
+ set_fsopt = 1;
break;
default:
@@ -90,6 +87,67 @@ static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
return 0;
};
+ if (set_fsopt) {
+ const char *str;
+
+ if (arg_is_set(cmd, resizefs_ARG) && arg_is_set(cmd, fs_ARG)) {
+ log_error("Options --fs and --resizefs cannot be used together.");
+ log_error("--resizefs is equivalent to --fs resize.");
+ return 0;
+ }
+
+ if ((str = arg_str_value(cmd, fs_ARG, NULL))) {
+ if (!strcmp(str, "checksize") ||
+ !strcmp(str, "resize") ||
+ !strcmp(str, "resize_fsadm")) {
+ strncpy(lp->fsopt, str, sizeof(lp->fsopt)-1);
+ } else if (!strcmp(str, "ignore")) {
+ lp->fsopt[0] = '\0';
+ } else {
+ log_error("Unknown --fs value.");
+ return 0;
+ }
+ lp->user_set_fs = 1;
+ } else if (arg_is_set(cmd, resizefs_ARG)) {
+ /* --resizefs alone equates to --fs resize */
+ strncpy(lp->fsopt, "resize", sizeof(lp->fsopt)-1);
+ lp->user_set_fs = 1;
+ } else {
+ /*
+ * Use checksize when no fs option is specified.
+ * checksize with extend does nothing: the LV
+ * is extended and any fs is ignored.
+ * checksize with reduce checks for an fs that
+ * needs reducing: the LV is reduced only if the
+ * fs does not need to be reduced (or no fs.)
+ */
+ strncpy(lp->fsopt, "checksize", sizeof(lp->fsopt)-1);
+ }
+
+ if (lp->fsopt[0])
+ lp->nofsck = arg_is_set(cmd, nofsck_ARG);
+
+ if (!strcmp(lp->fsopt, "resize_fsadm") && arg_is_set(cmd, fsmode_ARG)) {
+ log_error("The --fsmode option does not apply to resize_fsadm.");
+ return 0;
+ }
+
+ if ((str = arg_str_value(cmd, fsmode_ARG, NULL))) {
+ if (!strcmp(str, "nochange") ||
+ !strcmp(str, "offline") ||
+ !strcmp(str, "manage")) {
+ strncpy(lp->fsmode, str, sizeof(lp->fsmode)-1);
+ lp->user_set_fsmode = 1;
+ } else {
+ log_error("Unknown --fsmode value.");
+ return 0;
+ }
+ } else {
+ /* Use manage when no fsmode option is specified. */
+ strncpy(lp->fsmode, "manage", sizeof(lp->fsmode)-1);
+ }
+ }
+
if (set_extents_and_size) {
if ((lp->extents = arg_uint_value(cmd, extents_ARG, 0))) {
lp->sign = arg_sign_value(cmd, extents_ARG, 0);
@@ -121,6 +179,17 @@ static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
return_0;
}
+ if ((lp->resize == LV_REDUCE) &&
+ (type_str ||
+ arg_is_set(cmd, mirrors_ARG) ||
+ arg_is_set(cmd, stripes_ARG) ||
+ arg_is_set(cmd, stripesize_ARG))) {
+ /* should be obvious since reduce doesn't alloc space. */
+ log_print_unless_silent("Ignoring type, stripes, stripesize and mirrors "
+ "arguments when reducing.");
+ goto out;
+ }
+
if (arg_is_set(cmd, mirrors_ARG)) {
if (arg_sign_value(cmd, mirrors_ARG, SIGN_NONE) != SIGN_NONE) {
log_error("Mirrors argument may not be signed.");
@@ -146,7 +215,7 @@ static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
log_error("Stripesize may not be negative.");
return 0;
}
-
+out:
return 1;
}
@@ -237,6 +306,7 @@ static int _lvresize_single(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle)
{
struct lvresize_params *lp = (struct lvresize_params *) handle->custom_handle;
+ int ret;
if (cmd->position_argc > 1) {
/* First pos arg is required LV, remaining are optional PVs. */
@@ -245,11 +315,13 @@ static int _lvresize_single(struct cmd_context *cmd, struct logical_volume *lv,
} else
lp->pvh = &lv->vg->pvs;
- if (!lv_resize(cmd, lv, lp))
- return ECMD_FAILED;
+ ret = lv_resize(cmd, lv, lp);
- log_print_unless_silent("Logical volume %s successfully resized.",
- display_lvname(lv));
+ if (ret || lp->extend_fs_error)
+ log_print_unless_silent("Logical volume %s successfully resized.",
+ display_lvname(lv));
+ if (!ret)
+ return ECMD_FAILED;
return ECMD_PROCESSED;
}
@@ -279,6 +351,7 @@ int lvresize_cmd(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle;
struct lvresize_params lp;
+ int retries = 0;
int ret;
if (!_lvresize_params(cmd, &lp))
@@ -289,9 +362,25 @@ int lvresize_cmd(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &lp;
+retry:
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
handle, NULL, &_lvresize_single);
+ /*
+ * The VG can be changed by another command while it is unlocked
+ * during fs resize. The fs steps likely succeeded, and this
+ * retry will likely find that no more fs steps are needed, and
+ * will resize the LV directly.
+ */
+ if (lp.vg_changed_error && !retries) {
+ lp.vg_changed_error = 0;
+ retries = 1;
+ goto retry;
+ } else if (lp.vg_changed_error && retries) {
+ log_error("VG changed during file system resize, LV not resized.");
+ ret = ECMD_FAILED;
+ }
+
destroy_processing_handle(cmd, handle);
if (lp.lockd_lv_refresh_path && !lockd_lv_refresh(cmd, &lp))
8 months, 3 weeks
main - lvresize: restructure code
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=18722dfdf4d3e6f172d...
Commit: 18722dfdf4d3e6f172d0b2af8bbdc4a154ea1dc0
Parent: 55e9494e5fe3e3d2790fca6330b848a577e0b1c0
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Sep 9 16:07:07 2022 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Sep 9 16:18:55 2022 -0500
lvresize: restructure code
Rewrite top level resize function to prepare for adding
new fs resizing.
---
lib/commands/cmd_enum.h | 19 +
lib/commands/toolcontext.h | 2 +
lib/locking/lvmlockd.c | 6 +-
lib/metadata/lv_manip.c | 942 +++++++++++++++++++++++----------------
lib/metadata/metadata-exported.h | 39 +-
lib/metadata/metadata.c | 12 +
lib/metadata/pool_manip.c | 3 +
test/shell/lvextend-thin-full.sh | 11 +-
test/shell/lvresize-full.sh | 13 +-
tools/command-lines.in | 20 +-
tools/lvextend.c | 2 +-
tools/lvmcmdline.c | 13 +
tools/lvreduce.c | 2 +-
tools/lvresize.c | 346 ++++++++------
tools/tools.h | 16 +-
15 files changed, 889 insertions(+), 557 deletions(-)
diff --git a/lib/commands/cmd_enum.h b/lib/commands/cmd_enum.h
new file mode 100644
index 000000000..939af81c3
--- /dev/null
+++ b/lib/commands/cmd_enum.h
@@ -0,0 +1,19 @@
+#ifndef _CMD_ENUM_H
+#define _CMD_ENUM_H
+
+/*
+ * tools/cmds.h is generated by the Makefile. For each command definition
+ * in command-lines.in, cmds.h contains:
+ * cmd(foo_CMD, foo)
+ *
+ * This header adds each of the foo_CMD's into an enum, so there's
+ * a unique integer identifier for each command definition.
+ */
+
+enum {
+#define cmd(a, b) a ,
+#include "../tools/cmds.h"
+#undef cmd
+};
+
+#endif
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 7a4979b33..eb2d1922b 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -18,6 +18,7 @@
#include "lib/device/dev-cache.h"
#include "lib/device/dev-type.h"
+#include "lib/commands/cmd_enum.h"
#include <limits.h>
@@ -94,6 +95,7 @@ struct cmd_context {
const char *name; /* needed before cmd->command is set */
struct command_name *cname;
struct command *command;
+ int command_enum; /* duplicate from command->command_enum for lib code */
char **argv;
struct arg_values *opt_arg_values;
struct dm_list arg_value_groups;
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
index f0183db3d..2ef0900d4 100644
--- a/lib/locking/lvmlockd.c
+++ b/lib/locking/lvmlockd.c
@@ -577,8 +577,9 @@ static int _extend_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
(uint32_t)(new_size_sectors * SECTOR_SIZE));
lp.size = new_size_sectors;
+ lp.pvh = &vg->pvs;
- if (!lv_resize(lv, &lp, &vg->pvs)) {
+ if (!lv_resize(cmd, lv, &lp)) {
log_error("Extend sanlock LV %s to size %s failed.",
display_lvname(lv), display_size(cmd, lp.size));
return 0;
@@ -2733,6 +2734,9 @@ int lockd_lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
if (!_lvmlockd_connected)
return 0;
+ if (lv_is_lockd_sanlock_lv(lv))
+ return 1;
+
/*
* A special case for gfs2 where we want to allow lvextend
* of an LV that has an existing shared lock, which is normally
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index a9057830d..e819db8d5 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -4935,8 +4935,8 @@ static int _validate_stripesize(const struct volume_group *vg,
return 1;
}
-static int _request_confirmation(const struct logical_volume *lv,
- const struct lvresize_params *lp)
+static int _lv_reduce_confirmation(struct logical_volume *lv,
+ struct lvresize_params *lp)
{
const struct volume_group *vg = lv->vg;
struct lvinfo info = { 0 };
@@ -4946,15 +4946,7 @@ static int _request_confirmation(const struct logical_volume *lv,
return 0;
}
- if (lp->resizefs) {
- if (!info.exists) {
- log_error("Logical volume %s must be activated "
- "before resizing filesystem.",
- display_lvname(lv));
- return 0;
- }
- return 1;
- } else if (lv_is_vdo(lv) && !info.exists) {
+ if (lv_is_vdo(lv) && !info.exists) {
log_error("Logical volume %s must be activated "
"before reducing device size.",
display_lvname(lv));
@@ -5064,8 +5056,9 @@ static uint32_t _adjust_amount(dm_percent_t percent, int policy_threshold, int p
return (policy_amount < percent) ? (uint32_t) percent : (uint32_t) policy_amount;
}
-static int _lvresize_adjust_policy(const struct logical_volume *lv,
- uint32_t *amount, uint32_t *meta_amount)
+/* "amount" here is percent */
+int lv_extend_policy_calculate_percent(struct logical_volume *lv,
+ uint32_t *amount, uint32_t *meta_amount)
{
struct cmd_context *cmd = lv->vg->cmd;
dm_percent_t percent;
@@ -5111,8 +5104,10 @@ static int _lvresize_adjust_policy(const struct logical_volume *lv,
}
}
- if (policy_threshold >= 100)
+ if (policy_threshold >= 100) {
+ log_debug("lvextend policy disabled by threshold 100");
return 1; /* nothing to do */
+ }
if (!policy_amount) {
log_error("Can't extend %s with %s autoextend percent set to 0%%.",
@@ -5148,6 +5143,8 @@ static int _lvresize_adjust_policy(const struct logical_volume *lv,
*amount = _adjust_amount(percent, policy_threshold, policy_amount);
+ log_debug("lvextend policy calculated percentages main %u meta %u from threshold %d percent %d",
+ *amount, *meta_amount, policy_threshold, policy_amount);
return 1;
}
@@ -5184,120 +5181,6 @@ static uint32_t _lvseg_get_stripes(struct lv_segment *seg, uint32_t *stripesize)
return 0;
}
-static int _lvresize_check(struct logical_volume *lv,
- struct lvresize_params *lp)
-{
- struct volume_group *vg = lv->vg;
- struct lv_segment *seg = first_seg(lv);
-
- if (lv_is_external_origin(lv)) {
- /*
- * Since external-origin can be activated read-only,
- * there is no way to use extended areas.
- */
- log_error("Cannot resize external origin logical volume %s.",
- display_lvname(lv));
- return 0;
- }
-
- if (lv_is_raid_image(lv) || lv_is_raid_metadata(lv)) {
- log_error("Cannot resize a RAID %s directly",
- lv_is_raid_image(lv) ? "image" : "metadata area");
- return 0;
- }
-
- if (lv_is_raid_with_tracking(lv)) {
- log_error("Cannot resize logical volume %s while it is "
- "tracking a split image.", display_lvname(lv));
- return 0;
- }
-
- if ((seg_is_raid4(seg) || seg_is_any_raid5(seg)) && seg->area_count < 3) {
- log_error("Cannot resize %s LV %s. Convert to more stripes first.",
- lvseg_name(seg), display_lvname(lv));
- return 0;
- }
-
- if (lv_is_raid(lv) &&
- lp->resize == LV_REDUCE) {
- unsigned attrs = 0;
- const struct segment_type *segtype = first_seg(lv)->segtype;
-
- if (!segtype->ops->target_present ||
- !segtype->ops->target_present(lv->vg->cmd, NULL, &attrs) ||
- !(attrs & RAID_FEATURE_SHRINK)) {
- log_error("RAID module does not support shrinking.");
- return 0;
- }
- }
-
- if (!lv_is_visible(lv) &&
- !lv_is_thin_pool_metadata(lv) &&
- !lv_is_vdo_pool_data(lv) &&
- !lv_is_lockd_sanlock_lv(lv)) {
- log_error("Can't resize internal logical volume %s.", display_lvname(lv));
- return 0;
- }
-
- if (lv_is_locked(lv)) {
- log_error("Can't resize locked logical volume %s.", display_lvname(lv));
- return 0;
- }
-
- if (lv_is_converting(lv)) {
- log_error("Can't resize logical volume %s while "
- "lvconvert in progress.", display_lvname(lv));
- return 0;
- }
-
- if (lp->stripe_size) {
- if (!(vg->fid->fmt->features & FMT_SEGMENTS)) {
- log_print_unless_silent("Varied stripesize not supported. Ignoring.");
- lp->stripe_size = lp->stripes = 0;
- } else if (!_validate_stripesize(vg, lp))
- return_0;
- }
-
- if (lp->resizefs &&
- (lv_is_thin_pool(lv) ||
- lv_is_thin_pool_data(lv) ||
- lv_is_thin_pool_metadata(lv) ||
- lv_is_vdo_pool(lv) ||
- lv_is_vdo_pool_data(lv) ||
- lv_is_pool_metadata_spare(lv) ||
- lv_is_lockd_sanlock_lv(lv))) {
- log_print_unless_silent("Ignoring --resizefs as volume %s does not have a filesystem.",
- display_lvname(lv));
- lp->resizefs = 0;
- }
-
- if (lp->stripes &&
- !(vg->fid->fmt->features & FMT_SEGMENTS)) {
- log_print_unless_silent("Varied striping not supported. Ignoring.");
- lp->stripes = 0;
- }
-
- if (lp->mirrors &&
- !(vg->fid->fmt->features & FMT_SEGMENTS)) {
- log_print_unless_silent("Mirrors not supported. Ignoring.");
- lp->mirrors = 0;
- }
-
- if (lv_component_is_active(lv)) {
- log_error("Cannot resize logical volume %s with active component LV(s).",
- display_lvname(lv));
- return 0;
- }
-
- if (lv_is_integrity(lv) || lv_raid_has_integrity(lv)) {
- if (lp->resize == LV_REDUCE) {
- log_error("Cannot reduce LV with integrity.");
- return 0;
- }
- }
- return 1;
-}
-
static int _lvresize_adjust_size(struct volume_group *vg,
uint64_t size, sign_t sign,
uint32_t *extents)
@@ -5327,17 +5210,23 @@ static int _lvresize_adjust_size(struct volume_group *vg,
/*
* If percent options were used, convert them into actual numbers of extents.
+ * FIXME: fix cases where lp->extents is initially used as a percentage,
+ * and is then rewritten to be a number of extents (simply save the percent
+ * value elsewhere.)
*/
static int _lvresize_extents_from_percent(const struct logical_volume *lv,
- struct lvresize_params *lp,
- struct dm_list *pvh)
+ struct lvresize_params *lp)
{
const struct volume_group *vg = lv->vg;
uint32_t pv_extent_count;
uint32_t old_extents = lp->extents;
+ log_debug("lvresize_extents_from_percent type %d extents %u percent_value %u",
+ lp->percent, lp->extents, lp->percent_value);
+
switch (lp->percent) {
case PERCENT_VG:
+ /* rewrites lp->extents from percentage to extents */
lp->extents = percent_of_extents(lp->extents, vg->extent_count,
(lp->sign != SIGN_MINUS));
if ((lp->sign == SIGN_NONE) && (lp->extents > (lv->le_count + vg->free_count))) {
@@ -5348,21 +5237,45 @@ static int _lvresize_extents_from_percent(const struct logical_volume *lv,
}
break;
case PERCENT_FREE:
+ /* rewrites lp->extents from percentage to extents */
lp->extents = percent_of_extents(lp->extents, vg->free_count,
(lp->sign != SIGN_MINUS));
break;
case PERCENT_LV:
- lp->extents = percent_of_extents(lp->extents, lv->le_count,
- (lp->sign != SIGN_MINUS));
+ if (lp->extents) {
+ /* rewrites lp->extents from percentage to extents */
+ lp->extents = percent_of_extents(lp->extents, lv->le_count,
+ (lp->sign != SIGN_MINUS));
+ } else if (lp->percent_value) {
+ old_extents = lp->percent_value;
+ lp->extents = percent_of_extents(lp->percent_value, lv->le_count,
+ (lp->sign != SIGN_MINUS));
+ }
break;
case PERCENT_PVS:
- if (pvh != &vg->pvs) {
- pv_extent_count = pv_list_extents_free(pvh);
- lp->extents = percent_of_extents(lp->extents, pv_extent_count,
+ if (lp->pvh != &vg->pvs) {
+ pv_extent_count = pv_list_extents_free(lp->pvh);
+ if (lp->extents) {
+ /* rewrites lp->extents from percentage to extents */
+ lp->extents = percent_of_extents(lp->extents, pv_extent_count,
(lp->sign != SIGN_MINUS));
- } else
- lp->extents = percent_of_extents(lp->extents, vg->extent_count,
+ } else if (lp->percent_value) {
+ /* lvresize has PVs args and no size of exents options */
+ old_extents = lp->percent_value;
+ lp->extents = percent_of_extents(lp->percent_value, pv_extent_count,
(lp->sign != SIGN_MINUS));
+ }
+ } else {
+ if (lp->extents) {
+ /* rewrites lp->extents from percentage to extents */
+ lp->extents = percent_of_extents(lp->extents, vg->extent_count,
+ (lp->sign != SIGN_MINUS));
+ } else if (lp->percent_value) {
+ old_extents = lp->percent_value;
+ lp->extents = percent_of_extents(lp->percent_value, vg->extent_count,
+ (lp->sign != SIGN_MINUS));
+ }
+ }
break;
case PERCENT_ORIGIN:
if (!lv_is_cow(lv)) {
@@ -5430,7 +5343,7 @@ static uint32_t _lv_pe_count(struct logical_volume *lv)
/* FIXME Avoid having variables like lp->extents mean different things at different places */
static int _lvresize_adjust_extents(struct logical_volume *lv,
struct lvresize_params *lp,
- struct dm_list *pvh)
+ int *matches_existing)
{
struct volume_group *vg = lv->vg;
struct cmd_context *cmd = vg->cmd;
@@ -5711,12 +5624,12 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
}
if ((lp->extents == existing_logical_extents) && !lp->use_policies) {
- if (!lp->resizefs && !lp->poolmetadata_size) {
- log_error("New size (%d extents) matches existing size (%d extents).",
- lp->extents, existing_logical_extents);
- return 0;
- }
- lp->resize = LV_EXTEND; /* lets pretend zero size extension */
+ log_print("New size (%d extents) matches existing size (%d extents).",
+ lp->extents, existing_logical_extents);
+ if (lp->resize == LV_ANY)
+ lp->resize = LV_EXTEND; /* lets pretend zero size extension */
+ *matches_existing = 1;
+ return 1;
}
/* Perform any rounding to produce complete stripes. */
@@ -5771,12 +5684,12 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
}
lp->resize = LV_EXTEND;
} else if ((lp->extents == existing_logical_extents) && !lp->use_policies) {
- if (!lp->resizefs && !lp->poolmetadata_size) {
- log_error("New size (%d extents) matches existing size "
- "(%d extents)", lp->extents, existing_logical_extents);
- return 0;
- }
- lp->resize = LV_EXTEND;
+ log_print("New size (%d extents) matches existing size (%d extents)",
+ lp->extents, existing_logical_extents);
+ if (lp->resize == LV_ANY)
+ lp->resize = LV_EXTEND;
+ *matches_existing = 1;
+ return 1;
}
/*
@@ -5794,8 +5707,52 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
return 1;
}
-static int _lvresize_check_type(const struct logical_volume *lv,
- const struct lvresize_params *lp)
+static int _lv_reduce_vdo_discard(struct cmd_context *cmd,
+ struct logical_volume *lv,
+ struct lvresize_params *lp)
+{
+ char name[PATH_MAX];
+ struct device *dev;
+ struct volume_group *vg = lv->vg;
+
+ /* FIXME: stop using dev-cache and struct device here, dev-cache
+ should only be used for scanning headers/metadata to find PVs. */
+
+ if (dm_snprintf(name, sizeof(name), "%s%s/%s", cmd->dev_dir,
+ vg->name, lv->name) < 0) {
+ log_error("Name too long - device not discarded (%s)", lv->name);
+ return 0;
+ }
+
+ if (!(dev = dev_cache_get(cmd, name, NULL))) {
+ log_error("%s: not found: device not discarded.", name);
+ return 0;
+ }
+
+ if (!dev_discard_max_bytes(cmd->dev_types, dev) ||
+ !dev_discard_granularity(cmd->dev_types, dev)) {
+ log_error("%s: max bytes and granularity query fails.", name);
+ dev_destroy_file(dev);
+ return 0;
+ }
+
+ log_warn("WARNING: %s: Discarding %s at offset " FMTu64 ", please wait...",
+ name, display_size(cmd, (uint64_t)(lv->le_count - lp->extents) * vg->extent_size),
+ ((uint64_t)lp->extents * vg->extent_size) << SECTOR_SHIFT);
+
+ if (!dev_discard_blocks(dev, ((uint64_t)lp->extents * vg->extent_size) << SECTOR_SHIFT,
+ ((uint64_t)(lv->le_count - lp->extents) * vg->extent_size) << SECTOR_SHIFT)) {
+ log_error("%s: discarding failed.", name);
+ dev_destroy_file(dev);
+ return 0;
+ }
+
+ dev_destroy_file(dev);
+ return 1;
+}
+
+static int _lv_resize_check_type(struct logical_volume *lv,
+ struct lvresize_params *lp)
{
struct lv_segment *seg;
@@ -5812,6 +5769,20 @@ static int _lvresize_check_type(const struct logical_volume *lv,
}
}
+ if (lv_is_raid_image(lv) || lv_is_raid_metadata(lv)) {
+ log_error("Cannot resize a RAID %s directly for %s",
+ lv_is_raid_image(lv) ? "image" : "metadata area",
+ display_lvname(lv));
+ return 0;
+ }
+
+ seg = first_seg(lv);
+ if ((seg_is_raid4(seg) || seg_is_any_raid5(seg)) && seg->area_count < 3) {
+ log_error("Cannot resize %s LV %s. Convert to more stripes first.",
+ lvseg_name(seg), display_lvname(lv));
+ return 0;
+ }
+
if (lp->resize == LV_REDUCE) {
if (lv_is_thin_pool_data(lv)) {
log_error("Thin pool volumes %s cannot be reduced in size yet.",
@@ -5832,6 +5803,21 @@ static int _lvresize_check_type(const struct logical_volume *lv,
log_error("Reduce not yet allowed on LVs with writecache attached.");
return 0;
}
+ if (lv_is_raid(lv)) {
+ unsigned attrs = 0;
+ const struct segment_type *segtype = first_seg(lv)->segtype;
+
+ if (!segtype->ops->target_present ||
+ !segtype->ops->target_present(lv->vg->cmd, NULL, &attrs) ||
+ !(attrs & RAID_FEATURE_SHRINK)) {
+ log_error("RAID module does not support shrinking.");
+ return 0;
+ }
+ }
+ if (lv_is_integrity(lv) || lv_raid_has_integrity(lv)) {
+ log_error("Cannot reduce LV with integrity.");
+ return 0;
+ }
} else if (lp->resize == LV_EXTEND) {
if (lv_is_thin_pool_metadata(lv) &&
(!(seg = find_pool_seg(first_seg(lv))) ||
@@ -5856,12 +5842,15 @@ static int _lvresize_check_type(const struct logical_volume *lv,
return 0;
}
+ if ((lp->resize == LV_REDUCE) && (lp->pvh != &lv->vg->pvs))
+ log_print_unless_silent("Ignoring PVs on command line when reducing.");
+
return 1;
}
-static int _lvresize_volume(struct logical_volume *lv,
- struct lvresize_params *lp,
- struct dm_list *pvh)
+static int _lv_resize_volume(struct logical_volume *lv,
+ struct lvresize_params *lp,
+ struct dm_list *pvh)
{
struct volume_group *vg = lv->vg;
struct cmd_context *cmd = vg->cmd;
@@ -5895,24 +5884,32 @@ static int _lvresize_volume(struct logical_volume *lv,
display_lvname(lv),
display_size(cmd, (uint64_t) old_extents * vg->extent_size), old_extents,
display_size(cmd, (uint64_t) lv->le_count * vg->extent_size), lv->le_count);
-
- /* Resizing metadata and PV list is not specified -> maintain size of _pmspare volume */
- if ((&vg->pvs == pvh) && lv_is_pool_metadata(lv))
- (void) handle_pool_metadata_spare(vg, 0, pvh, 1);
}
return 1;
}
-static int _lvresize_prepare(struct logical_volume *lv,
- struct lvresize_params *lp,
- struct dm_list *pvh)
+static int _lv_resize_adjust_size(struct logical_volume *lv,
+ struct lvresize_params *lp,
+ int *matches_existing)
{
/* Resolve extents from size */
- if (lp->size && !_lvresize_adjust_size(lv->vg, lp->size, lp->sign, &lp->extents))
- return_0;
- else if (lp->extents && !_lvresize_extents_from_percent(lv, lp, pvh))
- return_0;
+ if (lp->size) {
+ if (!_lvresize_adjust_size(lv->vg, lp->size, lp->sign, &lp->extents))
+ return_0;
+ }
+
+ /* set lp->extents based on lp->percent_value */
+ else if (lp->percent_value) {
+ if (!_lvresize_extents_from_percent(lv, lp))
+ return_0;
+ }
+
+ /* rewrites lp->extents from percentage to extents */
+ else if (lp->extents && (lp->percent != PERCENT_NONE)) {
+ if (!_lvresize_extents_from_percent(lv, lp))
+ return_0;
+ }
/* Ensure stripe boundary extents! */
if (!lp->percent && lv_is_raid(lv))
@@ -5920,18 +5917,15 @@ static int _lvresize_prepare(struct logical_volume *lv,
seg_is_raid1(first_seg(lv)) ? 0 : _raid_stripes_count(first_seg(lv)),
lp->resize == LV_REDUCE ? 0 : 1);
- if (!_lvresize_adjust_extents(lv, lp, pvh))
- return_0;
-
- if (!_lvresize_check_type(lv, lp))
+ if (!_lvresize_adjust_extents(lv, lp, matches_existing))
return_0;
return 1;
}
-/* Set aux LV properties, we can't use those from command line */
-static struct logical_volume *_lvresize_setup_aux(struct logical_volume *lv,
- struct lvresize_params *lp)
+/* Set thin pool metadata properties, we can't use those from command line */
+static void _setup_params_for_extend_metadata(struct logical_volume *lv,
+ struct lvresize_params *lp)
{
struct lv_segment *mseg = last_seg(lv);
@@ -5942,272 +5936,466 @@ static struct logical_volume *_lvresize_setup_aux(struct logical_volume *lv,
lp->resizefs = 0;
lp->stripes = lp->mirrors ? mseg->area_count / lp->mirrors : 0;
lp->stripe_size = mseg->stripe_size;
+}
- return lv;
+
+static int _lv_resize_check_used(struct logical_volume *lv)
+{
+ if (lv_is_locked(lv)) {
+ log_error("Can't resize locked logical volume %s.", display_lvname(lv));
+ return 0;
+ }
+
+ if (lv_is_converting(lv)) {
+ log_error("Can't resize logical volume %s while lvconvert in progress.", display_lvname(lv));
+ return 0;
+ }
+
+ if (lv_component_is_active(lv)) {
+ log_error("Cannot resize logical volume %s with active component LV(s).", display_lvname(lv));
+ return 0;
+ }
+
+ if (lv_is_raid_with_tracking(lv)) {
+ log_error("Cannot resize logical volume %s while it is tracking a split image.", display_lvname(lv));
+ return 0;
+ }
+
+ if (lv_is_external_origin(lv)) {
+ /*
+ * Since external-origin can be activated read-only,
+ * there is no way to use extended areas.
+ */
+ log_error("Cannot resize external origin logical volume %s.",
+ display_lvname(lv));
+ return 0;
+ }
+
+ return 1;
}
-int lv_resize(struct logical_volume *lv,
- struct lvresize_params *lp,
- struct dm_list *pvh)
+int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvresize_params *lp)
{
+ struct lvresize_params lp_meta;
struct volume_group *vg = lv->vg;
- struct cmd_context *cmd = vg->cmd;
- struct logical_volume *lock_lv = (struct logical_volume*) lv_lock_holder(lv);
- struct logical_volume *aux_lv = NULL; /* Note: aux_lv never resizes fs */
- struct logical_volume *resizable_layer_lv;
- struct lvresize_params aux_lp;
struct lv_segment *seg = first_seg(lv);
+ struct logical_volume *lv_top = NULL;
+ struct logical_volume *lv_main = NULL;
+ struct logical_volume *lv_meta = NULL;
+ struct logical_volume *lv_main_layer = NULL;
+ struct logical_volume *lv_meta_layer = NULL;
+ int main_size_matches = 0;
+ int meta_size_matches = 0;
+ int is_extend = (lp->resize == LV_EXTEND);
+ int is_reduce = (lp->resize == LV_REDUCE);
int activated = 0;
- int ret = 0;
int status;
- struct device *dev;
- char name[PATH_MAX];
+ int ret = 0;
+
+ memset(&lp_meta, 0, sizeof(lp_meta));
+
+ /*
+ * Some checks apply to the LV command arg (don't require top/bottom
+ * LVs in a stack), and don't require knowing if the command is doing
+ * extend or reduce (determined later).
+ */
+
+ if (lp->stripe_size && !_validate_stripesize(vg, lp))
+ return_0;
+
+ /*
+ * The only types of !visible/internal/non-top LVs that can be directly
+ * resized via the command arg. Other internal LVs are resized
+ * indirectly when resizing a top LV.
+ */
+ if (!lv_is_visible(lv) &&
+ !lv_is_thin_pool_data(lv) &&
+ !lv_is_thin_pool_metadata(lv) &&
+ !lv_is_vdo_pool_data(lv) &&
+ !lv_is_lockd_sanlock_lv(lv)) {
+ log_error("Can't resize internal logical volume %s.", display_lvname(lv));
+ return 0;
+ }
- if (lp->use_policies) {
- if (!lv_is_cow(lv) &&
- !lv_is_thin_pool(lv) &&
- !lv_is_vdo_pool(lv)) {
- log_error("Policy-based resize is supported only for snapshot, thin pool and vdo pool volumes.");
+ /*
+ * resizefs applies to the LV command arg, not to the top LV or lower
+ * resizable LV.
+ */
+ if (lp->resizefs) {
+ if (!lv_is_active(lv)) {
+ log_error("Logical volume %s must be activated before resizing filesystem.",
+ display_lvname(lv));
return 0;
}
+ /* types of LVs that can hold a file system */
+ if (!(lv_is_linear(lv) || lv_is_striped(lv) || lv_is_raid(lv) ||
+ lv_is_mirror(lv) || lv_is_thin_volume(lv) || lv_is_vdo(lv) ||
+ lv_is_cache(lv) || lv_is_writecache(lv))) {
+ log_print_unless_silent("Ignoring --resizefs for LV type %s.",
+ seg ? seg->segtype->name : "unknown");
+ lp->resizefs = 0;
+ }
+ }
- lp->extents = 0;
- lp->sign = SIGN_PLUS;
- lp->percent = PERCENT_LV;
+ /*
+ * Figure out which LVs are going to be extended, and set params
+ * to the requested extents/size for each. Some LVs are extended
+ * only by extending an underlying LV. Extending some top level
+ * LVs results in extending multiple underlying LVs.
+ *
+ * lv_top is the top level LV in stack.
+ * lv_main is the main LV to be resized.
+ * lv_meta is always a thin pool metadata LV.
+ *
+ * lv_main_layer/lv_meta_layer may be LV types (like cache) that are
+ * layered over the main/meta LVs. These layer LVs are skipped over
+ * by get_resizable_layer_lv() which finds the bottom-most layer
+ * which is originally resized. The layer LVs are resized indirectly
+ * as a result of the lower data-holding LVs being resized.
+ *
+ * In the simplest case there is no layering/stacking, and
+ * lv == lv_main == lv_main_layer == lv_top
+ */
- aux_lp = *lp;
- if (!_lvresize_adjust_policy(lv, &lp->extents, &aux_lp.extents))
+ if (cmd->command_enum == lvextend_policy_CMD) {
+ /* lvextend --use-policies may extend main or meta or both */
+ lv_top = lv;
+ if (lv_is_thin_pool(lv)) {
+ if (lp->policy_percent_main) {
+ lv_main = seg_lv(first_seg(lv), 0); /* thin pool data */
+ lp->percent_value = lp->policy_percent_main;
+ }
+ if (lp->policy_percent_meta) {
+ lv_meta = first_seg(lv)->metadata_lv; /* thin pool metadata */
+ _setup_params_for_extend_metadata(lv_meta, &lp_meta);
+ /* override setup function which isn't right for policy use */
+ lp_meta.percent = PERCENT_LV;
+ lp_meta.sign = SIGN_PLUS;
+ lp_meta.percent_value = lp->policy_percent_meta;
+ lp_meta.pvh = lp->pvh;
+ }
+ } else if (lv_is_vdo_pool(lv)) {
+ lv_main = seg_lv(first_seg(lv), 0); /* vdo pool data */
+ lp->percent_value = lp->policy_percent_main;
+ } else if (lv_is_cow(lv)) {
+ lv_main = lv;
+ lp->percent_value = lp->policy_percent_main;
+ } else
return_0;
- if (!lp->extents) {
- if (!aux_lp.extents)
- return 1; /* Nothing to do */
- /* Resize thin-pool metadata as mainlv */
- lv = seg->metadata_lv; /* metadata LV */
- lp->extents = aux_lp.extents;
- } else if (aux_lp.extents) {
- /* Also resize thin-pool metadata */
- aux_lv = _lvresize_setup_aux(seg->metadata_lv, &aux_lp);
- }
- } else if (lp->poolmetadata_size) {
- /* Validate --poolmetadata_size supported volumes here */
- if (!lv_is_thin_pool(lv) && !lv_is_thin_pool_metadata(lv)) {
+ } else if ((cmd->command_enum == lvextend_pool_metadata_CMD) ||
+ (cmd->command_enum == lvresize_pool_metadata_CMD)) {
+ /* lvresize|lvextend --poolmetadatasize, extends only thin pool metadata */
+ if (lv_is_thin_pool(lv)) {
+ lv_top = lv;
+ lv_meta = first_seg(lv)->metadata_lv; /* thin pool metadata */
+ } else if (lv_is_thin_pool_metadata(lv)) {
+ lv_top = _get_top_layer_lv(lv); /* thin pool LV */
+ lv_meta = lv;
+ } else {
log_error("--poolmetadatasize can be used only with thin pools.");
return 0;
}
- if (!lp->extents && !lp->size) {
- /* When only --poolmetadatasize given and any size option
- * switch directly to resize metadata LV */
- if (lv_is_thin_pool(lv))
- lv = seg->metadata_lv;
- lp->size = lp->poolmetadata_size;
- lp->sign = lp->poolmetadata_sign;
+ lp_meta = *lp;
+ _setup_params_for_extend_metadata(lv_meta, &lp_meta);
+ lp_meta.size = lp->poolmetadata_size;
+ lp_meta.sign = lp->poolmetadata_sign;
+ lp->poolmetadata_size = 0;
+ lp->poolmetadata_sign = 0;
+
+ } else if (lv_is_thin_pool(lv) && lp->poolmetadata_size) {
+ /* extend both thin pool data and metadata */
+ lv_top = lv;
+ lv_main = seg_lv(first_seg(lv), 0); /* thin pool data */
+ lv_meta = first_seg(lv)->metadata_lv; /* thin pool metadata */
+ lp_meta = *lp;
+ _setup_params_for_extend_metadata(lv_meta, &lp_meta);
+ lp_meta.size = lp->poolmetadata_size;
+ lp_meta.sign = lp->poolmetadata_sign;
+ lp->poolmetadata_size = 0;
+ lp->poolmetadata_sign = 0;
+
+ } else if (lv_is_thin_pool_metadata(lv)) {
+ /* extend only thin pool metadata */
+ lv_top = _get_top_layer_lv(lv); /* thin pool LV */
+ lv_meta = lv;
+ lp_meta = *lp;
+ _setup_params_for_extend_metadata(lv_meta, &lp_meta);
+ if (lp->poolmetadata_size) {
+ lp_meta.size = lp->poolmetadata_size;
+ lp_meta.size = lp->poolmetadata_sign;
lp->poolmetadata_size = 0;
- } else if (lv_is_thin_pool(lv)) {
- aux_lp = *lp;
- aux_lv = _lvresize_setup_aux(seg->metadata_lv, &aux_lp);
- aux_lp.size = lp->poolmetadata_size;
- aux_lp.sign = lp->poolmetadata_sign;
- } else {
- log_error("--poolmetadatasize for thin-pool metadata cannot be used with size.");
- return 0;
+ lp->poolmetadata_sign = 0;
}
+ /* else lp_meta.extents|size from lp->extents|size above */
+
+ } else if (lv_is_thin_pool(lv)) {
+ /* extend thin pool data and possibly metadata */
+ lv_top = lv;
+ lv_main = seg_lv(first_seg(lv), 0);
+ /* Do not set lv_meta to the thin pool metadata here.
+ See below "Possibly enable lv_meta extend". */
}
- resizable_layer_lv = _get_resizable_layer_lv(lv);
- if (!(lv = _get_top_layer_lv(lv)))
- return_0;
+ /*
+ * None of the special cases above (selecting which LVs to extend
+ * depending on options set and type of LV) have applied, so this
+ * is the standard case.
+ */
+ if (!lv_main && !lv_meta) {
+ lv_top = _get_top_layer_lv(lv);
+ lv_main_layer = lv;
+ lv_main = _get_resizable_layer_lv(lv_main_layer);
+ } else {
+ lv_main_layer = lv_main;
+ lv_meta_layer = lv_meta;
+ if (lv_main)
+ lv_main = _get_resizable_layer_lv(lv_main_layer);
+ if (lv_meta)
+ lv_meta = _get_resizable_layer_lv(lv_meta_layer);
+ }
+ /* Clear layer variables if no layer exists. */
+ if (lv_main_layer == lv_main)
+ lv_main_layer = NULL;
+ if (lv_meta_layer == lv_meta)
+ lv_meta_layer = NULL;
- if (!_lvresize_check(lv, lp))
- return_0;
+ /*
+ * LVs to work with are now determined:
+ * lv_top is always set, it is not used to resize, but is used
+ * to reload dm devices for the lv.
+ * If lv_main is set, it is resized.
+ * If lv_meta is set, it is resized.
+ * If lv_meta is not set, it may be set below and resized.
+ */
- /* Always should have lp->size or lp->extents */
- if (!_lvresize_prepare(resizable_layer_lv, lp, pvh))
+ if (!_lv_resize_check_used(lv_top))
return_0;
-
- if ((lp->resize != LV_REDUCE) && !aux_lv && !lp->poolmetadata_size &&
- (&vg->pvs == pvh) && lv_is_thin_pool(lv)) {
- /* When thin-pool data part is extended, automatically extend also metadata part
- * to have the metadata chunks for adressing all data blocks
- * Do this only when PV list is not defined and --poolmetadatasize is unspecified */
- aux_lp = *lp;
- seg = first_seg(lv);
- aux_lp.size = estimate_thin_pool_metadata_size(lp->extents, vg->extent_size, seg->chunk_size);
- if (aux_lp.size > seg->metadata_lv->size) {
- log_verbose("Also going to resize thin-pool metadata to match bigger data.");
- aux_lv = _lvresize_setup_aux(seg->metadata_lv, &aux_lp);
- aux_lp.sign = SIGN_NONE;
- } else
- aux_lp.size = 0;
- }
-
- if (aux_lv && (aux_lv = _get_resizable_layer_lv(aux_lv)) &&
- !_lvresize_prepare(aux_lv, &aux_lp, pvh))
+ if (lv_main && (lv_main != lv_top) && !_lv_resize_check_used(lv_main))
return_0;
- if (((lp->resize == LV_REDUCE) ||
- (aux_lv && aux_lp.resize == LV_REDUCE)) &&
- (pvh != &vg->pvs))
- log_print_unless_silent("Ignoring PVs on command line when reducing.");
+ /*
+ * Set a new size for lv_main.
+ */
+ if (lv_main) {
+ /* sets lp extents and lp resize */
+ if (!_lv_resize_adjust_size(lv_main, lp, &main_size_matches))
+ return_0;
+ /* sanity check the result of adjust_size */
+ if (lp->extents == 0)
+ return_0;
+ /* adjust_size resolves LV_ANY to EXTEND|REDUCE */
+ if (lp->resize == LV_ANY)
+ return_0;
+ if (is_extend && (lp->resize != LV_EXTEND))
+ return_0;
+ if (is_reduce && (lp->resize != LV_REDUCE))
+ return_0;
+ is_extend = (lp->resize == LV_EXTEND);
+ is_reduce = (lp->resize == LV_REDUCE);
- /* Request confirmation before operations that are often mistakes. */
- /* aux_lv never resize fs */
- if ((lp->resizefs || (lp->resize == LV_REDUCE)) &&
- !_request_confirmation(lv, lp))
- return_0;
+ if (!_lv_resize_check_type(lv_main, lp))
+ return_0;
- if (lp->resizefs) {
- if (!lp->nofsck &&
- !_fsadm_cmd(FSADM_CMD_CHECK, lv, 0, lp->yes, lp->force, &status)) {
- if (status != FSADM_CHECK_FAILS_FOR_MOUNTED) {
- log_error("Filesystem check failed.");
- return 0;
- }
- /* some filesystems support online resize */
- }
+ if (is_reduce && !main_size_matches && !lp->resizefs &&
+ !_lv_reduce_confirmation(lv, lp))
+ return_0;
+ }
- /* FIXME forks here */
- if ((lp->resize == LV_REDUCE) &&
- !_fsadm_cmd(FSADM_CMD_RESIZE, lv, lp->extents, lp->yes, lp->force, NULL)) {
- log_error("Filesystem resize failed.");
- return 0;
+ /*
+ * Possibly enable lv_meta extend if not already enabled. If lv_meta
+ * for a thin pool is not already being extended, and user requested
+ * extending the thin pool, then we may need to automatically include
+ * extending lv_meta in addition to lv_main (data), so that the
+ * metadata size is sufficient for the extended data size.
+ *
+ * If specific PVs were named to extend, this is taken to mean that
+ * only the thin pool data should be extended (using those PVs), and
+ * the thin pool metadata should not be automatically extended (since
+ * it would likely want to be extended using different PVs.)
+ */
+ if (lv_is_thin_pool(lv_top) && is_extend && lv_main && !lv_meta && (&vg->pvs == lp->pvh)) {
+ struct lv_segment *tpseg = first_seg(lv_top);
+ uint64_t meta_size = estimate_thin_pool_metadata_size(lp->extents, vg->extent_size, tpseg->chunk_size);
+ if (meta_size > tpseg->metadata_lv->size) {
+ log_verbose("Extending thin pool metadata to %llu for larger data", (unsigned long long)meta_size);
+ lv_meta = tpseg->metadata_lv;
+ lp_meta = *lp;
+ _setup_params_for_extend_metadata(lv_meta, &lp_meta);
+ lp_meta.size = meta_size;
+ lp_meta.sign = SIGN_NONE;
+ /* meta may have a layer over it */
+ lv_meta_layer = lv_meta;
+ lv_meta = _get_resizable_layer_lv(lv_meta_layer);
+ if (lv_meta == lv_meta_layer)
+ lv_meta_layer = NULL;
}
}
- if (!lp->extents && (!aux_lv || !aux_lp.extents)) {
- lp->extents = lv->le_count;
- goto out; /* Nothing to do */
+ /*
+ * Set a new size for lv_meta (extend only.)
+ */
+ if (lv_meta) {
+ /* sets lp extents and lp resize */
+ if (!_lv_resize_adjust_size(lv_meta, &lp_meta, &meta_size_matches))
+ return_0;
+ /* sanity check the result of adjust_size */
+ if (lp_meta.extents == 0)
+ return_0;
+ /* adjust_size resolves lp_meta.resize to EXTEND|REDUCE */
+ /* _lv_resize_check_type errors if resize is EXTEND for thin meta */
+ if (!_lv_resize_check_type(lv_meta, &lp_meta))
+ return_0;
}
- if (lv_is_thin_pool(lock_lv) && /* Lock holder is thin-pool */
- !lv_is_active(lock_lv)) {
+ /*
+ * No resizing is needed.
+ */
+ if ((main_size_matches && meta_size_matches) ||
+ (main_size_matches && !lv_meta) ||
+ (meta_size_matches && !lv_main)) {
+ log_error("No size change.");
+ return 0;
+ }
+ /*
+ * Active 'hidden' -tpool can be waiting for resize, but the pool LV
+ * itself might be inactive. Here plain suspend/resume would not work.
+ * So active temporarily pool LV (with on disk metadata) then use
+ * suspend and resume and deactivate pool LV, instead of searching for
+ * an active thin volume.
+ */
+ if (lv_is_thin_pool(lv_top) && !lv_is_active(lv_top)) {
if (!activation()) {
- log_error("Cannot resize %s without using "
- "device-mapper kernel driver.",
- display_lvname(lock_lv));
- return 0;
+ log_error("Cannot resize %s without using device-mapper kernel driver.",
+ display_lvname(lv_top));
+ return_0;
}
- /*
- * Active 'hidden' -tpool can be waiting for resize, but the
- * pool LV itself might be inactive.
- * Here plain suspend/resume would not work.
- * So active temporarily pool LV (with on disk metadata)
- * then use suspend and resume and deactivate pool LV,
- * instead of searching for an active thin volume.
- */
- if (!activate_lv(cmd, lock_lv)) {
- log_error("Failed to activate %s.", display_lvname(lock_lv));
- return 0;
+ if (!activate_lv(cmd, lv_top)) {
+ log_error("Failed to activate %s.", display_lvname(lv_top));
+ return_0;
}
-
activated = 1;
}
- /* Send DISCARD/TRIM to reduced area of VDO volumes
- * TODO: enable thin and provide
- * TODO2: we need polling method */
- if ((lp->resize == LV_REDUCE) && lv_is_vdo(lv)) {
- if (dm_snprintf(name, sizeof(name), "%s%s/%s", lv->vg->cmd->dev_dir,
- lv->vg->name, lv->name) < 0) {
- log_error("Name too long - device not discarded (%s)", lv->name);
- return 0;
- }
-
- if (!(dev = dev_cache_get(lv->vg->cmd, name, NULL))) {
- log_error("%s: not found: device not discarded.", name);
- return 0;
- }
+ /*
+ * If the LV is locked due to being active, this lock call is a no-op.
+ * Otherwise, this acquires a transient lock on the lv (not PERSISTENT)
+ */
+ if (!lockd_lv_resize(cmd, lv_top, "ex", 0, lp))
+ goto_out;
- if (!dev_discard_max_bytes(cmd->dev_types, dev) ||
- !dev_discard_granularity(cmd->dev_types, dev)) {
- log_error("%s: max bytes and granularity query fails.", name);
- dev_destroy_file(dev);
- return 0;
+ /*
+ * Check the file system, and shrink the fs before reducing lv.
+ * TODO: libblkid fs type, fs last_block, mount state,
+ * unlock vg, mount|unmount if needed, fork fs shrink,
+ * lock vg, rescan devs, recheck fs type last_block.
+ * (at end mount|unmount if needed to restore initial state.)
+ */
+ if (lp->resizefs && !lp->nofsck &&
+ !_fsadm_cmd(FSADM_CMD_CHECK, lv_top, 0, lp->yes, lp->force, &status)) {
+ if (status != FSADM_CHECK_FAILS_FOR_MOUNTED) {
+ log_error("Filesystem check failed.");
+ goto out;
}
+ /* some filesystems support online resize */
+ }
+ if (lp->resizefs && is_reduce &&
+ !_fsadm_cmd(FSADM_CMD_RESIZE, lv_top, lp->extents, lp->yes, lp->force, NULL)) {
+ log_error("Filesystem resize failed.");
+ goto out;
+ }
- log_warn("WARNING: %s: Discarding %s at offset " FMTu64 ", please wait...",
- name, display_size(cmd, (uint64_t)(lv->le_count - lp->extents) * vg->extent_size),
- ((uint64_t)lp->extents * vg->extent_size) << SECTOR_SHIFT);
-
- if (!dev_discard_blocks(dev, ((uint64_t)lp->extents * vg->extent_size) << SECTOR_SHIFT,
- ((uint64_t)(lv->le_count - lp->extents) * vg->extent_size) << SECTOR_SHIFT)) {
- log_error("%s: discarding failed.", name);
- dev_destroy_file(dev);
- return 0;
- }
+ /*
+ * Send DISCARD/TRIM to reduced area of VDO volumes
+ * TODO: enable thin and provide
+ * TODO2: we need polling method
+ */
+ if (is_reduce && lv_is_vdo(lv_top) && !_lv_reduce_vdo_discard(cmd, lv_top, lp))
+ goto_out;
- dev_destroy_file(dev);
- }
/*
- * If the LV is locked from activation, this lock call is a no-op.
- * Otherwise, this acquires a transient lock on the lv (not PERSISTENT).
+ * Remove any striped raid reshape space for LV resizing (not common).
*/
- if (!lockd_lv_resize(cmd, lock_lv, "ex", 0, lp))
+ if (lv_meta && first_seg(lv_meta)->reshape_len && !lv_raid_free_reshape_space(lv_meta))
+ return_0;
+ if (lv_main && first_seg(lv_main)->reshape_len && !lv_raid_free_reshape_space(lv_main))
return_0;
- /* Remove any striped raid reshape space for LV resizing */
- if (aux_lv && first_seg(aux_lv)->reshape_len)
- if (!lv_raid_free_reshape_space(aux_lv))
- return_0;
- if (first_seg(resizable_layer_lv)->reshape_len)
- if (!lv_raid_free_reshape_space(resizable_layer_lv))
- return_0;
-
- if (aux_lv) {
- if (!_lvresize_volume(aux_lv, &aux_lp, pvh))
- goto_bad;
+ /*
+ * The core of the actual lv resizing.
+ * Allocate or free extents in the VG, adjust LV segments to reflect
+ * new requested size, write VG metadata, reload the dm device stack
+ * (reload from the top LV.) Do lv_meta first.
+ * When extending lv_meta, also extend (or create) the pool's spare
+ * meta lv to match the size of lv_meta (only do this when the
+ * command is not limited to allocating from specific PVs.)
+ */
- /* store vg on disk(s) */
- if (aux_lp.size_changed && !lv_update_and_reload(lock_lv))
- goto_bad;
- }
+ if (!lv_meta)
+ goto do_main;
+ if (!_lv_resize_volume(lv_meta, &lp_meta, lp->pvh))
+ goto_out;
+ if (!lp_meta.size_changed)
+ goto do_main;
+ if ((&vg->pvs == lp->pvh) && !handle_pool_metadata_spare(vg, 0, lp->pvh, 1))
+ stack;
+ if (!lv_update_and_reload(lv_top))
+ goto_out;
+ log_debug("Resized thin pool metadata %s to %u extents.", display_lvname(lv_meta), lp_meta.extents);
- if (!_lvresize_volume(resizable_layer_lv, lp, pvh))
- goto_bad;
+ do_main:
- /* store vg on disk(s) */
+ if (!lv_main)
+ goto end_main;
+ if (!_lv_resize_volume(lv_main, lp, lp->pvh))
+ goto_out;
if (!lp->size_changed)
- goto out; /* No table reload needed */
+ goto_out;
+ if (!lv_update_and_reload(lv_top))
+ goto_out;
+ log_debug("Resized %s to %u extents.", display_lvname(lv_main), lp->extents);
- if (!lv_update_and_reload(lock_lv))
- goto_bad;
+ end_main:
- if (lv_is_cow_covering_origin(lv))
- if (!monitor_dev_for_events(cmd, lv, 0, 0))
+ /*
+ * other maintenance:
+ * - update lvm pool metadata (drop messages).
+ * - print warnings about overprovisioning.
+ * - stop monitoring cow snapshot larger than origin
+ */
+ 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_main && lv_is_cow_covering_origin(lv_main)) {
+ if (!monitor_dev_for_events(cmd, lv_main, 0, 0))
stack;
-
- if (lv_is_thin_pool(lock_lv)) {
- /* Update lvm pool metadata (drop messages). */
- if (!update_thin_pool_lv(lock_lv, 1))
- goto_bad;
}
- /* Check for over provisioning when extended */
- if ((lp->resize == LV_EXTEND) && lv_is_thin_type(lv))
- thin_pool_check_overprovisioning(lv);
-
-out:
- log_print_unless_silent("Logical volume %s successfully resized.",
- display_lvname(lv));
-
- if (lp->resizefs && (lp->resize == LV_EXTEND) &&
- !_fsadm_cmd(FSADM_CMD_RESIZE, lv, lp->extents, lp->yes, lp->force, NULL))
- goto_bad;
+ /*
+ * Extend the file system.
+ * TODO: libblkid fs type, mount state,
+ * unlock vg, mount|unmount if needed, fork fs grow,
+ * mount|unmount if needed to restore initial state.
+ */
+ if (lp->resizefs && is_extend &&
+ !_fsadm_cmd(FSADM_CMD_RESIZE, lv_top, lp->extents, lp->yes, lp->force, NULL)) {
+ log_warn("Filesystem resize failed.");
+ goto out;
+ }
ret = 1;
-bad:
- if (activated) {
- if (!sync_local_dev_names(lock_lv->vg->cmd)) {
- log_error("Failed to sync local devices before deactivating LV %s.",
- display_lvname(lock_lv));
- return 0;
- }
- if (!deactivate_lv(cmd, lock_lv)) {
- log_error("Problem deactivating %s.", display_lvname(lock_lv));
- ret = 0;
- }
+ out:
+ if (activated) {
+ if (!sync_local_dev_names(cmd))
+ stack;
+ if (!deactivate_lv(cmd, lv_top))
+ log_warn("Problem deactivating %s.", display_lvname(lv_top));
}
return ret;
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index deaf3f30c..048b7553f 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -297,6 +297,9 @@
int lv_layout_and_role(struct dm_pool *mem, const struct logical_volume *lv,
struct dm_list **layout, struct dm_list **role);
+int lv_is_linear(struct logical_volume *lv);
+int lv_is_striped(struct logical_volume *lv);
+
/* Ordered list - see lv_manip.c */
typedef enum {
AREA_UNASSIGNED,
@@ -661,42 +664,33 @@ struct pvcreate_params {
};
struct lvresize_params {
- int argc;
- char **argv;
-
- const char *vg_name; /* only-used when VG is not yet opened (in /tools) */
- const char *lv_name;
-
- const struct segment_type *segtype;
-
- uint64_t poolmetadata_size;
- sign_t poolmetadata_sign;
-
- /* Per LV applied parameters */
-
enum {
LV_ANY = 0,
LV_REDUCE = 1,
LV_EXTEND = 2
} resize;
-
- int use_policies;
-
alloc_policy_t alloc;
int yes;
int force;
int nosync;
int nofsck;
int resizefs;
+ int use_policies;
+ const struct segment_type *segtype;
unsigned mirrors;
uint32_t stripes;
uint64_t stripe_size;
- uint32_t extents;
uint64_t size;
+ uint32_t extents;
sign_t sign;
- percent_type_t percent;
+ percent_type_t percent; /* the type of percentage, not a value */
+ uint32_t percent_value; /* 0 - 100 */
+ uint64_t poolmetadata_size;
+ sign_t poolmetadata_sign;
+ uint32_t policy_percent_main;
+ uint32_t policy_percent_meta;
int approx_alloc;
int extents_are_pes; /* Is 'extents' counting PEs or LEs? */
@@ -705,6 +699,8 @@ struct lvresize_params {
const char *lockopt;
char *lockd_lv_refresh_path; /* set during resize to use for refresh at the end */
char *lockd_lv_refresh_uuid; /* set during resize to use for refresh at the end */
+
+ struct dm_list *pvh; /* list of pvs to use */
};
void pvcreate_params_set_defaults(struct pvcreate_params *pp);
@@ -745,9 +741,10 @@ int vgs_are_compatible(struct cmd_context *cmd,
struct volume_group *vg_to);
uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname);
-int lv_resize(struct logical_volume *lv,
- struct lvresize_params *lp,
- struct dm_list *pvh);
+int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvresize_params *lp);
+int lv_extend_policy_calculate_percent(struct logical_volume *lv,
+ uint32_t *amount, uint32_t *meta_amount);
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const char *vgid,
uint32_t read_flags, uint32_t lockd_state,
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 1cda1888f..95f25eef8 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -5302,3 +5302,15 @@ int get_visible_lvs_using_pv(struct cmd_context *cmd, struct volume_group *vg, s
return 1;
}
+int lv_is_linear(struct logical_volume *lv)
+{
+ struct lv_segment *seg = first_seg(lv);
+ return segtype_is_linear(seg->segtype);
+}
+
+int lv_is_striped(struct logical_volume *lv)
+{
+ struct lv_segment *seg = first_seg(lv);
+ return segtype_is_striped(seg->segtype);
+}
+
diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
index bb4b5f115..a6bfc2deb 100644
--- a/lib/metadata/pool_manip.c
+++ b/lib/metadata/pool_manip.c
@@ -737,6 +737,7 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
extents = MAX_SIZE;
if (!lv) {
+ log_debug("Adding new pool metadata spare %u extents.", extents);
if (!_alloc_pool_metadata_spare(vg, extents, pvh))
return_0;
@@ -746,6 +747,8 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
seg = last_seg(lv);
seg_mirrors = lv_mirror_count(lv);
+ log_debug("Extending pool metadata spare from %u to %u extents.",
+ lv->le_count, extents);
/* Check spare LV is big enough and preserve segtype */
if ((lv->le_count < extents) && seg &&
!lv_extend(lv, seg->segtype,
diff --git a/test/shell/lvextend-thin-full.sh b/test/shell/lvextend-thin-full.sh
index 263ab2fb9..69d15e3b0 100644
--- a/test/shell/lvextend-thin-full.sh
+++ b/test/shell/lvextend-thin-full.sh
@@ -41,16 +41,15 @@ lvcreate -L2M -n $lv1 $vg
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
-# Cannot resize if set to 0%
-not lvextend --use-policies --config 'activation{thin_pool_autoextend_percent = 0}' $vg/pool 2>&1 | tee err
-grep "0%" err
-
-# Locally active LV is needed
+# active thin pool is needed to use policy
not lvextend --use-policies $vg/pool 2>&1 | tee err
-grep "locally" err
lvchange -ay $vg
+# Cannot resize if set to 0%
+not lvextend --use-policies --config 'activation{thin_pool_autoextend_percent = 0}' $vg/pool 2>&1 | tee err
+grep "0%" err
+
# Creation of new LV is not allowed when thinpool is over threshold
not lvcreate -V10 $vg/pool
diff --git a/test/shell/lvresize-full.sh b/test/shell/lvresize-full.sh
index dcf93a7b2..1ad9f32b1 100644
--- a/test/shell/lvresize-full.sh
+++ b/test/shell/lvresize-full.sh
@@ -37,15 +37,19 @@ lvs -a $vg
"$MKFS" "$lvdev"
# this should resolve to resize to same actual size
-lvreduce -r -f -l-100%FREE $vg/$lv1
+not lvreduce -l-100%FREE $vg/$lv1
+not lvreduce -r -f -l-100%FREE $vg/$lv1
"$FSCK" -n "$lvdev"
# size should remain the same
-lvextend -r -f -l+100%FREE $vg/$lv1
+# lvresize fails with same result with or without -r
+not lvextend -l+100%FREE $vg/$lv1
+not lvextend -r -f -l+100%FREE $vg/$lv1
"$FSCK" -n "$lvdev"
#lvchange -an $vg/$lv1
-lvresize -r -f -l+100%FREE $vg/$lv1
+not lvresize -l+100%FREE $vg/$lv1
+not lvresize -r -f -l+100%FREE $vg/$lv1
"$FSCK" -n "$lvdev"
# Check there is really file system resize happening
@@ -55,7 +59,8 @@ lvresize -r -f -l+100%FREE $vg/$lv1
grep "20000 blocks" out
SIZE=$(get lv_field $vg/$lv1 size)
-lvresize -r -f -l-100%FREE $vg/$lv1
+not lvresize -l-100%FREE $vg/$lv1
+not lvresize -r -f -l-100%FREE $vg/$lv1
test "$SIZE" = "$(get lv_field $vg/$lv1 size)"
"$FSCK" -n "$lvdev" | tee out
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 6e9e7bdea..0cb9425c1 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1382,7 +1382,7 @@ OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--stripes Number, --stripesize SizeKB, --poolmetadatasize PSizeMB,
--type SegType
OP: PV ...
-ID: lvextend_by_size
+ID: lvextend_size
DESC: Extend an LV by a specified size.
lvextend LV PV ...
@@ -1390,25 +1390,25 @@ OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB,
--type SegType
-ID: lvextend_by_pv
+ID: lvextend_pv
DESC: Extend an LV by specified PV extents.
-lvextend --poolmetadatasize PSizeMB LV_thinpool
+lvextend --poolmetadatasize PSizeMB LV_thinpool_linear
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --stripes Number, --stripesize SizeKB,
--type SegType
OP: PV ...
-ID: lvextend_pool_metadata_by_size
+ID: lvextend_pool_metadata
DESC: Extend a pool metadata SubLV by a specified size.
-lvextend --usepolicies LV_thinpool_snapshot
+lvextend --usepolicies LV_snapshot_thinpool_vdopool
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs,
--type SegType
OP: PV ...
-ID: lvextend_by_policy
+ID: lvextend_policy
DESC: Extend an LV according to a predefined policy.
---
@@ -1456,7 +1456,7 @@ DESC: Remove the devices file entry for the given PVID.
lvreduce --size NSizeMB LV
OO: --autobackup Bool, --force, --nofsck, --noudevsync,
--reportformat ReportFmt, --resizefs
-ID: lvreduce_general
+ID: lvreduce_size
---
@@ -1487,7 +1487,7 @@ OO: --alloc Alloc, --autobackup Bool, --force,
--stripes Number, --stripesize SizeKB, --poolmetadatasize PSizeMB,
--type SegType
OP: PV ...
-ID: lvresize_by_size
+ID: lvresize_size
DESC: Resize an LV by a specified size.
lvresize LV PV ...
@@ -1495,7 +1495,7 @@ OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB,
--type SegType
-ID: lvresize_by_pv
+ID: lvresize_pv
DESC: Resize an LV by specified PV extents.
lvresize --poolmetadatasize PSizeMB LV_thinpool
@@ -1504,7 +1504,7 @@ OO: --alloc Alloc, --autobackup Bool, --force,
--reportformat ReportFmt, --stripes Number, --stripesize SizeKB,
--type SegType
OP: PV ...
-ID: lvresize_pool_metadata_by_size
+ID: lvresize_pool_metadata
DESC: Resize a pool metadata SubLV by a specified size.
---
diff --git a/tools/lvextend.c b/tools/lvextend.c
index 865bb965e..e915a95cf 100644
--- a/tools/lvextend.c
+++ b/tools/lvextend.c
@@ -17,5 +17,5 @@
int lvextend(struct cmd_context *cmd, int argc, char **argv)
{
- return lvresize(cmd, argc, argv);
+ return lvresize_cmd(cmd, argc, argv);
}
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index ba3ca220b..a5bb6a5c5 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -165,6 +165,16 @@ static const struct command_function _command_functions[CMD_COUNT] = {
{ pvscan_display_CMD, pvscan_display_cmd },
{ pvscan_cache_CMD, pvscan_cache_cmd },
+
+ /* lvextend/lvreduce/lvresize */
+ { lvextend_policy_CMD, lvextend_policy_cmd },
+ { lvextend_pool_metadata_CMD, lvresize_cmd },
+ { lvresize_pool_metadata_CMD, lvresize_cmd },
+ { lvextend_pv_CMD, lvresize_cmd },
+ { lvresize_pv_CMD, lvresize_cmd },
+ { lvextend_size_CMD, lvresize_cmd },
+ { lvreduce_size_CMD, lvresize_cmd },
+ { lvresize_size_CMD, lvresize_cmd },
};
@@ -3153,6 +3163,9 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
if (!(cmd->command = _find_command(cmd, cmd->name, &argc, argv)))
return EINVALID_CMD_LINE;
+ /* avoid this by letting lib code use cmd->command */
+ cmd->command_enum = cmd->command->command_enum;
+
/*
* If option --foo is set which is listed in IO (ignore option) in
* command-lines.in, then unset foo. Commands won't usually use an
diff --git a/tools/lvreduce.c b/tools/lvreduce.c
index 7b5d1583a..721d7f1b9 100644
--- a/tools/lvreduce.c
+++ b/tools/lvreduce.c
@@ -17,5 +17,5 @@
int lvreduce(struct cmd_context *cmd, int argc, char **argv)
{
- return lvresize(cmd, argc, argv);
+ return lvresize_cmd(cmd, argc, argv);
}
diff --git a/tools/lvresize.c b/tools/lvresize.c
index f39f03a40..a7148e52c 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -15,119 +15,110 @@
#include "tools.h"
-static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
- struct lvresize_params *lp)
+static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
{
- const char *cmd_name = command_name(cmd);
const char *type_str = arg_str_value(cmd, type_ARG, NULL);
int only_linear = 0;
+ int set_extents_and_size = 0;
- if (type_str) {
- if (!strcmp(type_str, "linear")) {
- type_str = "striped";
- only_linear = 1; /* User requested linear only target */
- }
+ memset(lp, 0, sizeof(struct lvresize_params));
- if (!(lp->segtype = get_segtype_from_string(cmd, type_str)))
- return_0;
- }
+ switch (cmd->command->command_enum) {
+ case lvextend_policy_CMD:
+ lp->resize = LV_EXTEND;
+ lp->size = 0;
+ lp->extents = 0;
+ lp->percent = PERCENT_LV;
+ lp->sign = SIGN_PLUS;
+ lp->poolmetadata_size = 0;
+ lp->use_policies = 1;
+ break;
+
+ case lvextend_pool_metadata_CMD:
+ case lvresize_pool_metadata_CMD:
+ lp->resize = LV_EXTEND;
+ lp->size = 0;
+ lp->extents = 0;
+ lp->percent = PERCENT_NONE;
+ lp->sign = SIGN_NONE;
+ lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0);
+ lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
+ break;
+
+ case lvextend_pv_CMD:
+ case lvresize_pv_CMD:
+ lp->resize = LV_EXTEND;
+ lp->size = 0;
+ lp->extents = 0;
+ lp->percent_value = 100;
+ lp->percent = PERCENT_PVS;
+ lp->sign = SIGN_PLUS;
+ lp->poolmetadata_size = 0;
+ lp->resizefs = arg_is_set(cmd, resizefs_ARG);
+ lp->nofsck = arg_is_set(cmd, nofsck_ARG);
+ break;
+
+ case lvextend_size_CMD:
+ lp->resize = LV_EXTEND;
+ lp->resizefs = arg_is_set(cmd, resizefs_ARG);
+ lp->nofsck = arg_is_set(cmd, nofsck_ARG);
+ if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0)))
+ lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
+ set_extents_and_size = 1;
+ break;
- if (!strcmp(cmd_name, "lvreduce"))
+ case lvreduce_size_CMD:
lp->resize = LV_REDUCE;
- else if (!strcmp(cmd_name, "lvextend"))
- lp->resize = LV_EXTEND;
- else
+ lp->poolmetadata_size = 0;
+ lp->resizefs = arg_is_set(cmd, resizefs_ARG);
+ lp->nofsck = arg_is_set(cmd, nofsck_ARG);
+ set_extents_and_size = 1;
+ break;
+
+ case lvresize_size_CMD:
lp->resize = LV_ANY;
+ lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0);
+ lp->resizefs = arg_is_set(cmd, resizefs_ARG);
+ lp->nofsck = arg_is_set(cmd, nofsck_ARG);
+ if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0)))
+ lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
+ set_extents_and_size = 1;
+ break;
- lp->sign = lp->poolmetadata_sign = SIGN_NONE;
-
- if ((lp->use_policies = arg_is_set(cmd, usepolicies_ARG))) {
- /* do nothing; lv_resize will handle --use-policies itself */
- if (arg_from_list_is_set(cmd, NULL,
- chunksize_ARG, extents_ARG,
- poolmetadatasize_ARG,
- regionsize_ARG,
- size_ARG,
- stripes_ARG, stripesize_ARG,
- -1))
- log_print_unless_silent("Ignoring size parameters with --use-policies.");
- } else {
- /*
- * Allow omission of extents and size if the user has given us
- * one or more PVs. Most likely, the intent was "resize this
- * LV the best you can with these PVs"
- * If only --poolmetadatasize is specified with list of PVs,
- * then metadata will be extended there.
- */
+ default:
+ log_error(INTERNAL_ERROR "unknown lvresize type");
+ return 0;
+ };
+
+ if (set_extents_and_size) {
if ((lp->extents = arg_uint_value(cmd, extents_ARG, 0))) {
- lp->sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE);
+ lp->sign = arg_sign_value(cmd, extents_ARG, 0);
lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
}
-
- if (arg_from_list_is_zero(cmd, "may not be zero",
- chunksize_ARG, extents_ARG,
- poolmetadatasize_ARG,
- regionsize_ARG,
- size_ARG,
- stripes_ARG, stripesize_ARG,
- virtualsize_ARG,
- -1))
- return_0;
-
- if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0))) {
- lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
- if (lp->poolmetadata_sign == SIGN_MINUS) {
- log_error("Can't reduce pool metadata size.");
- return 0;
- }
- }
-
if ((lp->size = arg_uint64_value(cmd, size_ARG, 0))) {
- lp->sign = arg_sign_value(cmd, size_ARG, SIGN_NONE);
+ lp->sign = arg_sign_value(cmd, size_ARG, 0);
lp->percent = PERCENT_NONE;
}
-
if (lp->size && lp->extents) {
log_error("Please specify either size or extents but not both.");
return 0;
}
-
- if (!lp->extents &&
- !lp->size &&
- !lp->poolmetadata_size &&
- (argc >= 2)) {
- lp->extents = 100;
- lp->percent = PERCENT_PVS;
- lp->sign = SIGN_PLUS;
- }
}
- if (lp->resize == LV_EXTEND && lp->sign == SIGN_MINUS) {
- log_error("Negative argument not permitted - use lvreduce.");
- return 0;
- }
+ lp->alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, 0);
+ lp->yes = arg_is_set(cmd, yes_ARG);
+ lp->force = arg_is_set(cmd, force_ARG),
+ lp->nosync = arg_is_set(cmd, nosync_ARG);
+ lp->lockopt = arg_str_value(cmd, lockopt_ARG, NULL);
- if (lp->resize == LV_REDUCE &&
- ((lp->sign == SIGN_PLUS) ||
- (lp->poolmetadata_sign == SIGN_PLUS))) {
- log_error("Positive sign not permitted - use lvextend.");
- return 0;
- }
-
- if (!argc) {
- log_error("Please provide the logical volume name.");
- return 0;
- }
-
- lp->lv_name = argv[0];
-
- if (!validate_lvname_param(cmd, &lp->vg_name, &lp->lv_name))
- return_0;
+ if (type_str) {
+ if (!strcmp(type_str, "linear")) {
+ type_str = "striped";
+ only_linear = 1; /* User requested linear only target */
+ }
- /* Check for $LVM_VG_NAME */
- if (!lp->vg_name && !(lp->vg_name = extract_vgname(cmd, NULL))) {
- log_error("Please specify a logical volume path.");
- return 0;
+ if (!(lp->segtype = get_segtype_from_string(cmd, type_str)))
+ return_0;
}
if (arg_is_set(cmd, mirrors_ARG)) {
@@ -156,66 +147,150 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
return 0;
}
- lp->argc = --argc;
- lp->argv = ++argv;
-
return 1;
}
-static int _lvresize_single(struct cmd_context *cmd, const char *vg_name,
- struct volume_group *vg, struct processing_handle *handle)
+/*
+ * lvextend --use-policies is usually called by dmeventd, as a method of
+ * "auto extending" an LV as it's used. It checks how full a snapshot cow or
+ * thin pool is, and extends it if it's too full, based on threshold settings
+ * in lvm.conf for when to auto extend it.
+ *
+ * The extension of a thin pool LV can involve extending either the data sub
+ * LV, the metadata sub LV, or both, so there may be two LVs extended here.
+ */
+static int _lv_extend_policy(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvresize_params *lp, int *skipped)
{
- struct lvresize_params *lp = (struct lvresize_params *) handle->custom_handle;
- struct dm_list *pvh;
- struct logical_volume *lv;
- int ret = ECMD_FAILED;
-
- /* Does LV exist? */
- if (!(lv = find_lv(vg, lp->lv_name))) {
- log_error("Logical volume %s not found in volume group %s.",
- lp->lv_name, vg->name);
- goto out;
+ struct lvresize_params lp_meta;
+ uint32_t percent_main = 0;
+ uint32_t percent_meta = 0;
+ int is_active;
+
+ memset(&lp_meta, 0, sizeof(lp_meta));
+
+ if (!lv_is_cow(lv) && !lv_is_thin_pool(lv) && !lv_is_vdo_pool(lv)) {
+ log_error("lvextend policy is supported only for snapshot, thin pool and vdo pool volumes.");
+ *skipped = 1;
+ return 0;
+ }
+
+ is_active = lv_is_active(lv);
+
+ if (vg_is_shared(lv->vg) && !is_active) {
+ log_debug("lvextend policy requires LV to be active in a shared VG.");
+ *skipped = 1;
+ return 1;
+ }
+
+ if (lv_is_thin_pool(lv) && !is_active) {
+ log_error("lvextend using policy requires the thin pool to be active.");
+ return 0;
}
- if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc, lp->argv, 1) : &vg->pvs))
- goto_out;
+ /*
+ * Calculate the percent of extents to extend the LV based on current
+ * usage info from the kernel and policy settings from lvm.conf, e.g.
+ * autoextend_threshold, autoextend_percent. For thin pools, both the
+ * thin pool data LV and thin pool metadata LV may need to be extended.
+ * In this case, percent_main is the amount to extend the data LV, and
+ * percent_meta is the amount to extend the metadata LV.
+ */
+ if (!lv_extend_policy_calculate_percent(lv, &percent_main, &percent_meta))
+ return_0;
+
+ if (!percent_main && !percent_meta) {
+ log_debug("lvextend policy not needed.");
+ *skipped = 1;
+ return 1;
+ }
- if (!lv_resize(lv, lp, pvh))
- goto_out;
+ *skipped = 0;
+ lp->policy_percent_main = percent_main;
+ lp->policy_percent_meta = percent_meta;
+
+ return lv_resize(cmd, lv, lp);
+}
+
+static int _lvextend_policy_single(struct cmd_context *cmd, struct logical_volume *lv,
+ struct processing_handle *handle)
+{
+ struct lvresize_params *lp = (struct lvresize_params *) handle->custom_handle;
+ int skipped = 0;
+
+ if (cmd->position_argc > 1) {
+ /* First pos arg is required LV, remaining are optional PVs. */
+ if (!(lp->pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
+ return_ECMD_FAILED;
+ } else
+ lp->pvh = &lv->vg->pvs;
+
+ if (!_lv_extend_policy(cmd, lv, lp, &skipped))
+ return ECMD_FAILED;
+
+ if (!skipped)
+ log_print_unless_silent("Logical volume %s successfully resized.", display_lvname(lv));
+ return ECMD_PROCESSED;
+}
+
+static int _lvresize_single(struct cmd_context *cmd, struct logical_volume *lv,
+ struct processing_handle *handle)
+{
+ struct lvresize_params *lp = (struct lvresize_params *) handle->custom_handle;
+
+ if (cmd->position_argc > 1) {
+ /* First pos arg is required LV, remaining are optional PVs. */
+ if (!(lp->pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
+ return_ECMD_FAILED;
+ } else
+ lp->pvh = &lv->vg->pvs;
+
+ if (!lv_resize(cmd, lv, lp))
+ return ECMD_FAILED;
+
+ log_print_unless_silent("Logical volume %s successfully resized.",
+ display_lvname(lv));
+ return ECMD_PROCESSED;
+}
+
+int lvextend_policy_cmd(struct cmd_context *cmd, int argc, char **argv)
+{
+ struct processing_handle *handle;
+ struct lvresize_params lp;
+ int ret;
+
+ if (!_lvresize_params(cmd, &lp))
+ return EINVALID_CMD_LINE;
+
+ if (!(handle = init_processing_handle(cmd, NULL)))
+ return ECMD_FAILED;
+
+ handle->custom_handle = &lp;
+
+ ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
+ handle, NULL, &_lvextend_policy_single);
+
+ destroy_processing_handle(cmd, handle);
- ret = ECMD_PROCESSED;
-out:
return ret;
}
-int lvresize(struct cmd_context *cmd, int argc, char **argv)
+int lvresize_cmd(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle;
- struct lvresize_params lp = {
- .alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, 0),
- .yes = arg_is_set(cmd, yes_ARG),
- .force = arg_is_set(cmd, force_ARG),
- .nofsck = arg_is_set(cmd, nofsck_ARG),
- .nosync = arg_is_set(cmd, nosync_ARG),
- .resizefs = arg_is_set(cmd, resizefs_ARG),
- .lockopt = arg_str_value(cmd, lockopt_ARG, NULL),
- };
+ struct lvresize_params lp;
int ret;
- if (!_lvresize_params(cmd, argc, argv, &lp)) {
- stack;
+ if (!_lvresize_params(cmd, &lp))
return EINVALID_CMD_LINE;
- }
- if (!(handle = init_processing_handle(cmd, NULL))) {
- log_error("Failed to initialize processing handle.");
+ if (!(handle = init_processing_handle(cmd, NULL)))
return ECMD_FAILED;
- }
handle->custom_handle = &lp;
- ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, 0, handle,
- &_lvresize_single);
+ ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
+ handle, NULL, &_lvresize_single);
destroy_processing_handle(cmd, handle);
@@ -224,3 +299,16 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
return ret;
}
+
+/*
+ * All lvresize command defs have their own function,
+ * so the generic function name is unused.
+ */
+
+int lvresize(struct cmd_context *cmd, int argc, char **argv)
+{
+ log_error(INTERNAL_ERROR "Missing function for command definition %d:%s.",
+ cmd->command->command_index, cmd->command->command_id);
+ return ECMD_FAILED;
+}
+
diff --git a/tools/tools.h b/tools/tools.h
index 2636c22da..36da3bc7e 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -45,19 +45,18 @@
#include "lib/notify/lvmnotify.h"
#include "lib/label/hints.h"
+/*
+ * cmd_enum.h uses the generated cmds.h to create the enum with an ID
+ * for each command definition in command-lines.in.
+ */
+#include "lib/commands/cmd_enum.h"
+
#include <ctype.h>
#include <sys/types.h>
#define CMD_LEN 256
#define MAX_ARGS 64
-/* define the enums for each unique ID in command defs in command-lines.in */
-enum {
-#define cmd(a, b) a ,
-#include "cmds.h"
-#undef cmd
-};
-
/* define the enums for the values accepted by command line --options, foo_VAL */
enum {
#define val(a, b, c, d) a ,
@@ -296,4 +295,7 @@ int lvconvert_cachevol_attach_single(struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle);
+int lvresize_cmd(struct cmd_context *cmd, int argc, char **argv);
+int lvextend_policy_cmd(struct cmd_context *cmd, int argc, char **argv);
+
#endif
8 months, 3 weeks
main - remove libblkid flag BLKID_SUBLKS_FSINFO
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=55e9494e5fe3e3d2790...
Commit: 55e9494e5fe3e3d2790fca6330b848a577e0b1c0
Parent: b869a6ff7a3d254a56ad78444e7d7f8af93d6844
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Sep 9 16:14:27 2022 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Sep 9 16:14:27 2022 -0500
remove libblkid flag BLKID_SUBLKS_FSINFO
This flag is not needed in fs_block_size_and_type()
added in the previous commit.
---
lib/device/dev-type.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 1e97f6c85..b1cf5b431 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -842,7 +842,7 @@ int fs_block_size_and_type(const char *pathname, uint32_t *fs_block_size_bytes,
BLKID_SUBLKS_UUID | BLKID_SUBLKS_UUIDRAW |
BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE |
BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION |
- BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_FSINFO);
+ BLKID_SUBLKS_MAGIC);
rc = blkid_do_safeprobe(probe);
if (rc < 0) {
log_debug("Failed libblkid probe for %s", pathname);
8 months, 3 weeks
main - fix fs block size detection
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=b869a6ff7a3d254a56a...
Commit: b869a6ff7a3d254a56ad78444e7d7f8af93d6844
Parent: 6b05d6bd833c463b9a2074b2aa2bdaa531e7ab01
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Sep 9 15:16:56 2022 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Sep 9 15:50:00 2022 -0500
fix fs block size detection
blkid_get_tag_value() is not a reliable way to query the fs
BLOCK_SIZE, so use the "probe" functions instead.
---
lib/device/dev-type.c | 65 ++++++++++++++++++++++++------
lib/device/dev-type.h | 3 +-
lib/metadata/integrity_manip.c | 4 +-
test/shell/integrity-blocksize.sh | 42 +++++++++----------
test/shell/lvextend-caches-on-thindata.sh | 2 +-
test/shell/writecache-cache-blocksize-2.sh | 2 +-
test/shell/writecache-cache-blocksize.sh | 2 +-
test/shell/writecache.sh | 2 +-
tools/lvconvert.c | 4 +-
9 files changed, 84 insertions(+), 42 deletions(-)
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 1dc895b54..1e97f6c85 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -823,26 +823,67 @@ out:
}
#ifdef BLKID_WIPING_SUPPORT
-int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
+int fs_block_size_and_type(const char *pathname, uint32_t *fs_block_size_bytes, char *fstype, int *nofs)
{
- char *block_size_str = NULL;
+ blkid_probe probe = NULL;
+ const char *type_str = NULL, *size_str = NULL;
+ size_t len;
+ int ret = 1;
+ int rc;
- if ((block_size_str = blkid_get_tag_value(NULL, "BLOCK_SIZE", pathname))) {
- *fs_block_size = (uint32_t)atoi(block_size_str);
- free(block_size_str);
- log_debug("Found blkid BLOCK_SIZE %u for fs on %s", *fs_block_size, pathname);
- return 1;
- } else {
- log_debug("No blkid BLOCK_SIZE for fs on %s", pathname);
- *fs_block_size = 0;
+ if (!(probe = blkid_new_probe_from_filename(pathname))) {
+ log_error("Failed libblkid probe setup for %s", pathname);
return 0;
}
+
+ blkid_probe_enable_superblocks(probe, 1);
+ blkid_probe_set_superblocks_flags(probe,
+ BLKID_SUBLKS_LABEL | BLKID_SUBLKS_LABELRAW |
+ BLKID_SUBLKS_UUID | BLKID_SUBLKS_UUIDRAW |
+ BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE |
+ BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION |
+ BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_FSINFO);
+ rc = blkid_do_safeprobe(probe);
+ if (rc < 0) {
+ log_debug("Failed libblkid probe for %s", pathname);
+ ret = 0;
+ goto out;
+ } else if (rc == 1) {
+ /* no file system on the device */
+ log_debug("No file system found on %s.", pathname);
+ if (nofs)
+ *nofs = 1;
+ goto out;
+ }
+
+ if (!blkid_probe_lookup_value(probe, "TYPE", &type_str, &len) && len && type_str) {
+ if (fstype)
+ strncpy(fstype, type_str, FSTYPE_MAX);
+ } else {
+ /* any difference from blkid_do_safeprobe rc=1? */
+ log_debug("No file system type on %s.", pathname);
+ if (nofs)
+ *nofs = 1;
+ goto out;
+ }
+
+ if (fs_block_size_bytes) {
+ if (!blkid_probe_lookup_value(probe, "BLOCK_SIZE", &size_str, &len) && len && size_str)
+ *fs_block_size_bytes = atoi(size_str);
+ else
+ *fs_block_size_bytes = 0;
+ }
+
+ log_debug("Found blkid fstype %s fsblocksize %s on %s",
+ type_str ?: "none", size_str ?: "unused", pathname);
+out:
+ blkid_free_probe(probe);
+ return ret;
}
#else
-int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
+int fs_block_size_and_type(const char *pathname, uint32_t *fs_block_size_bytes, char *fstype, int *nofs)
{
log_debug("Disabled blkid BLOCK_SIZE for fs.");
- *fs_block_size = 0;
return 0;
}
#endif
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
index 17c997641..4f793b0e0 100644
--- a/lib/device/dev-type.h
+++ b/lib/device/dev-type.h
@@ -101,7 +101,8 @@ int dev_is_nvme(struct dev_types *dt, struct device *dev);
int dev_is_lv(struct device *dev);
-int get_fs_block_size(const char *pathname, uint32_t *fs_block_size);
+#define FSTYPE_MAX 16
+int fs_block_size_and_type(const char *pathname, uint32_t *fs_block_size_bytes, char *fstype, int *nofs);
int dev_is_used_by_active_lv(struct cmd_context *cmd, struct device *dev, int *used_by_lv_count,
char **used_by_dm_name, char **used_by_vg_uuid, char **used_by_lv_uuid);
diff --git a/lib/metadata/integrity_manip.c b/lib/metadata/integrity_manip.c
index e053ac5f6..e9895b836 100644
--- a/lib/metadata/integrity_manip.c
+++ b/lib/metadata/integrity_manip.c
@@ -372,7 +372,7 @@ static int _set_integrity_block_size(struct cmd_context *cmd, struct logical_vol
}
/*
- * get_fs_block_size() returns the libblkid BLOCK_SIZE value,
+ * fs_block_size_and_type() returns the libblkid BLOCK_SIZE value,
* where libblkid has fs-specific code to set BLOCK_SIZE to the
* value we need here.
*
@@ -382,7 +382,7 @@ static int _set_integrity_block_size(struct cmd_context *cmd, struct logical_vol
* value the block size, but it's possible values are not the same
* as xfs's, and do not seem to relate directly to the device LBS.
*/
- rv = get_fs_block_size(pathname, &fs_block_size);
+ rv = fs_block_size_and_type(pathname, &fs_block_size, NULL, NULL);
if (!rv || !fs_block_size) {
int use_bs;
diff --git a/test/shell/integrity-blocksize.sh b/test/shell/integrity-blocksize.sh
index 4e47ce427..55a618f7f 100644
--- a/test/shell/integrity-blocksize.sh
+++ b/test/shell/integrity-blocksize.sh
@@ -41,7 +41,7 @@ aux prepare_devs 1
vgcreate $vg "$dev1"
lvcreate -n $lv1 -l8 $vg
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
+blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
lvchange -an $vg
vgremove -ff $vg
@@ -149,9 +149,9 @@ lvremove -y $vg2/$lv1
lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1
aux wipefs_a /dev/$vg1/$lv1
mkfs.xfs -f "$DM_DEV_DIR/$vg1/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"512\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"512\"
lvconvert --raidintegrity y $vg1/$lv1
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"512\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"512\"
mount "$DM_DEV_DIR/$vg1/$lv1" $mnt
umount $mnt
pvck --dump metadata $LOOP1 | grep 'block_size = 512'
@@ -161,9 +161,9 @@ lvremove -y $vg1/$lv1
lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg2
aux wipefs_a /dev/$vg2/$lv1
mkfs.xfs -f "$DM_DEV_DIR/$vg2/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
lvconvert --raidintegrity y $vg2/$lv1
-blkid -c /dev/null "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
mount "$DM_DEV_DIR/$vg2/$lv1" $mnt
umount $mnt
pvck --dump metadata $LOOP3 | grep 'block_size = 4096'
@@ -173,9 +173,9 @@ lvremove -y $vg2/$lv1
lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1
aux wipefs_a /dev/$vg1/$lv1
mkfs.ext4 -b 1024 "$DM_DEV_DIR/$vg1/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
lvconvert --raidintegrity y $vg1/$lv1
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
mount "$DM_DEV_DIR/$vg1/$lv1" $mnt
umount $mnt
pvck --dump metadata $LOOP1 | grep 'block_size = 512'
@@ -185,11 +185,11 @@ lvremove -y $vg1/$lv1
lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1
aux wipefs_a /dev/$vg1/$lv1
mkfs.ext4 -b 1024 "$DM_DEV_DIR/$vg1/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
lvchange -an $vg1/$lv1
lvconvert --raidintegrity y $vg1/$lv1
lvchange -ay $vg1/$lv1
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
mount "$DM_DEV_DIR/$vg1/$lv1" $mnt
umount $mnt
pvck --dump metadata $LOOP1 | grep 'block_size = 1024'
@@ -199,9 +199,9 @@ lvremove -y $vg1/$lv1
lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg2
aux wipefs_a /dev/$vg2/$lv1
mkfs.ext4 "$DM_DEV_DIR/$vg2/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
lvconvert --raidintegrity y $vg2/$lv1
-blkid -c /dev/null "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
mount "$DM_DEV_DIR/$vg2/$lv1" $mnt
umount $mnt
pvck --dump metadata $LOOP3 | grep 'block_size = 4096'
@@ -211,10 +211,10 @@ lvremove -y $vg2/$lv1
lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1
aux wipefs_a /dev/$vg1/$lv1
mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg1/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\"
lvconvert --raidintegrity y --raidintegrityblocksize 512 $vg1/$lv1
lvs -o raidintegrityblocksize $vg1/$lv1 | grep 512
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\"
mount "$DM_DEV_DIR/$vg1/$lv1" $mnt
umount $mnt
pvck --dump metadata $LOOP1 | grep 'block_size = 512'
@@ -224,13 +224,13 @@ lvremove -y $vg1/$lv1
lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1
aux wipefs_a /dev/$vg1/$lv1
mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg1/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\"
lvchange -an $vg1/$lv1
# lv needs to be inactive to increase LBS from 512
lvconvert --raidintegrity y --raidintegrityblocksize 1024 $vg1/$lv1
lvs -o raidintegrityblocksize $vg1/$lv1 | grep 1024
lvchange -ay $vg1/$lv1
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\"
mount "$DM_DEV_DIR/$vg1/$lv1" $mnt
umount $mnt
pvck --dump metadata $LOOP1 | grep 'block_size = 1024'
@@ -240,9 +240,9 @@ lvremove -y $vg1/$lv1
lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1
aux wipefs_a /dev/$vg1/$lv1
mkfs.ext4 -b 1024 "$DM_DEV_DIR/$vg1/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
lvconvert --raidintegrity y --raidintegrityblocksize 512 $vg1/$lv1
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\"
mount "$DM_DEV_DIR/$vg1/$lv1" $mnt
umount $mnt
pvck --dump metadata $LOOP1 | grep 'block_size = 512'
@@ -267,14 +267,14 @@ mkfs.xfs -f "$DM_DEV_DIR/$vg1/$lv1"
mount "$DM_DEV_DIR/$vg1/$lv1" $mnt
echo "test" > $mnt/test
umount $mnt
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"512\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"512\"
lvchange -an $vg1/$lv1
lvconvert --raidintegrity y $vg1/$lv1
lvchange -ay $vg1/$lv1
mount "$DM_DEV_DIR/$vg1/$lv1" $mnt
cat $mnt/test
umount $mnt
-blkid -c /dev/null "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"512\"
+blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"512\"
pvck --dump metadata $LOOP1 | grep 'block_size = 512'
lvchange -an $vg1/$lv1
lvremove -y $vg1/$lv1
@@ -286,14 +286,14 @@ mkfs.xfs -f "$DM_DEV_DIR/$vg2/$lv1"
mount "$DM_DEV_DIR/$vg2/$lv1" $mnt
echo "test" > $mnt/test
umount $mnt
-blkid -c /dev/null "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
lvchange -an $vg2/$lv1
lvconvert --raidintegrity y $vg2/$lv1
lvchange -ay $vg2/$lv1
mount "$DM_DEV_DIR/$vg2/$lv1" $mnt
cat $mnt/test
umount $mnt
-blkid -c /dev/null "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
+blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\"
pvck --dump metadata $LOOP3 | grep 'block_size = 4096'
lvchange -an $vg2/$lv1
lvremove -y $vg2/$lv1
diff --git a/test/shell/lvextend-caches-on-thindata.sh b/test/shell/lvextend-caches-on-thindata.sh
index 35b70546f..2000c005e 100644
--- a/test/shell/lvextend-caches-on-thindata.sh
+++ b/test/shell/lvextend-caches-on-thindata.sh
@@ -122,7 +122,7 @@ aux prepare_devs 6 400 # want 400M of usable space from each dev
vgcreate $vg "$dev1"
lvcreate -n $lv1 -L300 $vg
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
+blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
lvchange -an $vg
vgremove -ff $vg
diff --git a/test/shell/writecache-cache-blocksize-2.sh b/test/shell/writecache-cache-blocksize-2.sh
index 0ab715d50..d50b36950 100644
--- a/test/shell/writecache-cache-blocksize-2.sh
+++ b/test/shell/writecache-cache-blocksize-2.sh
@@ -164,7 +164,7 @@ aux prepare_devs 2 301
vgcreate $vg "$dev1"
lvcreate -n $lv1 -L300 $vg
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
+blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
lvchange -an $vg
vgremove -ff $vg
diff --git a/test/shell/writecache-cache-blocksize.sh b/test/shell/writecache-cache-blocksize.sh
index c38700755..18be6ed46 100644
--- a/test/shell/writecache-cache-blocksize.sh
+++ b/test/shell/writecache-cache-blocksize.sh
@@ -154,7 +154,7 @@ aux prepare_devs 2 301
vgcreate $vg "$dev1"
lvcreate -n $lv1 -L300 $vg
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
+blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
lvchange -an $vg
vgremove -ff $vg
diff --git a/test/shell/writecache.sh b/test/shell/writecache.sh
index 9cb6d3f94..9d1a5c09e 100644
--- a/test/shell/writecache.sh
+++ b/test/shell/writecache.sh
@@ -29,7 +29,7 @@ aux prepare_devs 2 301
vgcreate $vg "$dev1"
lvcreate -n $lv1 -L 300 $vg
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
-blkid -c /dev/null "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
+blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
lvchange -an $vg
vgremove -ff $vg
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 6e5d748cc..8888cac28 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -5996,7 +5996,7 @@ static int _set_writecache_block_size(struct cmd_context *cmd,
}
/*
- * get_fs_block_size() returns the libblkid BLOCK_SIZE value,
+ * fs_block_size_and_type() returns the libblkid BLOCK_SIZE value,
* where libblkid has fs-specific code to set BLOCK_SIZE to the
* value we need here.
*
@@ -6008,7 +6008,7 @@ static int _set_writecache_block_size(struct cmd_context *cmd,
*
* With 512 LBS and 4K PBS, mkfs.xfs will use xfs sector size 4K.
*/
- rv = get_fs_block_size(pathname, &fs_block_size);
+ rv = fs_block_size_and_type(pathname, &fs_block_size, NULL, NULL);
skip_fs:
if (!rv || !fs_block_size) {
if (block_size_setting)
8 months, 3 weeks
main - gitignore: update
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=6b05d6bd833c463b9a2...
Commit: 6b05d6bd833c463b9a2074b2aa2bdaa531e7ab01
Parent: 19db3b3e456010fe8e2e3815bf12deba690c7303
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Sep 5 12:08:50 2022 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Wed Sep 7 15:00:15 2022 +0200
gitignore: update
---
.gitignore | 21 ++++++++++++++++++---
udev/.gitignore | 1 +
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/.gitignore b/.gitignore
index 8c1672bd2..224d43cd6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,10 @@
*.sw*
*~
+# gcov files:
+*.gcda
+*.gcno
+
.export.sym
.exported_symbols_generated
.gdb_history
@@ -39,9 +43,11 @@ make.tmpl
coverity/coverity_model.xml
-# gcov files:
-*.gcda
-*.gcno
+/libdm/.symver_check
+
+daemons/clvmd
+daemons/dmfilemapd
+daemons/lvmetad/
tools/man-generator
tools/man-generator.c
@@ -102,6 +108,8 @@ test/api/thin_percent.t
test/api/vglist.t
test/api/vgtest.t
test/lib/aux
+test/lib/cache-mq.profile
+test/lib/cache-smq.profile
test/lib/check
test/lib/clvmd
test/lib/dm-version-expected
@@ -111,6 +119,7 @@ test/lib/dmstats
test/lib/fail
test/lib/flavour-ndev-cluster
test/lib/flavour-ndev-cluster-lvmpolld
+test/lib/flavour-ndev-devicesfile
test/lib/flavour-ndev-lvmetad
test/lib/flavour-ndev-lvmetad-lvmpolld
test/lib/flavour-ndev-lvmpolld
@@ -120,6 +129,7 @@ test/lib/flavour-udev-cluster-lvmpolld
test/lib/flavour-udev-lvmetad
test/lib/flavour-udev-lvmetad-lvmpolld
test/lib/flavour-udev-lvmlockd-dlm
+test/lib/flavour-udev-lvmlockd-idm
test/lib/flavour-udev-lvmlockd-sanlock
test/lib/flavour-udev-lvmlockd-test
test/lib/flavour-udev-lvmpolld
@@ -132,8 +142,11 @@ test/lib/lvm
test/lib/lvm-wrapper
test/lib/lvmchange
test/lib/lvmdbusd.profile
+test/lib/lvmdevices
test/lib/lvmetad
test/lib/lvmpolld
+test/lib/lvm_import_vdo
+test/lib/lvm_vdo_wrapper
test/lib/not
test/lib/paths
test/lib/paths-common
@@ -143,5 +156,7 @@ test/lib/test
test/lib/thin-performance.profile
test/lib/utils
test/lib/version-expected
+test/lib/vgimportdevices
+
test/unit/dmraid_t.c
test/unit/unit-test
diff --git a/udev/.gitignore b/udev/.gitignore
index 303d78761..24884bd4e 100644
--- a/udev/.gitignore
+++ b/udev/.gitignore
@@ -1,5 +1,6 @@
10-dm.rules
11-dm-lvm.rules
13-dm-disk.rules
+69-dm-lvm.rules
69-dm-lvm-metad.rules
95-dm-notify.rules
9 months
main - tests: cache use 300M XFS
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=19db3b3e456010fe8e2...
Commit: 19db3b3e456010fe8e2e3815bf12deba690c7303
Parent: e295610d42904e41f295e58b02e0c0577c26c702
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Sep 7 01:02:29 2022 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Wed Sep 7 15:00:15 2022 +0200
tests: cache use 300M XFS
---
test/shell/cache-single-options.sh | 4 ++--
test/shell/cache-single-split.sh | 16 ++++++++--------
test/shell/cache-single-types.sh | 6 +++---
test/shell/cache-single-usage.sh | 4 ++--
4 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/test/shell/cache-single-options.sh b/test/shell/cache-single-options.sh
index 3be88d222..c736e5220 100644
--- a/test/shell/cache-single-options.sh
+++ b/test/shell/cache-single-options.sh
@@ -25,11 +25,11 @@ mkdir -p "$mount_dir"
# generate random data
dd if=/dev/urandom of=pattern1 bs=512K count=1
-aux prepare_devs 5 64
+aux prepare_devs 5 310
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
-lvcreate -n $lv1 -l 8 -an $vg "$dev1"
+lvcreate -n $lv1 -L 300 -an $vg "$dev1"
lvcreate -n $lv2 -l 4 -an $vg "$dev2"
lvcreate -n $lv3 -l 4 -an $vg "$dev3"
lvcreate -n $lv4 -l 4 -an $vg "$dev4"
diff --git a/test/shell/cache-single-split.sh b/test/shell/cache-single-split.sh
index ffe4292de..fa4c3fd9d 100644
--- a/test/shell/cache-single-split.sh
+++ b/test/shell/cache-single-split.sh
@@ -59,11 +59,11 @@ mkdir -p "$mount_dir"
# generate random data
dd if=/dev/urandom of=pattern1 bs=512K count=1
-aux prepare_devs 4
+aux prepare_devs 4 310
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4"
-lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev4"
+lvcreate -n $lv1 -L 300 -an $vg "$dev1" "$dev4"
lvcreate -n $lv2 -l 4 -an $vg "$dev2"
#
@@ -227,7 +227,7 @@ vgextend --restoremissing $vg "$dev2"
#
lvremove $vg/$lv2
-lvcreate -n $lv2 -l 14 -an $vg "$dev2" "$dev3"
+lvcreate -n $lv2 -l 14 -an $vg "$dev2:0-10" "$dev3"
lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1
@@ -263,7 +263,7 @@ mount_umount $lv1
#
lvremove $vg/$lv2
-lvcreate -n $lv2 -l 14 -an $vg "$dev2" "$dev3"
+lvcreate -n $lv2 -l 14 -an $vg "$dev2:0-10" "$dev3"
lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1
@@ -301,7 +301,7 @@ vgextend --restoremissing $vg "$dev3"
lvremove $vg/$lv1
lvremove $vg/$lv2
-lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev4"
+lvcreate -n $lv1 -L 300 -an $vg "$dev1:0-10" "$dev4"
lvcreate -n $lv2 -l 4 -an $vg "$dev2"
lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1
@@ -330,7 +330,7 @@ mount_umount $lv1
lvremove $vg/$lv1
-lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev4"
+lvcreate -n $lv1 -L 300 -an $vg "$dev1:0-10" "$dev4"
lvcreate -n $lv2 -l 4 -an $vg "$dev2"
lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1
@@ -364,7 +364,7 @@ mount_umount $lv1
lvremove $vg/$lv1
-lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev4"
+lvcreate -n $lv1 -L 300 -an $vg "$dev1:0-10" "$dev4"
lvcreate -n $lv2 -l 4 -an $vg "$dev2"
lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1
@@ -395,7 +395,7 @@ mount_umount $lv1
lvremove $vg/$lv1
-lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev4"
+lvcreate -n $lv1 -L 300 -an $vg "$dev1:0-10" "$dev4"
lvcreate -n $lv2 -l 4 -an $vg "$dev2"
lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1
diff --git a/test/shell/cache-single-types.sh b/test/shell/cache-single-types.sh
index 85582420d..1e67e7eda 100644
--- a/test/shell/cache-single-types.sh
+++ b/test/shell/cache-single-types.sh
@@ -26,11 +26,11 @@ mkdir -p "$mount_dir"
# generate random data
dd if=/dev/urandom of=pattern1 bs=512K count=1
-aux prepare_devs 4 64
+aux prepare_devs 4 310
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4"
-lvcreate --type raid1 -m 1 -n $lv1 -l 8 $vg "$dev1" "$dev2"
+lvcreate --type raid1 -m 1 -n $lv1 -L 300 --nosync $vg "$dev1" "$dev2"
lvcreate --type raid1 -m 1 -n $lv2 -l 4 $vg "$dev3" "$dev4"
@@ -69,7 +69,7 @@ lvchange -an $vg/$lv1
lvconvert --splitcache $vg/$lv1
check lv_field $vg/$lv1 segtype raid1
-check lv_field $vg/$lv2 segtype raid1
+check lv_field $vg/$lv2 segtype raid1
lvchange -ay $vg/$lv1
lvchange -ay $vg/$lv2
diff --git a/test/shell/cache-single-usage.sh b/test/shell/cache-single-usage.sh
index 9bc9b67c5..2c47d05e0 100644
--- a/test/shell/cache-single-usage.sh
+++ b/test/shell/cache-single-usage.sh
@@ -28,13 +28,13 @@ mkdir -p "$mount_dir"
# generate random data
dd if=/dev/urandom of=pattern1 bs=512K count=1
-aux prepare_devs 2 64
+aux prepare_devs 2 310
vgcreate $SHARED $vg "$dev1"
vgextend $vg "$dev2"
-lvcreate -n $lv1 -l 8 -an $vg "$dev1"
+lvcreate -n $lv1 -L 300 -an $vg "$dev1"
lvcreate -n $lv2 -l 4 -an $vg "$dev2"
9 months
main - tests: fsadm 300m xfs
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=e295610d42904e41f29...
Commit: e295610d42904e41f295e58b02e0c0577c26c702
Parent: 570dbad52718f558fb679a5f5ed87b101bfb39c1
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Aug 31 12:22:59 2022 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Wed Sep 7 15:00:15 2022 +0200
tests: fsadm 300m xfs
---
test/shell/fsadm-crypt.sh | 28 +++++++++++++++-------------
test/shell/fsadm-renamed.sh | 8 ++++----
test/shell/fsadm.sh | 8 ++++----
3 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/test/shell/fsadm-crypt.sh b/test/shell/fsadm-crypt.sh
index 2004db957..3b0c46aca 100644
--- a/test/shell/fsadm-crypt.sh
+++ b/test/shell/fsadm-crypt.sh
@@ -20,7 +20,7 @@ export LVM_TEST_PREFER_BRD=0
. lib/inittest
-aux prepare_vg 1 300
+aux prepare_vg 1 1300
# set to "skip" to avoid testing given fs and test warning result
# i.e. check_reiserfs=skip
@@ -200,8 +200,8 @@ check_missing cryptsetup || skip
vgchange -s 128k
lvcreate -n $lv1 -L25M $vg
-lvcreate -n ${lv1}bar -L35M $vg
-lvcreate -n ${lv1}plain -L35M $vg
+lvcreate -n ${lv1}bar -L335M $vg
+lvcreate -n ${lv1}plain -L335M $vg
create_crypt_device
trap 'cleanup_mounted_and_teardown' EXIT
@@ -266,9 +266,9 @@ test_ext3_small_shrink() {
}
test_xfs_resize() {
- mkfs.xfs -l internal,size=1536b -f "$3"
+ mkfs.xfs -f "$3"
- fsadm --lvresize resize $1 30M
+ fsadm --lvresize resize $1 330M
# Fails - not enough space for 4M fs
lvresize -L+10M -r $1
not lvreduce -L10M -r $1
@@ -281,7 +281,7 @@ test_xfs_resize() {
}
test_xfs_small_shrink() {
- mkfs.xfs -l internal,size=1536b -f "$3"
+ mkfs.xfs -f "$3"
not lvresize -L-1 -r $1
fscheck_xfs "$3"
@@ -345,7 +345,7 @@ test_ext3_inactive() {
test_xfs_inactive() {
crypt_open "$2" $PWD2 "$4"
- mkfs.xfs -l internal,size=1536b -f "$3"
+ mkfs.xfs -f "$3"
crypt_close "$4"
not fsadm --lvresize resize $1 30M
@@ -426,7 +426,7 @@ test_ext3_plain() {
}
test_xfs_plain() {
- mkfs.xfs -l internal,size=1536b -f "$3"
+ mkfs.xfs -f "$3"
not fsadm --lvresize resize $1 30M
not lvresize -L+10M -r $1
@@ -434,7 +434,7 @@ test_xfs_plain() {
fscheck_xfs "$3"
lvresize -f -L+10M $1
- fsadm --cryptresize resize $3 40M
+ fsadm --cryptresize resize $3 345M
# no shrink support in xfs
not fsadm --cryptresize resize $3 35M
fscheck_xfs "$3"
@@ -446,7 +446,7 @@ test_xfs_plain() {
crypt_open_plain "$2" $PWD3 "$4"
fscheck_xfs "$3"
- lvresize -f -L35M $1
+ lvresize -f -L320M $1
}
test_reiserfs_plain() {
@@ -492,7 +492,7 @@ test_ext3_detached() {
}
test_xfs_detached() {
- mkfs.xfs -l internal,size=1536b -f "$3"
+ mkfs.xfs -f "$3"
not fsadm --lvresize resize $1 30M
not lvresize -L+10M -r $1
@@ -560,8 +560,10 @@ if check_missing ext3; then
fi
if check_missing xfs; then
+ lvresize -f -L310M $vg_lv
+ cryptsetup resize $CRYPT_NAME
test_xfs_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
- lvresize -f -L25M $vg_lv
+ lvresize -f -L325M $vg_lv
cryptsetup resize $CRYPT_NAME
test_xfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
@@ -570,7 +572,7 @@ if check_missing xfs; then
test_xfs_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN"
crypt_close "$CRYPT_NAME_PLAIN"
- lvresize -f -L100M $vg_lv
+ lvresize -f -L310M $vg_lv
cryptsetup resize $CRYPT_NAME
test_xfs_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV"
lvresize -f -L25M $vg_lv
diff --git a/test/shell/fsadm-renamed.sh b/test/shell/fsadm-renamed.sh
index 50c6d3ee5..5e2e2ed78 100644
--- a/test/shell/fsadm-renamed.sh
+++ b/test/shell/fsadm-renamed.sh
@@ -16,7 +16,7 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
-aux prepare_vg 1 80
+aux prepare_vg 1 700
vg_lv=$vg/$lv1
vg_lv_ren=${vg_lv}_renamed
@@ -63,11 +63,11 @@ if not which "$i" ; then
continue
fi
-lvcreate -n $lv1 -L20M $vg
+lvcreate -n $lv1 -L300M $vg
case "$i" in
*ext3) MKFS_ARGS="-b1024 -j" ;;
-*xfs) MKFS_ARGS="-l internal,size=1700b -f" ;;
+*xfs) MKFS_ARGS="-l internal,size=64m -f" ;;
*reiserfs) MKFS_ARGS="-s 513 -f" ;;
esac
@@ -97,7 +97,7 @@ fail lvresize -y -L+10M -r $vg_lv_ren
# fails on unknown mountpoint (FIXME: umount)
not umount "$dev_vg_lv"
-lvcreate -L20 -n $lv1 $vg
+lvcreate -L300 -n $lv1 $vg
"$i" $MKFS_ARGS "$dev_vg_lv"
aux udev_wait
diff --git a/test/shell/fsadm.sh b/test/shell/fsadm.sh
index c5b3774c2..fea86813d 100644
--- a/test/shell/fsadm.sh
+++ b/test/shell/fsadm.sh
@@ -16,7 +16,7 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
-aux prepare_vg 1 100
+aux prepare_vg 1 400
# set to "skip" to avoid testing given fs and test warning result
# i.e. check_reiserfs=skip
@@ -179,10 +179,10 @@ if check_missing ext3; then
fi
if check_missing xfs; then
- mkfs.xfs -l internal,size=2000b -f "$dev_vg_lv"
+ lvresize -L 300M $vg_lv
+ mkfs.xfs -l internal -f "$dev_vg_lv"
- fsadm --lvresize resize $vg_lv 30M
- # Fails - not enough space for 4M fs
+ fsadm --lvresize resize $vg_lv 320M
lvresize -L+10M -r $vg_lv
not lvreduce -L10M -r $vg_lv
9 months