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:
parent
7b748b7cb8
commit
4d2b1a0660
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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) &&
|
||||
|
@ -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))
|
||||
|
@ -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,\
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user