On 5/8/20 9:21 AM, Dhaval Giani wrote:
On Fri, May 8, 2020 at 7:46 AM Tom Hromatka <tom.hroma...@oracle.com> wrote:

This commit adds cgroup v2 support to cgroup_init(),
cg_test_mounted_fs(), and cgroup_get_cgroup().  With these
changes, cgget and cgset now work on a cgroup v1 mount, a
cgroup v2 mount, or a cgroup v2 unified mount hierarchy.


There is a lot of stuff happening in this patch.

Could you please split the patch slightly?

- prepwork introducing needed fields (Version field comes to mind straight
up)
- pre reqs needed for v2 support
- v2 support


Sure!  Splitting it up as you outlined above should definitely
make reviewing it easier.

I'll send out a v2 in the next few days.

Thanks.

Tom



I *think* the patch looks fine, but my 8am brain is slow :), the patch
split will make it easier to parse the review :)


Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com>
---
  src/api.c                | 142 ++++++++++++++++++++++++++++++++++-----
  src/libcgroup-internal.h |   6 ++
  2 files changed, 132 insertions(+), 16 deletions(-)

diff --git a/src/api.c b/src/api.c
index 3845352f07cf..0c05f851391a 100644
--- a/src/api.c
+++ b/src/api.c
@@ -63,6 +63,12 @@ static __thread char errtext[MAXLEN];
  /* Task command name length */
  #define TASK_COMM_LEN 16

+/* cgroup v2 controllers file */
+#define CGV2_CONTROLLERS_FILE "cgroup.controllers"
+
+/* maximum line length when reading the cgroup.controllers file */
+#define LL_MAX                 100
+
  /* Check if cgroup_init has been called or not. */
  static int cgroup_initialized;

@@ -1086,6 +1092,7 @@ static int cgroup_process_v1_mnt(char
*controllers[], struct mntent *ent,
                 cg_mount_table[*mnt_tbl_idx].mount.path[FILENAME_MAX-1] =
                         '\0';
                 cg_mount_table[*mnt_tbl_idx].mount.next = NULL;
+               cg_mount_table[*mnt_tbl_idx].version = CGROUP_V1;




                 cgroup_dbg("Found cgroup option %s, count %d\n",
                         ent->mnt_opts, *mnt_tbl_idx);
                 (*mnt_tbl_idx)++;
@@ -1147,6 +1154,96 @@ out:
         return ret;
  }

+/**
+ * Process a cgroup v2 mount and add it to cg_mount_table if it's not a
+ * duplicate.
+ *
+ *     @param ent File system description of cgroup mount being processed
+ *     @param mnt_tbl_idx cg_mount_table index
+ */
+static int cgroup_process_v2_mnt(struct mntent *ent, int *mnt_tbl_idx)
+{
+       char cgroup_controllers_path[FILENAME_MAX];
+       char *ret_c = NULL, line[LL_MAX], *stok_buff = NULL;
+       int ret = 0, i, duplicate;
+       FILE *fp = NULL;
+
+       /* determine what v2 controllers are available on this mount */
+       snprintf(cgroup_controllers_path, FILENAME_MAX, "%s/%s",
ent->mnt_dir,
+                CGV2_CONTROLLERS_FILE);
+
+       fp = fopen(cgroup_controllers_path, "re");
+       if (!fp) {
+               ret = ECGOTHER;
+               goto out;
+       }
+
+       ret_c = fgets(line, LL_MAX, fp);
+       if (ret_c == NULL) {
+               ret = ECGEOF;
+               goto out;
+       }
+
+       /* remove the trailing newline */
+       ret_c[strlen(ret_c) - 1] = '\0';
+
+       /*
+        * cgroup.controllers returns a list of available controllers in
+        * the following format:
+        *      cpuset cpu io memory pids rdma
+        */
+       stok_buff = strtok(ret_c, " ");
+       while (stok_buff) {
+               /* do not have duplicates in mount table */
+               duplicate = 0;
+
+               for  (i = 0; i < *mnt_tbl_idx; i++) {
+                       if (strncmp(cg_mount_table[i].name, stok_buff,
+                                       FILENAME_MAX) == 0) {
+                               duplicate = 1;
+                               break;
+                       }
+               }
+
+               if (duplicate) {
+                       cgroup_dbg("controller %s is already mounted on
%s\n",
+                               stok_buff, cg_mount_table[i].mount.path);
+
+                       ret = cg_add_duplicate_mount(&cg_mount_table[i],
+                                       ent->mnt_dir);
+                       if (ret)
+                               goto out;
+
+                       /* advance to the next controller */
+                       stok_buff = strtok(NULL, " ");
+                       continue;
+               }
+
+               /* this controller is not in the mount table.  add it */
+               strncpy(cg_mount_table[*mnt_tbl_idx].name,
+                       stok_buff, FILENAME_MAX);
+               cg_mount_table[*mnt_tbl_idx].name[FILENAME_MAX-1] = '\0';
+               strncpy(cg_mount_table[*mnt_tbl_idx].mount.path,
+                       ent->mnt_dir, FILENAME_MAX);
+               cg_mount_table[*mnt_tbl_idx].mount.path[FILENAME_MAX-1] =
+                       '\0';
+               cg_mount_table[*mnt_tbl_idx].mount.next = NULL;
+               cg_mount_table[*mnt_tbl_idx].version = CGROUP_V2;
+               cgroup_dbg("Found cgroup option %s, count %d\n",
+                       stok_buff, *mnt_tbl_idx);
+               (*mnt_tbl_idx)++;
+
+               /* advance to the next controller */
+               stok_buff = strtok(NULL, " ");
+       }
+
+out:
+       if (fp)
+               fclose(fp);
+
+       return ret;
+}
+
  /**
   * cgroup_init(), initializes the MOUNT_POINT.
   *
@@ -1255,6 +1352,16 @@ int cgroup_init(void)
                         if (ret)
                                 goto unlock_exit;
                 }
+               else if (strcmp(ent->mnt_type, "cgroup2") == 0) {
+                       ret = cgroup_process_v2_mnt(ent, &found_mnt);
+                       if (ret == ECGEOF)
+                               /* The controllers file was empty.  Ignore
and
+                                * move on.
+                                */
+                               continue;
+                       else if (ret)
+                               goto unlock_exit;
+               }
         }

         free(temp_ent);
