]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
abstraction: Add function to convert from one cgroup version to another
authorTom Hromatka <tom.hromatka@oracle.com>
Wed, 15 Dec 2021 20:18:54 +0000 (20:18 +0000)
committerTom Hromatka <tom.hromatka@oracle.com>
Thu, 3 Feb 2022 21:42:08 +0000 (14:42 -0700)
Add a function - cgroup_convert_cgroup() - that can convert from
one cgroup version to another.  This function will be the building
block for the libcgroup abstraction layer.

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

index 89c60ac2c58e5df9fbfde6922edefbe4551b0464..0960a7d37a330bee05a4bc4f019fe2a244d4393c 100644 (file)
@@ -590,6 +590,23 @@ int cg_chmod_recursive(struct cgroup *cgroup, mode_t dir_mode,
  */
 char *cgroup_get_cgroup_name(struct cgroup *cgroup);
 
+/*
+ * Convert from one cgroup version to another version
+ *
+ * @param out_cgroup Destination cgroup
+ * @param out_version Destination cgroup version
+ * @param in_cgroup Source cgroup
+ * @param in_version Source cgroup version, only used if set to v1 or v2
+ *
+ * @return 0 on success
+ *         ECGFAIL conversion failed
+ *         ECGCONTROLLERNOTEQUAL incorrect controller version provided
+ */
+int cgroup_convert_cgroup(struct cgroup * const out_cgroup,
+                         enum cg_version_t out_version,
+                         const struct cgroup * const in_cgroup,
+                         enum cg_version_t in_version);
+
 /**
  * @}
  * @}
index 7616aab539b2878852ae233beec999769782c7d7..319f01612aee387f181bedc4ca4f5da31974108e 100644 (file)
@@ -29,6 +29,7 @@
 #include <unistd.h>
 
 #include "abstraction-common.h"
+#include "abstraction-map.h"
 
 int cgroup_strtol(const char * const in_str, int base,
                  long int * const out_value)
@@ -114,3 +115,105 @@ out:
 
        return ret;
 }
+
+static int convert_setting(struct cgroup_controller * const out_cgc,
+                          const struct control_value * const in_ctrl_val)
+{
+       const struct cgroup_abstraction_map *convert_tbl;
+       int tbl_sz = 0;
+       int ret = ECGINVAL;
+       int i;
+
+       switch (out_cgc->version) {
+       case CGROUP_V1:
+               convert_tbl = cgroup_v2_to_v1_map;
+               tbl_sz = cgroup_v2_to_v1_map_sz;
+               break;
+       case CGROUP_V2:
+               convert_tbl = cgroup_v1_to_v2_map;
+               tbl_sz = cgroup_v1_to_v2_map_sz;
+               break;
+       default:
+               ret = ECGFAIL;
+               goto out;
+       }
+
+       for (i = 0; i < tbl_sz; i++) {
+               if (strcmp(convert_tbl[i].in_setting, in_ctrl_val->name) == 0) {
+                       ret = convert_tbl[i].cgroup_convert(out_cgc,
+                                       in_ctrl_val->value,
+                                       convert_tbl[i].out_setting,
+                                       convert_tbl[i].in_dflt,
+                                       convert_tbl[i].out_dflt);
+                       if (ret)
+                               goto out;
+               }
+       }
+
+out:
+       return ret;
+}
+
+static int convert_controller(struct cgroup_controller * const out_cgc,
+                             const struct cgroup_controller * const in_cgc)
+{
+       int ret;
+       int i;
+
+
+       if (in_cgc->version == out_cgc->version) {
+               ret = cgroup_copy_controller_values(out_cgc, in_cgc);
+               /* regardless of success/failure, there's nothing more to do */
+               goto out;
+       }
+
+       for (i = 0; i < in_cgc->index; i++) {
+               ret = convert_setting(out_cgc, in_cgc->values[i]);
+               if (ret)
+                       goto out;
+       }
+
+out:
+       return ret;
+}
+
+int cgroup_convert_cgroup(struct cgroup * const out_cgroup,
+                         enum cg_version_t out_version,
+                         const struct cgroup * const in_cgroup,
+                         enum cg_version_t in_version)
+{
+       struct cgroup_controller *cgc;
+       int ret = 0;
+       int i;
+
+       for (i = 0; i < in_cgroup->index; i++) {
+               cgc = cgroup_add_controller(out_cgroup,
+                                           in_cgroup->controller[i]->name);
+               if (cgc == NULL) {
+                       ret = ECGFAIL;
+                       goto out;
+               }
+
+               /* the user has overridden the version */
+               if (in_version == CGROUP_V1 || in_version == CGROUP_V2) {
+                       in_cgroup->controller[i]->version = in_version;
+               }
+
+               cgc->version = out_version;
+
+               if (cgc->version == CGROUP_UNK ||
+                   cgc->version == CGROUP_DISK) {
+                       ret = cgroup_get_controller_version(cgc->name,
+                               &cgc->version);
+                       if (ret)
+                               goto out;
+               }
+
+               ret = convert_controller(cgc, in_cgroup->controller[i]);
+               if (ret)
+                       goto out;
+       }
+
+out:
+       return ret;
+}
index 68098cd3accbb2bc1a022d66126bdbb26296e0b0..d99a2ce73c044c65c39c8138061be52bbd62027d 100644 (file)
@@ -139,3 +139,7 @@ CGROUP_2.0 {
        cg_mount_table_lock;
        cgroup_get_controller_version;
 } CGROUP_0.42;
+
+CGROUP_3.0 {
+       cgroup_convert_cgroup;
+} CGROUP_2.0;