cgroups.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Topi Miettinen <toiwoton@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Topi Miettinen <toiwoton@gmail.com>,
	Ingo Molnar <mingo@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>, Tejun Heo <tj@kernel.org>,
	Li Zefan <lizefan@huawei.com>,
	Johannes Weiner <hannes@cmpxchg.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Michal Hocko <mhocko@suse.com>,
	Vladimir Davydov <vdavydov@virtuozzo.com>,
	Joe Perches <joe@perches.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Andrea Arcangeli <aarcange@redhat.com>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	Andi Kleen <ak@linux.intel.com>, Oleg Nesterov <oleg@redhat.com>,
	Cyrill Gorcunov <gorcunov@openvz.org>,
	Mateusz Guzik <mguzik@redhat.com>,
	John Stultz <john.stultz@linaro.org>,
	Ben Segall <bsegall@google.com>, Rik van Riel <riel@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	"open list:CONTROL GROUP CGROUP" <cgroups@vger.kernel.org>
Subject: [PATCH 07/14] resource limits: track highwater mark of user processes
Date: Fri, 15 Jul 2016 13:35:54 +0300	[thread overview]
Message-ID: <1468578983-28229-8-git-send-email-toiwoton@gmail.com> (raw)
In-Reply-To: <1468578983-28229-1-git-send-email-toiwoton@gmail.com>

Track maximum number of processes per user, to be able to configure
RLIMIT_NPROC resource limits. The information is available
with taskstats and cgroupstats netlink socket.

Signed-off-by: Topi Miettinen <toiwoton@gmail.com>
---
 include/linux/sched.h | 30 ++++++++++++++++++++++++++++++
 kernel/cgroup.c       | 31 +++++++++++++++++++++++++++----
 kernel/cred.c         |  1 +
 kernel/fork.c         |  2 ++
 kernel/sys.c          |  2 ++
 kernel/tsacct.c       | 23 ++++++++++++++++++++++-
 6 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index e4d7482..d6af49b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -840,6 +840,7 @@ static inline int signal_group_exit(const struct signal_struct *sig)
 struct user_struct {
 	atomic_t __count;	/* reference count */
 	atomic_t processes;	/* How many processes does this user have? */
+	atomic_t max_processes;	/* How many processes has this user had at the same time? */
 	atomic_t sigpending;	/* How many pending signals does this user have? */
 #ifdef CONFIG_INOTIFY_USER
 	atomic_t inotify_watches; /* How many inotify watches does this user have? */
@@ -3344,6 +3345,27 @@ static inline void update_resource_highwatermark(unsigned int limit,
 {
 	task_update_resource_highwatermark(current, limit, r);
 }
+
+static inline void user_update_maxproc_highwatermark(struct user_struct *u)
+{
+	int processes;
+
+	processes = atomic_read(&u->processes);
+	if (atomic_read(&u->max_processes) < processes)
+		atomic_set(&u->max_processes, processes);
+}
+
+static inline void task_update_maxproc_highwatermark(struct task_struct *t)
+{
+	const struct cred *tcred;
+
+	rcu_read_lock();
+	tcred = __task_cred(t);
+
+	user_update_maxproc_highwatermark(tcred->user);
+
+	rcu_read_unlock();
+}
 #else
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
@@ -3370,6 +3392,14 @@ static inline void update_resource_highwatermark(unsigned int limit,
 						 unsigned long r)
 {
 }
+
+static inline void user_update_maxproc_highwatermark(struct user_struct *u)
+{
+}
+
+static inline void task_update_maxproc_highwatermark(struct task_struct *t)
+{
+}
 #endif
 
 #ifndef TASK_SIZE_OF
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 9b2d805..38a272f 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4660,6 +4660,23 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type,
 	return 0;
 }
 
+static void cgroup_update_maxproc_highwatermark(struct cgroup *cgrp,
+						struct task_struct *t)
+{
+	const struct cred *tcred;
+	struct user_struct *u;
+	int max_processes;
+
+	tcred = __task_cred(t);
+	u = tcred->user;
+
+	user_update_maxproc_highwatermark(u);
+
+	max_processes = atomic_read(&u->max_processes);
+	if (cgrp->stats.resource_hiwater[RLIMIT_NPROC] < max_processes)
+		cgrp->stats.resource_hiwater[RLIMIT_NPROC] = max_processes;
+}
+
 /*
  * Update cgroupstats based on the stats from exiting task
  */
@@ -4678,10 +4695,16 @@ static void cgroup_update_stats_from_task(struct cgroup *cgrp,
 		seq = nextseq;
 		flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
 		for (i = 0; i < RLIM_NLIMITS; i++)
-			if (cgrp->stats.resource_hiwater[i] <
-			    sig->resource_highwatermark[i])
-				cgrp->stats.resource_hiwater[i] =
-					sig->resource_highwatermark[i];
+			switch(i) {
+			case RLIMIT_NPROC:
+				cgroup_update_maxproc_highwatermark(cgrp, tsk);
+				break;
+			default:
+				if (cgrp->stats.resource_hiwater[i] <
+				    sig->resource_highwatermark[i])
+					cgrp->stats.resource_hiwater[i] =
+						sig->resource_highwatermark[i];
+			}
 
 		/* If lockless access failed, take the lock. */
 		nextseq = 1;
diff --git a/kernel/cred.c b/kernel/cred.c
index 0c0cd8a..e12ab6e 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -467,6 +467,7 @@ int commit_creds(struct cred *new)
 	rcu_assign_pointer(task->cred, new);
 	if (new->user != old->user)
 		atomic_dec(&old->user->processes);
+	user_update_maxproc_highwatermark(new->user);
 	alter_cred_subscribers(old, -2);
 
 	/* send notifications */
diff --git a/kernel/fork.c b/kernel/fork.c
index 4a7ec0c..3f636c7 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1640,6 +1640,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 		nr_threads++;
 	}
 
+	task_update_maxproc_highwatermark(p);
+
 	total_forks++;
 	spin_unlock(&current->sighand->siglock);
 	syscall_tracepoint_update(p);
diff --git a/kernel/sys.c b/kernel/sys.c
index d84c87e..f1def17 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -439,6 +439,8 @@ static int set_user(struct cred *new)
 	else
 		current->flags &= ~PF_NPROC_EXCEEDED;
 
+	user_update_maxproc_highwatermark(new_user);
+
 	free_uid(new->user);
 	new->user = new_user;
 	return 0;
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 231bae3..9fd4cef 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -184,6 +184,19 @@ void acct_clear_integrals(struct task_struct *tsk)
 	tsk->acct_vm_mem1 = 0;
 }
 
