1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

cache: enable usage of --cachemetadataformat

lvcreate and lvconvert may select cache metadata format when caching LV.
By default lvm2 picks best available format.
This commit is contained in:
Zdenek Kabelac 2017-02-26 20:18:37 +01:00
parent 7b748b7cb8
commit 4d2b1a0660
9 changed files with 116 additions and 5 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.169 -
=====================================
Add option for lvcreate/lvconvert --cachemetadataformat auto|1|2.
Support cache segment with configurable metadata format.
Add allocation/cache_metadata_format profilable setttings.
Use function cache_set_params() for both lvcreate and lvconvert.

View File

@ -675,6 +675,26 @@ static const char *_get_default_cache_policy(struct cmd_context *cmd)
return def;
}
/* Autodetect best available cache metadata format for a user */
static cache_metadata_format_t _get_default_cache_metadata_format(struct cmd_context *cmd)
{
const struct segment_type *segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_CACHE);
unsigned attr;
cache_metadata_format_t f;
if (!segtype ||
!segtype->ops->target_present ||
!segtype->ops->target_present(cmd, NULL, &attr)) {
f = CACHE_METADATA_FORMAT_1;
log_warn("WARNING: Cannot detect default cache metadata format, using format: %u.", f);
} else {
f = (attr & CACHE_FEATURE_METADATA2) ? CACHE_METADATA_FORMAT_2 : CACHE_METADATA_FORMAT_1;
log_debug_metadata("Detected default cache metadata format: %u.", f);
}
return f;
}
int cache_set_policy(struct lv_segment *seg, const char *name,
const struct dm_config_tree *settings)
{
@ -773,12 +793,85 @@ out:
return r;
}
/*
* Sets metadata format on cache pool segment with these rules:
* 1. When 'cache-pool' segment is passed, sets only for selected formats (1 or 2).
* 2. For 'cache' segment passed in we know cache pool segment.
* When passed format is 0 (UNSELECTED) with 'cache' segment - it's the moment
* lvm2 has to figure out 'default' metadata format (1 or 2) from
* configuration or profiles.
* 3. If still unselected or selected format is != 1, figure the best supported format
* and either use it or validate users settings is possible.
*
* Reasoning: A user may create cache-pool and may or may not specify CMFormat.
* If the CMFormat has been selected (1 or 2) store this in metadata, otherwise
* for an unused cache-pool UNSELECTED CMFormat is used. When caching LV, CMFormat
* must be decided and from this moment it's always stored. To support backward
* compatibility 'CMFormat 1' is used when it is NOT specified for a cached LV in
* lvm2 metadata (no metadata_format=#F element in cache-pool segment).
*/
int cache_set_metadata_format(struct lv_segment *seg, cache_metadata_format_t format)
{
cache_metadata_format_t best;
struct profile *profile = seg->lv->profile;
if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv);
else if (seg_is_cache_pool(seg)) {
if (format == CACHE_METADATA_FORMAT_UNSELECTED)
return 1; /* Format can be selected later when caching LV */
} else {
log_error(INTERNAL_ERROR "Cannot set cache metadata format for non cache volume %s.",
display_lvname(seg->lv));
return 0;
}
/* Check if we need to search for configured cache metadata format */
if (format == CACHE_METADATA_FORMAT_UNSELECTED) {
if (seg->cache_metadata_format != CACHE_METADATA_FORMAT_UNSELECTED)
return 1; /* Format already selected in cache pool */
/* Check configurations and profiles */
format = find_config_tree_int(seg->lv->vg->cmd, allocation_cache_metadata_format_CFG,
profile);
}
/* See what is a 'best' available cache metadata format
* when the specifed format is other then always existing CMFormat 1 */
if (format != CACHE_METADATA_FORMAT_1) {
best = _get_default_cache_metadata_format(seg->lv->vg->cmd);
/* Format was not selected, so use best present on a system */
if (format == CACHE_METADATA_FORMAT_UNSELECTED)
format = best;
else if (format != best) {
/* Format is not valid (Only Format 1 or 2 is supported ATM) */
log_error("Cache metadata format %u is not supported by kernel target.", format);
return 0;
}
}
switch (format) {
case CACHE_METADATA_FORMAT_2: seg->lv->status |= LV_METADATA_FORMAT; break;
case CACHE_METADATA_FORMAT_1: seg->lv->status &= ~LV_METADATA_FORMAT; break;
default:
log_error(INTERNAL_ERROR "Invalid cache metadata format %u for cache volume %s.",
format, display_lvname(seg->lv));
return 0;
}
seg->cache_metadata_format = format;
return 1;
}
/*
* Universal 'wrapper' function do-it-all
* to update all commonly specified cache parameters
*/
int cache_set_params(struct lv_segment *seg,
uint32_t chunk_size,
cache_metadata_format_t format,
cache_mode_t mode,
const char *policy_name,
const struct dm_config_tree *policy_settings)
@ -786,6 +879,9 @@ int cache_set_params(struct lv_segment *seg,
struct lv_segment *pool_seg;
struct cmd_context *cmd = seg->lv->vg->cmd;
if (!cache_set_metadata_format(seg, format))
return_0;
if (!cache_set_cache_mode(seg, mode))
return_0;

View File

@ -7664,6 +7664,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (lv_is_cache_pool(lv)) {
if (!cache_set_params(first_seg(lv),
lp->chunk_size,
lp->cache_metadata_format,
lp->cache_mode,
lp->policy_name,
lp->policy_settings)) {
@ -7872,6 +7873,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (!cache_set_params(first_seg(lv),
lp->chunk_size,
lp->cache_metadata_format,
lp->cache_mode,
lp->policy_name,
lp->policy_settings))

View File

@ -1267,10 +1267,12 @@ const char *display_cache_mode(const struct lv_segment *seg);
const char *get_cache_mode_name(const struct lv_segment *cache_seg);
int set_cache_mode(cache_mode_t *mode, const char *cache_mode);
int cache_set_cache_mode(struct lv_segment *cache_seg, cache_mode_t mode);
int cache_set_metadata_format(struct lv_segment *cache_seg, cache_metadata_format_t format);
int cache_set_policy(struct lv_segment *cache_seg, const char *name,
const struct dm_config_tree *settings);
int cache_set_params(struct lv_segment *seg,
uint32_t chunk_size,
cache_metadata_format_t format,
cache_mode_t mode,
const char *policy_name,
const struct dm_config_tree *policy_settings);

View File

@ -622,6 +622,7 @@ static int _lvchange_persistent(struct cmd_context *cmd,
static int _lvchange_cache(struct cmd_context *cmd, struct logical_volume *lv)
{
cache_metadata_format_t format;
cache_mode_t mode;
const char *name;
struct dm_config_tree *settings = NULL;
@ -632,7 +633,7 @@ static int _lvchange_cache(struct cmd_context *cmd, struct logical_volume *lv)
if (lv_is_cache(lv))
pool_seg = first_seg(pool_seg->pool_lv);
if (!get_cache_params(cmd, &chunk_size, &mode, &name, &settings))
if (!get_cache_params(cmd, &chunk_size, &format, &mode, &name, &settings))
goto_out;
if ((mode != CACHE_MODE_UNSELECTED) &&

View File

@ -2679,6 +2679,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
uint32_t meta_extents;
uint32_t chunk_size;
int chunk_calc;
cache_metadata_format_t cache_metadata_format;
cache_mode_t cache_mode;
const char *policy_name;
struct dm_config_tree *policy_settings = NULL;
@ -2795,7 +2796,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
goto_bad;
if (to_cachepool &&
!get_cache_params(cmd, &chunk_size, &cache_mode, &policy_name, &policy_settings))
!get_cache_params(cmd, &chunk_size, &cache_metadata_format, &cache_mode, &policy_name, &policy_settings))
goto_bad;
if (metadata_lv)
@ -3020,7 +3021,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
/* Apply settings to the new pool seg */
if (to_cachepool) {
if (!cache_set_params(seg, chunk_size, cache_mode, policy_name, policy_settings))
if (!cache_set_params(seg, chunk_size, cache_metadata_format, cache_mode, policy_name, policy_settings))
goto_bad;
} else {
seg->transaction_id = 0;
@ -3127,6 +3128,7 @@ static int _lvconvert_to_cache_vol(struct cmd_context *cmd,
{
struct logical_volume *cache_lv;
uint32_t chunk_size = 0;
cache_metadata_format_t cache_metadata_format;
cache_mode_t cache_mode;
const char *policy_name;
struct dm_config_tree *policy_settings = NULL;
@ -3135,7 +3137,7 @@ static int _lvconvert_to_cache_vol(struct cmd_context *cmd,
if (!validate_lv_cache_create_pool(cachepool_lv))
return_0;
if (!get_cache_params(cmd, &chunk_size, &cache_mode, &policy_name, &policy_settings))
if (!get_cache_params(cmd, &chunk_size, &cache_metadata_format, &cache_mode, &policy_name, &policy_settings))
goto_bad;
if (!archive(lv->vg))
@ -3144,7 +3146,7 @@ static int _lvconvert_to_cache_vol(struct cmd_context *cmd,
if (!(cache_lv = lv_cache_create(cachepool_lv, lv)))
goto_bad;
if (!cache_set_params(first_seg(cache_lv), chunk_size, cache_mode, policy_name, policy_settings))
if (!cache_set_params(first_seg(cache_lv), chunk_size, cache_metadata_format, cache_mode, policy_name, policy_settings))
goto_bad;
if (!lv_update_and_reload(cache_lv))

View File

@ -645,6 +645,7 @@ static int _read_cache_params(struct cmd_context *cmd,
if (!get_cache_params(cmd,
&lp->chunk_size,
&lp->cache_metadata_format,
&lp->cache_mode,
&lp->policy_name,
&lp->policy_settings))
@ -787,6 +788,7 @@ static int _lvcreate_params(struct cmd_context *cmd,
type_ARG
#define CACHE_POOL_ARGS \
cachemetadataformat_ARG,\
cachemode_ARG,\
cachepool_ARG,\
cachepolicy_ARG,\

View File

@ -1343,6 +1343,7 @@ static int _validate_cachepool_params(const char *name,
int get_cache_params(struct cmd_context *cmd,
uint32_t *chunk_size,
cache_metadata_format_t *cache_metadata_format,
cache_mode_t *cache_mode,
const char **name,
struct dm_config_tree **settings)
@ -1363,6 +1364,9 @@ int get_cache_params(struct cmd_context *cmd,
display_size(cmd, *chunk_size));
}
*cache_metadata_format = (cache_metadata_format_t)
arg_uint_value(cmd, cachemetadataformat_ARG, CACHE_METADATA_FORMAT_UNSELECTED);
*cache_mode = (cache_mode_t) arg_uint_value(cmd, cachemode_ARG, CACHE_MODE_UNSELECTED);
*name = arg_str_value(cmd, cachepolicy_ARG, NULL);

View File

@ -221,6 +221,7 @@ int get_stripe_params(struct cmd_context *cmd, const struct segment_type *segtyp
int get_cache_params(struct cmd_context *cmd,
uint32_t *chunk_size,
cache_metadata_format_t *format,
cache_mode_t *cache_mode,
const char **name,
struct dm_config_tree **settings);