On 1/16/20 10:43 AM, Nikola Forró wrote:
Order of parameters usually doesn't matter, but that's not the case with
memory.limit_in_bytes and memory.memsw.limit_in_bytes. When the latter
is first in the list of parameters, the resulting configuration is not
loadable with cgconfigparser.

Nice.  Good find.


This happens because when a cgroup is created, both memory.limit_in_bytes
and memory.memsw.limit_in_bytes parameters are initialized to highest
value possible (RESOURCE_MAX). And because memory.memsw.limit_in_bytes
must be always higher or equal to memory.limit_in_bytes, it's impossible
to change its value first.

Make sure that after constructing parameter list of memory subsystem,
the mentioned parameters are in correct order.

Signed-off-by: Nikola Forró <nfo...@redhat.com>
---
  src/api.c | 24 ++++++++++++++++++++++++
  1 file changed, 24 insertions(+)

diff --git a/src/api.c b/src/api.c
index c37855f..92730e6 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2715,6 +2715,30 @@ int cgroup_get_cgroup(struct cgroup *cgroup)
                        }
                }
                closedir(dir);
+
+               if (! strcmp(cgc->name, "memory")) {
+                       /*
+                        * Make sure that memory.limit_in_bytes is placed before
+                        * memory.memsw.limit_in_bytes in the list of values
+                        */
+                       int memsw_limit = -1;
+                       int mem_limit = -1;
+
+                       for (j = 0; j < cgc->index; j++) {
+                               if (! strcmp(cgc->values[j]->name,
+                                                               
"memory.memsw.limit_in_bytes"))
+                                       memsw_limit = j;
+                               else if (! strcmp(cgc->values[j]->name,
+                                                                       
"memory.limit_in_bytes"))
+                                       mem_limit = j;
+                       }
+
+                       if (memsw_limit >= 0 && memsw_limit < mem_limit) {
+                               struct control_value *val = 
cgc->values[memsw_limit];
+                               cgc->values[memsw_limit] = 
cgc->values[mem_limit];
+                               cgc->values[mem_limit] = val;
+                       }
+               }

I feel like it would make sense to create a separate function with
these memory checks.  cgroup_get_cgroup() is getting pretty long, and
splitting these changes out would make for better readability and
testability.

In fact, I prototyped that up quickly.  Here are the two commits I
made for this:
https://github.com/drakenclimber/libcgroup/commit/bcf34c6fa7739f1dc69f190086e8ca398a8e42ab
https://github.com/drakenclimber/libcgroup/commit/f0faaa01600a30f593cbf7afd5328bc96452397f

And here's the code coverage.  I was able to achieve 100% coverage!
https://coveralls.io/builds/28160581/source?filename=src/api.c#L2620

I believe the logic is functionally correct.

Thanks.

Tom

        }
/* Check if the group really exists or not */



_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to