+enum paramtype {
+ PT_NONE = 0,
+ PT_SETPARAM,
+ PT_CONFPARAM
+};
+
+
+#define PS_NONE 0
+#define PS_PARAM_FOUND 1
+#define PS_PARAM_SET 2
+#define PS_VAL_FOUND 4
+#define PS_VAL_SET 8
+#define PS_DEVICE_FOUND 16
+#define PS_DEVICE_SET 32
+
+#define PARAM_SZ 256
+
+static struct cfg_type_data {
+ enum paramtype ptype;
+ char *type_name;
+} cfg_type_table[] = {
+ { PT_SETPARAM, "set_param" },
+ { PT_CONFPARAM, "conf_param" },
+ { PT_NONE, "none" }
+};
+
+static struct cfg_stage_data {
+ int pstage;
+ char *stage_name;
+} cfg_stage_table[] = {
+ { PS_PARAM_FOUND, "parameter" },
+ { PS_VAL_FOUND, "value" },
+ { PS_DEVICE_FOUND, "device" },
+ { PS_NONE, "none" }
+};
+
+
+void conf_to_set_param(enum paramtype confset, const char *param,
+ const char *device, char *buf,
+ int bufsize)
+{
+ char *tmp;
+
+ if (confset == PT_SETPARAM) {
+ strncpy(buf, param, bufsize);
+ return;
+ }
+
+ /*
+ * sys.* params are top level, we just need to trim the sys.
+ */
+ tmp = strstr(param, "sys.");
+ if (tmp != NULL) {
+ tmp += 4;
+ strncpy(buf, tmp, bufsize);
+ return;
+ }
+
+ /*
+ * parameters look like type.parameter, we need to stick the device
+ * in the middle. Example combine mdt.identity_upcall with device
+ * lustre-MDT0000 for mdt.lustre-MDT0000.identity_upcall
+ */
+
+ tmp = strchrnul(param, '.');
+ snprintf(buf, tmp - param + 1, "%s", param);
+ buf += tmp - param;
+ bufsize -= tmp - param;
+ snprintf(buf, bufsize, ".%s%s", device, tmp);
+}
+
+int lcfg_setparam_yaml(char *func, char *filename)
+{
+ FILE *file;
+ yaml_parser_t parser;
+ yaml_token_t token;
+ int rc = 0;
+
+ enum paramtype confset = PT_NONE;
+ int param = PS_NONE;
+ char *tmp;
+ char parameter[PARAM_SZ];
+ char value[PARAM_SZ];
+ char device[PARAM_SZ];
+
+ file = fopen(filename, "rb");
+ yaml_parser_initialize(&parser);
+ yaml_parser_set_input_file(&parser, file);
+
+ /*
+ * Search tokens for conf_param or set_param
+ * The token after "parameter" goes into parameter
+ * The token after "value" goes into value
+ * when we have all 3, create param=val and call the
+ * appropriate function for set/conf param
+ */
+ while (token.type != YAML_STREAM_END_TOKEN && rc == 0) {
+ int i;
+
+ yaml_token_delete(&token);
+ if (!yaml_parser_scan(&parser, &token)) {
+ rc = 1;
+ break;
+ }
+
+ if (token.type != YAML_SCALAR_TOKEN)
+ continue;
+
+ for (i = 0; cfg_type_table[i].ptype != PT_NONE; i++) {
+ if (!strncmp((char *)token.data.alias.value,
+ cfg_type_table[i].type_name,
+ strlen(cfg_type_table[i].type_name))) {
+ confset = cfg_type_table[i].ptype;
+ break;
+ }
+ }
+
+ if (confset == PT_NONE)
+ continue;
+
+ for (i = 0; cfg_stage_table[i].pstage != PS_NONE; i++) {
+ if (!strncmp((char *)token.data.alias.value,
+ cfg_stage_table[i].stage_name,
+ strlen(cfg_stage_table[i].stage_name))) {
+ param |= cfg_stage_table[i].pstage;
+ break;
+ }
+ }
+
+ if (cfg_stage_table[i].pstage != PS_NONE)
+ continue;
+
+ if (param & PS_PARAM_FOUND) {
+ conf_to_set_param(confset,
+ (char *)token.data.alias.value,
+ device, parameter, PARAM_SZ);
+ param |= PS_PARAM_SET;
+ param &= ~PS_PARAM_FOUND;
+
+ /*
+ * we're getting parameter: param=val
+ * copy val and mark that we've got it in case
+ * there is no value: tag
+ */
+ tmp = strchrnul(parameter, '=');
+ if (*tmp == '=') {
+ strncpy(value, tmp+1, sizeof(value));
+ *tmp = '\0';
+ param |= PS_VAL_SET;
+ } else {
+ continue;
+ }
+ } else if (param & PS_VAL_FOUND) {
+ strncpy(value, (char *)token.data.alias.value,
+ PARAM_SZ);
+ param |= PS_VAL_SET;
+ param &= ~PS_VAL_FOUND;
+ } else if (param & PS_DEVICE_FOUND) {
+ strncpy(device, (char *)token.data.alias.value,
+ PARAM_SZ);
+ param |= PS_DEVICE_SET;
+ param &= ~PS_DEVICE_FOUND;
+ }
+
+ if (confset && param & PS_VAL_SET && param & PS_PARAM_SET) {
+ int size = strlen(parameter) + strlen(value) + 2;
+ char *buf = malloc(size);
+
+ if (buf == NULL) {
+ rc = 2;
+ break;
+ }
+ snprintf(buf, size, "%s=%s", parameter, value);
+
+ printf("set_param: %s\n", buf);
+ rc = lcfg_setparam_perm(func, buf);
+
+ confset = PT_NONE;
+ param = PS_NONE;
+ parameter[0] = '\0';
+ value[0] = '\0';
+ device[0] = '\0';
+ free(buf);
+ }
+ }
+
+ yaml_parser_delete(&parser);
+ fclose(file);
+
+ return rc;
+}
+