mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
thin: reworked thin feature detection
Rework thin feature detection to support runtime section to allow to disable them selectively. New lvm.conf option is born: global/thin_disabled_features
This commit is contained in:
parent
99018b37ee
commit
5ec20e267f
@ -1,5 +1,6 @@
|
|||||||
Version 2.02.99 -
|
Version 2.02.99 -
|
||||||
===================================
|
===================================
|
||||||
|
Add lvm.conf option global/thin_disabled_features.
|
||||||
Add lvconvert support to swap thin pool metadata volume.
|
Add lvconvert support to swap thin pool metadata volume.
|
||||||
Implement internal function detach_pool_metadata_lv().
|
Implement internal function detach_pool_metadata_lv().
|
||||||
Fix lvm2app to return all property sizes in bytes.
|
Fix lvm2app to return all property sizes in bytes.
|
||||||
|
@ -524,6 +524,16 @@ global {
|
|||||||
# String with options passed with thin_check command. By default,
|
# String with options passed with thin_check command. By default,
|
||||||
# option '-q' is for quiet output.
|
# option '-q' is for quiet output.
|
||||||
thin_check_options = [ "-q" ]
|
thin_check_options = [ "-q" ]
|
||||||
|
|
||||||
|
# If set, given features are not used by thin driver.
|
||||||
|
# This can be helpful not just for testing, but i.e. allows to avoid
|
||||||
|
# using problematic implementation of some thin feature.
|
||||||
|
# Features:
|
||||||
|
# block_size
|
||||||
|
# discards
|
||||||
|
# discards_non_power_2
|
||||||
|
#
|
||||||
|
# thin_disabled_features = [ "discards", "block_size" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
activation {
|
activation {
|
||||||
|
@ -37,6 +37,24 @@
|
|||||||
log_error(t " segment %s of logical volume %s.", ## p, \
|
log_error(t " segment %s of logical volume %s.", ## p, \
|
||||||
dm_config_parent_name(sn), seg->lv->name), 0;
|
dm_config_parent_name(sn), seg->lv->name), 0;
|
||||||
|
|
||||||
|
/* List of features with their kernel target version */
|
||||||
|
static const struct feature {
|
||||||
|
uint32_t maj;
|
||||||
|
uint32_t min;
|
||||||
|
unsigned thin_feature;
|
||||||
|
const char *feature;
|
||||||
|
} _features[] = {
|
||||||
|
{ 1, 1, THIN_FEATURE_DISCARDS, "discards" },
|
||||||
|
{ 1, 1, THIN_FEATURE_EXTERNAL_ORIGIN, "external_origin" },
|
||||||
|
{ 1, 4, THIN_FEATURE_BLOCK_SIZE, "block_size" },
|
||||||
|
{ 1, 5, THIN_FEATURE_DISCARDS_NON_POWER_2, "discards_non_power_2" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _lvmconf[] = "global/thin_disabled_features";
|
||||||
|
/* TODO: using static field heer, maybe should be part of segment_type */
|
||||||
|
static unsigned _feature_mask;
|
||||||
|
static int _log_feature_mask;
|
||||||
|
|
||||||
static int _thin_target_present(struct cmd_context *cmd,
|
static int _thin_target_present(struct cmd_context *cmd,
|
||||||
const struct lv_segment *seg,
|
const struct lv_segment *seg,
|
||||||
unsigned *attributes);
|
unsigned *attributes);
|
||||||
@ -541,8 +559,9 @@ static int _thin_target_present(struct cmd_context *cmd,
|
|||||||
{
|
{
|
||||||
static int _checked = 0;
|
static int _checked = 0;
|
||||||
static int _present = 0;
|
static int _present = 0;
|
||||||
static int _attrs = 0;
|
static unsigned _attrs = 0;
|
||||||
uint32_t maj, min, patchlevel;
|
uint32_t maj, min, patchlevel;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
if (!_checked) {
|
if (!_checked) {
|
||||||
_present = target_present(cmd, THIN_MODULE, 1);
|
_present = target_present(cmd, THIN_MODULE, 1);
|
||||||
@ -552,35 +571,27 @@ static int _thin_target_present(struct cmd_context *cmd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maj >=1 && min >= 1)
|
for (i = 0; i < sizeof(_features)/sizeof(*_features); i++)
|
||||||
_attrs |= THIN_FEATURE_DISCARDS;
|
if (maj >= _features[i].maj && min >= _features[i].min)
|
||||||
|
_attrs |= _features[i].thin_feature;
|
||||||
else
|
else
|
||||||
/* FIXME Log this as WARNING later only if the user asked for the feature to be used but it's not present */
|
log_very_verbose("Target " THIN_MODULE " does not support %s.",
|
||||||
log_debug("Target " THIN_MODULE " does not support discards.");
|
_features[i].feature);
|
||||||
|
|
||||||
if (maj >=1 && min >= 1)
|
|
||||||
_attrs |= THIN_FEATURE_EXTERNAL_ORIGIN;
|
|
||||||
else
|
|
||||||
/* FIXME Log this as WARNING later only if the user asked for the feature to be used but it's not present */
|
|
||||||
log_debug("Target " THIN_MODULE " does not support external origins.");
|
|
||||||
|
|
||||||
if (maj >=1 && min >= 4)
|
|
||||||
_attrs |= THIN_FEATURE_BLOCK_SIZE;
|
|
||||||
else
|
|
||||||
/* FIXME Log this as WARNING later only if the user asked for the feature to be used but it's not present */
|
|
||||||
log_debug("Target " THIN_MODULE " does not support non power of 2 block sizes.");
|
|
||||||
|
|
||||||
if (maj >=1 && min >= 5)
|
|
||||||
_attrs |= THIN_FEATURE_DISCARDS_NON_POWER_2;
|
|
||||||
else
|
|
||||||
/* FIXME Log this as WARNING later only if the user asked for the feature to be used but it's not present */
|
|
||||||
log_debug("Target " THIN_MODULE " does not support discards for non power of 2 block sizes.");
|
|
||||||
|
|
||||||
_checked = 1;
|
_checked = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes)
|
if (attributes) {
|
||||||
*attributes = _attrs;
|
if (_log_feature_mask) {
|
||||||
|
for (i = 0; i < sizeof(_features)/sizeof(*_features); i++)
|
||||||
|
if ((_attrs & _features[i].thin_feature) &&
|
||||||
|
!(_feature_mask & _features[i].thin_feature))
|
||||||
|
log_very_verbose("Target "THIN_MODULE " %s support disabled by %s",
|
||||||
|
_features[i].feature, _lvmconf);
|
||||||
|
_log_feature_mask = 0; /* log just once */
|
||||||
|
}
|
||||||
|
*attributes = _attrs & _feature_mask;
|
||||||
|
}
|
||||||
|
|
||||||
return _present;
|
return _present;
|
||||||
}
|
}
|
||||||
@ -653,7 +664,11 @@ int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *segl
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct segment_type *segtype;
|
struct segment_type *segtype;
|
||||||
|
const struct dm_config_node *cn;
|
||||||
|
const struct dm_config_value *cv;
|
||||||
|
const char *str;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
unsigned mask = 0;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(reg_segtypes)/sizeof(reg_segtypes[0]); ++i) {
|
for (i = 0; i < sizeof(reg_segtypes)/sizeof(reg_segtypes[0]); ++i) {
|
||||||
segtype = dm_zalloc(sizeof(*segtype));
|
segtype = dm_zalloc(sizeof(*segtype));
|
||||||
@ -682,5 +697,29 @@ int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *segl
|
|||||||
log_very_verbose("Initialised segtype: %s", segtype->name);
|
log_very_verbose("Initialised segtype: %s", segtype->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Support runtime lvm.conf changes */
|
||||||
|
if ((cn = find_config_tree_node(cmd, _lvmconf))) {
|
||||||
|
for (cv = cn->v; cv; cv = cv->next) {
|
||||||
|
if (cv->type != DM_CFG_STRING) {
|
||||||
|
log_error("Ignoring invalid string in config file %s.",
|
||||||
|
_lvmconf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
str = cv->v.str;
|
||||||
|
if (!*str) {
|
||||||
|
log_error("Ignoring empty string in config file %s.",
|
||||||
|
_lvmconf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (i = 0; i < sizeof(_features)/sizeof(*_features); i++)
|
||||||
|
if (strcasecmp(str, _features[i].feature) == 0)
|
||||||
|
mask |= _features[i].thin_feature;
|
||||||
|
}
|
||||||
|
_log_feature_mask = (mask != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store as 'and' mask in static field */
|
||||||
|
_feature_mask = ~mask;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user