]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
cgdelete: fix the display problem
authorWeng Meiling <wengmeiling.weng@huawei.com>
Thu, 31 Jul 2014 08:30:51 +0000 (10:30 +0200)
committerWeng Meiling <wengmeiling.weng@huawei.com>
Thu, 31 Jul 2014 08:30:51 +0000 (10:30 +0200)
When multi subsystems mounted on one place like this:

$ lssubsys -m
cpu,cpuacct /cgroup/cpu

$ lscgroup
cpu,cpuacct:/
cpu,cpuacct:/test

if we delete the cgroup with the cgdelete -g, and specifying multi
controllers like this:

$ cgdelete -g cpu,cpuacct:test

or

$ cgdelete -g cpu:test -g cpuacct:test

it will report error:
cgdelete: cannot remove group 'test': No such file or directory

this patch fix the problem.

v1 -> v2
 - make cgdelete -g cpu:/test -g cpu:test failed.
v2 -> v3
 - make cgdelete -g cpu:test -g cpu:test1 ok.
v3 -> v4
 - make cgdelete -g cpuacct:test -g cpu:test -g cpuacct:test failed.
 - add some comments
 - fix the uninitialized warning
v4 -> v5 (created by Ivana Hutarova Varekova, acked by Weng Meiling)
 - make cgdelete -g cpuacct:test -g cpu:test -g cpu:test failed
 - join extended cgroup list variables to one record, do the list dynamic (static version can exceed the given limit and the safe static limit is quite high)

Signed-off-by: Weng Meiling <wengmeiling.weng@huawei.com>
Signed-off-by: Ivana Hutarova Varekova <varekova@redhat.com>
Acked-by: Weng Meiling <wengmeiling.weng@huawei.com>
Acked-by: Ivana Hutarova Varekova <varekova@redhat.com>
src/tools/cgdelete.c

index 190310f1acda936959eb6e199e57b98d1a93e8f5..43cc47c22d22abeae6734c483187db02c43171fb 100644 (file)
@@ -33,6 +33,13 @@ static struct option const long_options[] =
        {NULL, 0, NULL, 0}
 };
 
+struct ext_cgroup_record {
+       char name[FILENAME_MAX];        /* controller name */
+       char controller[FILENAME_MAX];  /* cgroup name */
+       int h_number;                   /* hierarchy number */
+};
+
+
 static void usage(int status, const char *program_name)
 {
        if (status != 0) {
@@ -51,6 +58,69 @@ static void usage(int status, const char *program_name)
                "all subgroups\n");
 }
 
+/*
+ * Skip adding controller which points to the same cgroup when delete
+ * cgroup with specifying multi controllers. Just skip controller which
+ * cgroup and hierarchy number is same
+ */
+static int skip_add_controller(int counter, int *skip,
+               struct ext_cgroup_record *ecg_list)
+{
+       int k;
+       struct controller_data info;
+       void *handle;
+       int ret = 0;
+
+       /* find out hierarchy number of added cgroup */
+       ecg_list[counter].h_number = 0;
+       ret = cgroup_get_all_controller_begin(&handle, &info);
+       while (ret == 0) {
+               if (!strcmp(info.name, ecg_list[counter].name)) {
+                       /* hierarchy number found out, set it */
+                       ecg_list[counter].h_number = info.hierarchy;
+                       break;
+               }
+               ret = cgroup_get_all_controller_next(&handle, &info);
+       }
+       cgroup_get_all_controller_end(&handle);
+
+       /* deal with cgroup_get_controller_begin/next ret values */
+       if (ret == ECGEOF)
+               ret = 0;
+       if (ret) {
+               fprintf(stderr, "cgroup_get_controller_begin/next failed(%s)\n",
+                       cgroup_strerror(ret));
+               return ret;
+       }
+
+       /* found out whether the hierarchy should be skipped */
+       *skip = 0;
+       for (k = 0; k < counter; k++) {
+               if ((!strcmp(ecg_list[k].name, ecg_list[counter].name)) &&
+                       (ecg_list[k].h_number == ecg_list[counter].h_number)) {
+                       /* we found a control group in the same hierarchy */
+                       if (strcmp(ecg_list[k].controller,
+                               ecg_list[counter].controller)) {
+                               /*
+                                * it is a different controller ->
+                                * if there is not one cgroup for the same
+                                * controller, skip it
+                                */
+                               *skip = 1;
+                       } else {
+                               /*
+                                * there is the identical group,controller pair
+                                * don't skip it
+                                */
+                               *skip = 0;
+                               return ret;
+                       }
+               }
+       }
+
+       return ret;
+}
+
 
 int main(int argc, char *argv[])
 {
@@ -60,6 +130,11 @@ int main(int argc, char *argv[])
        int flags = 0;
        int final_ret = 0;
 
+       int counter = 0;
+       int max = 0;
+       struct ext_cgroup_record *ecg_list = NULL;
+       int skip;
+
        struct cgroup_group_spec **cgroup_list = NULL;
        struct cgroup *cgroup;
        struct cgroup_controller *cgc;
@@ -80,6 +155,13 @@ int main(int argc, char *argv[])
                goto err;
        }
 
+       ecg_list = calloc(argc, sizeof(struct ext_cgroup_record *));
+       if (cgroup_list == NULL) {
+               fprintf(stderr, "%s: out of memory\n", argv[0]);
+               ret = -1;
+               goto err;
+       }
+
        /*
         * Parse arguments
         */
@@ -138,6 +220,44 @@ int main(int argc, char *argv[])
                /* add controllers to the cgroup */
                j = 0;
                while (cgroup_list[i]->controllers[j]) {
+                       skip = 0;
+                       /*
+                        * save controller name, cg name and hierarchy number
+                        * to determine whether we should skip adding controller
+                        */
+                       if (counter == max) {
+                               /*
+                                * there is not enough space to store them,
+                                * create it
+                                */
+                               max = max + argc;
+                               ecg_list = (struct ext_cgroup_record *)
+                                       realloc(ecg_list,
+                                       max * sizeof(struct ext_cgroup_record));
+                               if (!ecg_list) {
+                                       fprintf(stderr, "%s: ", argv[0]);
+                                       fprintf(stderr, "not enough memory\n");
+                                       final_ret = -1;
+                                       goto err;
+                               }
+                       }
+
+                       strncpy(ecg_list[counter].controller,
+                               cgroup_list[i]->controllers[j], FILENAME_MAX);
+                       ecg_list[counter].controller[FILENAME_MAX - 1] = '\0';
+                       strncpy(ecg_list[counter].name,
+                               cgroup_list[i]->path, FILENAME_MAX);
+                       ecg_list[counter].name[FILENAME_MAX - 1] = '\0';
+
+                       ret = skip_add_controller(counter, &skip, ecg_list);
+                       if (ret)
+                               goto err;
+
+                       if (skip) {
+                               /* don't add the controller, goto next one */
+                               goto next;
+                       }
+
                        cgc = cgroup_add_controller(cgroup,
                                cgroup_list[i]->controllers[j]);
                        if (!cgc) {
@@ -149,6 +269,8 @@ int main(int argc, char *argv[])
                                cgroup_free(&cgroup);
                                goto err;
                        }
+next:
+                       counter++;
                        j++;
                }
 
@@ -167,6 +289,9 @@ int main(int argc, char *argv[])
 
        ret = final_ret;
 err:
+       if (ecg_list)
+               free(ecg_list);
+
        if (cgroup_list) {
                for (i = 0; i < argc; i++) {
                        if (cgroup_list[i])