summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2015-08-11 14:01:12 +0200
committerZdenek Kabelac <zkabelac@redhat.com>2015-08-12 14:32:24 +0200
commitf0c18fceb43d77b0a79685fc7b1c8bbe64df7e97 (patch)
tree0d518cbc849b52b5ccf06a8a8572f78ae448e868
parent22a1337a9ba1ebf73c3f0b27f621d9d8917bf6cf (diff)
downloadlvm2-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_NEW1
-rw-r--r--lib/cache_segtype/cache.c51
-rw-r--r--lib/metadata/cache_manip.c129
-rw-r--r--lib/metadata/lv.c2
-rw-r--r--lib/metadata/lv_manip.c31
-rw-r--r--lib/metadata/metadata-exported.h9
-rw-r--r--lib/report/report.c2
-rw-r--r--tools/lvchange.c2
-rw-r--r--tools/lvconvert.c8
9 files changed, 165 insertions, 70 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index 7c35d13e6..7fcf49a13 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -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;