+static __u64 task_get_maxproc_highwatermark(struct task_struct *t)
+{
+	const struct cred *tcred;
+	struct user_struct *u;
+
+	tcred = __task_cred(t);
+	u = tcred->user;
+
+	user_update_maxproc_highwatermark(u);
+
+	return (__u64)atomic_read(&u->max_processes);
+}
+
 /*
  * fill in resource accounting fields
  */
@@ -201,7 +214,15 @@ void racct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
 		seq = nextseq;
 		flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
 		for (i = 0; i < RLIM_NLIMITS; i++)
-			stats->resource_hiwater[i] = (__u64)sig->resource_highwatermark[i];
+			switch(i) {
+			case RLIMIT_NPROC:
+				stats->resource_hiwater[i] =
+					task_get_maxproc_highwatermark(tsk);
+				break;
+			default:
+				stats->resource_hiwater[i] =
+					(__u64)sig->resource_highwatermark[i];
+			}
 
 		/* If lockless access failed, take the lock. */
 		nextseq = 1;
-- 
2.8.1


  parent reply	other threads:[~2016-07-15 10:35 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-15 10:35 [PATCH 00/14] Present useful limits to user (v2) Topi Miettinen
2016-07-15 10:35 ` [PATCH 02/14] resource limits: aggregate task highwater marks to cgroup level Topi Miettinen
2016-07-15 12:38   ` kbuild test robot
2016-07-15 14:10   ` Tejun Heo
2016-07-15 17:15     ` Topi Miettinen
2016-07-18 22:52       ` Tejun Heo
2016-07-19 16:57         ` Topi Miettinen
2016-07-19 18:18           ` Tejun Heo
2016-07-15 10:35 ` Topi Miettinen [this message]
2016-07-15 12:43 ` [PATCH 00/14] Present useful limits to user (v2) Peter Zijlstra
2016-07-15 13:52   ` Topi Miettinen
2016-07-15 13:59     ` Peter Zijlstra
2016-07-15 16:57       ` Topi Miettinen
     [not found]       ` <20160715135956.GA3115-ndre7Fmf5hadTX5a5knrm8zTDFooKrT+cvkQGrU6aU0@public.gmane.org>
2016-07-15 20:54         ` H. Peter Anvin
2016-07-15 13:04 ` Balbir Singh
2016-07-15 16:35   ` Topi Miettinen
2016-07-18 22:05     ` Doug Ledford
2016-07-19 16:53       ` Topi Miettinen
2016-07-15 14:19 ` Richard Weinberger
2016-07-15 17:19   ` Topi Miettinen
2016-07-18 21:25   ` Doug Ledford
2016-08-03 18:20 ` Topi Miettinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1468578983-28229-8-git-send-email-toiwoton@gmail.com \
    --to=toiwoton@gmail.com \
    --cc=aarcange@redhat.com \
    --cc=ak@linux.intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=bsegall@google.com \
    --cc=cgroups@vger.kernel.org \
    --cc=ebiederm@xmission.com \
    --cc=fweisbec@gmail.com \
    --cc=gorcunov@openvz.org \
    --cc=hannes@cmpxchg.org \
    --cc=joe@perches.com \
    --cc=john.stultz@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan@huawei.com \
    --cc=mguzik@redhat.com \
    --cc=mhocko@suse.com \
    --cc=mingo@redhat.com \
    --cc=oleg@redhat.com \
    --cc=peterz@infradead.org \
    --cc=riel@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=tj@kernel.org \
    --cc=vdavydov@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).