]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
api.c/wrapper/abstraction: Save previous setting name in control_value
authorTom Hromatka <tom.hromatka@oracle.com>
Wed, 15 Dec 2021 20:37:37 +0000 (20:37 +0000)
committerTom Hromatka <tom.hromatka@oracle.com>
Thu, 3 Feb 2022 21:42:32 +0000 (14:42 -0700)
When there's an N->1 mapping, the abstraction layer needs
to know which "1" setting to map back to.  Add a field to
struct control_value that saves off the original setting,
so that the abstraction layer can know how to map back from
an N->1 setting.

A good example of this is cpu.max/cpu.cfs_quota_us.  The
abstraction layer will map cpu.cfs_quota_us to cpu.max.
During the return conversion, the abstraction layer needs
to know whether to map cpu.max to cfs_quota_us or
cfs_period_us.

Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
Reviewed-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
src/abstraction-common.c
src/api.c
src/libcgroup-internal.h
src/wrapper.c

index a93bf3223e99470bd74ef2a24f1ec411df36aaab..6852afcb0a492408f2544cfc1fbfde62e73d3705 100644 (file)
@@ -155,7 +155,19 @@ static int convert_setting(struct cgroup_controller * const out_cgc,
        }
 
        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,
index e2ff6441ffe97b56305b9d69a223acaacdd4a030..5fbf0248fae3c80d18f6ba4a636c279e8180125e 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -2296,6 +2296,18 @@ int cgroup_copy_controller_values(struct cgroup_controller * const dst,
                        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;
        }
 
@@ -2308,6 +2320,9 @@ err:
                        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]);
                }
        }
index 616271feee8c629ef24d6df1c2a6a1902bb4d311..056085bc57c8d0f2b21e62c482e2713397ec305c 100644 (file)
@@ -93,6 +93,13 @@ struct control_value {
 
        /* 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;
 };
 
index 2b2876565a68b2089d3c89e3093fc68ae6b62880..150e6c4bbda46ea9b3fba8af43a38dcc635ecc15 100644 (file)
@@ -170,6 +170,8 @@ void cgroup_free_controllers(struct cgroup *cgroup)
                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]);
                }