summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac24
-rw-r--r--include/configure.h.in7
-rw-r--r--lib/Makefile.in1
-rw-r--r--lib/device/dev-type.c111
-rw-r--r--lib/device/dev-type.h3
-rw-r--r--lib/device/filesystem.c484
-rw-r--r--lib/device/filesystem.h54
-rw-r--r--lib/metadata/lv_manip.c777
-rw-r--r--lib/metadata/metadata-exported.h4
-rw-r--r--lib/metadata/metadata.c4
-rw-r--r--lib/metadata/metadata.h2
-rwxr-xr-xscripts/fsadm.sh2
-rw-r--r--test/shell/fsadm-crypt-fsresize.sh612
-rw-r--r--test/shell/fsadm-crypt.sh130
-rw-r--r--test/shell/fsadm.sh36
-rw-r--r--test/shell/hints.sh4
-rw-r--r--test/shell/lvresize-fs-crypt.sh131
-rw-r--r--test/shell/lvresize-fs.sh1120
-rw-r--r--test/shell/lvresize-full.sh7
-rw-r--r--test/shell/lvresize-mirror.sh2
-rw-r--r--test/shell/lvresize-rounding.sh10
-rw-r--r--test/shell/relative-sign-options.sh16
-rw-r--r--tools/args.h24
-rw-r--r--tools/command-lines.in12
-rw-r--r--tools/lvresize.c61
25 files changed, 3453 insertions, 185 deletions
diff --git a/configure.ac b/configure.ac
index ba02f1f9b..3aa6b1064 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1713,6 +1713,24 @@ 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.])
+MOUNT_PATH="/usr/bin/mount"
+AC_DEFINE_UNQUOTED(MOUNT_PATH, ["$MOUNT_PATH"], [Path to mount binary.])
+
+UMOUNT_PATH="/usr/bin/umount"
+AC_DEFINE_UNQUOTED(UMOUNT_PATH, ["$UMOUNT_PATH"], [Path to umount binary.])
+
+E2FSCK_PATH="$SBINDIR/e2fsck"
+AC_DEFINE_UNQUOTED(E2FSCK_PATH, ["$E2FSCK_PATH"], [Path to e2fsck binary.])
+
+RESIZE2FS_PATH="$SBINDIR/resize2fs"
+AC_DEFINE_UNQUOTED(RESIZE2FS_PATH, ["$RESIZE2FS_PATH"], [Path to resize2fs binary.])
+
+XFS_GROWFS_PATH="$SBINDIR/xfs_growfs"
+AC_DEFINE_UNQUOTED(XFS_GROWFS_PATH, ["$XFS_GROWFS_PATH"], [Path to xfs_growfs binary.])
+
+CRYPTSETUP_PATH="$SBINDIR/cryptsetup"
+AC_DEFINE_UNQUOTED(CRYPTSETUP_PATH, ["$CRYPTSETUP_PATH"], [Path to cryptsetup binary.])
+
################################################################################
dnl -- dmeventd pidfile and executable path
if test "$BUILD_DMEVENTD" = yes; then
@@ -1882,6 +1900,12 @@ AC_SUBST(DM_LIB_PATCHLEVEL)
AC_SUBST(ELDFLAGS)
AC_SUBST(FSADM)
AC_SUBST(FSADM_PATH)
+AC_SUBST(MOUNT_PATH)
+AC_SUBST(UMOUNT_PATH)
+AC_SUBST(E2FSCK_PATH)
+AC_SUBST(RESIZE2FS_PATH)
+AC_SUBST(XFS_GROWFS_PATH)
+AC_SUBST(CRYPTSETUP_PATH)
AC_SUBST(BLKDEACTIVATE)
AC_SUBST(HAVE_LIBDL)
AC_SUBST(HAVE_REALTIME)
diff --git a/include/configure.h.in b/include/configure.h.in
index e0d971bbf..58da11a02 100644
--- a/include/configure.h.in
+++ b/include/configure.h.in
@@ -132,8 +132,13 @@
/* Define to 1 to include the LVM editline shell. */
#undef EDITLINE_SUPPORT
-/* Path to fsadm binary. */
+/* Paths to binaries. */
#undef FSADM_PATH
+#undef MOUNT_PATH
+#undef UMOUNT_PATH
+#undef E2FSCK_PATH
+#undef RESIZE2FS_PATH
+#undef XFS_GROWFS_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/device/dev-type.c b/lib/device/dev-type.c
index 939eb4aeb..aa8e2c4a3 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
@@ -838,6 +843,102 @@ int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
return 0;
}
}
+
+int get_fs_type(const char *pathname, char *fstype)
+{
+ char *str = NULL;
+
+ if ((str = blkid_get_tag_value(NULL, "TYPE", pathname))) {
+ strncpy(fstype, str, FSTYPE_MAX);
+ free(str);
+ log_debug("Found blkid TYPE %s on %s", str, pathname);
+ return 1;
+ } else {
+ log_debug("No blkid TYPE for fs on %s", pathname);
+ return 0;
+ }
+}
+
+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->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->block_size_bytes, (unsigned long long)fslastblock, fsblocksize,
+ (unsigned long long)fsi->fs_last_byte);
+ return 1;
+}
+
#else
int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
{
@@ -845,6 +946,16 @@ int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
*fs_block_size = 0;
return 0;
}
+int get_fs_type(const char *pathname, char *fstype)
+{
+ log_debug("Disabled blkid TYPE 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 17c997641..33157d577 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
@@ -102,6 +103,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);
+int get_fs_type(const char *pathname, char *fstype);
+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..4bdb88863
--- /dev/null
+++ b/lib/device/filesystem.c
@@ -0,0 +1,484 @@
+/*
+ * 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 <dirent.h>
+#include <mntent.h>
+#include <sys/ioctl.h>
+
+/*
+ * 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.
+ */
+static 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, &params);
+
+ 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;
+}
+
+/*
+ * 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 6
+
+int fs_fsck_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi)
+{
+ const char *argv[FS_CMD_MAX_ARGS + 4];
+ int args = 0;
+ int status;
+
+ if (strncmp(fsi->fstype, "ext", 3)) {
+ log_error("fsck not supported for %s.", fsi->fstype);
+ return_0;
+ }
+
+ /*
+ * ext234: e2fsck -f -p path
+ * TODO: replace -p with -y based on yes_ARG, or other?
+ */
+
+ argv[0] = E2FSCK_PATH; /* defined by configure */
+ argv[++args] = "-f";
+ argv[++args] = "-p";
+ argv[++args] = fsi->fs_dev_path;
+ argv[++args] = NULL;
+
+ log_print("Checking file system %s with %s on %s...",
+ fsi->fstype, E2FSCK_PATH, display_lvname(lv));
+
+ if (!exec_cmd(cmd, argv, &status, 1)) {
+ log_error("e2fsck failed on %s.", display_lvname(lv));
+ return 0;
+ }
+
+ log_print("Checked file system %s on %s.", fsi->fstype, display_lvname(lv));
+ return 1;
+}
+
+int fs_reduce_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
+ uint64_t newsize_bytes)
+{
+ char newsize_kb_str[16] = { 0 };
+ const char *argv[FS_CMD_MAX_ARGS + 4];
+ int args = 0;
+ int status;
+
+ if (!strncmp(fsi->fstype, "ext", 3)) {
+ if (dm_snprintf(newsize_kb_str, 16, "%lluk", (unsigned long long)(newsize_bytes/1024)) < 0)
+ return_0;
+
+ /*
+ * ext234 shrink: resize2fs path newsize
+ */
+ argv[0] = RESIZE2FS_PATH; /* defined by configure */
+ argv[++args] = fsi->fs_dev_path;
+ argv[++args] = newsize_kb_str;
+ argv[++args] = NULL;
+
+ } else {
+ log_error("fs reduce not supported for %s.", fsi->fstype);
+ return_0;
+ }
+
+ log_print("Reducing file system %s on %s...", fsi->fstype, display_lvname(lv));
+
+ if (!exec_cmd(cmd, argv, &status, 1)) {
+ log_error("Failed to reduce %s file system on %s.", fsi->fstype, display_lvname(lv));
+ return 0;
+ }
+
+ log_print("Reduced file system %s to %s (%llu bytes) on %s.",
+ fsi->fstype, display_size(cmd, newsize_bytes/512),
+ (unsigned long long)newsize_bytes, display_lvname(lv));
+ return 1;
+}
+
+int fs_extend_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi)
+{
+ const char *argv[FS_CMD_MAX_ARGS + 4];
+ int args = 0;
+ int status;
+
+ if (!strncmp(fsi->fstype, "ext", 3)) {
+ /* TODO: include -f if lvm command inclues -f ? */
+ argv[0] = RESIZE2FS_PATH; /* defined by configure */
+ argv[++args] = fsi->fs_dev_path;
+ argv[++args] = NULL;
+
+ } else if (!strcmp(fsi->fstype, "xfs")) {
+ argv[0] = XFS_GROWFS_PATH; /* defined by configure */
+ argv[++args] = fsi->fs_dev_path;
+ argv[++args] = NULL;
+
+ } else {
+ log_error("Extend not supported for %s file system.", fsi->fstype);
+ return_0;
+ }
+
+ log_print("Extending file system %s on %s...", fsi->fstype, display_lvname(lv));
+
+ if (!exec_cmd(cmd, argv, &status, 1)) {
+ log_error("Failed to extend %s file system on %s.", fsi->fstype, display_lvname(lv));
+ return 0;
+ }
+
+ log_print("Extended file system %s on %s.", fsi->fstype, display_lvname(lv));
+ return 1;
+}
+
+int fs_mount_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
+ int reuse_mount_dir)
+{
+ char mountdir[PATH_MAX];
+ const char *argv[FS_CMD_MAX_ARGS + 4];
+ int args = 0;
+ int status;
+
+ if (reuse_mount_dir) {
+ if (!fsi->mount_dir[0]) {
+ log_error("Cannot remount fs without previous mount dir.");
+ return 0;
+ }
+ memcpy(mountdir, fsi->mount_dir, PATH_MAX);
+ } else {
+ if (dm_snprintf(mountdir, sizeof(mountdir), "/tmp/%s_XXXXXX", cmd->name) < 0)
+ return_0;
+ if (!mkdtemp(mountdir)) {
+ log_error("Failed to create temp dir for mount: %s", strerror(errno));
+ return 0;
+ }
+ memcpy(fsi->mount_dir, mountdir, PATH_MAX);
+ fsi->temp_mount_dir = 1;
+ }
+
+ argv[0] = MOUNT_PATH; /* defined by configure */
+ argv[++args] = fsi->fs_dev_path;
+ argv[++args] = mountdir;
+ argv[++args] = NULL;
+
+ log_print("Mounting %s.", display_lvname(lv));
+
+ if (!exec_cmd(cmd, argv, &status, 1)) {
+ log_error("Failed to mount file system on %s at %s.", display_lvname(lv), mountdir);
+ return 0;
+ }
+
+ log_print("Mounted %s at %s dir %s.", display_lvname(lv),
+ reuse_mount_dir ? "original" : "temporary", mountdir);
+ return 1;
+}
+
+int fs_unmount_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi)
+{
+ const char *argv[FS_CMD_MAX_ARGS + 4];
+ int args = 0;
+ int status;
+
+ argv[0] = UMOUNT_PATH; /* defined by configure */
+ argv[++args] = fsi->fs_dev_path;
+ argv[++args] = NULL;
+
+ log_print("Unmounting %s.", display_lvname(lv));
+
+ if (!exec_cmd(cmd, argv, &status, 1)) {
+ log_error("Failed to unmount file system on %s.", display_lvname(lv));
+ return 0;
+ }
+
+ log_print("Unmounted %s.", display_lvname(lv));
+
+ if (fsi->temp_mount_dir) {
+ if (rmdir(fsi->mount_dir) < 0)
+ log_print("Error removing temp dir %s", fsi->mount_dir);
+ fsi->mount_dir[0] = '\0';
+ fsi->temp_mount_dir = 0;
+ }
+ return 1;
+}
+
+int crypt_resize_command(struct cmd_context *cmd, dev_t crypt_devt, uint64_t newsize_bytes)
+{
+ char crypt_path[PATH_MAX];
+ const char *argv[FS_CMD_MAX_ARGS + 4];
+ char size_str[16] = { 0 };
+ int args = 0;
+ int status;
+
+ if (dm_snprintf(crypt_path, sizeof(crypt_path), "/dev/dm-%d", (int)MINOR(crypt_devt)) < 0)
+ return_0;
+
+ if (dm_snprintf(size_str, sizeof(size_str), "%llu", (unsigned long long)newsize_bytes/512) < 0)
+ return_0;
+
+ argv[0] = CRYPTSETUP_PATH; /* defined by configure */
+ argv[++args] = "resize";
+ if (newsize_bytes) {
+ argv[++args] = "--size";
+ argv[++args] = size_str;
+ }
+ argv[++args] = crypt_path;
+ argv[++args] = NULL;
+
+ log_print("Resizing crypt device %s...", crypt_path);
+
+ if (!exec_cmd(cmd, argv, &status, 1)) {
+ log_error("Failed to cryptsetup resize %s to %s (%llu sectors)",
+ crypt_path, display_size(cmd, newsize_bytes/512),
+ (unsigned long long)newsize_bytes/512);
+ return 0;
+ }
+
+ if (newsize_bytes)
+ log_print("Resized crypt device %s to %s (%llu sectors)",
+ crypt_path, display_size(cmd, newsize_bytes/512),
+ (unsigned long long)newsize_bytes/512);
+ else
+ log_print("Resized crypt device %s.", crypt_path);
+
+ return 1;
+}
+
diff --git a/lib/device/filesystem.h b/lib/device/filesystem.h
new file mode 100644
index 000000000..1e83469cb
--- /dev/null
+++ b/lib/device/filesystem.h
@@ -0,0 +1,54 @@
+/*
+ * 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 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;
+ unsigned temp_mount_dir: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_fsck_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi);
+int fs_reduce_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
+ uint64_t newsize_bytes);
+int fs_extend_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi);
+int fs_mount_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
+ int reuse_mount_dir);
+int fs_unmount_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi);
+
+int crypt_resize_command(struct cmd_context *cmd, dev_t crypt_devt, uint64_t newsize_bytes);
+
+#endif
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 22f8324e2..05479520a 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;
@@ -5933,7 +5927,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 +5968,628 @@ 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_remount: resize the fs, mounting/unmounting the fs as needed,
+ * but avoiding mounting/unmounted when possible.
+ *
+ * --fs resize_keepmount: 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_unmount: resize the fs only while it's unmounted ("offline"),
+ * 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
+ *
+ * --fs resize: equivalent to resize_remount.
+ */
+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_keepmount")) {
+ /* can't mount|unmount to run fs resize */
+ if (fsi->needs_mount) {
+ log_error("File system needs to be mounted to reduce fs (see resize_remount).");
+ return 0;
+ }
+ if (fsi->needs_unmount) {
+ log_error("File system needs to be unmounted to reduce fs (see resize_remount).");
+ return 0;
+ }
+ } else if (!strcmp(lp->fsopt, "resize_unmount")) {
+ /* 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 resize_remount).");
+ return 0;
+ }
+ } else if (!strcmp(lp->fsopt, "resize_remount")) {
+ /* we can mount|unmount as needed to run fs resize */
+ } else if (!strcmp(lp->fsopt, "resize")) {
+ /* equivalent to resize_remount, but confirm mount change */
+ if (fsi->needs_mount || fsi->needs_unmount)
+ confirm_mount_change = 1;
+ } else {
+ log_error("Unknown file system resize option: %s", lp->fsopt);
+ 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
+ * the generic "resize" option was used (i.e. the user did not give
+ * specific direction about how to handle mounting|unmounting such as
+ * resize_unmount, resize_remount, resize_keepmount, so ask them.)
+ */
+ 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.
+ *
+ * resize_keepmount: don't change mount condition.
+ * if mounted: fs_extend
+ * if unmounted: fsck, fs_extend
+ *
+ * resize_unmount: extend offline, so unmount first if mounted.
+ * if mounted: unmount, fsck, fs_extend
+ * if unmounted: fsck, fs_extend
+ *
+ * resize_remount|resize: 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_keepmount")) {
+ 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_unmount")) {
+ 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_remount") || !strcmp(lp->fsopt, "resize")) {
+ 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.
+ *
+ * resize_keepmount: don't change mount condition.
+ * if mounted: fs_extend
+ * if unmounted: fail
+ *
+ * resize_unmount: extend offline, so unmount first if mounted.
+ * if mounted: fail
+ * if unmounted: fail
+ *
+ * resize_remount|resize: 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_keepmount")) {
+ if (fsi->mounted)
+ fsi->needs_extend = 1;
+ else if (fsi->unmounted) {
+ log_error("File system must be mounted to extend (see resize_remount).");
+ return 0;
+ }
+ } else if (!strcmp(lp->fsopt, "resize_unmount")) {
+ log_error("File system must be mounted to extend (see resize_remount).");
+ return 0;
+ } else if (!strcmp(lp->fsopt, "resize_remount") || !strcmp(lp->fsopt, "resize")) {
+ 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 because mount|unmount is needed, and
+ * the generic "resize" option was used (i.e. the user did not give
+ * specific direction about how to handle mounting|unmounting such
+ * as resize_umount, resize_remount, resize_keepmount, so ask them.)
+ */
+ if (!strcmp(lp->fsopt, "resize") && (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 mounted = 0, unmounted = 0;
+ 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_command() and
+ * crypt_resize_command() 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_command(cmd, fsinfo.crypt_devt, 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 (fsinfo.needs_unmount) {
+ if (!fs_unmount_command(cmd, lv, &fsinfo))
+ goto_out;
+ unmounted = 1;
+ }
+
+ if (fsinfo.needs_fsck) {
+ if (!fs_fsck_command(cmd, lv, &fsinfo))
+ goto_out;
+ }
+
+ if (fsinfo.needs_mount) {
+ if (!fs_mount_command(cmd, lv, &fsinfo, 0))
+ goto_out;
+ mounted = 1;
+ }
+
+ if (!fs_reduce_command(cmd, lv, &fsinfo, newsize_bytes_fs))
+ goto_out;
+
+ if (fsinfo.needs_crypt) {
+ if (!crypt_resize_command(cmd, fsinfo.crypt_devt, newsize_bytes_fs))
+ 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_error("VG was changed during fs operations, cannot reduce LV.");
+ 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;
+
+ /*
+ * put the fs back into the original mounted|unmounted state.
+ */
+ if (!strcmp(lp->fsopt, "resize_remount") || !strcmp(lp->fsopt, "resize")) {
+ if (mounted && !fs_unmount_command(cmd, lv, &fsinfo))
+ ret = 0;
+ if (unmounted && !fs_mount_command(cmd, lv, &fsinfo, 1))
+ ret = 0;
+ }
+ out:
+ return ret;
+}
+
+static int _fs_extend(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvresize_params *lp)
+{
+ struct fs_info fsinfo;
+ int mounted = 0, unmounted = 0;
+ 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;
+ }
+
+ /*
+ * 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 (fsinfo.needs_unmount) {
+ if (!fs_unmount_command(cmd, lv, &fsinfo))
+ goto_out;
+ unmounted = 1;
+ }
+
+ if (fsinfo.needs_fsck) {
+ if (!fs_fsck_command(cmd, lv, &fsinfo))
+ goto_out;
+ }
+
+ if (fsinfo.needs_crypt) {
+ if (!crypt_resize_command(cmd, fsinfo.crypt_devt, 0))
+ goto_out;
+ }
+
+ if (fsinfo.needs_mount) {
+ if (!fs_mount_command(cmd, lv, &fsinfo, 0))
+ goto_out;
+ mounted = 1;
+ }
+
+ if (!fs_extend_command(cmd, lv, &fsinfo))
+ goto_out;
+
+ ret = 1;
+
+ /*
+ * put the fs back into the original mounted|unmounted state.
+ */
+ if (!strcmp(lp->fsopt, "resize_remount") || !strcmp(lp->fsopt, "resize")) {
+ if (mounted && !fs_unmount_command(cmd, lv, &fsinfo))
+ ret = 0;
+ if (unmounted && !fs_mount_command(cmd, lv, &fsinfo, 1))
+ ret = 0;
+ }
+ out:
+ return ret;
+}
+
int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
struct lvresize_params *lp)
{
@@ -6019,26 +6635,6 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
}
/*
- * 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
* only by extending an underlying LV. Extending some top level
@@ -6197,10 +6793,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,46 +6857,105 @@ 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;
}
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';
+ }
+
+ /*
+ * Any fs option requires the LV already be active.
+ * (not sure why the command doesn't activate)
+ */
+ if (lp->fsopt[0] && !lv_is_active(lv_top)) {
+ log_error("Logical volume %s must be active for file system %s.",
+ display_lvname(lv_top), lp->fsopt);
+ return 0;
+ }
+
+ /*
+ * 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];
+
+ 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));
+ return 0;
+ }
+ if (!get_fs_type(lv_path, fstype)) {
+ log_error("File system not found for --resizefs or --fs options.");
+ return 0;
+ }
+ }
+
+ /*
+ * Warn and confirm if checksize has been disabled for reduce.
+ */
+ if (is_reduce && !lp->fsopt[0] && !_lv_reduce_confirmation(lv_top, lp))
+ 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;
- /*
- * 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;
+ }
}
/*
@@ -6376,16 +7027,22 @@ 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;
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 4fb6ad93a..21dd39646 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -674,8 +674,9 @@ struct lvresize_params {
int force;
int nosync;
int nofsck;
- int resizefs;
int use_policies;
+ int user_set_fs;
+ char fsopt[32]; /* set by --resizefs|--fs, empty for --fs ignore */
const struct segment_type *segtype;
unsigned mirrors;
@@ -695,6 +696,7 @@ 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 */
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 6c39ff845..5cebe9508 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -538,5 +538,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/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/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 2004db957..aefa722f1 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 30M
# 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 -l internal,size=1536b -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 -l internal,size=1536b -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 -l internal,size=1536b -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
@@ -561,7 +561,7 @@ fi
if check_missing xfs; then
test_xfs_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_xfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2"
@@ -570,10 +570,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 -L100M $vg_lv
+ lvresize --fs ignore -y -L100M $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
@@ -585,7 +585,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"
@@ -594,10 +594,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 c5b3774c2..a7b3cdf2f 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,23 @@ if check_missing xfs; then
fsadm --lvresize resize $vg_lv 30M
# Fails - not enough space for 4M fs
- lvresize -L+10M -r $vg_lv
- not lvreduce -L10M -r $vg_lv
+ 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 +209,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..26fc7e718
--- /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"
+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..8a0be0cec
--- /dev/null
+++ b/test/shell/lvresize-fs.sh
@@ -0,0 +1,1120 @@
+#!/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"
+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_remount (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_remount -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_unmount
+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_unmount -L+200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+# resize_unmount 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_keepmount
+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_keepmount -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_keepmount
+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_keepmount -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_remount (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_remount -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_unmount
+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_unmount -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_keepmount
+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_keepmount -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_keepmount
+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 resize_keepmount
+# with an unmounted fs fails
+not lvextend --fs resize_keepmount -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
+# lv must be active to do checksize, which is the default with no --fs setting
+not lvreduce -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+lvchange -an $vg/$lv
+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 requires active lv
+
+# 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 requires active lv
+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"
+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"
+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"
+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"
+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"
+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"
+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"
+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"
+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_keepmount | resize_unmount | resize_fsadm
+# while mounted and unmounted
+
+# lvreduce, ext4, active, mounted, --fs resize_keepmount
+# 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 keepmount doesn't let it
+not lvreduce --fs resize_keepmount -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_keepmount
+# 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_keepmount -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_unmount
+# 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
+# resize_unmount leaves the fs unmounted
+lvreduce --fs resize_unmount -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_unmount
+# 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_unmount -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"
+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_remount -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+not lvreduce --yes --fs resize_keepmount -L-200M $vg/$lv
+check lv_field $vg/$lv lv_size "456.00m"
+not lvreduce --yes --fs resize_unmount -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
+
+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 9229b8764..99d39ee91 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -301,6 +301,27 @@ 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,
+ "File system handling when resizing an LV.\n"
+ "\\fBchecksize\\fP: Only when reducing size, does nothing when extending.\n"
+ "Check the fs size and reduce the LV if the fs is not using the affected\n"
+ "space, i.e. the fs does not need to be shrunk. Fail the command without\n"
+ "reducing the fs or LV if the fs is using the affected space.\n"
+ "\\fBresize_remount\\fP: Resize the fs if needed. Mounts or unmounts the fs as\n"
+ "required (avoids mounting/unmounting when possible.)\n"
+ "Attempts to restore the original mount state when finished.\n"
+ "\\fBresize_keepmount\\fP: Resize the fs if needed, only if it can be done without\n"
+ "changing the current mount state. Fail the command without\n"
+ "resizing the fs or LV if an fs resize requires mounting or unmounting\n"
+ "\\fBresize_unmount\\fP: Resize the fs if needed, only while unmounted. Unmount the\n"
+ "fs if needed. Fail the command without resizing the fs\n"
+ "or LV if an fs resize is needed that requires the the fs to be mounted\n"
+ "\\fBresize\\fP: Equivalent to resize_remount.\n"
+ "\\fBresize_fsadm\\fP: Use the old method of calling fsadm to do handle the fs\n"
+ "(deprecated).\n"
+ "\\fBignore\\fP: Resize the LV without checking for or handling a file system.\n"
+ "WARNING: using ignore when reducing the LV size may cause data loss.\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")
@@ -1449,7 +1470,8 @@ 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 file system on the LV.\n"
+ "Equivalent to --fs resize_remount. See --fs for more options.\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 dd033630b..13400e6f4 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1379,7 +1379,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
OP: PV ...
ID: lvextend_size
DESC: Extend an LV by a specified size.
@@ -1388,7 +1388,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
ID: lvextend_pv
DESC: Extend an LV by specified PV extents.
@@ -1405,7 +1405,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
OP: PV ...
ID: lvextend_policy
DESC: Extend an LV according to a predefined policy.
@@ -1454,7 +1454,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
ID: lvreduce_size
---
@@ -1484,7 +1484,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
OP: PV ...
ID: lvresize_size
DESC: Resize an LV by a specified size.
@@ -1493,7 +1493,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
ID: lvresize_pv
DESC: Resize an LV by specified PV extents.
diff --git a/tools/lvresize.c b/tools/lvresize.c
index a7148e52c..3c0ae7737 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,43 @@ static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
return 0;
};
+ if (set_fsopt) {
+ const char *str;
+ if ((str = arg_str_value(cmd, fs_ARG, NULL))) {
+ if (!strcmp(str, "checksize") ||
+ !strcmp(str, "resize") ||
+ !strcmp(str, "resize_remount") ||
+ !strcmp(str, "resize_keepmount") ||
+ !strcmp(str, "resize_unmount") ||
+ !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 (set_extents_and_size) {
if ((lp->extents = arg_uint_value(cmd, extents_ARG, 0))) {
lp->sign = arg_sign_value(cmd, extents_ARG, 0);
@@ -237,6 +271,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 +280,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;
}