From 559b17143924dcf849277d25f895a91fb3c7eb6d Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 28 Apr 2021 16:44:23 -0500 Subject: lvreduce: check for file system that cannot be reduced New command line option --detectfs y|n (default y) --- lib/device/dev-type.c | 33 +++++++++++++++++++++++++++++++++ lib/device/dev-type.h | 2 ++ lib/metadata/lv_manip.c | 36 ++++++++++++++++++++++++++++++++++++ lib/metadata/metadata-exported.h | 1 + tools/args.h | 4 ++++ tools/command-lines.in | 6 +++--- tools/lvresize.c | 7 +++++++ 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 @@ -725,6 +725,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))) { -- cgit v1.2.1