Skip to content

Commit 3f26a88

Browse files
Werkovhtejun
authored andcommitted
cgroup/pids: Add pids.events.local
Hierarchical counting of events is not practical for watching when a particular pids.max is being hit. Therefore introduce .local flavor of events file (akin to memory controller) that collects only events relevant to given cgroup. The file is only added to the default hierarchy. Signed-off-by: Michal Koutný <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
1 parent 385a635 commit 3f26a88

File tree

2 files changed

+76
-18
lines changed

2 files changed

+76
-18
lines changed

Documentation/admin-guide/cgroup-v2.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,11 @@ PID Interface Files
22202220
The number of times the cgroup's total number of processes hit the pids.max
22212221
limit (see also pids_localevents).
22222222

2223+
pids.events.local
2224+
Similar to pids.events but the fields in the file are local
2225+
to the cgroup i.e. not hierarchical. The file modified event
2226+
generated on this file reflects only the local events.
2227+
22232228
Organisational operations are not blocked by cgroup policies, so it is
22242229
possible to have pids.current > pids.max. This can be done by either
22252230
setting the limit to be smaller than pids.current, or attaching enough

kernel/cgroup/pids.c

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,12 @@ struct pids_cgroup {
5757
atomic64_t limit;
5858
int64_t watermark;
5959

60-
/* Handle for "pids.events" */
60+
/* Handles for pids.events[.local] */
6161
struct cgroup_file events_file;
62+
struct cgroup_file events_local_file;
6263

6364
atomic64_t events[NR_PIDCG_EVENTS];
65+
atomic64_t events_local[NR_PIDCG_EVENTS];
6466
};
6567

6668
static struct pids_cgroup *css_pids(struct cgroup_subsys_state *css)
@@ -244,21 +246,23 @@ static void pids_event(struct pids_cgroup *pids_forking,
244246
struct pids_cgroup *p = pids_forking;
245247
bool limit = false;
246248

247-
for (; parent_pids(p); p = parent_pids(p)) {
248-
/* Only log the first time limit is hit. */
249-
if (atomic64_inc_return(&p->events[PIDCG_FORKFAIL]) == 1) {
250-
pr_info("cgroup: fork rejected by pids controller in ");
251-
pr_cont_cgroup_path(p->css.cgroup);
252-
pr_cont("\n");
253-
}
254-
cgroup_file_notify(&p->events_file);
255-
256-
if (!cgroup_subsys_on_dfl(pids_cgrp_subsys) ||
257-
cgrp_dfl_root.flags & CGRP_ROOT_PIDS_LOCAL_EVENTS)
258-
break;
249+
/* Only log the first time limit is hit. */
250+
if (atomic64_inc_return(&p->events_local[PIDCG_FORKFAIL]) == 1) {
251+
pr_info("cgroup: fork rejected by pids controller in ");
252+
pr_cont_cgroup_path(p->css.cgroup);
253+
pr_cont("\n");
254+
}
255+
cgroup_file_notify(&p->events_local_file);
256+
if (!cgroup_subsys_on_dfl(pids_cgrp_subsys) ||
257+
cgrp_dfl_root.flags & CGRP_ROOT_PIDS_LOCAL_EVENTS)
258+
return;
259259

260-
if (p == pids_over_limit)
260+
for (; parent_pids(p); p = parent_pids(p)) {
261+
if (p == pids_over_limit) {
261262
limit = true;
263+
atomic64_inc(&p->events_local[PIDCG_MAX]);
264+
cgroup_file_notify(&p->events_local_file);
265+
}
262266
if (limit)
263267
atomic64_inc(&p->events[PIDCG_MAX]);
264268

@@ -368,20 +372,68 @@ static s64 pids_peak_read(struct cgroup_subsys_state *css,
368372
return READ_ONCE(pids->watermark);
369373
}
370374

371-
static int pids_events_show(struct seq_file *sf, void *v)
375+
static int __pids_events_show(struct seq_file *sf, bool local)
372376
{
373377
struct pids_cgroup *pids = css_pids(seq_css(sf));
374378
enum pidcg_event pe = PIDCG_MAX;
379+
atomic64_t *events;
375380

376381
if (!cgroup_subsys_on_dfl(pids_cgrp_subsys) ||
377-
cgrp_dfl_root.flags & CGRP_ROOT_PIDS_LOCAL_EVENTS)
382+
cgrp_dfl_root.flags & CGRP_ROOT_PIDS_LOCAL_EVENTS) {
378383
pe = PIDCG_FORKFAIL;
384+
local = true;
385+
}
386+
events = local ? pids->events_local : pids->events;
379387

380-
seq_printf(sf, "max %lld\n", (s64)atomic64_read(&pids->events[pe]));
388+
seq_printf(sf, "max %lld\n", (s64)atomic64_read(&events[pe]));
389+
return 0;
390+
}
391+
392+
static int pids_events_show(struct seq_file *sf, void *v)
393+
{
394+
__pids_events_show(sf, false);
395+
return 0;
396+
}
397+
398+
static int pids_events_local_show(struct seq_file *sf, void *v)
399+
{
400+
__pids_events_show(sf, true);
381401
return 0;
382402
}
383403

384404
static struct cftype pids_files[] = {
405+
{
406+
.name = "max",
407+
.write = pids_max_write,
408+
.seq_show = pids_max_show,
409+
.flags = CFTYPE_NOT_ON_ROOT,
410+
},
411+
{
412+
.name = "current",
413+
.read_s64 = pids_current_read,
414+
.flags = CFTYPE_NOT_ON_ROOT,
415+
},
416+
{
417+
.name = "peak",
418+
.flags = CFTYPE_NOT_ON_ROOT,
419+
.read_s64 = pids_peak_read,
420+
},
421+
{
422+
.name = "events",
423+
.seq_show = pids_events_show,
424+
.file_offset = offsetof(struct pids_cgroup, events_file),
425+
.flags = CFTYPE_NOT_ON_ROOT,
426+
},
427+
{
428+
.name = "events.local",
429+
.seq_show = pids_events_local_show,
430+
.file_offset = offsetof(struct pids_cgroup, events_local_file),
431+
.flags = CFTYPE_NOT_ON_ROOT,
432+
},
433+
{ } /* terminate */
434+
};
435+
436+
static struct cftype pids_files_legacy[] = {
385437
{
386438
.name = "max",
387439
.write = pids_max_write,
@@ -407,6 +459,7 @@ static struct cftype pids_files[] = {
407459
{ } /* terminate */
408460
};
409461

462+
410463
struct cgroup_subsys pids_cgrp_subsys = {
411464
.css_alloc = pids_css_alloc,
412465
.css_free = pids_css_free,
@@ -415,7 +468,7 @@ struct cgroup_subsys pids_cgrp_subsys = {
415468
.can_fork = pids_can_fork,
416469
.cancel_fork = pids_cancel_fork,
417470
.release = pids_release,
418-
.legacy_cftypes = pids_files,
471+
.legacy_cftypes = pids_files_legacy,
419472
.dfl_cftypes = pids_files,
420473
.threaded = true,
421474
};

0 commit comments

Comments
 (0)