[LTP] [PATCH 1/3] lib/tst_pid: Find cgroup pid.max programmatically
Richard Palethorpe
rpalethorpe@suse.de
Tue Feb 28 14:50:39 CET 2023
Hello,
Teo Couprie Diaz <teo.coupriediaz@arm.com> writes:
> In some distributions, the two files used in lib/tst_pid.c are not
> available, but cgroups still imposes a task limit far smaller than
> the kernel pid_max.
> If the cgroup sysfs is mounted, we can use it to retrieve the current task
> limit imposed to the process. Implement the retrieval of this limit.
>
> This can be done by first checking /proc/self/cgroup to get the cgroup
> the process is in, which will be a path under the cgroup sysfs.
> To get the path to the cgroup sysfs, check /proc/self/mountinfo.
> Finally, concatenate those two paths with pid.max to get the full path
> to the file containing the limit.
>
> This patch changes the way read_session_pids_limit is called, not passing
> a format string to be completed anymore, but is still used the same way.
> A following patch will update this function.
>
> This fixes failures for msgstress04.
>
> Signed-off-by: Teo Couprie Diaz <teo.coupriediaz@arm.com>
> ---
> lib/tst_pid.c | 53 +++++++++++++++++++++++++++++++++++++++++----------
> 1 file changed, 43 insertions(+), 10 deletions(-)
>
> diff --git a/lib/tst_pid.c b/lib/tst_pid.c
> index 5595e79bd..3d0be6dcd 100644
> --- a/lib/tst_pid.c
> +++ b/lib/tst_pid.c
> @@ -32,8 +32,6 @@
>
> #define PID_MAX_PATH "/proc/sys/kernel/pid_max"
> #define THREADS_MAX_PATH "/proc/sys/kernel/threads-max"
> -#define CGROUPS_V1_SLICE_FMT "/sys/fs/cgroup/pids/user.slice/user-%d.slice/pids.max"
> -#define CGROUPS_V2_SLICE_FMT "/sys/fs/cgroup/user.slice/user-%d.slice/pids.max"
> /* Leave some available processes for the OS */
> #define PIDS_RESERVE 50
>
> @@ -97,18 +95,53 @@ static int read_session_pids_limit(const char *path_fmt, int uid,
>
> static int get_session_pids_limit(void (*cleanup_fn) (void))
> {
> - int max_pids, uid;
> + char path[PATH_MAX + 1];
> + char cgroup_pids[PATH_MAX + 1];
> + char catchall;
> + int uid, ret = 0;
>
> uid = get_session_uid();
> - max_pids = read_session_pids_limit(CGROUPS_V2_SLICE_FMT, uid, cleanup_fn);
> - if (max_pids < 0)
> - max_pids = read_session_pids_limit(CGROUPS_V1_SLICE_FMT, uid,
> - cleanup_fn);
> + /* Check for generic cgroup v1 pid.max */
> + ret = FILE_LINES_SCANF(cleanup_fn, "/proc/self/cgroup",
> + "%*d:pids:%s\n", cgroup_pids);
> + /*
> + * This is a bit of a hack of scanf format strings. Indeed, if all
> + * conversion specifications have been matched the return of scanf will be
> + * the same whether any outstanding literal characters match or not.
> + * As we want to match the literal part, we can add a catchall after it
> + * so that it won't be counted if the literal part doesn't match.
> + * This makes the macro go to the next line until the catchall, thus
> + * the literal parts, is matched.
> + *
> + * Assume that the root of the mount is '/'. It can be anything,
> + * but it should be '/' on any normal system.
> + */
> + if (!ret)
> + ret = FILE_LINES_SCANF(cleanup_fn, "/proc/self/mountinfo",
> + "%*s %*s %*s %*s %s %*[^-] - cgroup %*s %*[rw],pid%c",
> + path,
> &catchall);
Uhhff, I already implemented this logic in tst_cg_scan in tst_cgroup. In
there we scan the current CGroup hierarchy and build a data structure
which represents it.
I guess you are not aware of tst_cgroup?
> +
> + if (!ret) {
> + strncat(path, cgroup_pids, PATH_MAX);
> + strncat(path, "/pids.max", PATH_MAX);
> + return read_session_pids_limit(path, uid, cleanup_fn);
> + }
>
> - if (max_pids < 0)
> - return -1;
> + /* Check for generic cgroup v2 pid.max */
> + ret = FILE_LINES_SCANF(cleanup_fn, "/proc/self/cgroup",
> + "%*d::%s\n",
> cgroup_pids);
This has not been added to tst_cgroup because usually tests that need a
cgroup feature are moved to a cgroup created by LTP. We also check that
any required CGroups are available and mount them if necessary.
I suppose in this case we do not care if there is no CGroup hierarchy or
the pids controller is absent?
In any case I think tst_cgroup should be used or extended.
> + if (!ret)
> + ret = FILE_LINES_SCANF(cleanup_fn, "/proc/self/mountinfo",
> + "%*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);
> + }
>
> - return max_pids;
> + return -1;
> }
>
> int tst_get_free_pids_(void (*cleanup_fn) (void))
> --
> 2.25.1
--
Thank you,
Richard.
More information about the ltp
mailing list