Add a new libcgroup tool - cgxget.  cgxget is based upon cgget,
but it supports converting from cgroup version to another.

For example, a request like the following will work on a system
running the cgroup v1 cpu controller or the cgroup v2 cpu controller.
        $ cgxget -2 cpu.weight MyCgroup

The return value to the user will match the cgroup version requested.
If the user requests a v1 setting, the return value will be a cgroup
v1 setting.  And the same holds true for v2.

Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com>
---
 src/tools/Makefile.am |   8 ++-
 src/tools/cgget.c     | 115 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 111 insertions(+), 12 deletions(-)

diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index fd792853a27e..9b5380bc301a 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -5,8 +5,8 @@ LDADD = $(top_builddir)/src/.libs/libcgroup.la -lpthread
 
 if WITH_TOOLS
 
-bin_PROGRAMS = cgexec cgclassify cgcreate cgset cgget cgdelete lssubsys\
-               lscgroup cgsnapshot
+bin_PROGRAMS = cgexec cgclassify cgcreate cgset cgget cgxget cgdelete \
+               lssubsys lscgroup cgsnapshot
 
 sbin_PROGRAMS = cgconfigparser cgclear
 
@@ -30,6 +30,10 @@ cgget_SOURCES = cgget.c tools-common.c tools-common.h
 cgget_LIBS = $(CODE_COVERAGE_LIBS)
 cgget_CFLAGS = $(CODE_COVERAGE_CFLAGS)
 
+cgxget_SOURCES = cgget.c tools-common.c tools-common.h
+cgxget_LIBS = $(CODE_COVERAGE_LIBS)
+cgxget_CFLAGS = $(CODE_COVERAGE_CFLAGS) -DCGXGET
+
 cgconfigparser_SOURCES = cgconfig.c tools-common.c tools-common.h
 cgconfigparser_LIBS = $(CODE_COVERAGE_LIBS)
 cgconfigparser_CFLAGS = $(CODE_COVERAGE_CFLAGS)
diff --git a/src/tools/cgget.c b/src/tools/cgget.c
index 08c2286ca098..3359f551f6ad 100644
--- a/src/tools/cgget.c
+++ b/src/tools/cgget.c
@@ -11,6 +11,10 @@
 
 #include "tools-common.h"
 
+#ifdef CGXGET
+#include "abstraction-common.h"
+#endif
+
 #define MODE_SHOW_HEADERS              1
 #define MODE_SHOW_NAMES                        2
 
@@ -18,6 +22,10 @@
 
 static struct option const long_options[] =
 {
+#ifdef CGXGET
+       {"v1", no_argument, NULL, '1'},
+       {"v2", no_argument, NULL, '2'},
+#endif
        {"variable", required_argument, NULL, 'r'},
        {"help", no_argument, NULL, 'h'},
        {"all",  no_argument, NULL, 'a'},
@@ -38,17 +46,23 @@ static void usage(int status, const char *program_name)
                "   or: %s [-nv] [-r <name>] -g <controllers>:<path> ...\n",
                program_name, program_name);
        printf("Print parameter(s) of given group(s).\n");
-       printf("  -a, --all                     Print info about all relevant "\
-               "controllers\n");
-       printf("  -g <controllers>              Controller which info should "\
-               "be displayed\n");
-       printf("  -g <controllers>:<path>       Control group which info "\
-               "should be displayed\n");
+#ifdef CGXGET
+       printf("  -1, --v1                      Provided parameters are in "
+              "v1 format\n");
+       printf("  -2, --v2                      Provided parameters are in "
+              "v2 format\n");
+#endif
+       printf("  -a, --all                     Print info about all relevant "
+              "controllers\n");
+       printf("  -g <controllers>              Controller which info should "
+              "be displayed\n");
+       printf("  -g <controllers>:<path>       Control group which info "
+              "should be displayed\n");
        printf("  -h, --help                    Display this help\n");
        printf("  -n                            Do not print headers\n");
        printf("  -r, --variable  <name>        Define parameter to display\n");
