[LTP] [PATCH 2/3] lib/tst_pid: Go to parent cgroups for max value
Teo Couprie Diaz
teo.coupriediaz@arm.com
Wed Mar 1 11:33:34 CET 2023
Hello,
On 28/02/2023 14:07, Richard Palethorpe wrote:
> Hello,
>
> Teo Couprie Diaz <teo.coupriediaz@arm.com> writes:
>
>> A cgroup resource limitation can be either a number or "max".
> IIRC this is not true on V1, at least not historically. On some tests we
> have to simulate "max" when V1 is detected.
>
> Perhaps for pids.max specifically it is the case though?
You would have more experience than me on that front ! However, from my
understanding, for `pids.max` specifically it should be correct.
The kernel documentation[0] of the cgroup-v1 pid controller states :
> To set a cgroup to have no limit, set pids.max to “max”. This is the
default for all new cgroups [...]
And from my testing I was not able to generate a cgroup *without*
pids.max: it was always present and set to "max".
However, there is no `pids.max` for the root cgroup at all; it cannot be
enabled. Thus it could make sense that if the process is in the root
cgroup you had to simulate "max", because there wouldn't be `pids.max`
to read.
But as discussed on the first patch I will need to come back to this
series anyway and rework it to make use of tst_cgroup, and extend _that_
if needed, rather than slap some more functionality on top of tst_pid.
If I do so and still need to add a patch similar to this one I will keep
in mind that this might be only true for the pid controller, for cgroups
other than the root cgroup.
Thanks again for the review,
Best regards
Téo
[0]:
https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/pids.html#usage
>
>> 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