|
@@ -49,6 +49,12 @@ struct pids_cgroup {
|
|
|
*/
|
|
|
atomic64_t counter;
|
|
|
int64_t limit;
|
|
|
+
|
|
|
+ /* Handle for "pids.events" */
|
|
|
+ struct cgroup_file events_file;
|
|
|
+
|
|
|
+ /* Number of times fork failed because limit was hit. */
|
|
|
+ atomic64_t events_limit;
|
|
|
};
|
|
|
|
|
|
static struct pids_cgroup *css_pids(struct cgroup_subsys_state *css)
|
|
@@ -72,6 +78,7 @@ pids_css_alloc(struct cgroup_subsys_state *parent)
|
|
|
|
|
|
pids->limit = PIDS_MAX;
|
|
|
atomic64_set(&pids->counter, 0);
|
|
|
+ atomic64_set(&pids->events_limit, 0);
|
|
|
return &pids->css;
|
|
|
}
|
|
|
|
|
@@ -213,10 +220,21 @@ static int pids_can_fork(struct task_struct *task)
|
|
|
{
|
|
|
struct cgroup_subsys_state *css;
|
|
|
struct pids_cgroup *pids;
|
|
|
+ int err;
|
|
|
|
|
|
css = task_css_check(current, pids_cgrp_id, true);
|
|
|
pids = css_pids(css);
|
|
|
- return pids_try_charge(pids, 1);
|
|
|
+ err = pids_try_charge(pids, 1);
|
|
|
+ if (err) {
|
|
|
+ /* Only log the first time events_limit is incremented. */
|
|
|
+ if (atomic64_inc_return(&pids->events_limit) == 1) {
|
|
|
+ pr_info("cgroup: fork rejected by pids controller in ");
|
|
|
+ pr_cont_cgroup_path(task_cgroup(current, pids_cgrp_id));
|
|
|
+ pr_cont("\n");
|
|
|
+ }
|
|
|
+ cgroup_file_notify(&pids->events_file);
|
|
|
+ }
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static void pids_cancel_fork(struct task_struct *task)
|
|
@@ -288,6 +306,14 @@ static s64 pids_current_read(struct cgroup_subsys_state *css,
|
|
|
return atomic64_read(&pids->counter);
|
|
|
}
|
|
|
|
|
|
+static int pids_events_show(struct seq_file *sf, void *v)
|
|
|
+{
|
|
|
+ struct pids_cgroup *pids = css_pids(seq_css(sf));
|
|
|
+
|
|
|
+ seq_printf(sf, "max %ld\n", atomic64_read(&pids->events_limit));
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static struct cftype pids_files[] = {
|
|
|
{
|
|
|
.name = "max",
|
|
@@ -300,6 +326,12 @@ static struct cftype pids_files[] = {
|
|
|
.read_s64 = pids_current_read,
|
|
|
.flags = CFTYPE_NOT_ON_ROOT,
|
|
|
},
|
|
|
+ {
|
|
|
+ .name = "events",
|
|
|
+ .seq_show = pids_events_show,
|
|
|
+ .file_offset = offsetof(struct pids_cgroup, events_file),
|
|
|
+ .flags = CFTYPE_NOT_ON_ROOT,
|
|
|
+ },
|
|
|
{ } /* terminate */
|
|
|
};
|
|
|
|