[PATCH 3/9] cgroups: ability to stop res charge propagation on bounded ancestor

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Frederic Weisbecker <fweisbec@xxxxxxxxx>

Moving a task from a cgroup to another may require to substract its
resource charge from the old cgroup and add it to the new one.

For this to happen, the uncharge/charge propagation can just stop when we
reach the common ancestor for the two cgroups.  Further the performance
reasons, we also want to avoid to temporarily overload the common
ancestors with a non-accurate resource counter usage if we charge first
the new cgroup and uncharge the old one thereafter.  This is going to be a
requirement for the coming max number of task subsystem.

To solve this, provide a pair of new API that can charge/uncharge a
resource counter until we reach a given ancestor.

Signed-off-by: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Acked-by: Paul Menage <paul@xxxxxxxxxxxxxx>
Cc: Li Zefan <lizf@xxxxxxxxxxxxxx>
Cc: Johannes Weiner <hannes@xxxxxxxxxxx>
Cc: Aditya Kali <adityakali@xxxxxxxxxx>
Cc: Oleg Nesterov <oleg@xxxxxxxxxx>
Cc: Tim Hockin <thockin@xxxxxxxxxx>
Cc: Tejun Heo <htejun@xxxxxxxxx>
Cc: Containers <containers@xxxxxxxxxxxxxxxxxxxxxxxxxx>
Cc: Glauber Costa <glommer@xxxxxxxxx>
Cc: Cgroups <cgroups@xxxxxxxxxxxxxxx>
Cc: Daniel J Walsh <dwalsh@xxxxxxxxxx>
Cc: "Daniel P. Berrange" <berrange@xxxxxxxxxx>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@xxxxxxxxxxxxxx>
Cc: Max Kellermann <mk@xxxxxxxxxx>
Cc: Mandeep Singh Baines <msb@xxxxxxxxxxxx>
Acked-by: Kirill A. Shutemov <kirill@xxxxxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
---
 Documentation/cgroups/resource_counter.txt | 13 ++++++++++---
 include/linux/res_counter.h                |  4 ++++
 kernel/res_counter.c                       | 21 ++++++++++++++++-----
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/Documentation/cgroups/resource_counter.txt b/Documentation/cgroups/resource_counter.txt
index c4d99ed..57f41d5 100644
--- a/Documentation/cgroups/resource_counter.txt
+++ b/Documentation/cgroups/resource_counter.txt
@@ -83,7 +83,14 @@ to work with it.
 	res_counter->lock internally (it must be called with res_counter->lock
 	held). The force parameter indicates whether we can bypass the limit.
 
- e. u64 res_counter_uncharge[_locked]
+ e. int res_counter_charge_until(struct res_counter *counter,
+			     struct res_counter *limit, unsigned long val,
+			     struct res_counter **limit_fail_at)
+
+	The same as res_counter_charge(), but the charge propagation to
+	the hierarchy stops at the limit given in the "limit" parameter.
+
+ f. u64 res_counter_uncharge[_locked]
 			(struct res_counter *rc, unsigned long val)
 
 	When a resource is released (freed) it should be de-accounted
@@ -93,12 +100,12 @@ to work with it.
 
 	The _locked routines imply that the res_counter->lock is taken.
 
- f. u64 res_counter_uncharge_until
+ g. u64 res_counter_uncharge_until
 		(struct res_counter *rc, struct res_counter *top,
 		 unsinged long val)
 
 	Almost same as res_cunter_uncharge() but propagation of uncharge
-	stops when rc == top. This is useful when kill a res_coutner in
+	stops when rc == top. This is useful when kill a res_counter in
 	child cgroup.
 
  2.1 Other accounting routines
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h
index 92b9e18..9721fde 100644
--- a/include/linux/res_counter.h
+++ b/include/linux/res_counter.h
@@ -119,6 +119,10 @@ int __must_check res_counter_charge_locked(struct res_counter *counter,
 					   unsigned long val, bool force);
 int __must_check res_counter_charge(struct res_counter *counter,
 		unsigned long val, struct res_counter **limit_fail_at);
+int __must_check res_counter_charge_until(struct res_counter *counter,
+					  struct res_counter *top,
+					  unsigned long val,
+					  struct res_counter **limit_fail_at);
 int res_counter_charge_nofail(struct res_counter *counter,
 		unsigned long val, struct res_counter **limit_fail_at);
 
diff --git a/kernel/res_counter.c b/kernel/res_counter.c
index 6174478..dadb16e 100644
--- a/kernel/res_counter.c
+++ b/kernel/res_counter.c
@@ -40,8 +40,9 @@ int res_counter_charge_locked(struct res_counter *counter, unsigned long val,
 	return ret;
 }
 
-static int __res_counter_charge(struct res_counter *counter, unsigned long val,
-				struct res_counter **limit_fail_at, bool force)
+static int __res_counter_charge_until(struct res_counter *counter,
+			struct res_counter *top, unsigned long val,
+			struct res_counter **limit_fail_at, bool force)
 {
 	int ret, r;
 	unsigned long flags;
@@ -50,7 +51,7 @@ static int __res_counter_charge(struct res_counter *counter, unsigned long val,
 	r = ret = 0;
 	*limit_fail_at = NULL;
 	local_irq_save(flags);
-	for (c = counter; c != NULL; c = c->parent) {
+	for (c = counter; c != top; c = c->parent) {
 		spin_lock(&c->lock);
 		r = res_counter_charge_locked(c, val, force);
 		spin_unlock(&c->lock);
@@ -77,13 +78,23 @@ static int __res_counter_charge(struct res_counter *counter, unsigned long val,
 int res_counter_charge(struct res_counter *counter, unsigned long val,
 			struct res_counter **limit_fail_at)
 {
-	return __res_counter_charge(counter, val, limit_fail_at, false);
+	return __res_counter_charge_until(counter, NULL, val, limit_fail_at,
+					  false);
+}
+
+int res_counter_charge_until(struct res_counter *counter,
+			     struct res_counter *top, unsigned long val,
+			     struct res_counter **limit_fail_at)
+{
+	return __res_counter_charge_until(counter, top, val, limit_fail_at,
+					  false);
 }
 
 int res_counter_charge_nofail(struct res_counter *counter, unsigned long val,
 			      struct res_counter **limit_fail_at)
 {
-	return __res_counter_charge(counter, val, limit_fail_at, true);
+	return __res_counter_charge_until(counter, NULL, val, limit_fail_at,
+					  true);
 }
 
 u64 res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
-- 
1.8.3.1

_______________________________________________
Containers mailing list
Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linuxfoundation.org/mailman/listinfo/containers




[Index of Archives]     [Cgroups]     [Netdev]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux