}
for (i = 0; i < tbl_sz; i++) {
- if (strcmp(convert_tbl[i].in_setting, in_ctrl_val->name) == 0) {
+ /*
+ * For a few settings, e.g. cpu.max <-> cpu.cfs_quota_us/
+ * cpu.cfs_period_us, the conversion from the N->1 field
+ * (cpu.max) back to one of the other settings cannot be done
+ * without prior knowledge of our desired setting (quota or
+ * period in this example). If prev_name is set, it can guide
+ * us back to the correct mapping.
+ */
+ if (strcmp(convert_tbl[i].in_setting, in_ctrl_val->name) == 0 &&
+ (in_ctrl_val->prev_name == NULL ||
+ strcmp(in_ctrl_val->prev_name,
+ convert_tbl[i].out_setting) == 0)) {
+
ret = convert_tbl[i].cgroup_convert(out_cgc,
in_ctrl_val->value,
convert_tbl[i].out_setting,
dst_val->multiline_value = NULL;
}
+ if (src_val->prev_name) {
+ dst_val->prev_name =
+ strdup(src_val->prev_name);
+ if (!dst_val->prev_name) {
+ last_errno = errno;
+ ret = ECGOTHER;
+ goto err;
+ }
+ } else {
+ dst_val->prev_name = NULL;
+ }
+
dst_val->dirty = src_val->dirty;
}
if (dst->values[i]->multiline_value)
free(dst->values[i]->multiline_value);
+ if (dst->values[i]->prev_name)
+ free(dst->values[i]->prev_name);
+
free(dst->values[i]);
}
}
/* cgget uses this field for values that span multiple lines */
char *multiline_value;
+
+ /*
+ * The abstraction layer uses prev_name when there's an N->1 or
+ * 1->N relationship between cgroup v1 and v2 settings.
+ */
+ char *prev_name;
+
bool dirty;
};
for (j = 0; j < cgroup->controller[i]->index; j++) {
if (cgroup->controller[i]->values[j]->multiline_value)
free(cgroup->controller[i]->values[j]->multiline_value);
+ if (cgroup->controller[i]->values[j]->prev_name)
+ free(cgroup->controller[i]->values[j]->prev_name);
free(cgroup->controller[i]->values[j]);
}