diff options
author | Zdenek Kabelac <zkabelac@redhat.com> | 2015-08-11 14:01:12 +0200 |
---|---|---|
committer | Zdenek Kabelac <zkabelac@redhat.com> | 2015-08-12 14:32:24 +0200 |
commit | f0c18fceb43d77b0a79685fc7b1c8bbe64df7e97 (patch) | |
tree | 0d518cbc849b52b5ccf06a8a8572f78ae448e868 | |
parent | 22a1337a9ba1ebf73c3f0b27f621d9d8917bf6cf (diff) | |
download | lvm2-f0c18fceb43d77b0a79685fc7b1c8bbe64df7e97.tar.gz |
cache: api update
Change logic and naming of some internal API functions.
cache_set_mode() and cache_set_policy() both take segment.
cache mode is now correctly 'masked-in'.
If the passed segment is 'cache' segment - it will automatically
try to find 'defaults' according to profiles if the are NOT
specified on command line or they are NOT already set for cache-pool.
These defaults are never set for cache-pool.
-rw-r--r-- | WHATS_NEW | 1 | ||||
-rw-r--r-- | lib/cache_segtype/cache.c | 51 | ||||
-rw-r--r-- | lib/metadata/cache_manip.c | 129 | ||||
-rw-r--r-- | lib/metadata/lv.c | 2 | ||||
-rw-r--r-- | lib/metadata/lv_manip.c | 31 | ||||
-rw-r--r-- | lib/metadata/metadata-exported.h | 9 | ||||
-rw-r--r-- | lib/report/report.c | 2 | ||||
-rw-r--r-- | tools/lvchange.c | 2 | ||||
-rw-r--r-- | tools/lvconvert.c | 8 |
9 files changed, 165 insertions, 70 deletions
@@ -1,5 +1,6 @@ Version 2.02.128 - =================================== + Enhance internal API cache_set_mode() and cache_set_policy(). Enhance toollib's get_cache_params(). Runtime detect presence of cache smq policy. Add demo cache-mq and cache-smq profiles. diff --git a/lib/cache_segtype/cache.c b/lib/cache_segtype/cache.c index 93436a31c..052617317 100644 --- a/lib/cache_segtype/cache.c +++ b/lib/cache_segtype/cache.c @@ -71,23 +71,15 @@ static int _cache_pool_text_import(struct lv_segment *seg, if (dm_config_has_node(sn, "cache_mode")) { if (!(str = dm_config_find_str(sn, "cache_mode", NULL))) return SEG_LOG_ERROR("cache_mode must be a string in"); - if (!set_cache_pool_feature(&seg->feature_flags, str)) + if (!cache_set_mode(seg, str)) return SEG_LOG_ERROR("Unknown cache_mode in"); - } else - /* When missed in metadata, it's an old stuff - use writethrough */ - seg->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH; + } if (dm_config_has_node(sn, "policy")) { if (!(str = dm_config_find_str(sn, "policy", NULL))) return SEG_LOG_ERROR("policy must be a string in"); if (!(seg->policy_name = dm_pool_strdup(mem, str))) return SEG_LOG_ERROR("Failed to duplicate policy in"); - } else { - /* Cannot use 'just' default, so pick one */ - seg->policy_name = DEFAULT_CACHE_POLICY; /* FIXME make configurable */ - /* FIXME maybe here should be always 'mq' */ - log_warn("WARNING: cache_policy undefined, using default \"%s\" policy.", - seg->policy_name); } /* @@ -136,28 +128,33 @@ static int _cache_pool_text_export(const struct lv_segment *seg, { const char *cache_mode; - if (!(cache_mode = get_cache_pool_cachemode_name(seg))) - return_0; - - if (!seg->policy_name) { - log_error(INTERNAL_ERROR "Policy name for %s is not defined.", - display_lvname(seg->lv)); - return 0; - } - outf(f, "data = \"%s\"", seg_lv(seg, 0)->name); outf(f, "metadata = \"%s\"", seg->metadata_lv->name); outf(f, "chunk_size = %" PRIu32, seg->chunk_size); - outf(f, "cache_mode = \"%s\"", cache_mode); - outf(f, "policy = \"%s\"", seg->policy_name); - if (seg->policy_settings) { - if (strcmp(seg->policy_settings->key, "policy_settings")) { - log_error(INTERNAL_ERROR "Incorrect policy_settings tree, %s.", - seg->policy_settings->key); - return 0; + /* + * Cache pool used by a cache LV holds data. Not ideal, + * but not worth to break backward compatibility, by shifting + * content to cache segment + */ + if (cache_mode_is_set(seg)) { + if (!(cache_mode = get_cache_mode_name(seg))) + return_0; + outf(f, "cache_mode = \"%s\"", cache_mode); + } + + if (seg->policy_name) { + outf(f, "policy = \"%s\"", seg->policy_name); + + if (seg->policy_settings) { + if (strcmp(seg->policy_settings->key, "policy_settings")) { + log_error(INTERNAL_ERROR "Incorrect policy_settings tree, %s.", + seg->policy_settings->key); + return 0; + } + if (seg->policy_settings->child) + out_config_node(f, seg->policy_settings); } - out_config_node(f, seg->policy_settings); } return 1; diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c index 91fcd3b2e..fbd066366 100644 --- a/lib/metadata/cache_manip.c +++ b/lib/metadata/cache_manip.c @@ -29,7 +29,17 @@ #define DM_HINT_OVERHEAD_PER_BLOCK 8 /* bytes */ #define DM_MAX_HINT_WIDTH (4+16) /* bytes. FIXME Configurable? */ -const char *get_cache_pool_cachemode_name(const struct lv_segment *seg) +int cache_mode_is_set(const struct lv_segment *seg) +{ + if (seg_is_cache(seg)) + seg = first_seg(seg->pool_lv); + + return (seg->feature_flags & (DM_CACHE_FEATURE_WRITEBACK | + DM_CACHE_FEATURE_WRITETHROUGH | + DM_CACHE_FEATURE_PASSTHROUGH)) ? 1 : 0; +} + +const char *get_cache_mode_name(const struct lv_segment *seg) { if (seg->feature_flags & DM_CACHE_FEATURE_WRITEBACK) return "writeback"; @@ -46,19 +56,48 @@ const char *get_cache_pool_cachemode_name(const struct lv_segment *seg) return NULL; } -int set_cache_pool_feature(uint64_t *feature_flags, const char *str) +int cache_set_mode(struct lv_segment *seg, const char *str) { + struct cmd_context *cmd = seg->lv->vg->cmd; + int id; + uint64_t mode; + + if (!str && !seg_is_cache(seg)) + return 1; /* Defaults only for cache */ + + if (seg_is_cache(seg)) + seg = first_seg(seg->pool_lv); + + if (!str) { + if (cache_mode_is_set(seg)) + return 1; /* Default already set in cache pool */ + + id = allocation_cache_mode_CFG; + + /* If present, check backward compatible settings */ + if (!find_config_node(cmd, cmd->cft, id) && + find_config_node(cmd, cmd->cft, allocation_cache_pool_cachemode_CFG)) + id = allocation_cache_pool_cachemode_CFG; + + str = find_config_tree_str(cmd, id, NULL); + } + if (!strcmp(str, "writeback")) - *feature_flags |= DM_CACHE_FEATURE_WRITEBACK; + mode = DM_CACHE_FEATURE_WRITEBACK; else if (!strcmp(str, "writethrough")) - *feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH; - else if (!strcmp(str, "passhrough")) - *feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH; + mode = DM_CACHE_FEATURE_WRITETHROUGH; + else if (!strcmp(str, "passthrough")) + mode = DM_CACHE_FEATURE_PASSTHROUGH; else { - log_error("Cache pool feature \"%s\" is unknown.", str); + log_error("Cannot set unknown cache mode \"%s\".", str); return 0; } + seg->feature_flags &= ~(DM_CACHE_FEATURE_WRITEBACK | + DM_CACHE_FEATURE_WRITETHROUGH | + DM_CACHE_FEATURE_PASSTHROUGH); + seg->feature_flags |= mode; + return 1; } @@ -395,36 +434,72 @@ int lv_is_cache_origin(const struct logical_volume *lv) return seg && lv_is_cache(seg->lv) && !lv_is_pending_delete(seg->lv) && (seg_lv(seg, 0) == lv); } -int lv_cache_set_policy(struct logical_volume *lv, const char *name, - const struct dm_config_tree *settings) +int cache_set_policy(struct lv_segment *seg, const char *name, + const struct dm_config_tree *settings) { struct dm_config_node *cn; + const struct dm_config_node *cns; struct dm_config_tree *old = NULL, *new = NULL, *tmp = NULL; int r = 0; - struct lv_segment *seg = first_seg(lv); + const int passed_seg_is_cache = seg_is_cache(seg); - if (lv_is_cache(lv)) + if (passed_seg_is_cache) seg = first_seg(seg->pool_lv); - if (seg->policy_settings) { - if (!(old = dm_config_create())) - goto_out; - if (!(new = dm_config_create())) - goto_out; - new->root = settings->root; - old->root = seg->policy_settings; - new->cascade = old; - if (!(tmp = dm_config_flatten(new))) + if (name) { + if (!(seg->policy_name = dm_pool_strdup(seg->lv->vg->vgmem, name))) { + log_error("Failed to duplicate policy name."); + return 0; + } + } else if (!seg->policy_name && passed_seg_is_cache) + seg->policy_name = find_config_tree_str(seg->lv->vg->cmd, allocation_cache_policy_CFG, NULL); + + if (settings) { + if (!seg->policy_name) { + log_error(INTERNAL_ERROR "Can't set policy settings without policy name."); + return 0; + } + + if (seg->policy_settings) { + if (!(old = dm_config_create())) + goto_out; + if (!(new = dm_config_create())) + goto_out; + new->root = settings->root; + old->root = seg->policy_settings; + new->cascade = old; + if (!(tmp = dm_config_flatten(new))) + goto_out; + } + + if ((cn = dm_config_find_node((tmp) ? tmp->root : settings->root, "policy_settings")) && + !(seg->policy_settings = dm_config_clone_node_with_mem(seg->lv->vg->vgmem, cn, 0))) goto_out; - } + } else if (passed_seg_is_cache && /* Look for command's profile cache_policies */ + (cns = find_config_tree_node(seg->lv->vg->cmd, allocation_cache_settings_CFG_SECTION, NULL))) { + /* Try to find our section for given policy */ + for (cn = cns->child; cn; cn = cn->sib) { + /* Only matching section names */ + if (cn->v || strcmp(cn->key, seg->policy_name) != 0) + continue; + + if (!cn->child) + break; + + if (!(new = dm_config_create())) + goto_out; - if ((cn = dm_config_find_node((tmp) ? tmp->root : settings->root, "policy_settings")) && - !(seg->policy_settings = dm_config_clone_node_with_mem(lv->vg->vgmem, cn, 0))) - goto_out; + if (!(new->root = dm_config_clone_node_with_mem(new->mem, + cn->child, 1))) + goto_out; - if (name && !(seg->policy_name = dm_pool_strdup(lv->vg->vgmem, name))) { - log_error("Failed to duplicate policy name."); - goto out; + if (!(seg->policy_settings = dm_config_create_node(new, "policy_settings"))) + goto_out; + + seg->policy_settings->child = new->root; + + break; /* Only first match counts */ + } } restart: /* remove any 'default" nodes */ diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c index df784c173..c775077b5 100644 --- a/lib/metadata/lv.c +++ b/lib/metadata/lv.c @@ -131,7 +131,7 @@ char *lvseg_discards_dup(struct dm_pool *mem, const struct lv_segment *seg) char *lvseg_cachemode_dup(struct dm_pool *mem, const struct lv_segment *seg) { - const char *name = get_cache_pool_cachemode_name(seg); + const char *name = get_cache_mode_name(seg); if (!name) return_NULL; diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index b22773e5b..f13df1b2b 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -7264,17 +7264,26 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, memlock_unlock(vg->cmd); if (seg_is_cache_pool(lp) || seg_is_cache(lp)) { - pool_lv = pool_lv ? : lv; - if (!lv_cache_set_policy(pool_lv, lp->policy_name, lp->policy_settings)) - return_NULL; /* revert? */ - first_seg(pool_lv)->chunk_size = lp->chunk_size; - first_seg(pool_lv)->feature_flags = lp->feature_flags; - /* TODO: some calc_policy solution for cache ? */ - if (!recalculate_pool_chunk_size_with_dev_hints(pool_lv, lp->passed_args, - THIN_CHUNK_SIZE_CALC_METHOD_GENERIC)) { + if (!cache_set_mode(first_seg(lv), lp->cache_mode)) { + stack; + goto revert_new_lv; + } + + if (!cache_set_policy(first_seg(lv), lp->policy_name, lp->policy_settings)) { stack; goto revert_new_lv; } + + pool_lv = pool_lv ? : lv; + if (lp->chunk_size) { + first_seg(pool_lv)->chunk_size = lp->chunk_size; + /* TODO: some calc_policy solution for cache ? */ + if (!recalculate_pool_chunk_size_with_dev_hints(pool_lv, lp->passed_args, + THIN_CHUNK_SIZE_CALC_METHOD_GENERIC)) { + stack; + goto revert_new_lv; + } + } } else if (seg_is_raid(lp)) { first_seg(lv)->min_recovery_rate = lp->min_recovery_rate; first_seg(lv)->max_recovery_rate = lp->max_recovery_rate; @@ -7478,6 +7487,12 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, } lv = tmp_lv; + if (!cache_set_mode(first_seg(lv), lp->cache_mode)) + return_NULL; /* revert? */ + + if (!cache_set_policy(first_seg(lv), lp->policy_name, lp->policy_settings)) + return_NULL; /* revert? */ + if (!lv_update_and_reload(lv)) { /* FIXME Do a better revert */ log_error("Aborting. Manual intervention required."); diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index 03a866a8a..fff24f010 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -1153,8 +1153,11 @@ struct lv_status_cache { dm_percent_t dirty_usage; }; -const char *get_cache_pool_cachemode_name(const struct lv_segment *seg); -int set_cache_pool_feature(uint64_t *feature_flags, const char *str); +const char *get_cache_mode_name(const struct lv_segment *cache_seg); +int cache_mode_is_set(const struct lv_segment *seg); +int cache_set_mode(struct lv_segment *cache_seg, const char *str); +int cache_set_policy(struct lv_segment *cache_seg, const char *name, + const struct dm_config_tree *settings); int update_cache_pool_params(const struct segment_type *segtype, struct volume_group *vg, unsigned attr, int passed_args, uint32_t pool_data_extents, @@ -1165,8 +1168,6 @@ int validate_lv_cache_create_origin(const struct logical_volume *origin_lv); struct logical_volume *lv_cache_create(struct logical_volume *pool, struct logical_volume *origin); int lv_cache_remove(struct logical_volume *cache_lv); -int lv_cache_set_policy(struct logical_volume *cache_lv, const char *name, - const struct dm_config_tree *settings); int wipe_cache_pool(struct logical_volume *cache_pool_lv); /* -- metadata/cache_manip.c */ diff --git a/lib/report/report.c b/lib/report/report.c index c2ab99105..a17af327e 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -2079,7 +2079,7 @@ static int _cachemode_disp(struct dm_report *rh, struct dm_pool *mem, seg = first_seg(seg->pool_lv); if (seg_is_cache_pool(seg)) { - if (!(cachemode_str = get_cache_pool_cachemode_name(seg))) + if (!(cachemode_str = get_cache_mode_name(seg))) return_0; return dm_report_field_string(rh, field, &cachemode_str); diff --git a/tools/lvchange.c b/tools/lvchange.c index a6ad343d3..e24c07af8 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -692,7 +692,7 @@ static int _lvchange_cachepolicy(struct cmd_context *cmd, struct logical_volume if (!get_cache_params(cmd, NULL, &name, &settings)) goto_out; - if (!lv_cache_set_policy(lv, name, settings)) + if (!cache_set_policy(first_seg(lv), name, settings)) goto_out; if (!lv_update_and_reload(lv)) goto_out; diff --git a/tools/lvconvert.c b/tools/lvconvert.c index d48af6261..040272a64 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -3070,7 +3070,7 @@ mda_write: seg->zero_new_blocks = lp->zero ? 1 : 0; if ((lp->policy_name || lp->policy_settings) && - !lv_cache_set_policy(seg->lv, lp->policy_name, lp->policy_settings)) + !cache_set_policy(seg, lp->policy_name, lp->policy_settings)) return_0; /* Rename deactivated metadata LV to have _tmeta suffix */ @@ -3178,6 +3178,12 @@ static int _lvconvert_cache(struct cmd_context *cmd, if (!(cache_lv = lv_cache_create(pool_lv, origin_lv))) return_0; + if (!cache_set_mode(first_seg(cache_lv), lp->cache_mode)) + return_0; + + if (!cache_set_policy(first_seg(cache_lv), lp->policy_name, lp->policy_settings)) + return_0; + if (!lv_update_and_reload(cache_lv)) return_0; |