conf/example.conf.in | 10 ++++++++++ lib/config/config_settings.h | 9 +++++++++ lib/metadata/lv_manip.c | 14 +++++++++++--- lib/metadata/segtype.h | 2 ++ lib/vdo/vdo.c | 46 ++++++++++++++++++++++++++++++++++++-------- 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/conf/example.conf.in b/conf/example.conf.in index cd53147..d02965e 100644 --- a/conf/example.conf.in +++ b/conf/example.conf.in @@ -1195,6 +1195,16 @@ global { # This configuration option has an automatic default value. # vdo_format_options = [ "" ] + # Configuration option global/vdo_disabled_features. + # Features to not use in the vdo driver. + # This can be helpful for testing, or to avoid using a feature that is + # causing problems. Features include: online_rename + # + # Example + # vdo_disabled_features = [ "online_rename" ] + # + # This configuration option does not have a default value defined. + # Configuration option global/fsadm_executable. # The full path to the fsadm command. # LVM uses this command to help with lvresize -r operations. diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h index 3c4032e..f844594 100644 --- a/lib/config/config_settings.h +++ b/lib/config/config_settings.h @@ -1206,6 +1206,15 @@ cfg(global_vdo_format_executable_CFG, "vdo_format_executable", global_CFG_SECTIO cfg_array(global_vdo_format_options_CFG, "vdo_format_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_FORMAT_OPTIONS_CONFIG, VDO_1ST_VSN, NULL, 0, NULL, "List of options passed added to standard vdoformat command.\n") +cfg_array(global_vdo_disabled_features_CFG, "vdo_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 3, 11), NULL, 0, NULL, + "Features to not use in the vdo driver.\n" + "This can be helpful for testing, or to avoid using a feature that is\n" + "causing problems. Features include: online_rename\n" + "#\n" + "Example\n" + "vdo_disabled_features = [ \"online_rename\" ]\n" + "#\n") + cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FSADM_PATH, vsn(2, 2, 170), "@FSADM_PATH@", 0, NULL, "The full path to the fsadm command.\n" "LVM uses this command to help with lvresize -r operations.\n") diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index c740ba2..6c71263 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -4738,6 +4738,8 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv, struct lv_names lv_names = { .old = lv->name }; int old_lv_is_historical = lv_is_historical(lv); int historical; + unsigned attrs; + const struct segment_type *segtype; /* * rename is not allowed on sub LVs except for pools @@ -4763,9 +4765,15 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv, } if (lv_is_vdo_pool(lv) && lv_is_active(lv_lock_holder(lv))) { - log_error("Cannot rename active VDOPOOL volume %s.", - display_lvname(lv)); - return 0; + segtype = first_seg(lv)->segtype; + if (!segtype->ops->target_present || + !segtype->ops->target_present(lv->vg->cmd, NULL, &attrs) || + !(attrs & VDO_FEATURE_ONLINE_RENAME)) { + log_error("Cannot rename active VDOPOOL volume %s, " + "VDO target feature support is missing.", + display_lvname(lv)); + return 0; + } } if (update_mda && !archive(vg)) diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h index 08ddc35..2714a6b 100644 --- a/lib/metadata/segtype.h +++ b/lib/metadata/segtype.h @@ -349,6 +349,8 @@ int init_cache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib) int init_vdo_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); #endif +#define VDO_FEATURE_ONLINE_RENAME (1U << 0) /* version 6.2.3 */ + int init_writecache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); int init_integrity_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); diff --git a/lib/vdo/vdo.c b/lib/vdo/vdo.c index c43a5dc..bb7c784 100644 --- a/lib/vdo/vdo.c +++ b/lib/vdo/vdo.c @@ -25,6 +25,7 @@ #include "lib/metadata/segtype.h" #include "base/memory/zalloc.h" +static const char _vdo_module[] = MODULE_NAME_VDO; static unsigned _feature_mask; static int _bad_field(const char *field) @@ -391,18 +392,21 @@ static int _vdo_target_present(struct cmd_context *cmd, static const struct feature { uint32_t maj; uint32_t min; + uint32_t patchlevel; unsigned vdo_feature; const char *feature; } _features[] = { - { 1, 1, 0, "" }, - //{ 9, 9, VDO_FEATURE_RESIZE, "resize" }, + { 6, 2, 3, VDO_FEATURE_ONLINE_RENAME, "online_rename" }, }; - //static const char _lvmconf[] = "global/vdo_disabled_features"; + static const char _lvmconf[] = "global/vdo_disabled_features"; static int _vdo_checked = 0; static int _vdo_present = 0; static unsigned _vdo_attrs = 0; uint32_t i, maj, min, patchlevel; const struct segment_type *segtype; + const struct dm_config_node *cn; + const struct dm_config_value *cv; + const char *str; if (!activation()) return 0; @@ -419,8 +423,8 @@ static int _vdo_target_present(struct cmd_context *cmd, } if (maj < 6 || (maj == 6 && min < 2)) { - log_warn("WARNING: VDO target version %u.%u.%u is too old.", - maj, min, patchlevel); + log_warn("WARNING: Target %s version %u.%u.%u is too old.", + _vdo_module, maj, min, patchlevel); return 0; } @@ -437,15 +441,41 @@ static int _vdo_target_present(struct cmd_context *cmd, /* Prepare for adding supported features */ for (i = 0; i < DM_ARRAY_SIZE(_features); ++i) if ((maj > _features[i].maj) || - (maj == _features[i].maj && min >= _features[i].min)) + ((maj == _features[i].maj) && (min > _features[i].min)) || + ((maj == _features[i].maj) && (min == _features[i].min) && (patchlevel >= _features[i].patchlevel))) _vdo_attrs |= _features[i].vdo_feature; else log_very_verbose("Target %s does not support %s.", - TARGET_NAME_VDO, + _vdo_module, _features[i].feature); } if (attributes) { + if (!_feature_mask) { + /* Support runtime lvm.conf changes, N.B. avoid 32 feature */ + if ((cn = find_config_tree_array(cmd, global_vdo_disabled_features_CFG, NULL))) { + for (cv = cn->v; cv; cv = cv->next) { + if (cv->type != DM_CFG_STRING) { + log_warn("WARNING: Ignoring invalid string in config file %s.", + _lvmconf); + continue; + } + str = cv->v.str; + if (!*str) + continue; + for (i = 0; i < DM_ARRAY_SIZE(_features); ++i) + if (strcasecmp(str, _features[i].feature) == 0) + _feature_mask |= _features[i].vdo_feature; + } + } + _feature_mask = ~_feature_mask; + for (i = 0; i < DM_ARRAY_SIZE(_features); ++i) + if ((_vdo_attrs & _features[i].vdo_feature) && + !(_feature_mask & _features[i].vdo_feature)) + log_very_verbose("Target %s %s support disabled by %s.", + _vdo_module, + _features[i].feature, _lvmconf); + } *attributes = _vdo_attrs & _feature_mask; } @@ -456,7 +486,7 @@ static int _vdo_modules_needed(struct dm_pool *mem, const struct lv_segment *seg __attribute__((unused)), struct dm_list *modules) { - if (!str_list_add(mem, modules, MODULE_NAME_VDO)) { + if (!str_list_add(mem, modules, _vdo_module)) { log_error("String list allocation failed for VDO module."); return 0; }