diff options
Diffstat (limited to 'tools/toollib.c')
-rw-r--r-- | tools/toollib.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/tools/toollib.c b/tools/toollib.c index ee2419b8c..86eb2d0f4 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -1414,6 +1414,174 @@ out: return ok; } + +static int _get_one_integrity_setting(struct cmd_context *cmd, struct integrity_settings *settings, + char *key, char *val) +{ + if (!strncmp(key, "mode", strlen("mode"))) { + if (*val == 'D') + settings->mode[0] = 'D'; + else if (*val == 'J') + settings->mode[0] = 'J'; + else if (*val == 'B') + settings->mode[0] = 'B'; + else if (*val == 'R') + settings->mode[0] = 'R'; + else + goto_bad; + /* lvm assigns a default if the user doesn't. */ + return 1; + } + + if (!strncmp(key, "tag_size", strlen("tag_size"))) { + if (sscanf(val, "%u", &settings->tag_size) != 1) + goto_bad; + /* lvm assigns a default if the user doesn't. */ + return 1; + } + + if (!strncmp(key, "internal_hash", strlen("internal_hash"))) { + if (!(settings->internal_hash = strdup(val))) + goto_bad; + /* lvm assigns a default if the user doesn't. */ + return 1; + } + + /* + * For the following settings, lvm does not set a default value if the + * user does not specify their own value, and lets dm-integrity use its + * own default. + */ + + if (!strncmp(key, "journal_sectors", strlen("journal_sectors"))) { + if (sscanf(val, "%u", &settings->journal_sectors) != 1) + goto_bad; + settings->journal_sectors_set = 1; + return 1; + } + + if (!strncmp(key, "interleave_sectors", strlen("interleave_sectors"))) { + if (sscanf(val, "%u", &settings->interleave_sectors) != 1) + goto_bad; + settings->interleave_sectors_set = 1; + return 1; + } + + if (!strncmp(key, "buffer_sectors", strlen("buffer_sectors"))) { + if (sscanf(val, "%u", &settings->buffer_sectors) != 1) + goto_bad; + settings->buffer_sectors_set = 1; + return 1; + } + + if (!strncmp(key, "journal_watermark", strlen("journal_watermark"))) { + if (sscanf(val, "%u", &settings->journal_watermark) != 1) + goto_bad; + settings->journal_watermark_set = 1; + return 1; + } + + if (!strncmp(key, "commit_time", strlen("commit_time"))) { + if (sscanf(val, "%u", &settings->commit_time) != 1) + goto_bad; + settings->commit_time_set = 1; + return 1; + } + + if (!strncmp(key, "block_size", strlen("block_size"))) { + if (sscanf(val, "%u", &settings->block_size) != 1) + goto_bad; + settings->block_size_set = 1; + return 1; + } + + if (!strncmp(key, "bitmap_flush_interval", strlen("bitmap_flush_interval"))) { + if (sscanf(val, "%u", &settings->bitmap_flush_interval) != 1) + goto_bad; + settings->bitmap_flush_interval_set = 1; + return 1; + } + + if (!strncmp(key, "sectors_per_bit", strlen("sectors_per_bit"))) { + if (sscanf(val, "%llu", (unsigned long long *)&settings->sectors_per_bit) != 1) + goto_bad; + settings->sectors_per_bit_set = 1; + return 1; + } + + log_error("Unknown setting: %s", key); + return 0; + + bad: + log_error("Invalid setting: %s", key); + return 0; +} + +static int _get_integrity_settings(struct cmd_context *cmd, struct integrity_settings *settings) +{ + struct arg_value_group_list *group; + const char *str; + char key[64]; + char val[64]; + int num; + int pos; + + /* + * "grouped" means that multiple --integritysettings 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, integritysettings_ARG)) + continue; + + if (!(str = grouped_arg_str_value(group->arg_values, integritysettings_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; + } + + pos += num; + + if (!_get_one_integrity_setting(cmd, settings, key, val)) + return_0; + } + } + + return 1; +} + +int get_integrity_options(struct cmd_context *cmd, const char **arg, const char **meta_name, + struct integrity_settings *set) +{ + *arg = NULL; + *meta_name = NULL; + memset(set, 0, sizeof(struct integrity_settings)); + + if (arg_is_set(cmd, integrity_ARG)) + *arg = arg_str_value(cmd, integrity_ARG, NULL); + + if (arg_is_set(cmd, integritymetadata_ARG)) + *meta_name = arg_str_value(cmd, integritymetadata_ARG, NULL); + + if (arg_is_set(cmd, integritysettings_ARG)) { + if (!_get_integrity_settings(cmd, set)) + return_0; + } + + return 1; +} + /* FIXME move to lib */ static int _pv_change_tag(struct physical_volume *pv, const char *tag, int addtag) { @@ -2579,6 +2747,8 @@ static int _lv_is_type(struct cmd_context *cmd, struct logical_volume *lv, int l return seg_is_raid10(seg); case writecache_LVT: return seg_is_writecache(seg); + case integrity_LVT: + return seg_is_integrity(seg); case error_LVT: return !strcmp(seg->segtype->name, SEG_TYPE_NAME_ERROR); case zero_LVT: @@ -2637,6 +2807,8 @@ int get_lvt_enum(struct logical_volume *lv) return raid10_LVT; if (seg_is_writecache(seg)) return writecache_LVT; + if (seg_is_integrity(seg)) + return integrity_LVT; if (!strcmp(seg->segtype->name, SEG_TYPE_NAME_ERROR)) return error_LVT; |