mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-03 05:18:29 +03:00
cache: new API for libdm
This commit is contained in:
parent
824019531c
commit
3e230a8ad8
@ -38,8 +38,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
|
||||
uint32_t chunk_size;
|
||||
struct logical_volume *data_lv, *meta_lv;
|
||||
const char *str = NULL;
|
||||
char *argv_str;
|
||||
struct dm_pool *mem = seg->lv->vg->vgmem; //FIXME: what mempool should be used?
|
||||
struct dm_pool *mem = seg->lv->vg->vgmem;
|
||||
|
||||
if (!dm_config_has_node(sn, "data"))
|
||||
return SEG_LOG_ERROR("Cache data not specified in");
|
||||
@ -62,7 +61,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
|
||||
|
||||
/*
|
||||
* Read in features:
|
||||
* cache_mode = {writethrough|writeback}
|
||||
* cache_mode = {passthrough|writethrough|writeback}
|
||||
*
|
||||
* 'cache_mode' does not have to be present.
|
||||
*/
|
||||
@ -74,76 +73,30 @@ static int _cache_pool_text_import(struct lv_segment *seg,
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in core arguments (these are key/value pairs)
|
||||
* core_argc = <# args>
|
||||
* core_argv = "[<key> <value>]..."
|
||||
* Read in policy args:
|
||||
* mq {
|
||||
* migration_threshold=2048
|
||||
* sequention_threashold=100
|
||||
* random_threashold=200
|
||||
* read_promote_adjustment=10
|
||||
* write_promote_adjustment=20
|
||||
* discard_promote_adjustment=40
|
||||
*
|
||||
* 'core_argc' does not have to be present. If it is not present,
|
||||
* any other core_* fields are ignored. If it is present, then
|
||||
* 'core_argv' must be present - even if they are
|
||||
* 'core_argc = 0' and 'core_argv = ""'.
|
||||
*/
|
||||
if (dm_config_has_node(sn, "core_argc")) {
|
||||
if (!dm_config_has_node(sn, "core_argv"))
|
||||
return SEG_LOG_ERROR("not all core arguments defined in");
|
||||
|
||||
if (!dm_config_get_uint32(sn, "core_argc", &seg->core_argc))
|
||||
return SEG_LOG_ERROR("Unable to read core_argc in");
|
||||
|
||||
str = dm_config_find_str(sn, "core_argv", NULL);
|
||||
if ((str && !seg->core_argc) || (!str && seg->core_argc))
|
||||
return SEG_LOG_ERROR("core_argc and core_argv do"
|
||||
" not match in");
|
||||
|
||||
if (!(seg->core_argv =
|
||||
dm_pool_alloc(mem, sizeof(char *) * seg->core_argc)))
|
||||
return_0;
|
||||
if (str &&
|
||||
(!(argv_str = dm_pool_strdup(mem, str)) ||
|
||||
((int)seg->core_argc != dm_split_words(argv_str, seg->core_argc,
|
||||
0, (char **) seg->core_argv))))
|
||||
return SEG_LOG_ERROR("core_argc and core_argv do"
|
||||
" not match in");
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in policy:
|
||||
* policy_name = "<policy_name>"
|
||||
* policy_argc = <# args>
|
||||
* policy_argv = "[<key> <value>]..."
|
||||
* <key> = <value>
|
||||
* <key> = <value>
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* 'policy_name' does not have to be present. If it is not present,
|
||||
* any other policy_* fields are ignored. If it is present, then
|
||||
* the other policy_* fields must be present - even if they are
|
||||
* 'policy_argc = 0' and 'policy_argv = ""'.
|
||||
* If the policy is not present, default policy is used.
|
||||
*/
|
||||
if (dm_config_has_node(sn, "policy_name")) {
|
||||
if (!dm_config_has_node(sn, "policy_argc") ||
|
||||
!dm_config_has_node(sn, "policy_argv"))
|
||||
return SEG_LOG_ERROR("not all policy arguments defined in");
|
||||
if (!(str = dm_config_find_str(sn, "policy_name", NULL)))
|
||||
return SEG_LOG_ERROR("policy_name must be a string in");
|
||||
seg->policy_name = dm_pool_strdup(mem, str);
|
||||
for (; sn; sn = sn->sib)
|
||||
if (!sn->v) {
|
||||
if (seg->policy_args)
|
||||
return SEG_LOG_ERROR("only a singly policy is supported for");
|
||||
|
||||
if (!dm_config_get_uint32(sn, "policy_argc", &seg->policy_argc))
|
||||
return SEG_LOG_ERROR("Unable to read policy_argc in");
|
||||
|
||||
str = dm_config_find_str(sn, "policy_argv", NULL);
|
||||
if ((str && !seg->policy_argc) || (!str && seg->policy_argc))
|
||||
return SEG_LOG_ERROR("policy_argc and policy_argv do"
|
||||
" not match in");
|
||||
|
||||
if (!(seg->policy_argv =
|
||||
dm_pool_alloc(mem, sizeof(char *) * seg->policy_argc)))
|
||||
return_0;
|
||||
if (str &&
|
||||
(!(argv_str = dm_pool_strdup(mem, str)) ||
|
||||
((int)seg->policy_argc != dm_split_words(argv_str,
|
||||
seg->policy_argc,
|
||||
0, (char **) seg->policy_argv))))
|
||||
return SEG_LOG_ERROR("policy_argc and policy_argv do"
|
||||
" not match in");
|
||||
}
|
||||
if (!(seg->policy_args = dm_config_clone_node_with_mem(mem, sn, 0)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!attach_pool_data_lv(seg, data_lv))
|
||||
return_0;
|
||||
@ -165,8 +118,6 @@ static int _cache_pool_text_import_area_count(const struct dm_config_node *sn,
|
||||
static int _cache_pool_text_export(const struct lv_segment *seg,
|
||||
struct formatter *f)
|
||||
{
|
||||
unsigned i;
|
||||
char buf[256]; //FIXME: IS THERE AN 'outf' THAT DOESN'T DO NEWLINE?!?
|
||||
const char *cache_mode;
|
||||
|
||||
if (!(cache_mode = get_cache_pool_cachemode_name(seg)))
|
||||
@ -177,22 +128,8 @@ static int _cache_pool_text_export(const struct lv_segment *seg,
|
||||
outf(f, "chunk_size = %" PRIu32, seg->chunk_size);
|
||||
outf(f, "cache_mode = \"%s\"", cache_mode);
|
||||
|
||||
if (seg->core_argc) {
|
||||
outf(f, "core_argc = %u", seg->core_argc);
|
||||
outf(f, "core_argv = \"");
|
||||
for (i = 0; i < seg->core_argc; i++)
|
||||
outf(f, "%s%s", i ? " " : "", seg->core_argv[i]);
|
||||
outf(f, "\"");
|
||||
}
|
||||
|
||||
if (seg->policy_name) {
|
||||
outf(f, "policy_name = \"%s\"", seg->policy_name);
|
||||
outf(f, "policy_argc = %u", seg->policy_argc);
|
||||
buf[0] = '\0';
|
||||
for (i = 0; i < seg->policy_argc; i++)
|
||||
sprintf(buf, "%s%s", i ? " " : "", seg->policy_argv[i]);
|
||||
outf(f, "policy_argv = \"%s\"", buf);
|
||||
}
|
||||
if (seg->policy_args)
|
||||
out_config_node(f, seg->policy_args);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -284,6 +221,12 @@ static int _cache_text_import(struct lv_segment *seg,
|
||||
|
||||
if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0))
|
||||
return_0;
|
||||
|
||||
seg->cleaner_policy = 0;
|
||||
if (dm_config_has_node(sn, "cleaner") &&
|
||||
!dm_config_get_uint32(sn, "cleaner", &seg->cleaner_policy))
|
||||
return SEG_LOG_ERROR("Could not read cache cleaner in");
|
||||
|
||||
if (!attach_pool_lv(seg, pool_lv, NULL, NULL))
|
||||
return_0;
|
||||
|
||||
@ -306,6 +249,9 @@ static int _cache_text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
outf(f, "cache_pool = \"%s\"", seg->pool_lv->name);
|
||||
outf(f, "origin = \"%s\"", seg_lv(seg, 0)->name);
|
||||
|
||||
if (seg->cleaner_policy)
|
||||
outf(f, "cleaner = 1");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -321,6 +267,8 @@ static int _cache_add_target_line(struct dev_manager *dm,
|
||||
{
|
||||
struct lv_segment *cache_pool_seg = first_seg(seg->pool_lv);
|
||||
char *metadata_uuid, *data_uuid, *origin_uuid;
|
||||
const char *policy_name = seg->cleaner_policy ? "cleaner" :
|
||||
cache_pool_seg->policy_args ? cache_pool_seg->policy_args->key : NULL;
|
||||
|
||||
if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv, NULL)))
|
||||
return_0;
|
||||
@ -336,12 +284,12 @@ static int _cache_add_target_line(struct dev_manager *dm,
|
||||
metadata_uuid,
|
||||
data_uuid,
|
||||
origin_uuid,
|
||||
NULL,
|
||||
cache_pool_seg->policy_name,
|
||||
seg->cleaner_policy ? NULL : cache_pool_seg->policy_args,
|
||||
policy_name,
|
||||
cache_pool_seg->chunk_size))
|
||||
return_0;
|
||||
|
||||
return add_areas_line(dm, seg, node, 0u, seg->area_count);
|
||||
return 1;
|
||||
}
|
||||
#endif /* DEVMAPPER_SUPPORT */
|
||||
|
||||
|
@ -301,19 +301,11 @@ int lv_cache_remove(struct logical_volume *cache_lv)
|
||||
dm_pool_destroy(status->mem);
|
||||
|
||||
if (!is_cleaner) {
|
||||
/* We must swap in the cleaner to flush the cache */
|
||||
/* Switch to cleaner policy to flush the cache */
|
||||
log_print_unless_silent("Flushing cache for %s.", cache_lv->name);
|
||||
|
||||
/*
|
||||
* Is there are clean way to free the memory for the name
|
||||
* and argv when changing the policy?
|
||||
*/
|
||||
cache_seg->policy_name = "cleaner";
|
||||
cache_seg->policy_argc = 0;
|
||||
cache_seg->policy_argv = NULL;
|
||||
|
||||
cache_seg->cleaner_policy = 1;
|
||||
/* update the kernel to put the cleaner policy in place */
|
||||
if (!lv_update_and_reload(cache_lv))
|
||||
if (!lv_update_and_reload_origin(cache_lv))
|
||||
return_0;
|
||||
}
|
||||
|
||||
|
@ -425,15 +425,12 @@ struct lv_segment {
|
||||
thin_discards_t discards; /* For thin_pool */
|
||||
struct dm_list thin_messages; /* For thin_pool */
|
||||
struct logical_volume *external_lv; /* For thin */
|
||||
struct logical_volume *pool_lv; /* For thin */
|
||||
struct logical_volume *pool_lv; /* For thin, cache */
|
||||
uint32_t device_id; /* For thin, 24bit */
|
||||
|
||||
uint32_t feature_flags; /* For cache */
|
||||
unsigned core_argc; /* For cache */
|
||||
const char **core_argv; /* For cache */
|
||||
const char *policy_name; /* For cache */
|
||||
unsigned policy_argc; /* For cache */
|
||||
const char **policy_argv; /* For cache */
|
||||
uint64_t feature_flags; /* For cache_pool */
|
||||
struct dm_config_node *policy_args; /* For cache_pool (-> policy_name) */
|
||||
unsigned cleaner_policy; /* For cache */
|
||||
|
||||
struct logical_volume *replicator;/* For replicator-devs - link to replicator LV */
|
||||
struct logical_volume *rlog_lv; /* For replicators */
|
||||
@ -851,7 +848,7 @@ struct lvcreate_params {
|
||||
uint32_t min_recovery_rate; /* RAID */
|
||||
uint32_t max_recovery_rate; /* RAID */
|
||||
|
||||
uint32_t feature_flags; /* cache */
|
||||
uint64_t feature_flags; /* cache */
|
||||
|
||||
const struct segment_type *segtype; /* all */
|
||||
unsigned target_attr; /* all */
|
||||
|
@ -48,7 +48,7 @@ struct lvconvert_params {
|
||||
uint32_t stripes;
|
||||
uint32_t stripe_size;
|
||||
uint32_t read_ahead;
|
||||
uint32_t feature_flags; /* cache_pool */
|
||||
uint64_t feature_flags; /* cache_pool */
|
||||
|
||||
const struct segment_type *segtype;
|
||||
unsigned target_attr;
|
||||
|
Loading…
Reference in New Issue
Block a user