@@ -1314,7 +1421,8 @@ static int cg_test_mounted_fs(void)
                 goto done;
         }

-       while (strcmp(ent->mnt_type, "cgroup") != 0) {
+       while (strcmp(ent->mnt_type, "cgroup") != 0 &&
+              strcmp(ent->mnt_type, "cgroup2") != 0) {
                 ent = getmntent_r(proc_mount, temp_ent, mntent_buff,
                                                 sizeof(mntent_buff));
                 if (ent == NULL) {
@@ -2687,25 +2795,27 @@ int cgroup_get_cgroup(struct cgroup *cgroup)
                  * Get the uid and gid information
                  */

-               ret = asprintf(&control_path, "%s/tasks", path);
+               if (cg_mount_table[i].version == CGROUP_V1) {
+                       ret = asprintf(&control_path, "%s/tasks", path);

-               if (ret < 0) {
-                       last_errno = errno;
-                       error = ECGOTHER;
-                       goto unlock_error;
-               }
+                       if (ret < 0) {
+                               last_errno = errno;
+                               error = ECGOTHER;
+                               goto unlock_error;
+                       }

-               if (stat(control_path, &stat_buffer)) {
-                       last_errno = errno;
-                       free(control_path);
-                       error = ECGOTHER;
-                       goto unlock_error;
-               }
+                       if (stat(control_path, &stat_buffer)) {
+                               last_errno = errno;
+                               free(control_path);
+                               error = ECGOTHER;
+                               goto unlock_error;
+                       }

-               cgroup->tasks_uid = stat_buffer.st_uid;
-               cgroup->tasks_gid = stat_buffer.st_gid;
+                       cgroup->tasks_uid = stat_buffer.st_uid;
+                       cgroup->tasks_gid = stat_buffer.st_gid;

-               free(control_path);
+                       free(control_path);
+               }

                 cgc = cgroup_add_controller(cgroup,
                                 cg_mount_table[i].name);
diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h
index e31df512fcbe..dc292c661842 100644
--- a/src/libcgroup-internal.h
+++ b/src/libcgroup-internal.h
@@ -112,6 +112,11 @@ struct cg_mount_point {
         struct cg_mount_point *next;
  };

+enum cg_version_t {
+       CGROUP_V1,
+       CGROUP_V2,
+};
+
  struct cg_mount_table_s {
         /** Controller name. */
         char name[FILENAME_MAX];
@@ -120,6 +125,7 @@ struct cg_mount_table_s {
          */
         struct cg_mount_point mount;
         int index;
+       enum cg_version_t version;
  };

  struct cgroup_rules_data {
--
2.25.3



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




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

Reply via email to