Around one year ago, the following was reported:
http://comments.gmane.org/gmane.comp.lib.libcg.devel/3116
(Error when calling cgroup_modify_cgroup())

Today, I ran into the very same error. Inspecting the code
in libcg, it seemed to me that the best thing to avoid that
is to never attempt to write something the user never wrote to.

That is because if the user actually tries to write to a read-only
file, we should yield an error, making skipping read-only a bad
solution.

My solution is to add a field to the value structure indicating
whether or not it is dirty. cgroup_modify_cgroup then becomes a
flusher, and the problem goes away.

[ v2: Also mark dirty value writes using cgroup_set_value_* ]

Signed-off-by: Glauber Costa <glom...@parallels.com>
---
 src/api.c                |    9 ++++++++-
 src/libcgroup-internal.h |    1 +
 src/wrapper.c            |    5 +++++
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/api.c b/src/api.c
index 29de777..59cc0a0 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1420,6 +1420,9 @@ int cgroup_modify_cgroup(struct cgroup *cgroup)
                        cgroup->controller[i]->name))
                        continue;
                for (j = 0; j < cgroup->controller[i]->index; j++) {
+                       if (!cgroup->controller[i]->values[j]->dirty)
+                               continue;
+
                        ret = asprintf(&path, "%s%s", base,
                                cgroup->controller[i]->values[j]->name);
                        if (ret < 0) {
@@ -1433,6 +1436,7 @@ int cgroup_modify_cgroup(struct cgroup *cgroup)
                        path = NULL;
                        if (error)
                                goto err;
+                       cgroup->controller[i]->values[j]->dirty = false;
                }
        }
 err:
@@ -2317,7 +2321,7 @@ fill_error:
  */
 int cgroup_get_cgroup(struct cgroup *cgroup)
 {
-       int i;
+       int i, j;
        char path[FILENAME_MAX];
        DIR *dir = NULL;
        struct dirent *ctrl_dir = NULL;
@@ -2411,6 +2415,9 @@ int cgroup_get_cgroup(struct cgroup *cgroup)
                                continue;
 
                        error = cgroup_fill_cgc(ctrl_dir, cgroup, cgc, i);
+                       for (j = 0; j < cgc->index; j++)
+                               cgc->values[j]->dirty = false;
+
                        if (error == ECGFAIL) {
                                closedir(dir);
                                goto unlock_error;
diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h
index 1b3daf9..b253828 100644
--- a/src/libcgroup-internal.h
+++ b/src/libcgroup-internal.h
@@ -71,6 +71,7 @@ __BEGIN_DECLS
 struct control_value {
        char name[FILENAME_MAX];
        char value[CG_VALUE_MAX];
+       bool dirty;
 };
 
 struct cgroup_controller {
diff --git a/src/wrapper.c b/src/wrapper.c
index 50b8013..2d925d2 100644
--- a/src/wrapper.c
+++ b/src/wrapper.c
@@ -146,6 +146,7 @@ int cgroup_add_value_string(struct cgroup_controller 
*controller,
 
        strncpy(cntl_value->name, name, sizeof(cntl_value->name));
        strncpy(cntl_value->value, value, sizeof(cntl_value->value));
+       cntl_value->dirty = true;
        controller->values[controller->index] = cntl_value;
        controller->index++;
 
@@ -355,6 +356,7 @@ int cgroup_set_value_string(struct cgroup_controller 
*controller,
                struct control_value *val = controller->values[i];
                if (!strcmp(val->name, name)) {
                        strncpy(val->value, value, CG_VALUE_MAX);
+                       val->dirty = true;
                        return 0;
                }
        }
@@ -404,6 +406,7 @@ int cgroup_set_value_int64(struct cgroup_controller 
*controller,
                        if (ret >= sizeof(val->value) || ret < 0)
                                return ECGINVAL;
 
+                       val->dirty = true;
                        return 0;
                }
        }
@@ -452,6 +455,7 @@ int cgroup_set_value_uint64(struct cgroup_controller 
*controller,
                        if (ret >= sizeof(val->value) || ret < 0)
                                return ECGINVAL;
 
+                       val->dirty = true;
                        return 0;
                }
        }
@@ -511,6 +515,7 @@ int cgroup_set_value_bool(struct cgroup_controller 
*controller,
                        if (ret >= sizeof(val->value) || ret < 0)
                                return ECGINVAL;
 
+                       val->dirty = true;
                        return 0;
 
                }
-- 
1.7.10.2


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to