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 -
|
Version 2.02.169 -
|
||||||
=====================================
|
=====================================
|
||||||
|
Add option for lvcreate/lvconvert --cachemetadataformat auto|1|2.
|
||||||
Support cache segment with configurable metadata format.
|
Support cache segment with configurable metadata format.
|
||||||
Add allocation/cache_metadata_format profilable setttings.
|
Add allocation/cache_metadata_format profilable setttings.
|
||||||
Use function cache_set_params() for both lvcreate and lvconvert.
|
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;
|
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,
|
int cache_set_policy(struct lv_segment *seg, const char *name,
|
||||||
const struct dm_config_tree *settings)
|
const struct dm_config_tree *settings)
|
||||||
{
|
{
|
||||||
@ -773,12 +793,85 @@ out:
|
|||||||
return r;
|
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
|
* Universal 'wrapper' function do-it-all
|
||||||
* to update all commonly specified cache parameters
|
* to update all commonly specified cache parameters
|
||||||
*/
|
*/
|
||||||
int cache_set_params(struct lv_segment *seg,
|
int cache_set_params(struct lv_segment *seg,
|
||||||
uint32_t chunk_size,
|
uint32_t chunk_size,
|
||||||
|
cache_metadata_format_t format,
|
||||||
cache_mode_t mode,
|
cache_mode_t mode,
|
||||||
const char *policy_name,
|
const char *policy_name,
|
||||||
const struct dm_config_tree *policy_settings)
|
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 lv_segment *pool_seg;
|
||||||
struct cmd_context *cmd = seg->lv->vg->cmd;
|
struct cmd_context *cmd = seg->lv->vg->cmd;
|
||||||
|
|
||||||
|
if (!cache_set_metadata_format(seg, format))
|
||||||
|
return_0;
|
||||||
|
|
||||||
if (!cache_set_cache_mode(seg, mode))
|
if (!cache_set_cache_mode(seg, mode))
|
||||||
return_0;
|
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 (lv_is_cache_pool(lv)) {
|
||||||
if (!cache_set_params(first_seg(lv),
|
if (!cache_set_params(first_seg(lv),
|
||||||
lp->chunk_size,
|
lp->chunk_size,
|
||||||
|
lp->cache_metadata_format,
|
||||||
lp->cache_mode,
|
lp->cache_mode,
|
||||||
lp->policy_name,
|
lp->policy_name,
|
||||||
lp->policy_settings)) {
|
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),
|
if (!cache_set_params(first_seg(lv),
|
||||||
lp->chunk_size,
|
lp->chunk_size,
|
||||||
|
lp->cache_metadata_format,
|
||||||
lp->cache_mode,
|
lp->cache_mode,
|
||||||
lp->policy_name,
|
lp->policy_name,
|
||||||
lp->policy_settings))
|
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);
|
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 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_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,
|
int cache_set_policy(struct lv_segment *cache_seg, const char *name,
|
||||||
const struct dm_config_tree *settings);
|
const struct dm_config_tree *settings);
|
||||||
int cache_set_params(struct lv_segment *seg,
|
int cache_set_params(struct lv_segment *seg,
|
||||||
uint32_t chunk_size,
|
uint32_t chunk_size,
|
||||||
|
cache_metadata_format_t format,
|
||||||
cache_mode_t mode,
|
cache_mode_t mode,
|
||||||
const char *policy_name,
|
const char *policy_name,
|
||||||
const struct dm_config_tree *policy_settings);
|
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)
|
static int _lvchange_cache(struct cmd_context *cmd, struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
|
cache_metadata_format_t format;
|
||||||
cache_mode_t mode;
|
cache_mode_t mode;
|
||||||
const char *name;
|
const char *name;
|
||||||
struct dm_config_tree *settings = NULL;
|
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))
|
if (lv_is_cache(lv))
|
||||||
pool_seg = first_seg(pool_seg->pool_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;
|
goto_out;
|
||||||
|
|
||||||
if ((mode != CACHE_MODE_UNSELECTED) &&
|
if ((mode != CACHE_MODE_UNSELECTED) &&
|
||||||
|
@ -2679,6 +2679,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
|
|||||||
uint32_t meta_extents;
|
uint32_t meta_extents;
|
||||||
uint32_t chunk_size;
|
uint32_t chunk_size;
|
||||||
int chunk_calc;
|
int chunk_calc;
|
||||||
|
cache_metadata_format_t cache_metadata_format;
|
||||||
cache_mode_t cache_mode;
|
cache_mode_t cache_mode;
|
||||||
const char *policy_name;
|
const char *policy_name;
|
||||||
struct dm_config_tree *policy_settings = NULL;
|
struct dm_config_tree *policy_settings = NULL;
|
||||||
@ -2795,7 +2796,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
|
|||||||
goto_bad;
|
goto_bad;
|
||||||
|
|
||||||
if (to_cachepool &&
|
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;
|
goto_bad;
|
||||||
|
|
||||||
if (metadata_lv)
|
if (metadata_lv)
|
||||||
@ -3020,7 +3021,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
|
|||||||
|
|
||||||
/* Apply settings to the new pool seg */
|
/* Apply settings to the new pool seg */
|
||||||
if (to_cachepool) {
|
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;
|
goto_bad;
|
||||||
} else {
|
} else {
|
||||||
seg->transaction_id = 0;
|
seg->transaction_id = 0;
|
||||||
@ -3127,6 +3128,7 @@ static int _lvconvert_to_cache_vol(struct cmd_context *cmd,
|
|||||||
{
|
{
|
||||||
struct logical_volume *cache_lv;
|
struct logical_volume *cache_lv;
|
||||||
uint32_t chunk_size = 0;
|
uint32_t chunk_size = 0;
|
||||||
|
cache_metadata_format_t cache_metadata_format;
|
||||||
cache_mode_t cache_mode;
|
cache_mode_t cache_mode;
|
||||||
const char *policy_name;
|
const char *policy_name;
|
||||||
struct dm_config_tree *policy_settings = NULL;
|
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))
|
if (!validate_lv_cache_create_pool(cachepool_lv))
|
||||||
return_0;
|
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;
|
goto_bad;
|
||||||
|
|
||||||
if (!archive(lv->vg))
|
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)))
|
if (!(cache_lv = lv_cache_create(cachepool_lv, lv)))
|
||||||
goto_bad;
|
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;
|
goto_bad;
|
||||||
|
|
||||||
if (!lv_update_and_reload(cache_lv))
|
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,
|
if (!get_cache_params(cmd,
|
||||||
&lp->chunk_size,
|
&lp->chunk_size,
|
||||||
|
&lp->cache_metadata_format,
|
||||||
&lp->cache_mode,
|
&lp->cache_mode,
|
||||||
&lp->policy_name,
|
&lp->policy_name,
|
||||||
&lp->policy_settings))
|
&lp->policy_settings))
|
||||||
@ -787,6 +788,7 @@ static int _lvcreate_params(struct cmd_context *cmd,
|
|||||||
type_ARG
|
type_ARG
|
||||||
|
|
||||||
#define CACHE_POOL_ARGS \
|
#define CACHE_POOL_ARGS \
|
||||||
|
cachemetadataformat_ARG,\
|
||||||
cachemode_ARG,\
|
cachemode_ARG,\
|
||||||
cachepool_ARG,\
|
cachepool_ARG,\
|
||||||
cachepolicy_ARG,\
|
cachepolicy_ARG,\
|
||||||
|
@ -1343,6 +1343,7 @@ static int _validate_cachepool_params(const char *name,
|
|||||||
|
|
||||||
int get_cache_params(struct cmd_context *cmd,
|
int get_cache_params(struct cmd_context *cmd,
|
||||||
uint32_t *chunk_size,
|
uint32_t *chunk_size,
|
||||||
|
cache_metadata_format_t *cache_metadata_format,
|
||||||
cache_mode_t *cache_mode,
|
cache_mode_t *cache_mode,
|
||||||
const char **name,
|
const char **name,
|
||||||
struct dm_config_tree **settings)
|
struct dm_config_tree **settings)
|
||||||
@ -1363,6 +1364,9 @@ int get_cache_params(struct cmd_context *cmd,
|
|||||||
display_size(cmd, *chunk_size));
|
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);
|
*cache_mode = (cache_mode_t) arg_uint_value(cmd, cachemode_ARG, CACHE_MODE_UNSELECTED);
|
||||||
|
|
||||||
*name = arg_str_value(cmd, cachepolicy_ARG, NULL);
|
*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,
|
int get_cache_params(struct cmd_context *cmd,
|
||||||
uint32_t *chunk_size,
|
uint32_t *chunk_size,
|
||||||
|
cache_metadata_format_t *format,
|
||||||
cache_mode_t *cache_mode,
|
cache_mode_t *cache_mode,
|
||||||
const char **name,
|
const char **name,
|
||||||
struct dm_config_tree **settings);
|
struct dm_config_tree **settings);
|
||||||
|
Loading…
Reference in New Issue
Block a user