-       printf("  -v, --values-only             Print only values, not "\
-               "parameter names\n");
+       printf("  -v, --values-only             Print only values, not "
+              "parameter names\n");
 }
 
 static int get_controller_from_name(const char * const name,
@@ -163,7 +177,9 @@ static int parse_r_flag(struct cgroup **cg_list[], int * 
const cg_list_len,
        if (!cgc) {
                cgc = cgroup_add_controller(cg, cntl_value_controller);
                if (!cgc) {
-                       ret = ECGCONTROLLERCREATEFAILED;
+                       fprintf(stderr, "cgget: cannot find controller '%s'\n",
+                               cntl_value_controller);
+                       ret = ECGOTHER;
                        goto out;
                }
        }
@@ -366,9 +382,14 @@ static int parse_opt_args(int argc, char *argv[], struct 
cgroup **cg_list[],
 out:
        return ret;
 }
-
+#ifdef CGXGET
+static int parse_opts(int argc, char *argv[], struct cgroup **cg_list[],
+                     int * const cg_list_len, int * const mode,
+                     enum cg_version_t * const version)
+#else
 static int parse_opts(int argc, char *argv[], struct cgroup **cg_list[],
                      int * const cg_list_len, int * const mode)
+#endif
 {
        bool do_not_fill_controller = false;
        bool fill_controller = false;
@@ -377,8 +398,13 @@ static int parse_opts(int argc, char *argv[], struct 
cgroup **cg_list[],
        int c;
 
        /* Parse arguments. */
+#ifdef CGXGET
+       while ((c = getopt_long(argc, argv, "r:hnvg:a12", long_options, NULL))
+               > 0) {
+#else
        while ((c = getopt_long(argc, argv, "r:hnvg:a", long_options, NULL))
                > 0) {
+#endif
                switch (c) {
                case 'h':
                        usage(0, argv[0]);
@@ -419,6 +445,14 @@ static int parse_opts(int argc, char *argv[], struct 
cgroup **cg_list[],
                        if (ret)
                                goto err;
                        break;
+#ifdef CGXGET
+               case '1':
+                       *version = CGROUP_V1;
+                       break;
+               case '2':
+                       *version = CGROUP_V2;
+                       break;
+#endif
                default:
                        usage(1, argv[0]);
                        exit(1);
@@ -709,12 +743,57 @@ static void print_cgroups(struct cgroup *cg_list[], int 
cg_list_len, int mode)
        }
 }
 
+#ifdef CGXGET
+int convert_cgroups(struct cgroup **cg_list[], int cg_list_len,
+                   enum cg_version_t in_version,
+                   enum cg_version_t out_version)
+{
+       struct cgroup **cg_converted_list;
+       int i = 0, j, ret = 0;
+
+       cg_converted_list = malloc(cg_list_len * sizeof(struct cgroup *));
+       if (cg_converted_list == NULL)
+               goto out;
+
+       for (i = 0; i < cg_list_len; i++) {
+               cg_converted_list[i] = cgroup_new_cgroup((*cg_list)[i]->name);
+               if (cg_converted_list[i] == NULL) {
+                       ret = ECGCONTROLLERCREATEFAILED;
+                       goto out;
+               }
+
+               ret = cgroup_convert_cgroup(cg_converted_list[i],
+                       out_version, (*cg_list)[i], in_version);
+               if (ret)
+                       goto out;
+       }
+
+out:
+       if (ret) {
+               /* the conversion failed */
+               for (j = 0; j < i; j++)
+                       cgroup_free(&(cg_converted_list[i]));
+       } else {
+               /* the conversion succeeded.  free the old list */
+               for (i = 0; i < cg_list_len; i++)
+                       cgroup_free(cg_list[i]);
+
+               *cg_list = cg_converted_list;
+       }
+
+       return ret;
+}
+#endif
+
 int main(int argc, char *argv[])
 {
        struct cgroup **cg_list = NULL;
        int cg_list_len = 0;
        int ret = 0, i;
        int mode = MODE_SHOW_NAMES | MODE_SHOW_HEADERS;
+#ifdef CGXGET
+       enum cg_version_t version = CGROUP_UNK;
+#endif
 
        /* No parameter on input? */
        if (argc < 2) {
@@ -729,14 +808,30 @@ int main(int argc, char *argv[])
                goto err;
        }
 
+#ifdef CGXGET
+       ret = parse_opts(argc, argv, &cg_list, &cg_list_len, &mode, &version);
+#else
        ret = parse_opts(argc, argv, &cg_list, &cg_list_len, &mode);
+#endif
+       if (ret)
+               goto err;
+
+#ifdef CGXGET
+       ret = convert_cgroups(&cg_list, cg_list_len, version, CGROUP_DISK);
        if (ret)
                goto err;
+#endif
 
        ret = get_values(cg_list, cg_list_len);
        if (ret)
                goto err;
 
+#ifdef CGXGET
+       ret = convert_cgroups(&cg_list, cg_list_len, CGROUP_DISK, version);
+       if (ret)
+               goto err;
+#endif
+
        print_cgroups(cg_list, cg_list_len, mode);
 
 err:
-- 
2.26.2



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

Reply via email to