summaryrefslogtreecommitdiff
path: root/tools/toollib.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/toollib.c')
-rw-r--r--tools/toollib.c172
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;