This commit adds a function, cgroupv2_get_subtree_control(), that
will verify if a controller is enabled in the subtree control
file or not.

This function will be used in the next commit - "api.c: Add function to
check if a controller is enabled for a cgroup v2 cgroup" - to determine
if the requested cgroup v2 controller is enabled for a cgroup.  This is a
required check to ensure that the cgclassify/cgexec operation will
succeed.

Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com>
---
 src/api.c                | 66 ++++++++++++++++++++++++++++++++++++++++
 src/libcgroup-internal.h |  3 ++
 2 files changed, 69 insertions(+)

diff --git a/src/api.c b/src/api.c
index 274718bbe8f4..88042f95a51c 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1884,6 +1884,72 @@ err:
        return error;
 }
 
+/**
+ * Check if the requested cgroup controller is enabled on this subtree
+ *
+ * @param path Cgroup directory
+ * @param ctrl_name Name of the controller to check
+ * @param output parameter that indicates whether the controller is enabled\
+ */
+STATIC int cgroupv2_get_subtree_control(const char *path,
+                                       const char *ctrl_name,
+                                       bool * const enabled)
+{
+       char *path_copy = NULL, *saveptr = NULL, *token, *ret_c;
+       int ret, error = ECGROUPNOTMOUNTED;
+       char buffer[FILENAME_MAX];
+       FILE *fp = NULL;
+
+       if (!path || !ctrl_name || !enabled)
+               return ECGOTHER;
+
+       *enabled = false;
+
+       path_copy = (char *)malloc(FILENAME_MAX);
+       if (!path_copy)
+               goto out;
+
+       ret = snprintf(path_copy, FILENAME_MAX, "%s/%s", path,
+                      CGV2_SUBTREE_CTRL_FILE);
+       if (ret < 0)
+               goto out;
+
+       fp = fopen(path_copy, "re");
+       if (!fp) {
+               cgroup_warn("Warning: fopen failed\n");
+               last_errno = errno;
+               goto out;
+       }
+
+       ret_c = fgets(buffer, sizeof(buffer), fp);
+       if (ret_c == NULL)
+               /* The subtree control file is empty */
+               goto out;
+
+       /* remove the trailing newline */
+       ret_c[strlen(ret_c) - 1] = '\0';
+
+       /* Split the enabled controllers by " " and evaluate if the requested
+        * controller is enabled.
+        */
+       token = strtok_r(buffer, " ", &saveptr);
+       do {
+               if (strncmp(ctrl_name, token, FILENAME_MAX) == 0) {
+                       error = 0;
+                       *enabled = true;
+                       break;
+               }
+       } while ((token = strtok_r(NULL, " ", &saveptr)));
+
+out:
+       if (path_copy)
+               free(path_copy);
+       if (fp)
+               fclose(fp);
+
+       return error;
+}
+
 /**
  * Enable/Disable a controller in the cgroup v2 subtree_control file
  *
diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h
index 72ddc19ea6e5..b834202dcf6b 100644
--- a/src/libcgroup-internal.h
+++ b/src/libcgroup-internal.h
@@ -347,6 +347,9 @@ int cgroup_build_tasks_procs_path(char * const path,
                                  size_t path_sz, const char * const cg_name,
                                  const char * const ctrl_name);
 
+int cgroupv2_get_subtree_control(const char *path,
+                                const char *ctrl_name,
+                                bool * const enabled);
 #endif /* UNIT_TEST */
 
 __END_DECLS
-- 
2.25.4



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

Reply via email to