mirror of
git://sourceware.org/git/lvm2.git
synced 2025-03-10 16:58:47 +03:00
writecache: handle options from lvm.conf
User can place default settings into lvm.conf i.e.: allocation { cache_settings { writecache { block_size = 4096 } } }
This commit is contained in:
parent
8f50c5e79b
commit
c6639056e0
@ -1,5 +1,6 @@
|
|||||||
Version 2.03.15 -
|
Version 2.03.15 -
|
||||||
===================================
|
===================================
|
||||||
|
Improve support for metadata profiles for --type writecache.
|
||||||
Use cache or active DM device when available with new kernels.
|
Use cache or active DM device when available with new kernels.
|
||||||
Introduce function to utilize UUIDs from DM_DEVICE_LIST.
|
Introduce function to utilize UUIDs from DM_DEVICE_LIST.
|
||||||
Increase some hash table size to better support large device sets.
|
Increase some hash table size to better support large device sets.
|
||||||
|
314
tools/toollib.c
314
tools/toollib.c
@ -1196,159 +1196,123 @@ out:
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _get_one_writecache_setting(struct cmd_context *cmd, struct writecache_settings *settings,
|
static int _get_writecache_setting(struct cmd_context *cmd,
|
||||||
char *key, char *val, uint32_t *block_size_sectors)
|
struct dm_config_node *cn,
|
||||||
|
struct writecache_settings *settings,
|
||||||
|
uint32_t *block_size_sectors)
|
||||||
{
|
{
|
||||||
/* special case: block_size is not a setting but is set with the --cachesettings option */
|
char val[32];
|
||||||
if (!strncmp(key, "block_size", strlen("block_size"))) {
|
|
||||||
uint32_t block_size = 0;
|
|
||||||
if (sscanf(val, "%u", &block_size) != 1)
|
|
||||||
goto_bad;
|
|
||||||
if (block_size == 512)
|
|
||||||
*block_size_sectors = 1;
|
|
||||||
else if (block_size == 4096)
|
|
||||||
*block_size_sectors = 8;
|
|
||||||
else
|
|
||||||
goto_bad;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(key, "high_watermark", strlen("high_watermark"))) {
|
/* Try to find our section for given policy */
|
||||||
if (sscanf(val, "%llu", (unsigned long long *)&settings->high_watermark) != 1)
|
for (; cn; cn = cn->sib) {
|
||||||
goto_bad;
|
/* special case: block_size is not a setting but is set with the --cachesettings option */
|
||||||
if (settings->high_watermark > 100)
|
if (!strcmp(cn->key, "block_size")) {
|
||||||
goto_bad;
|
if (cn->v->type != DM_CFG_INT)
|
||||||
settings->high_watermark_set = 1;
|
goto_bad;
|
||||||
return 1;
|
if (cn->v->v.i == 512)
|
||||||
}
|
*block_size_sectors = 1;
|
||||||
|
else if (cn->v->v.i == 4096)
|
||||||
|
*block_size_sectors = 8;
|
||||||
|
else
|
||||||
|
goto_bad;
|
||||||
|
|
||||||
if (!strncmp(key, "low_watermark", strlen("low_watermark"))) {
|
} else if (!strcmp(cn->key, "high_watermark")) {
|
||||||
if (sscanf(val, "%llu", (unsigned long long *)&settings->low_watermark) != 1)
|
if (cn->v->type != DM_CFG_INT)
|
||||||
goto_bad;
|
goto_bad;
|
||||||
if (settings->low_watermark > 100)
|
settings->high_watermark = (uint64_t)cn->v->v.i;
|
||||||
goto_bad;
|
if (settings->high_watermark > 100)
|
||||||
settings->low_watermark_set = 1;
|
goto_bad;
|
||||||
return 1;
|
settings->high_watermark_set = 1;
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(key, "writeback_jobs", strlen("writeback_jobs"))) {
|
} else if (!strcmp(cn->key, "low_watermark")) {
|
||||||
if (sscanf(val, "%llu", (unsigned long long *)&settings->writeback_jobs) != 1)
|
if (cn->v->type != DM_CFG_INT)
|
||||||
goto_bad;
|
goto_bad;
|
||||||
settings->writeback_jobs_set = 1;
|
settings->low_watermark = (uint64_t)cn->v->v.i;
|
||||||
return 1;
|
if (settings->low_watermark > 100)
|
||||||
}
|
goto_bad;
|
||||||
|
settings->low_watermark_set = 1;
|
||||||
|
|
||||||
if (!strncmp(key, "autocommit_blocks", strlen("autocommit_blocks"))) {
|
} else if (!strcmp(cn->key, "writeback_jobs")) {
|
||||||
if (sscanf(val, "%llu", (unsigned long long *)&settings->autocommit_blocks) != 1)
|
if (cn->v->type != DM_CFG_INT)
|
||||||
goto_bad;
|
goto_bad;
|
||||||
settings->autocommit_blocks_set = 1;
|
settings->writeback_jobs = (uint64_t)cn->v->v.i;
|
||||||
return 1;
|
settings->writeback_jobs_set = 1;
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(key, "autocommit_time", strlen("autocommit_time"))) {
|
} else if (!strcmp(cn->key, "autocommit_blocks")) {
|
||||||
if (sscanf(val, "%llu", (unsigned long long *)&settings->autocommit_time) != 1)
|
if (cn->v->type != DM_CFG_INT)
|
||||||
goto_bad;
|
goto_bad;
|
||||||
settings->autocommit_time_set = 1;
|
settings->autocommit_blocks = (uint64_t)cn->v->v.i;
|
||||||
return 1;
|
settings->autocommit_blocks_set = 1;
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(key, "fua", strlen("fua"))) {
|
} else if (!strcmp(cn->key, "autocommit_time")) {
|
||||||
if (settings->nofua_set) {
|
if (cn->v->type != DM_CFG_INT)
|
||||||
log_error("Setting fua and nofua cannot both be set.");
|
goto_bad;
|
||||||
|
settings->autocommit_time = (uint64_t)cn->v->v.i;
|
||||||
|
settings->autocommit_time_set = 1;
|
||||||
|
|
||||||
|
} else if (!strcmp(cn->key, "fua")) {
|
||||||
|
if (settings->nofua_set) {
|
||||||
|
log_error("Setting fua and nofua cannot both be set.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cn->v->type != DM_CFG_INT)
|
||||||
|
goto_bad;
|
||||||
|
settings->fua = (unsigned)cn->v->v.i;
|
||||||
|
settings->fua_set = 1;
|
||||||
|
|
||||||
|
} else if (!strcmp(cn->key, "nofua")) {
|
||||||
|
if (settings->fua_set) {
|
||||||
|
log_error("Setting fua and nofua cannot both be set.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cn->v->type != DM_CFG_INT)
|
||||||
|
goto_bad;
|
||||||
|
settings->nofua = (unsigned)cn->v->v.i;
|
||||||
|
settings->nofua_set = 1;
|
||||||
|
|
||||||
|
} else if (!strcmp(cn->key, "cleaner")) {
|
||||||
|
if (cn->v->type != DM_CFG_INT)
|
||||||
|
goto_bad;
|
||||||
|
settings->cleaner = (unsigned) cn->v->v.i;
|
||||||
|
settings->cleaner_set = 1;
|
||||||
|
|
||||||
|
} else if (!strcmp(cn->key, "max_age")) {
|
||||||
|
if (cn->v->type != DM_CFG_INT)
|
||||||
|
goto_bad;
|
||||||
|
settings->max_age = (unsigned) cn->v->v.i;
|
||||||
|
settings->max_age_set = 1;
|
||||||
|
|
||||||
|
} else if (settings->new_key) {
|
||||||
|
log_error("Setting %s is not recognized. Only one unrecognized setting is allowed.", cn->key);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (sscanf(val, "%u", &settings->fua) != 1)
|
|
||||||
goto_bad;
|
|
||||||
settings->fua_set = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(key, "nofua", strlen("nofua"))) {
|
} else {
|
||||||
if (settings->fua_set) {
|
log_warn("Unrecognized writecache setting \"%s\" may cause activation failure.", cn->key);
|
||||||
log_error("Setting fua and nofua cannot both be set.");
|
if (yes_no_prompt("Use unrecognized writecache setting? [y/n]: ") == 'n') {
|
||||||
return 0;
|
log_error("Aborting writecache conversion.");
|
||||||
}
|
|
||||||
if (sscanf(val, "%u", &settings->nofua) != 1)
|
|
||||||
goto_bad;
|
|
||||||
settings->nofua_set = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(key, "cleaner", strlen("cleaner"))) {
|
|
||||||
if (sscanf(val, "%u", &settings->cleaner) != 1)
|
|
||||||
goto_bad;
|
|
||||||
settings->cleaner_set = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(key, "max_age", strlen("max_age"))) {
|
|
||||||
if (sscanf(val, "%u", &settings->max_age) != 1)
|
|
||||||
goto_bad;
|
|
||||||
settings->max_age_set = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings->new_key) {
|
|
||||||
log_error("Setting %s is not recognized. Only one unrecognized setting is allowed.", key);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warn("Unrecognized writecache setting \"%s\" may cause activation failure.", key);
|
|
||||||
if (yes_no_prompt("Use unrecognized writecache setting? [y/n]: ") == 'n') {
|
|
||||||
log_error("Aborting writecache conversion.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warn("Using unrecognized writecache setting: %s = %s.", key, val);
|
|
||||||
|
|
||||||
settings->new_key = dm_pool_strdup(cmd->mem, key);
|
|
||||||
settings->new_val = dm_pool_strdup(cmd->mem, val);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
bad:
|
|
||||||
log_error("Invalid setting: %s", key);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_writecache_settings(struct cmd_context *cmd, struct writecache_settings *settings,
|
|
||||||
uint32_t *block_size_sectors)
|
|
||||||
{
|
|
||||||
struct arg_value_group_list *group;
|
|
||||||
const char *str;
|
|
||||||
char key[64];
|
|
||||||
char val[64];
|
|
||||||
int num;
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "grouped" means that multiple --cachesettings options can be used.
|
|
||||||
* Each option is also allowed to contain multiple key = val pairs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
dm_list_iterate_items(group, &cmd->arg_value_groups) {
|
|
||||||
if (!grouped_arg_is_set(group->arg_values, cachesettings_ARG))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(str = grouped_arg_str_value(group->arg_values, cachesettings_ARG, NULL)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
pos = 0;
|
|
||||||
|
|
||||||
while (pos < strlen(str)) {
|
|
||||||
/* scan for "key1=val1 key2 = val2 key3= val3" */
|
|
||||||
|
|
||||||
memset(key, 0, sizeof(key));
|
|
||||||
memset(val, 0, sizeof(val));
|
|
||||||
|
|
||||||
if (sscanf(str + pos, " %63[^=]=%63s %n", key, val, &num) != 2) {
|
|
||||||
log_error("Invalid setting at: %s", str+pos);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += num;
|
settings->new_key = dm_pool_strdup(cmd->mem, cn->key);
|
||||||
|
switch (cn->v->type) {
|
||||||
|
case DM_CFG_INT:
|
||||||
|
snprintf(val, sizeof(val), FMTd64, cn->v->v.i);
|
||||||
|
settings->new_val = dm_pool_strdup(cmd->mem, val);
|
||||||
|
break;
|
||||||
|
case DM_CFG_STRING:
|
||||||
|
settings->new_val = dm_pool_strdup(cmd->mem, cn->v->v.str);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_error("Unsupported unrecognized setting %s value.", cn->key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!settings->new_key || !settings->new_val) {
|
||||||
|
log_error("Failed to copy unrecognized setting %s.", cn->key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_get_one_writecache_setting(cmd, settings, key, val, block_size_sectors))
|
log_warn("Using unrecognized writecache setting: %s = %s.",
|
||||||
return_0;
|
settings->new_key, settings->new_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1359,6 +1323,76 @@ int get_writecache_settings(struct cmd_context *cmd, struct writecache_settings
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
log_error("Invalid setting: %s", cn->key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_writecache_settings(struct cmd_context *cmd, struct writecache_settings *settings,
|
||||||
|
uint32_t *block_size_sectors)
|
||||||
|
{
|
||||||
|
struct arg_value_group_list *group;
|
||||||
|
struct dm_config_tree *result = NULL, *prev = NULL, *current = NULL;
|
||||||
|
const struct dm_config_node *cns, *cn;
|
||||||
|
int ok = 0;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "grouped" means that multiple --cachesettings options can be used.
|
||||||
|
* Each option is also allowed to contain multiple key = val pairs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
dm_list_iterate_items(group, &cmd->arg_value_groups) {
|
||||||
|
if (!grouped_arg_is_set(group->arg_values, cachesettings_ARG))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(current = dm_config_create()))
|
||||||
|
goto_out;
|
||||||
|
if (prev)
|
||||||
|
current->cascade = prev;
|
||||||
|
prev = current;
|
||||||
|
|
||||||
|
if (!(str = grouped_arg_str_value(group->arg_values, cachesettings_ARG, NULL)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!dm_config_parse_without_dup_node_check(current, str, str + strlen(str)))
|
||||||
|
goto_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current) {
|
||||||
|
if (!(result = dm_config_flatten(current)))
|
||||||
|
goto_out;
|
||||||
|
if (!_get_writecache_setting(cmd, result->root, settings, block_size_sectors))
|
||||||
|
goto_out;
|
||||||
|
|
||||||
|
} else if ((cns = find_config_tree_node(cmd, allocation_cache_settings_CFG_SECTION, NULL))) {
|
||||||
|
/* Fallback to lvm.conf cache settings for 'writecache{}' */
|
||||||
|
/* TODO: support profiles */
|
||||||
|
for (cn = cns->child; cn; cn = cn->sib) {
|
||||||
|
if (!cn->child)
|
||||||
|
continue; /* Ignore section without settings */
|
||||||
|
|
||||||
|
if (cn->v || strcmp(cn->key, "writecache") != 0)
|
||||||
|
continue; /* Ignore non-matching settings */
|
||||||
|
|
||||||
|
if (!_get_writecache_setting(cmd, cn->child, settings, block_size_sectors))
|
||||||
|
goto_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = 1;
|
||||||
|
out:
|
||||||
|
if (result)
|
||||||
|
dm_config_destroy(result);
|
||||||
|
|
||||||
|
while (prev) {
|
||||||
|
current = prev->cascade;
|
||||||
|
dm_config_destroy(prev);
|
||||||
|
prev = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME move to lib */
|
/* FIXME move to lib */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user