예제 #1
0
        /// <summary>Find the cgroup path for the specified subsystem.</summary>
        /// <param name="subsystem">The subsystem, e.g. "memory".</param>
        /// <returns>The cgroup path if found; otherwise, null.</returns>
        private static string FindCGroupPath(string subsystem, out CGroupVersion version)
        {
            if (TryFindHierarchyMount(subsystem, out version, out string hierarchyRoot, out string hierarchyMount) &&
                TryFindCGroupPathForSubsystem(subsystem, out string cgroupPathRelativeToMount))
            {
                // For a host cgroup, we need to append the relative path.
                // In a docker container, the root and relative path are the same and we don't need to append.
                return((hierarchyRoot != cgroupPathRelativeToMount) ?
                       hierarchyMount + cgroupPathRelativeToMount :
                       hierarchyMount);
            }

            return(null);
        }
예제 #2
0
        internal static bool TryFindHierarchyMount(string mountInfoFilePath, string subsystem, out CGroupVersion version, out string root, out string path)
        {
            if (File.Exists(mountInfoFilePath))
            {
                try
                {
                    using (var reader = new StreamReader(mountInfoFilePath))
                    {
                        string line;
                        while ((line = reader.ReadLine()) != null)
                        {
                            // Look for an entry that has cgroup as the "filesystem type"
                            // and, for cgroup1, that has options containing the specified subsystem
                            // See man page for /proc/[pid]/mountinfo for details, e.g.:
                            //     (1)(2)(3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)
                            //     36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
                            // but (7) is optional and could exist as multiple fields; the (8) separator marks
                            // the end of the optional values.

                            const string Separator           = " - ";
                            int          endOfOptionalFields = line.IndexOf(Separator);
                            if (endOfOptionalFields == -1)
                            {
                                // Malformed line.
                                continue;
                            }

                            string   postSeparatorLine      = line.Substring(endOfOptionalFields + Separator.Length);
                            string[] postSeparatorlineParts = postSeparatorLine.Split(' ');
                            if (postSeparatorlineParts.Length < 3)
                            {
                                // Malformed line.
                                continue;
                            }

                            bool validCGroup1Entry = ((postSeparatorlineParts[0] == "cgroup") &&
                                                      (Array.IndexOf(postSeparatorlineParts[2].Split(','), subsystem) >= 0));
                            bool validCGroup2Entry = postSeparatorlineParts[0] == "cgroup2";

                            if (!validCGroup1Entry && !validCGroup2Entry)
                            {
                                // Not the relevant entry.
                                continue;
                            }

                            // Found the relevant entry.  Extract the cgroup version, mount root and path.
                            switch (postSeparatorlineParts[0])
                            {
                            case "cgroup":
                                version = CGroupVersion.CGroup1;
                                break;

                            case "cgroup2":
                                version = CGroupVersion.CGroup2;
                                break;

                            default:
                                version = CGroupVersion.None;
                                Debug.Fail($"invalid value for CGroupVersion \"{postSeparatorlineParts[0]}\"");
                                break;
                            }

                            string[] lineParts = line.Substring(0, endOfOptionalFields).Split(' ');
                            root = lineParts[3];
                            path = lineParts[4];

                            return(true);
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.Fail($"Failed to read or parse \"{ProcMountInfoFilePath}\": {e}");
                }
            }

            version = CGroupVersion.None;
            root    = null;
            path    = null;
            return(false);
        }
예제 #3
0
 /// <summary>Find the cgroup mount information for the specified subsystem.</summary>
 /// <param name="subsystem">The subsystem, e.g. "memory".</param>
 /// <param name="root">The path of the directory in the filesystem which forms the root of this mount; null if not found.</param>
 /// <param name="path">The path of the mount point relative to the process's root directory; null if not found.</param>
 /// <returns>true if the mount was found; otherwise, null.</returns>
 private static bool TryFindHierarchyMount(string subsystem, out CGroupVersion version, out string root, out string path)
 {
     return(TryFindHierarchyMount(ProcMountInfoFilePath, subsystem, out version, out root, out path));
 }
예제 #4
0
 private static bool TryFindHierarchyMount(string subsystem, out CGroupVersion version, [NotNullWhen(true)] out string?root, [NotNullWhen(true)] out string?path)
 {
     return(TryFindHierarchyMount(ProcMountInfoFilePath, subsystem, out version, out root, out path));
 }