[LTP] [PATCH 2/3] lib/tst_pid: Go to parent cgroups for max value
Teo Couprie Diaz
teo.coupriediaz@arm.com
Wed Feb 15 15:54:39 CET 2023
A cgroup resource limitation can be either a number or "max".
It means that the cgroup will not be limited _more_ than it already is.
This can mean that it will use the kernel limit for the resource, if it
exists, or the limit of a parent cgroup.
This patch reworks "read_session_pids_limit" to go up the cgroup hierarchy
if it encounters a "max" value rather than a numerical one, using the
kernel limit in the event where it doesn't find any.
Clean up uid related code as it is not used anymore.
Signed-off-by: Teo Couprie Diaz <teo.coupriediaz@arm.com>
Co-developed-by: Beata Michalska <beata.michalska@arm.com>
Signed-off-by: Beata Michalska <beata.michalska@arm.com>
---
lib/tst_pid.c | 96 +++++++++++++++++++++++++++++----------------------
1 file changed, 54 insertions(+), 42 deletions(-)
diff --git a/lib/tst_pid.c b/lib/tst_pid.c
index 3d0be6dcd..ad1893290 100644
--- a/lib/tst_pid.c
+++ b/lib/tst_pid.c
@@ -44,50 +44,69 @@ pid_t tst_get_unused_pid_(void (*cleanup_fn) (void))
return pid;
}
-/*
- * Get the effective session UID - either one invoking current test via sudo
- * or the real UID.
- */
-static unsigned int get_session_uid(void)
+static int __read_pids_limit(const char *path, void (*cleanup_fn) (void))
{
- const char *sudo_uid;
+ char max_pids_value[100];
+ int max_pids;
- sudo_uid = getenv("SUDO_UID");
- if (sudo_uid) {
- unsigned int real_uid;
- int ret;
+ if (access(path, R_OK) != 0) {
+ tst_resm(TINFO, "Cannot read session user limits from '%s'", path);
+ return -1;
+ }
- ret = sscanf(sudo_uid, "%u", &real_uid);
- if (ret == 1)
- return real_uid;
+ SAFE_FILE_SCANF(cleanup_fn, path, "%s", max_pids_value);
+ if (strcmp(max_pids_value, "max")) {
+ max_pids = SAFE_STRTOL(max_pids_value, 0, INT_MAX);
+ tst_resm(TINFO, "Found limit of processes %d (from %s)",
+ max_pids, path);
+ } else {
+ max_pids = -1;
}
- return getuid();
+ return max_pids;
}
-static int read_session_pids_limit(const char *path_fmt, int uid,
- void (*cleanup_fn) (void))
+/*
+ * Take the path to the cgroup mount and to the current cgroup pid controller
+ * and try to find the PID limit imposed by cgroup.
+ * Go up the cgroup hierarchy if needed, otherwise use the kernel PID limit.
+ */
+static int read_session_pids_limit(const char *cgroup_mount,
+ const char *cgroup_path, void (*cleanup_fn) (void))
{
- int max_pids, ret;
- char max_pid_value[100];
- char path[PATH_MAX];
-
- ret = snprintf(path, sizeof(path), path_fmt, uid);
+ int ret, cgroup_depth = 0, max_pids = -1;
+ char path[PATH_MAX + 1], file_path[PATH_MAX + 1];
+ const char *sub_path = cgroup_path;
+
+ /* Find the number of groups we can go up. */
+ do {
+ cgroup_depth += 1;
+ sub_path++;
+ sub_path = strchr(sub_path, '/');
+ } while (sub_path);
+
+ ret = snprintf(path, sizeof(path), "%s%s", cgroup_mount, cgroup_path);
if (ret < 0 || (size_t)ret >= sizeof(path))
return -1;
- if (access(path, R_OK) != 0) {
- tst_resm(TINFO, "Cannot read session user limits from '%s'", path);
- return -1;
+ for (int i = 0 ; i < cgroup_depth ; i++) {
+ /* Create a path to read from. */
+ ret = snprintf(file_path, sizeof(file_path), "%s/pids.max", path);
+ if (ret < 0 || (size_t)ret >= sizeof(file_path))
+ return -1;
+
+ max_pids = __read_pids_limit(file_path, cleanup_fn);
+ if (max_pids >= 0)
+ return max_pids;
+
+ strncat(path, "/..", PATH_MAX);
}
- SAFE_FILE_SCANF(cleanup_fn, path, "%s", max_pid_value);
- if (!strcmp(max_pid_value, "max")) {
+ if (max_pids < 0) {
+ /* Read kernel imposed limits */
SAFE_FILE_SCANF(cleanup_fn, PID_MAX_PATH, "%d", &max_pids);
- tst_resm(TINFO, "Found limit of processes %d (from %s=max)", max_pids, path);
- } else {
- max_pids = SAFE_STRTOL(max_pid_value, 0, INT_MAX);
- tst_resm(TINFO, "Found limit of processes %d (from %s)", max_pids, path);
+ tst_resm(TINFO, "Using kernel processes limit of %d",
+ max_pids);
}
return max_pids;
@@ -98,9 +117,8 @@ static int get_session_pids_limit(void (*cleanup_fn) (void))
char path[PATH_MAX + 1];
char cgroup_pids[PATH_MAX + 1];
char catchall;
- int uid, ret = 0;
+ int ret = 0;
- uid = get_session_uid();
/* Check for generic cgroup v1 pid.max */
ret = FILE_LINES_SCANF(cleanup_fn, "/proc/self/cgroup",
"%*d:pids:%s\n", cgroup_pids);
@@ -121,11 +139,8 @@ static int get_session_pids_limit(void (*cleanup_fn) (void))
"%*s %*s %*s %*s %s %*[^-] - cgroup %*s %*[rw],pid%c",
path, &catchall);
- if (!ret) {
- strncat(path, cgroup_pids, PATH_MAX);
- strncat(path, "/pids.max", PATH_MAX);
- return read_session_pids_limit(path, uid, cleanup_fn);
- }
+ if (!ret)
+ return read_session_pids_limit(path, cgroup_pids, cleanup_fn);
/* Check for generic cgroup v2 pid.max */
ret = FILE_LINES_SCANF(cleanup_fn, "/proc/self/cgroup",
@@ -135,11 +150,8 @@ static int get_session_pids_limit(void (*cleanup_fn) (void))
"%*s %*s %*s %*s %s %*[^-] - cgroup2 %c",
path, &catchall);
- if (!ret) {
- strncat(path, cgroup_pids, PATH_MAX);
- strncat(path, "/pids.max", PATH_MAX);
- return read_session_pids_limit(path, uid, cleanup_fn);
- }
+ if (!ret)
+ return read_session_pids_limit(path, cgroup_pids, cleanup_fn);
return -1;
}
--
2.25.1
More information about the ltp
mailing list