summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2021-04-28 16:44:23 -0500
committerDavid Teigland <teigland@redhat.com>2021-04-28 17:12:25 -0500
commitae51c9bff429774f57fc26f136221902272e7e71 (patch)
tree86fb55977f5ac60842ddda40d98ecbc2a356f9e8
parent4dc5d4ac7e7a9457ccc46ff04796b347e58bf4da (diff)
downloadlvm2-dev-dct-lvreduce-check.tar.gz
lvreduce: check for file system that cannot be reduceddev-dct-lvreduce-check
New command line option --checkfs y|n New config setting global/lvreduce_checkfs=1|0 The default lvm.conf setting is 1 (enabled). The command line option overrides lvm.conf. If the new lvm.conf setting is not changed, and the new command line option is not used, then lvreduce will check the LV and look a file system type that it knows can be reduced (ext4). It will activate the LV if it's not active already to do this check. The LV will not be reduced unless a file system type is found that lvreduce knows is reducible (only ext4 at this point.) if lvm.conf lvreduce_checkfs=1 and --checkfs is not used, then lvreduce will check fs. (This is the default.) if lvm.conf lvreduce_checkfs=0 and --checkfs is not used, then lvreduce will not check fs. if --checkfs y then lvreduce will check fs, overriding any lvm.conf setting. if --checkfs n then lvreduce will not check fs, overriding any lvm.conf setting.
-rw-r--r--lib/config/config_settings.h9
-rw-r--r--lib/device/dev-type.c33
-rw-r--r--lib/device/dev-type.h2
-rw-r--r--lib/metadata/lv_manip.c36
-rw-r--r--lib/metadata/metadata-exported.h1
-rw-r--r--tools/args.h4
-rw-r--r--tools/command-lines.in6
-rw-r--r--tools/lvresize.c7
8 files changed, 95 insertions, 3 deletions
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index d3a42a153..cb6bcb242 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -1115,6 +1115,15 @@ cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_pa
"Previously this was always shown as /dev/vgname/lvname even when that\n"
"was never a valid path in the /dev filesystem.\n")
+cfg(global_lvreduce_checkfs_CFG, "lvreduce_checkfs", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 3, 12), 0, 0, NULL,
+ "Control if lvreduce will check for a file system that cannot be reduced.\n"
+ "When enabled, lvreduce will read the LV to check that the file system type\n"
+ "can be reduced. If the file system type cannot be reduced, then lvreduce\n"
+ "will not be performed. The LV will be activated, if it is not already active,\n"
+ "to check for a file system. When disabled, lvreduce will not check for\n"
+ "file systems on the LV. This risks corrupting the file system.\n"
+ "The command line option --checkfs y|n will override this setting.\n")
+
cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 3, 1), 0, 0, NULL,
"Activate LVs based on system-generated device events.\n"
"When a PV appears on the system, a system-generated uevent triggers\n"
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 1b335722d..9b41b0f2f 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -726,6 +726,39 @@ int get_fs_block_size(struct device *dev, uint32_t *fs_block_size)
#endif
#ifdef BLKID_WIPING_SUPPORT
+int get_fs_can_reduce(const char *pathname, int *fs_can_reduce, char *fs_buf, int fs_buf_len)
+{
+ char *fs_str = NULL;
+
+ if ((fs_str = blkid_get_tag_value(NULL, "TYPE", pathname))) {
+ if (fs_buf && fs_buf_len)
+ strncpy(fs_buf, fs_str, fs_buf_len-1);
+
+ log_debug("Found blkid filesystem TYPE %s on %s", fs_str, pathname);
+
+ if (fs_str && !strcmp(fs_str, "ext4"))
+ *fs_can_reduce = 1;
+ else
+ *fs_can_reduce = 0;
+
+ free(fs_str);
+ return 1;
+ } else {
+ log_debug("No blkid filesystem TYPE found for %s", pathname);;
+ *fs_can_reduce = 0;
+ return 0;
+ }
+}
+#else
+int get_fs_can_reduce(const char *pathname, int *fs_can_reduce, char *fs_buf, int fs_buf_len)
+{
+ log_warn("Disabled blkid for fs type check.");
+ *fs_can_reduce = 0;
+ return 0;
+}
+#endif
+
+#ifdef BLKID_WIPING_SUPPORT
static inline int _type_in_flag_list(const char *type, uint32_t flag_list)
{
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
index 45377c144..8e46815ed 100644
--- a/lib/device/dev-type.h
+++ b/lib/device/dev-type.h
@@ -102,4 +102,6 @@ int dev_is_lv(struct device *dev);
int get_fs_block_size(struct device *dev, uint32_t *fs_block_size);
+int get_fs_can_reduce(const char *pathname, int *fs_can_reduce, char *fs_buf, int fs_buf_len);
+
#endif
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 508f78c13..c5e28734e 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -6050,6 +6050,42 @@ int lv_resize(struct logical_volume *lv,
(pvh != &vg->pvs))
log_print_unless_silent("Ignoring PVs on command line when reducing.");
+ if (lp->checkfs) {
+ char pathname[PATH_MAX];
+ char *dmname;
+ char fs_buf[16] = {0};
+ int fs_can_reduce = 0;
+
+ /* if lv is not active, activate it */
+ if (!lv_is_active(lv)) {
+ if (!activate_lv(cmd, lv)) {
+ log_error("Failed to activate %s for --checkfs.", display_lvname(lv));
+ return 0;
+ }
+ if (!sync_local_dev_names(cmd))
+ return_0;
+ activated = 1;
+ }
+
+ if (!(dmname = dm_build_dm_name(cmd->mem, vg->name, lv->name, NULL)))
+ return_0;
+
+ if (dm_snprintf(pathname, sizeof(pathname), "%s/%s", dm_dir(), dmname) < 0)
+ return_0;
+
+ /* use blkid to check fs type, we know which types can reduce */
+ if (!get_fs_can_reduce(pathname, &fs_can_reduce, fs_buf, sizeof(fs_buf))) {
+ log_error("Failed to find file system type for --checkfs.");
+ goto bad;
+ }
+
+ if (!fs_can_reduce) {
+ log_error("Found file system type %s that cannot be reduced (see --checkfs).",
+ fs_buf[0] ? fs_buf : "unknown");
+ goto bad;
+ }
+ }
+
/* Request confirmation before operations that are often mistakes. */
/* aux_lv never resize fs */
if ((lp->resizefs || (lp->resize == LV_REDUCE)) &&
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index c6116350f..f4719e08b 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -687,6 +687,7 @@ struct lvresize_params {
int nosync;
int nofsck;
int resizefs;
+ int checkfs;
unsigned mirrors;
uint32_t stripes;
diff --git a/tools/args.h b/tools/args.h
index 741c82b9f..f6ff9c1ca 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -155,6 +155,10 @@ arg(cachesize_ARG, '\0', "cachesize", sizemb_VAL, 0, 0,
arg(check_ARG, '\0', "check", 0, 0, 0,
"Check the content of the devices file.\n")
+arg(checkfs_ARG, '\0', "checkfs", bool_VAL, 0, 0,
+ "Check the LV for file system information. This activates the LV if\n"
+ "needed so that the LV can be read to look for fs superblocks.\n")
+
arg(commandprofile_ARG, '\0', "commandprofile", string_VAL, 0, 0,
"The command profile to use for command configuration.\n"
"See \\fBlvm.conf\\fP(5) for more information about profiles.\n")
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 164516a2e..a7700c441 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1449,7 +1449,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, --checkfs Bool
ID: lvreduce_general
---
@@ -1479,7 +1479,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, --checkfs Bool
OP: PV ...
ID: lvresize_by_size
DESC: Resize an LV by a specified size.
@@ -1488,7 +1488,7 @@ lvresize LV PV ...
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB,
---type SegType
+--type SegType, --checkfs Bool
ID: lvresize_by_pv
DESC: Resize an LV by specified PV extents.
diff --git a/tools/lvresize.c b/tools/lvresize.c
index f39f03a40..f0faf6dff 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -39,6 +39,13 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
else
lp->resize = LV_ANY;
+ if (lp->resize == LV_REDUCE) {
+ if (arg_is_set(cmd, checkfs_ARG))
+ lp->checkfs = arg_int_value(cmd, checkfs_ARG, 1);
+ else
+ lp->checkfs = find_config_tree_bool(cmd, global_lvreduce_checkfs_CFG, NULL);
+ }
+
lp->sign = lp->poolmetadata_sign = SIGN_NONE;
if ((lp->use_policies = arg_is_set(cmd, usepolicies_ARG))) {