]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
api.c: add support for cgroup.threads
authorKamalesh Babulal <kamalesh.babulal@oracle.com>
Thu, 27 Jan 2022 19:47:55 +0000 (12:47 -0700)
committerTom Hromatka <tom.hromatka@oracle.com>
Thu, 27 Jan 2022 19:48:11 +0000 (12:48 -0700)
cgroup_build_tasks_procs_path(), that builds the proc path for moving
the tid, doesn't check for the cgroup type and appends cgroup.procs for
both cgroup v1/v2.  With cgroup v2, this results in building a wrong
proc path if the cgroup type is threaded. This patch adds support to
check for the cgroup v2 type and build the proc path according to the
below table:

cgroup.type     | proc file      | Description                        |
----------------+----------------+------------------------------------+
domain          | cgroup.procs   | regular cgroup, all threads gets   |
                |                | moved to the cgroup.               |
domain threaded | cgroup.procs   | root of threaded subtree, all      |
                |                | threads gets moved to the cgroup.  |
threaded        | cgroup.threads | cgroup under threaded subtree,     |
|  | single threads with matching tid,  |
|  | gets moved to the cgroup.          |
domain invalid  | N/A            | invalid state of a cgroup under the|
                |                | threaded subtree.                  |

Closes: https://github.com/libcgroup/libcgroup/issues/64
Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
cherry picked from commit 4c577f91050b1ad00e5ed2b2abb40fc4978db996)

src/api.c

index 8f7a28c490cee60729305ca76dc1e8f6097304d0..cf3ff6c91021e87ef5801e858f9d87ccfb5cf556 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -1534,11 +1534,72 @@ char *cg_build_path(const char *name, char *path, const char *type)
        return path;
 }
 
+static int cgroup_get_cg_type(const char * const path, char * const type,
+                             size_t type_sz)
+{
+       char cg_type_path[FILENAME_MAX];
+       char cg_type[LL_MAX];
+       int len, err = 0;
+       FILE *fp = NULL;
+       struct stat st;
+       int stat_ret;
+
+       snprintf(cg_type_path, FILENAME_MAX, "%scgroup.type", path);
+       /* file cgroup.type, doesn't exist for root cgroup. */
+       stat_ret = stat(cg_type_path, &st);
+       if (stat_ret != 0) {
+               snprintf(type, type_sz, "cgroup.procs");
+               goto out;
+       }
+
+       fp = fopen(cg_type_path, "re");
+       if (!fp) {
+               cgroup_warn("Warning: failed to open file %s: %s\n",
+                               cg_type_path, strerror(errno));
+               err = ECGOTHER;
+               goto out;
+       }
+
+       if (fgets(cg_type, LL_MAX, fp) == NULL) {
+               cgroup_warn("Warning: failed to read file %s: %s\n",
+                               cg_type_path, strerror(errno));
+               err = ECGOTHER;
+               goto out;
+       }
+
+       len = strlen(cg_type) - 1;
+       /*
+        * Append cgroup.threads to the path, if the cgroup.type is
+        * threaded and cgroup.procs for type domain, domain threaded.
+        * domain type is used for regular cgroup and domain threaded
+        * for root of threaded cgroup v2 subtree.  Another possible
+        * type is domain invalid, it's an invalid state, under the
+        * threaded subtree.
+        */
+       if (strncmp(cg_type, "domain", len) == 0 ||
+           strncmp(cg_type, "domain threaded", len) == 0) {
+               snprintf(type, type_sz, "cgroup.procs");
+       } else if (strncmp(cg_type, "threaded", len) == 0) {
+               snprintf(type, type_sz, "cgroup.threads");
+       } else {
+               cgroup_warn("Warning: invalid %scgroup.type: %s\n",
+                               path, cg_type);
+               err = ECGOTHER;
+       }
+
+out:
+       if (fp)
+               fclose(fp);
+
+       return err;
+}
+
 int cgroup_build_tasks_procs_path(char * const path,
                                  size_t path_sz, const char * const cg_name,
                                  const char * const ctrl_name)
 {
        enum cg_version_t version;
+       char cg_type[LL_MAX];
        int err = ECGOTHER;
 
        if (!cg_build_path(cg_name, path, ctrl_name))
@@ -1554,8 +1615,11 @@ int cgroup_build_tasks_procs_path(char * const path,
                err = 0;
                break;
        case CGROUP_V2:
-               strncat(path, "cgroup.procs", path_sz - strlen(path));
-               err = 0;
+               err = cgroup_get_cg_type(path, cg_type, sizeof(cg_type));
+               if (err)
+                       goto error;
+
+               strncat(path, cg_type , path_sz - strlen(path));
                break;
        default:
                err = ECGOTHER;
@@ -1566,6 +1630,8 @@ error:
        if (err)
                path[0] = '\0';
 
+       cgroup_dbg("cgroup build procs path: %s\n", path);
+
        return err;
 }