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-30 13:47:22 -0500
commit559b17143924dcf849277d25f895a91fb3c7eb6d (patch)
treea19ac6bf65680efb8fe751b2c5cfb1fb8df32946
parent4dc5d4ac7e7a9457ccc46ff04796b347e58bf4da (diff)
downloadlvm2-dev-dct-lvreduce-check-2.tar.gz
lvreduce: check for file system that cannot be reduceddev-dct-lvreduce-check-2
New command line option --detectfs y|n (default y)
-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
7 files changed, 86 insertions, 3 deletions
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..b53673293 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->detectfs) {
+ 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 --detectfs.", 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 --detectfs.");
+ goto bad;
+ }
+
+ if (!fs_can_reduce) {
+ log_error("Found file system type %s that cannot be reduced (from --detectfs).",
+ 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..06be68a48 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 detectfs;
unsigned mirrors;
uint32_t stripes;
diff --git a/tools/args.h b/tools/args.h
index 741c82b9f..b880a6c25 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(detectfs_ARG, '\0', "detectfs", 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..f6e45dc61 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, --detectfs 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, --detectfs 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, --detectfs 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..ab434ba14 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, detectfs_ARG))
+ lp->detectfs = arg_int_value(cmd, detectfs_ARG, 1);
+ else
+ lp->detectfs = 1;
+ }
+
lp->sign = lp->poolmetadata_sign = SIGN_NONE;
if ((lp->use_policies = arg_is_set(cmd, usepolicies_ARG))) {