Home » Mailing lists » Devel » [PATCH] cgroup: Remove RCU from task->cgroups 
	
		
		
			| [PATCH] cgroup: Remove RCU from task->cgroups [message #41911] | 
			Sun, 21 November 2010 02:00   | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		The synchronize_rcu call in cgroup_attach_task can be very 
expensive.  All fastpath accesses to task->cgroups already 
use task_lock() or cgroup_lock() to protect against updates, 
and only the CGROUP_DEBUG files have RCU read-side critical 
sections. 
 
This patch replaces rcu_read_lock() with task_lock(current) 
around the debug file acceses to current->cgroups and removes 
the synchronize_rcu call in cgroup_attach_task. 
 
Signed-off-by: Colin Cross <ccross@android.com> 
--- 
 kernel/cgroup.c |   22 ++++++++-------------- 
 1 files changed, 8 insertions(+), 14 deletions(-) 
 
diff --git a/kernel/cgroup.c b/kernel/cgroup.c 
index 66a416b..4a40183 100644 
--- a/kernel/cgroup.c 
+++ b/kernel/cgroup.c 
@@ -725,14 +725,11 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task, 
  * cgroup_attach_task(), which overwrites one tasks cgroup pointer with 
  * another.  It does so using cgroup_mutex, however there are 
  * several performance critical places that need to reference 
- * task->cgroup without the expense of grabbing a system global 
+ * task->cgroups without the expense of grabbing a system global 
  * mutex.  Therefore except as noted below, when dereferencing or, as 
- * in cgroup_attach_task(), modifying a task'ss cgroup pointer we use 
+ * in cgroup_attach_task(), modifying a task's cgroups pointer we use 
  * task_lock(), which acts on a spinlock (task->alloc_lock) already in 
  * the task_struct routinely used for such matters. 
- * 
- * P.S.  One more locking exception.  RCU is used to guard the 
- * update of a tasks cgroup pointer by cgroup_attach_task() 
  */ 
  
 /** 
@@ -1786,7 +1783,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 
 		retval = -ESRCH; 
 		goto out; 
 	} 
-	rcu_assign_pointer(tsk->cgroups, newcg); 
+	tsk->cgroups = newcg; 
 	task_unlock(tsk); 
  
 	/* Update the css_set linked lists if we're using them */ 
@@ -1802,7 +1799,6 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 
 			ss->attach(ss, cgrp, oldcgrp, tsk, false); 
 	} 
 	set_bit(CGRP_RELEASABLE, &oldcgrp->flags); 
-	synchronize_rcu(); 
 	put_css_set(cg); 
  
 	/* 
@@ -4827,9 +4823,9 @@ static u64 current_css_set_refcount_read(struct cgroup *cont, 
 { 
 	u64 count; 
  
-	rcu_read_lock(); 
+	task_lock(current); 
 	count = atomic_read(¤t->cgroups->refcount); 
-	rcu_read_unlock(); 
+	task_unlock(current); 
 	return count; 
 } 
  
@@ -4838,12 +4834,10 @@ static int current_css_set_cg_links_read(struct cgroup *cont, 
 					 struct seq_file *seq) 
 { 
 	struct cg_cgroup_link *link; 
-	struct css_set *cg; 
  
 	read_lock(&css_set_lock); 
-	rcu_read_lock(); 
-	cg = rcu_dereference(current->cgroups); 
-	list_for_each_entry(link, &cg->cg_links, cg_link_list) { 
+	task_lock(current); 
+	list_for_each_entry(link, ¤t->cgroups->cg_links, cg_link_list) { 
 		struct cgroup *c = link->cgrp; 
 		const char *name; 
  
@@ -4854,7 +4848,7 @@ static int current_css_set_cg_links_read(struct cgroup *cont, 
 		seq_printf(seq, "Root %d group %s\n", 
 			   c->root->hierarchy_id, name); 
 	} 
-	rcu_read_unlock(); 
+	task_unlock(current); 
 	read_unlock(&css_set_lock); 
 	return 0; 
 } 
--  
1.7.3.1 
 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	| 
		
 |  
	
		
		
			| [PATCH] cgroup: Convert synchronize_rcu to call_rcu in cgroup_attach_task [message #41917 is a reply to message #41916] | 
			Mon, 22 November 2010 04:06    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		The synchronize_rcu call in cgroup_attach_task can be very 
expensive.  All fastpath accesses to task->cgroups that expect 
task->cgroups not to change already use task_lock() or 
cgroup_lock() to protect against updates, and, in cgroup.c, 
only the CGROUP_DEBUG files have RCU read-side critical 
sections. 
 
sched.c uses RCU read-side-critical sections on task->cgroups, 
but only to ensure that a dereference of task->cgroups does 
not become invalid, not that it doesn't change. 
 
This patch adds a function put_css_set_rcu, which delays the 
put until after a grace period has elapsed.  This ensures that 
any RCU read-side critical sections that dereferenced 
task->cgroups in sched.c have completed before the css_set is 
deleted.  The synchronize_rcu()/put_css_set() combo in 
cgroup_attach_task() can then be replaced with 
put_css_set_rcu(). 
 
Also converts the CGROUP_DEBUG files that access 
current->cgroups to use task_lock(current) instead of 
rcu_read_lock(). 
 
Signed-off-by: Colin Cross <ccross@android.com> 
 
--- 
 
This version fixes the problems with the previous patch by 
keeping the use of RCU in cgroup_attach_task, but allowing 
cgroup_attach_task to return immediately by deferring the 
final put_css_reg to an rcu callback. 
 
 include/linux/cgroup.h |    4 +++ 
 kernel/cgroup.c        |   58 ++++++++++++++++++++++++++++++++++++++---------- 
 2 files changed, 50 insertions(+), 12 deletions(-) 
 
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h 
index ed4ba11..fd26218 100644 
--- a/include/linux/cgroup.h 
+++ b/include/linux/cgroup.h 
@@ -287,6 +287,10 @@ struct css_set { 
  
 	/* For RCU-protected deletion */ 
 	struct rcu_head rcu_head; 
+ 
+	/* For RCU-delayed puts */ 
+	atomic_t delayed_put_count; 
+	struct work_struct delayed_put_work; 
 }; 
  
 /* 
diff --git a/kernel/cgroup.c b/kernel/cgroup.c 
index 66a416b..c7348e7 100644 
--- a/kernel/cgroup.c 
+++ b/kernel/cgroup.c 
@@ -298,7 +298,8 @@ static int cgroup_init_idr(struct cgroup_subsys *ss, 
  
 /* css_set_lock protects the list of css_set objects, and the 
  * chain of tasks off each css_set.  Nests outside task->alloc_lock 
- * due to cgroup_iter_start() */ 
+ * due to cgroup_iter_start().  Never locked in irq context, so 
+ * the non-irq variants of write_lock and read_lock are used. */ 
 static DEFINE_RWLOCK(css_set_lock); 
 static int css_set_count; 
  
@@ -396,6 +397,39 @@ static inline void put_css_set_taskexit(struct css_set *cg) 
 	__put_css_set(cg, 1); 
 } 
  
+/* work function, executes in process context */ 
+static void __put_css_set_rcu(struct work_struct *work) 
+{ 
+	struct css_set *cg; 
+	cg = container_of(work, struct css_set, delayed_put_work); 
+ 
+	while (atomic_add_unless(&cg->delayed_put_count, -1, 0)) 
+		put_css_set(cg); 
+} 
+ 
+/* rcu callback, executes in softirq context */ 
+static void _put_css_set_rcu(struct rcu_head *obj) 
+{ 
+	struct css_set *cg = container_of(obj, struct css_set, rcu_head); 
+ 
+	/* the rcu callback happens in softirq context, but css_set_lock 
+	 * is not irq safe, so bounce to process context. 
+	 */ 
+	schedule_work(&cg->delayed_put_work); 
+} 
+ 
+/* put_css_set_rcu - helper function to delay a put until after an rcu 
+ * grace period 
+ * 
+ * free_css_set_rcu can never be called if there are outstanding 
+ * put_css_set_rcu calls, so we can reuse cg->rcu_head. 
+ */ 
+static inline void put_css_set_rcu(struct css_set *cg) 
+{ 
+	if (atomic_inc_return(&cg->delayed_put_count) == 1) 
+		call_rcu(&cg->rcu_head, _put_css_set_rcu); 
+} 
+ 
 /* 
  * compare_css_sets - helper function for find_existing_css_set(). 
  * @cg: candidate css_set being tested 
@@ -620,9 +654,11 @@ static struct css_set *find_css_set( 
 	} 
  
 	atomic_set(&res->refcount, 1); 
+	atomic_set(&res->delayed_put_count, 0); 
 	INIT_LIST_HEAD(&res->cg_links); 
 	INIT_LIST_HEAD(&res->tasks); 
 	INIT_HLIST_NODE(&res->hlist); 
+	INIT_WORK(&res->delayed_put_work, __put_css_set_rcu); 
  
 	/* Copy the set of subsystem state objects generated in 
 	 * find_existing_css_set() */ 
@@ -725,9 +761,9 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task, 
  * cgroup_attach_task(), which overwrites one tasks cgroup pointer with 
  * another.  It does so using cgroup_mutex, however there are 
  * several performance critical places that need to reference 
- * task->cgroup without the expense of grabbing a system global 
+ * task->cgroups without the expense of grabbing a system global 
  * mutex.  Therefore except as noted below, when dereferencing or, as 
- * in cgroup_attach_task(), modifying a task'ss cgroup pointer we use 
+ * in cgroup_attach_task(), modifying a task's cgroups pointer we use 
  * task_lock(), which acts on a spinlock (task->alloc_lock) already in 
  * the task_struct routinely used for such matters. 
  * 
@@ -1802,8 +1838,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 
 			ss->attach(ss, cgrp, oldcgrp, tsk, false); 
 	} 
 	set_bit(CGRP_RELEASABLE, &oldcgrp->flags); 
-	synchronize_rcu(); 
-	put_css_set(cg); 
+	put_css_set_rcu(cg); 
  
 	/* 
 	 * wake up rmdir() waiter. the rmdir should fail since the cgroup 
@@ -3900,6 +3935,7 @@ int __init cgroup_init_early(void) 
 	INIT_LIST_HEAD(&init_css_set.cg_links); 
 	INIT_LIST_HEAD(&init_css_set.tasks); 
 	INIT_HLIST_NODE(&init_css_set.hlist); 
+	INIT_WORK(&init_css_set.delayed_put_work, __put_css_set_rcu); 
 	css_set_count = 1; 
 	init_cgroup_root(&rootnode); 
 	root_count = 1; 
@@ -4827,9 +4863,9 @@ static u64 current_css_set_refcount_read(struct cgroup *cont, 
 { 
 	u64 count; 
  
-	rcu_read_lock(); 
+	task_lock(current); 
 	count = atomic_read(¤t->cgroups->refcount); 
-	rcu_read_unlock(); 
+	task_unlock(current); 
 	return count; 
 } 
  
@@ -4838,12 +4874,10 @@ static int current_css_set_cg_links_read(struct cgroup *cont, 
 					 struct seq_file *seq) 
 { 
 	struct cg_cgroup_link *link; 
-	struct css_set *cg; 
  
 	read_lock(&css_set_lock); 
-	rcu_read_lock(); 
-	cg = rcu_dereference(current->cgroups); 
-	list_for_each_entry(link, &cg->cg_links, cg_link_list) { 
+	task_lock(current); 
+	list_for_each_entry(link, ¤t->cgroups->cg_links, cg_link_list) { 
 		struct cgroup *c = link->cgrp; 
 		const char *name; 
  
@@ -4854,7 +4888,7 @@ static int current_css_set_cg_links_read(struct cgroup *cont, 
 		seq_printf(seq, "Root %d group %s\n", 
 			   c->root->hierarchy_id, name); 
 	} 
-	rcu_read_unlock(); 
+	task_unlock(current); 
 	read_unlock(&css_set_lock); 
 	return 0; 
 } 
--  
1.7.3.1 
 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH] cgroup: Convert synchronize_rcu to call_rcu in cgroup_attach_task [message #41918 is a reply to message #41917] | 
			Tue, 23 November 2010 08:58    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On Tue, Nov 23, 2010 at 12:14 AM, Li Zefan <lizf@cn.fujitsu.com> wrote: 
> 12:06, Colin Cross wrote: 
>> The synchronize_rcu call in cgroup_attach_task can be very 
>> expensive.  All fastpath accesses to task->cgroups that expect 
>> task->cgroups not to change already use task_lock() or 
>> cgroup_lock() to protect against updates, and, in cgroup.c, 
>> only the CGROUP_DEBUG files have RCU read-side critical 
>> sections. 
>> 
>> sched.c uses RCU read-side-critical sections on task->cgroups, 
>> but only to ensure that a dereference of task->cgroups does 
>> not become invalid, not that it doesn't change. 
>> 
> 
> Other cgroup subsystems also use rcu_read_lock to access task->cgroups, 
> for example net_cls cgroup and device cgroup. 
I believe the same comment applies as sched.c, I'll update the commit message. 
 
> I don't think the performance of task attaching is so critically 
> important that we have to use call_rcu() instead of synchronize_rcu()? 
On my desktop, moving a task between cgroups averages 100 ms, and on 
an Tegra2 SMP ARM platform it takes 20 ms.  Moving a task with many 
threads can take hundreds of milliseconds or more.  With this patch it 
takes 50 microseconds to move one task, a 400x improvement. 
 
>> This patch adds a function put_css_set_rcu, which delays the 
>> put until after a grace period has elapsed.  This ensures that 
>> any RCU read-side critical sections that dereferenced 
>> task->cgroups in sched.c have completed before the css_set is 
>> deleted.  The synchronize_rcu()/put_css_set() combo in 
>> cgroup_attach_task() can then be replaced with 
>> put_css_set_rcu(). 
>> 
> 
>> Also converts the CGROUP_DEBUG files that access 
>> current->cgroups to use task_lock(current) instead of 
>> rcu_read_lock(). 
>> 
> 
> What for? What do we gain from doing this for those debug 
> interfaces? 
Left over from the previous patch that incorrectly dropped RCU 
completely.  I'll put the rcu_read_locks back. 
 
>> Signed-off-by: Colin Cross <ccross@android.com> 
>> 
>> --- 
>> 
>> This version fixes the problems with the previous patch by 
>> keeping the use of RCU in cgroup_attach_task, but allowing 
>> cgroup_attach_task to return immediately by deferring the 
>> final put_css_reg to an rcu callback. 
>> 
>>  include/linux/cgroup.h |    4 +++ 
>>  kernel/cgroup.c        |   58 ++++++++++++++++++++++++++++++++++++++---------- 
>>  2 files changed, 50 insertions(+), 12 deletions(-) 
> 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH] cgroup: Convert synchronize_rcu to call_rcu in cgroup_attach_task [message #41919 is a reply to message #41918] | 
			Tue, 23 November 2010 20:22    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On Tue, Nov 23, 2010 at 12:58 AM, Colin Cross <ccross@android.com> wrote: 
> On Tue, Nov 23, 2010 at 12:14 AM, Li Zefan <lizf@cn.fujitsu.com> wrote: 
>> 12:06, Colin Cross wrote: 
>>> The synchronize_rcu call in cgroup_attach_task can be very 
>>> expensive.  All fastpath accesses to task->cgroups that expect 
>>> task->cgroups not to change already use task_lock() or 
>>> cgroup_lock() to protect against updates, and, in cgroup.c, 
>>> only the CGROUP_DEBUG files have RCU read-side critical 
>>> sections. 
>>> 
>>> sched.c uses RCU read-side-critical sections on task->cgroups, 
>>> but only to ensure that a dereference of task->cgroups does 
>>> not become invalid, not that it doesn't change. 
>>> 
>> 
>> Other cgroup subsystems also use rcu_read_lock to access task->cgroups, 
>> for example net_cls cgroup and device cgroup. 
> I believe the same comment applies as sched.c, I'll update the commit message. 
> 
>> I don't think the performance of task attaching is so critically 
>> important that we have to use call_rcu() instead of synchronize_rcu()? 
> On my desktop, moving a task between cgroups averages 100 ms, and on 
> an Tegra2 SMP ARM platform it takes 20 ms.  Moving a task with many 
> threads can take hundreds of milliseconds or more.  With this patch it 
> takes 50 microseconds to move one task, a 400x improvement. 
> 
>>> This patch adds a function put_css_set_rcu, which delays the 
>>> put until after a grace period has elapsed.  This ensures that 
>>> any RCU read-side critical sections that dereferenced 
>>> task->cgroups in sched.c have completed before the css_set is 
>>> deleted.  The synchronize_rcu()/put_css_set() combo in 
>>> cgroup_attach_task() can then be replaced with 
>>> put_css_set_rcu(). 
>>> 
>> 
>>> Also converts the CGROUP_DEBUG files that access 
>>> current->cgroups to use task_lock(current) instead of 
>>> rcu_read_lock(). 
>>> 
>> 
>> What for? What do we gain from doing this for those debug 
>> interfaces? 
> Left over from the previous patch that incorrectly dropped RCU 
> completely.  I'll put the rcu_read_locks back. 
> 
>>> Signed-off-by: Colin Cross <ccross@android.com> 
>>> 
>>> --- 
>>> 
>>> This version fixes the problems with the previous patch by 
>>> keeping the use of RCU in cgroup_attach_task, but allowing 
>>> cgroup_attach_task to return immediately by deferring the 
>>> final put_css_reg to an rcu callback. 
>>> 
>>>  include/linux/cgroup.h |    4 +++ 
>>>  kernel/cgroup.c        |   58 ++++++++++++++++++++++++++++++++++++++---------- 
>>>  2 files changed, 50 insertions(+), 12 deletions(-) 
>> 
> 
 
This patch has another problem - calling put_css_set_rcu twice before 
an rcu grace period has elapsed would not guarantee the appropriate 
rcu grace period for the second call.  I'll try a new approach, moving 
the parts of put_css_set that need to be protected by rcu into 
free_css_set_rcu. 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH] cgroup: Convert synchronize_rcu to call_rcu in cgroup_attach_task [message #41921 is a reply to message #41917] | 
			Wed, 24 November 2010 02:10    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On Tue, Nov 23, 2010 at 6:06 PM, Li Zefan <lizf@cn.fujitsu.com> wrote: 
> Paul Menage wrote: 
>> On Sun, Nov 21, 2010 at 8:06 PM, Colin Cross <ccross@android.com> wrote: 
>>> The synchronize_rcu call in cgroup_attach_task can be very 
>>> expensive.  All fastpath accesses to task->cgroups that expect 
>>> task->cgroups not to change already use task_lock() or 
>>> cgroup_lock() to protect against updates, and, in cgroup.c, 
>>> only the CGROUP_DEBUG files have RCU read-side critical 
>>> sections. 
>> 
>> I definitely agree with the goal of using lighter-weight 
>> synchronization than the current synchronize_rcu() call. However, 
>> there are definitely some subtleties to worry about in this code. 
>> 
>> One of the reasons originally for the current synchronization was to 
>> avoid the case of calling subsystem destroy() callbacks while there 
>> could still be threads with RCU references to the subsystem state. The 
>> fact that synchronize_rcu() was called within a cgroup_mutex critical 
>> section meant that an rmdir (or any other significant cgrooup 
>> management action) couldn't possibly start until any RCU read sections 
>> were done. 
>> 
>> I suspect that when we moved a lot of the cgroup teardown code from 
>> cgroup_rmdir() to cgroup_diput() (which also has a synchronize_rcu() 
>> call in it) this restriction could have been eased, but I think I left 
>> it as it was mostly out of paranoia that I was missing/forgetting some 
>> crucial reason for keeping it in place. 
>> 
>> I'd suggest trying the following approach, which I suspect is similar 
>> to what you were suggesting in your last email 
>> 
>> 1) make find_existing_css_set ignore css_set objects with a zero refcount 
>> 2) change __put_css_set to be simply 
>> 
>> if (atomic_dec_and_test(&cg->refcount)) { 
>>   call_rcu(&cg->rcu_head, free_css_set_rcu); 
>> } 
> 
> If we do this, it's not anymore safe to use get_css_set(), which just 
> increments the refcount without checking if it's zero. 
 
I used an alternate approach, removing the css_set from the hash table 
in put_css_set, but delaying the deletion to free_css_set_rcu.  That 
way, nothing can get another reference to the css_set to call 
get_css_set on. 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| [PATCH 2/2] cgroup: Remove call to synchronize_rcu in cgroup_attach_task [message #41923 is a reply to message #41921] | 
			Wed, 24 November 2010 05:37    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		synchronize_rcu can be very expensive, averaging 100 ms in 
some cases.  In cgroup_attach_task, it is used to prevent 
a task->cgroups pointer dereferenced in an RCU read side 
critical section from being invalidated, by delaying the 
call to put_css_set until after an RCU grace period. 
 
To avoid the call to synchronize_rcu, make the put_css_set 
call rcu-safe by moving the deletion of the css_set links 
into free_css_set_work, scheduled by the rcu callback 
free_css_set_rcu. 
 
The decrement of the cgroup refcount is no longer 
synchronous with the call to put_css_set, which can result 
in the cgroup refcount staying positive after the last call 
to cgroup_attach_task returns.  To allow the cgroup to be 
deleted with cgroup_rmdir synchronously after 
cgroup_attach_task, have rmdir check the refcount of all 
associated css_sets.  If cgroup_rmdir is called on a cgroup 
for which the css_sets all have refcount zero but the 
cgroup refcount is nonzero, reuse the rmdir waitqueue to 
block the rmdir until free_css_set_work is called. 
 
Signed-off-by: Colin Cross <ccross@android.com> 
--- 
 include/linux/cgroup.h |    1 + 
 kernel/cgroup.c        |  120 +++++++++++++++++++++++++++++------------------- 
 2 files changed, 74 insertions(+), 47 deletions(-) 
 
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h 
index 9e13078..49fdff0 100644 
--- a/include/linux/cgroup.h 
+++ b/include/linux/cgroup.h 
@@ -279,6 +279,7 @@ struct css_set { 
  
 	/* For RCU-protected deletion */ 
 	struct rcu_head rcu_head; 
+	struct work_struct work; 
 }; 
  
 /* 
diff --git a/kernel/cgroup.c b/kernel/cgroup.c 
index 34e855e..e752c83 100644 
--- a/kernel/cgroup.c 
+++ b/kernel/cgroup.c 
@@ -267,6 +267,33 @@ static void cgroup_release_agent(struct work_struct *work); 
 static DECLARE_WORK(release_agent_work, cgroup_release_agent); 
 static void check_for_release(struct cgroup *cgrp); 
  
+/* 
+ * A queue for waiters to do rmdir() cgroup. A tasks will sleep when 
+ * cgroup->count == 0 && list_empty(&cgroup->children) && subsys has some 
+ * reference to css->refcnt. In general, this refcnt is expected to goes down 
+ * to zero, soon. 
+ * 
+ * CGRP_WAIT_ON_RMDIR flag is set under cgroup's inode->i_mutex; 
+ */ 
+DECLARE_WAIT_QUEUE_HEAD(cgroup_rmdir_waitq); 
+ 
+static void cgroup_wakeup_rmdir_waiter(struct cgroup *cgrp) 
+{ 
+	if (unlikely(test_and_clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags))) 
+		wake_up_all(&cgroup_rmdir_waitq); 
+} 
+ 
+void cgroup_exclude_rmdir(struct cgroup_subsys_state *css) 
+{ 
+	css_get(css); 
+} 
+ 
+void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css) 
+{ 
+	cgroup_wakeup_rmdir_waiter(css->cgroup); 
+	css_put(css); 
+} 
+ 
 /* Link structure for associating css_set objects with cgroups */ 
 struct cg_cgroup_link { 
 	/* 
@@ -326,10 +353,35 @@ static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[]) 
 	return &css_set_table[index]; 
 } 
  
+static void free_css_set_work(struct work_struct *work) 
+{ 
+	struct css_set *cg = container_of(work, struct css_set, work); 
+	struct cg_cgroup_link *link; 
+	struct cg_cgroup_link *saved_link; 
+ 
+	write_lock(&css_set_lock); 
+	list_for_each_entry_safe(link, saved_link, &cg->cg_links, 
+				 cg_link_list) { 
+		struct cgroup *cgrp = link->cgrp; 
+		list_del(&link->cg_link_list); 
+		list_del(&link->cgrp_link_list); 
+		if (atomic_dec_and_test(&cgrp->count)) { 
+			check_for_release(cgrp); 
+			cgroup_wakeup_rmdir_waiter(cgrp); 
+		} 
+		kfree(link); 
+	} 
+	write_unlock(&css_set_lock); 
+ 
+	kfree(cg); 
+} 
+ 
 static void free_css_set_rcu(struct rcu_head *obj) 
 { 
 	struct css_set *cg = container_of(obj, struct css_set, rcu_head); 
-	kfree(cg); 
+ 
+	INIT_WORK(&cg->work, free_css_set_work); 
+	schedule_work(&cg->work); 
 } 
  
 /* We don't maintain the lists running through each css_set to its 
@@ -348,8 +400,6 @@ static inline void get_css_set(struct css_set *cg) 
  
 static void put_css_set(struct css_set *cg) 
 { 
-	struct cg_cgroup_link *link; 
-	struct cg_cgroup_link *saved_link; 
 	/* 
 	 * Ensure that the refcount doesn't hit zero while any readers 
 	 * can see it. Similar to atomic_dec_and_lock(), but for an 
@@ -363,21 +413,9 @@ static void put_css_set(struct css_set *cg) 
 		return; 
 	} 
  
-	/* This css_set is dead. unlink it and release cgroup refcounts */ 
 	hlist_del(&cg->hlist); 
 	css_set_count--; 
  
-	list_for_each_entry_safe(link, saved_link, &cg->cg_links, 
-				 cg_link_list) { 
-		struct cgroup *cgrp = link->cgrp; 
-		list_del(&link->cg_link_list); 
-		list_del(&link->cgrp_link_list); 
-		if (atomic_dec_and_test(&cgrp->count)) 
-			check_for_release(cgrp); 
- 
-		kfree(link); 
-	} 
- 
 	write_unlock(&css_set_lock); 
 	call_rcu(&cg->rcu_head, free_css_set_rcu); 
 } 
@@ -711,9 +749,9 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task, 
  * cgroup_attach_task(), which overwrites one tasks cgroup pointer with 
  * another.  It does so using cgroup_mutex, however there are 
  * several performance critical places that need to reference 
- * task->cgroup without the expense of grabbing a system global 
+ * task->cgroups without the expense of grabbing a system global 
  * mutex.  Therefore except as noted below, when dereferencing or, as 
- * in cgroup_attach_task(), modifying a task'ss cgroup pointer we use 
+ * in cgroup_attach_task(), modifying a task's cgroups pointer we use 
  * task_lock(), which acts on a spinlock (task->alloc_lock) already in 
  * the task_struct routinely used for such matters. 
  * 
@@ -895,33 +933,6 @@ static void cgroup_d_remove_dir(struct dentry *dentry) 
 } 
  
 /* 
- * A queue for waiters to do rmdir() cgroup. A tasks will sleep when 
- * cgroup->count == 0 && list_empty(&cgroup->children) && subsys has some 
- * reference to css->refcnt. In general, this refcnt is expected to goes down 
- * to zero, soon. 
- * 
- * CGRP_WAIT_ON_RMDIR flag is set under cgroup's inode->i_mutex; 
- */ 
-DECLARE_WAIT_QUEUE_HEAD(cgroup_rmdir_waitq); 
- 
-static void cgroup_wakeup_rmdir_waiter(struct cgroup *cgrp) 
-{ 
-	if (unlikely(test_and_clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags))) 
-		wake_up_all(&cgroup_rmdir_waitq); 
-} 
- 
-void cgroup_exclude_rmdir(struct cgroup_subsys_state *css) 
-{ 
-	css_get(css); 
-} 
- 
-void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css) 
-{ 
-	cgroup_wakeup_rmdir_waiter(css->cgroup); 
-	css_put(css); 
-} 
- 
-/* 
  * Call with cgroup_mutex held. Drops reference counts on modules, including 
  * any duplicate ones that parse_cgroupfs_options took. If this function 
  * returns an error, no reference counts are touched. 
@@ -1788,7 +1799,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 
 			ss->attach(ss, cgrp, oldcgrp, tsk, false); 
 	} 
 	set_bit(CGRP_RELEASABLE, &cgrp->flags); 
-	synchronize_rcu(); 
+	/* put_css_set will not destroy cg until after an RCU grace period */ 
 	put_css_set(cg); 
  
 	/* 
@@ -3546,6 +3557,21 @@ static int cgroup_clear_css_refs(struct cgroup *cgrp) 
 	return !failed; 
 } 
  
+/* checks if all of the css_sets attached to a cgroup have a refcount of 0. 
+ * Must be called with css_set_lock held */ 
+static int cgroup_css_sets_empty(struct cgroup *cgrp) 
+{ 
+	struct cg_cgroup_link *link; 
+ 
+	list_for_each_entry(link, &cgrp->css_sets, cgrp_link_list) { 
+		struct css_set *cg = link->cg; 
+		if (atomic_read(&cg->refcount) > 0) 
+			return 0; 
+	} 
+ 
+	return 1; 
+} 
+ 
 static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) 
 { 
 	struct cgroup *cgrp = dentry->d_fsdata; 
@@ -3558,7 +3584,7 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) 
 	/* the vfs holds both inode->i_mutex already */ 
 again: 
 	mutex_lock(&cgroup_mutex); 
-	if (atomic_read(&cgrp->count) != 0) { 
+	if (!cgroup_css_sets_empty(cgrp)) { 
 		mutex_unlock(&cgroup_mutex); 
 		return -EBUSY; 
 	} 
@@ -3591,7 +3617,7 @@ again: 
  
 	mutex_lock(&cgroup_mutex); 
 	parent = cgrp->parent; 
-	if (atomic_read(&cgrp->count) || !list_empty(&cgrp->children)) { 
+	if (!cgroup_css_sets_empty(cgrp) || !list_empty(&cgrp->children)) { 
 		clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags); 
 		mutex_unlock(&cgroup_mutex); 
 		return -EBUSY; 
--  
1.7.3.1 
 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
...
  
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| [PATCH 1/2] cgroup: Set CGRP_RELEASABLE when adding to a cgroup [message #41924 is a reply to message #41921] | 
			Wed, 24 November 2010 05:37    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		Changes the meaning of CGRP_RELEASABLE to be set on any cgroup 
that has ever had a task or cgroup in it, or had css_get called 
on it.  The bit is set in cgroup_attach_task, cgroup_create, 
and __css_get.  It is not necessary to set the bit in 
cgroup_fork, as the task is either in the root cgroup, in 
which can never be released, or the task it was forked from 
already set the bit in croup_attach_task. 
 
Signed-off-by: Colin Cross <ccross@android.com> 
--- 
 include/linux/cgroup.h |   12 +-------- 
 kernel/cgroup.c        |   54 ++++++++++++++++++++--------------------------- 
 2 files changed, 25 insertions(+), 41 deletions(-) 
 
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h 
index ed4ba11..9e13078 100644 
--- a/include/linux/cgroup.h 
+++ b/include/linux/cgroup.h 
@@ -84,12 +84,6 @@ enum { 
 	CSS_REMOVED, /* This CSS is dead */ 
 }; 
  
-/* Caller must verify that the css is not for root cgroup */ 
-static inline void __css_get(struct cgroup_subsys_state *css, int count) 
-{ 
-	atomic_add(count, &css->refcnt); 
-} 
- 
 /* 
  * Call css_get() to hold a reference on the css; it can be used 
  * for a reference obtained via: 
@@ -97,6 +91,7 @@ static inline void __css_get(struct cgroup_subsys_state *css, int count) 
  * - task->cgroups for a locked task 
  */ 
  
+extern void __css_get(struct cgroup_subsys_state *css, int count); 
 static inline void css_get(struct cgroup_subsys_state *css) 
 { 
 	/* We don't need to reference count the root state */ 
@@ -143,10 +138,7 @@ static inline void css_put(struct cgroup_subsys_state *css) 
 enum { 
 	/* Control Group is dead */ 
 	CGRP_REMOVED, 
-	/* 
-	 * Control Group has previously had a child cgroup or a task, 
-	 * but no longer (only if CGRP_NOTIFY_ON_RELEASE is set) 
-	 */ 
+	/* Control Group has ever had a child cgroup or a task */ 
 	CGRP_RELEASABLE, 
 	/* Control Group requires release notifications to userspace */ 
 	CGRP_NOTIFY_ON_RELEASE, 
diff --git a/kernel/cgroup.c b/kernel/cgroup.c 
index 66a416b..34e855e 100644 
--- a/kernel/cgroup.c 
+++ b/kernel/cgroup.c 
@@ -338,7 +338,15 @@ static void free_css_set_rcu(struct rcu_head *obj) 
  * compiled into their kernel but not actually in use */ 
 static int use_task_css_set_links __read_mostly; 
  
-static void __put_css_set(struct css_set *cg, int taskexit) 
+/* 
+ * refcounted get/put for css_set objects 
+ */ 
+static inline void get_css_set(struct css_set *cg) 
+{ 
+	atomic_inc(&cg->refcount); 
+} 
+ 
+static void put_css_set(struct css_set *cg) 
 { 
 	struct cg_cgroup_link *link; 
 	struct cg_cgroup_link *saved_link; 
@@ -364,12 +372,8 @@ static void __put_css_set(struct css_set *cg, int taskexit) 
 		struct cgroup *cgrp = link->cgrp; 
 		list_del(&link->cg_link_list); 
 		list_del(&link->cgrp_link_list); 
-		if (atomic_dec_and_test(&cgrp->count) && 
-		    notify_on_release(cgrp)) { 
-			if (taskexit) 
-				set_bit(CGRP_RELEASABLE, &cgrp->flags); 
+		if (atomic_dec_and_test(&cgrp->count)) 
 			check_for_release(cgrp); 
-		} 
  
 		kfree(link); 
 	} 
@@ -379,24 +383,6 @@ static void __put_css_set(struct css_set *cg, int taskexit) 
 } 
  
 /* 
- * refcounted get/put for css_set objects 
- */ 
-static inline void get_css_set(struct css_set *cg) 
-{ 
-	atomic_inc(&cg->refcount); 
-} 
- 
-static inline void put_css_set(struct css_set *cg) 
-{ 
-	__put_css_set(cg, 0); 
-} 
- 
-static inline void put_css_set_taskexit(struct css_set *cg) 
-{ 
-	__put_css_set(cg, 1); 
-} 
- 
-/* 
  * compare_css_sets - helper function for find_existing_css_set(). 
  * @cg: candidate css_set being tested 
  * @old_cg: existing css_set for a task 
@@ -1801,7 +1787,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 
 		if (ss->attach) 
 			ss->attach(ss, cgrp, oldcgrp, tsk, false); 
 	} 
-	set_bit(CGRP_RELEASABLE, &oldcgrp->flags); 
+	set_bit(CGRP_RELEASABLE, &cgrp->flags); 
 	synchronize_rcu(); 
 	put_css_set(cg); 
  
@@ -3427,6 +3413,8 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, 
 	if (err < 0) 
 		goto err_remove; 
  
+	set_bit(CGRP_RELEASABLE, &parent->flags); 
+ 
 	/* The cgroup directory was pre-locked for us */ 
 	BUG_ON(!mutex_is_locked(&cgrp->dentry->d_inode->i_mutex)); 
  
@@ -3645,7 +3633,6 @@ again: 
 	cgroup_d_remove_dir(d); 
 	dput(d); 
  
-	set_bit(CGRP_RELEASABLE, &parent->flags); 
 	check_for_release(parent); 
  
 	/* 
@@ -4240,7 +4227,7 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks) 
 	tsk->cgroups = &init_css_set; 
 	task_unlock(tsk); 
 	if (cg) 
-		put_css_set_taskexit(cg); 
+		put_css_set(cg); 
 } 
  
 /** 
@@ -4410,6 +4397,14 @@ static void check_for_release(struct cgroup *cgrp) 
 } 
  
 /* Caller must verify that the css is not for root cgroup */ 
+void __css_get(struct cgroup_subsys_state *css, int count) 
+{ 
+	atomic_add(count, &css->refcnt); 
+	set_bit(CGRP_RELEASABLE, &css->cgroup->flags); 
+} 
+EXPORT_SYMBOL_GPL(__css_get); 
+ 
+/* Caller must verify that the css is not for root cgroup */ 
 void __css_put(struct cgroup_subsys_state *css, int count) 
 { 
 	struct cgroup *cgrp = css->cgroup; 
@@ -4417,10 +4412,7 @@ void __css_put(struct cgroup_subsys_state *css, int count) 
 	rcu_read_lock(); 
 	val = atomic_sub_return(count, &css->refcnt); 
 	if (val == 1) { 
-		if (notify_on_release(cgrp)) { 
-			set_bit(CGRP_RELEASABLE, &cgrp->flags); 
-			check_for_release(cgrp); 
-		} 
+		check_for_release(cgrp); 
 		cgroup_wakeup_rmdir_waiter(cgrp); 
 	} 
 	rcu_read_unlock(); 
--  
1.7.3.1 
 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH 1/2] cgroup: Set CGRP_RELEASABLE when adding to a cgroup [message #41925 is a reply to message #41924] | 
			Thu, 25 November 2010 00:11    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On Wed, Nov 24, 2010 at 3:54 PM, Paul Menage <menage@google.com> wrote: 
> On Tue, Nov 23, 2010 at 9:37 PM, Colin Cross <ccross@android.com> wrote: 
>> @@ -364,12 +372,8 @@ static void __put_css_set(struct css_set *cg, int taskexit) 
>>                struct cgroup *cgrp = link->cgrp; 
>>                list_del(&link->cg_link_list); 
>>                list_del(&link->cgrp_link_list); 
>> -               if (atomic_dec_and_test(&cgrp->count) && 
>> -                   notify_on_release(cgrp)) { 
>> -                       if (taskexit) 
>> -                               set_bit(CGRP_RELEASABLE, &cgrp->flags); 
>> +               if (atomic_dec_and_test(&cgrp->count)) 
>>                        check_for_release(cgrp); 
>> -               } 
> 
> We seem to have lost some notify_on_release() checks - maybe move that 
> to check_for_release()? 
check_for_release immediately calls cgroup_is_releasable, which checks 
for the same bit as notify_on_release.  There's no need for 
CGRP_RELEASABLE to depend on notify_on_release, or to check 
notify_on_release before calling check_for_release. 
 
>>  /* Caller must verify that the css is not for root cgroup */ 
>> +void __css_get(struct cgroup_subsys_state *css, int count) 
>> +{ 
>> +       atomic_add(count, &css->refcnt); 
>> +       set_bit(CGRP_RELEASABLE, &css->cgroup->flags); 
>> +} 
> 
> Is css_get() the right place to be putting this? It's not clear to me 
> why a subsystem taking a refcount on a cgroup's state should render it 
> releasable when it drops that refcount. 
I matched the existing behavior, __css_put sets CGRP_RELEASABLE when 
refcnt goes to 0. 
 
> Should we maybe clear the CGRP_RELEASABLE flag right before doing the 
> userspace callback? 
Actually, I think CGRP_RELEASABLE can be dropped entirely. 
check_for_release is only called from __css_put, cgroup_rmdir, and 
__put_css_set (or free_css_set_work after my second patch).  Those all 
imply that __css_get, get_css_set, or cgroup_create have been 
previously called, which are the functions that set CGRP_RELEASABLE. 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH 1/2] cgroup: Set CGRP_RELEASABLE when adding to a cgroup [message #41926 is a reply to message #41925] | 
			Thu, 25 November 2010 00:18    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On Wed, Nov 24, 2010 at 4:11 PM, Colin Cross <ccross@android.com> wrote: 
> On Wed, Nov 24, 2010 at 3:54 PM, Paul Menage <menage@google.com> wrote: 
>> On Tue, Nov 23, 2010 at 9:37 PM, Colin Cross <ccross@android.com> wrote: 
>>> @@ -364,12 +372,8 @@ static void __put_css_set(struct css_set *cg, int taskexit) 
>>>                struct cgroup *cgrp = link->cgrp; 
>>>                list_del(&link->cg_link_list); 
>>>                list_del(&link->cgrp_link_list); 
>>> -               if (atomic_dec_and_test(&cgrp->count) && 
>>> -                   notify_on_release(cgrp)) { 
>>> -                       if (taskexit) 
>>> -                               set_bit(CGRP_RELEASABLE, &cgrp->flags); 
>>> +               if (atomic_dec_and_test(&cgrp->count)) 
>>>                        check_for_release(cgrp); 
>>> -               } 
>> 
>> We seem to have lost some notify_on_release() checks - maybe move that 
>> to check_for_release()? 
> check_for_release immediately calls cgroup_is_releasable, which checks 
> for the same bit as notify_on_release.  There's no need for 
> CGRP_RELEASABLE to depend on notify_on_release, or to check 
> notify_on_release before calling check_for_release. 
> 
>>>  /* Caller must verify that the css is not for root cgroup */ 
>>> +void __css_get(struct cgroup_subsys_state *css, int count) 
>>> +{ 
>>> +       atomic_add(count, &css->refcnt); 
>>> +       set_bit(CGRP_RELEASABLE, &css->cgroup->flags); 
>>> +} 
>> 
>> Is css_get() the right place to be putting this? It's not clear to me 
>> why a subsystem taking a refcount on a cgroup's state should render it 
>> releasable when it drops that refcount. 
> I matched the existing behavior, __css_put sets CGRP_RELEASABLE when 
> refcnt goes to 0. 
> 
>> Should we maybe clear the CGRP_RELEASABLE flag right before doing the 
>> userspace callback? 
> Actually, I think CGRP_RELEASABLE can be dropped entirely. 
> check_for_release is only called from __css_put, cgroup_rmdir, and 
> __put_css_set (or free_css_set_work after my second patch).  Those all 
> imply that __css_get, get_css_set, or cgroup_create have been 
> previously called, which are the functions that set CGRP_RELEASABLE. 
Nevermind, that's not true - get_css_set does not set CGRP_RELEASABLE, 
cgroup_attach_task does. 
 
If CGRP_RELEASABLE is not cleared before the callback, the 
release_agent would be run once when the last task was removed from 
the cgroup, and then again if a task failed to be added to the empty 
cgroup because the task was exiting, so clearing the flag sounds like 
a good idea. 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH 1/2] cgroup: Set CGRP_RELEASABLE when adding to a cgroup [message #41928 is a reply to message #41924] | 
			Fri, 03 December 2010 03:07    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On Wed, Nov 24, 2010 at 4:21 PM, Paul Menage <menage@google.com> wrote: 
> On Wed, Nov 24, 2010 at 4:11 PM, Colin Cross <ccross@android.com> wrote: 
>>> 
>>> We seem to have lost some notify_on_release() checks - maybe move that 
>>> to check_for_release()? 
>> check_for_release immediately calls cgroup_is_releasable, which checks 
>> for the same bit as notify_on_release.  There's no need for 
>> CGRP_RELEASABLE to depend on notify_on_release, or to check 
>> notify_on_release before calling check_for_release. 
> 
> OK. 
> 
>> I matched the existing behavior, __css_put sets CGRP_RELEASABLE when 
>> refcnt goes to 0. 
>> 
> 
> Ah, we do appear to have had that behaviour for a while. I don't 
> remember the justification for it at this point :-) 
> 
>> check_for_release is only called from __css_put, cgroup_rmdir, and 
>> __put_css_set (or free_css_set_work after my second patch).  Those all 
>> imply that __css_get, get_css_set, or cgroup_create have been 
>> previously called, which are the functions that set CGRP_RELEASABLE. 
> 
> Not in one case - if we create a new cgroup and try to move a thread 
> into it, but the thread is exiting as we move it, we'll call 
> put_css_set() on the new css_set, which will drop the refcount on the 
> target cgroup back to 0. We wouldn't want the auto-release 
> notification to kick in in that situation, I think. 
 
Clearing the CGRP_RELEASABLE bit any time after the tests in 
check_for_release introduces a race if __css_get is called between the 
check and clearing the bit - the cgroup will have an entry, but the 
bit will not be set.  Without additional locking in __css_get, I don't 
see any way to safely clear CGRP_RELEASABLE. 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH 1/2] cgroup: Set CGRP_RELEASABLE when adding to a cgroup [message #41941 is a reply to message #41924] | 
			Fri, 17 December 2010 01:12    | 
		 
		
			
				
				
				
					
						  
						Colin Cross
						 Messages: 15 Registered: November 2010 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On Thu, Dec 16, 2010 at 4:54 PM, Paul Menage <menage@google.com> wrote: 
> On Thu, Dec 2, 2010 at 7:07 PM, Colin Cross <ccross@android.com> wrote: 
>>> Not in one case - if we create a new cgroup and try to move a thread 
>>> into it, but the thread is exiting as we move it, we'll call 
>>> put_css_set() on the new css_set, which will drop the refcount on the 
>>> target cgroup back to 0. We wouldn't want the auto-release 
>>> notification to kick in in that situation, I think. 
>> 
>> Clearing the CGRP_RELEASABLE bit any time after the tests in 
>> check_for_release introduces a race if __css_get is called between the 
>> check and clearing the bit - the cgroup will have an entry, but the 
>> bit will not be set.  Without additional locking in __css_get, I don't 
>> see any way to safely clear CGRP_RELEASABLE. 
> 
> I don't quite follow your argument here. Are you saying that the 
> problem is that you could end up spawning a release agent for a cgroup 
> that was no longer releasable since it now had a process in it again? 
> If so, then I don't think that's a problem - spurious release agent 
> invocations for non-empty cgroups will always happen occasionally due 
> to races between the kernel and userspace. But a failed move of a task 
> into a previously-empty cgroup shouldn't trigger the agent. 
 
No, if you add a new process to the group while check_for_release, the 
bit could get set by the add for the new process, then cleared by the 
concurrently running check_for_release.  The release agent would be 
spawned with a process in the group, which is fine, but when 
RELEASABLE bit would be clear.  When the new process was removed, 
check_for_release would not call the release agent at all. 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH 2/2] cgroup: Remove call to synchronize_rcu in cgroup_attach_task [message #41949 is a reply to message #41923] | 
			Fri, 28 January 2011 01:17    | 
		 
		
			
				
				
				
					
						  
						Bryan Huntsman
						 Messages: 4 Registered: January 2011 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On 11/23/2010 09:37 PM, Colin Cross wrote: 
> synchronize_rcu can be very expensive, averaging 100 ms in 
> some cases.  In cgroup_attach_task, it is used to prevent 
> a task->cgroups pointer dereferenced in an RCU read side 
> critical section from being invalidated, by delaying the 
> call to put_css_set until after an RCU grace period. 
>  
> To avoid the call to synchronize_rcu, make the put_css_set 
> call rcu-safe by moving the deletion of the css_set links 
> into free_css_set_work, scheduled by the rcu callback 
> free_css_set_rcu. 
>  
> The decrement of the cgroup refcount is no longer 
> synchronous with the call to put_css_set, which can result 
> in the cgroup refcount staying positive after the last call 
> to cgroup_attach_task returns.  To allow the cgroup to be 
> deleted with cgroup_rmdir synchronously after 
> cgroup_attach_task, have rmdir check the refcount of all 
> associated css_sets.  If cgroup_rmdir is called on a cgroup 
> for which the css_sets all have refcount zero but the 
> cgroup refcount is nonzero, reuse the rmdir waitqueue to 
> block the rmdir until free_css_set_work is called. 
>  
> Signed-off-by: Colin Cross <ccross@android.com> 
> --- 
>  include/linux/cgroup.h |    1 + 
>  kernel/cgroup.c        |  120 +++++++++++++++++++++++++++++------------------- 
>  2 files changed, 74 insertions(+), 47 deletions(-) 
>  
> diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h 
> index 9e13078..49fdff0 100644 
> --- a/include/linux/cgroup.h 
> +++ b/include/linux/cgroup.h 
> @@ -279,6 +279,7 @@ struct css_set { 
>   
>  	/* For RCU-protected deletion */ 
>  	struct rcu_head rcu_head; 
> +	struct work_struct work; 
>  }; 
>   
>  /* 
> diff --git a/kernel/cgroup.c b/kernel/cgroup.c 
> index 34e855e..e752c83 100644 
> --- a/kernel/cgroup.c 
> +++ b/kernel/cgroup.c 
> @@ -267,6 +267,33 @@ static void cgroup_release_agent(struct work_struct *work); 
>  static DECLARE_WORK(release_agent_work, cgroup_release_agent); 
>  static void check_for_release(struct cgroup *cgrp); 
>   
> +/* 
> + * A queue for waiters to do rmdir() cgroup. A tasks will sleep when 
> + * cgroup->count == 0 && list_empty(&cgroup->children) && subsys has some 
> + * reference to css->refcnt. In general, this refcnt is expected to goes down 
> + * to zero, soon. 
> + * 
> + * CGRP_WAIT_ON_RMDIR flag is set under cgroup's inode->i_mutex; 
> + */ 
> +DECLARE_WAIT_QUEUE_HEAD(cgroup_rmdir_waitq); 
> + 
> +static void cgroup_wakeup_rmdir_waiter(struct cgroup *cgrp) 
> +{ 
> +	if (unlikely(test_and_clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags))) 
> +		wake_up_all(&cgroup_rmdir_waitq); 
> +} 
> + 
> +void cgroup_exclude_rmdir(struct cgroup_subsys_state *css) 
> +{ 
> +	css_get(css); 
> +} 
> + 
> +void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css) 
> +{ 
> +	cgroup_wakeup_rmdir_waiter(css->cgroup); 
> +	css_put(css); 
> +} 
> + 
>  /* Link structure for associating css_set objects with cgroups */ 
>  struct cg_cgroup_link { 
>  	/* 
> @@ -326,10 +353,35 @@ static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[]) 
>  	return &css_set_table[index]; 
>  } 
>   
> +static void free_css_set_work(struct work_struct *work) 
> +{ 
> +	struct css_set *cg = container_of(work, struct css_set, work); 
> +	struct cg_cgroup_link *link; 
> +	struct cg_cgroup_link *saved_link; 
> + 
> +	write_lock(&css_set_lock); 
> +	list_for_each_entry_safe(link, saved_link, &cg->cg_links, 
> +				 cg_link_list) { 
> +		struct cgroup *cgrp = link->cgrp; 
> +		list_del(&link->cg_link_list); 
> +		list_del(&link->cgrp_link_list); 
> +		if (atomic_dec_and_test(&cgrp->count)) { 
> +			check_for_release(cgrp); 
> +			cgroup_wakeup_rmdir_waiter(cgrp); 
> +		} 
> +		kfree(link); 
> +	} 
> +	write_unlock(&css_set_lock); 
> + 
> +	kfree(cg); 
> +} 
> + 
>  static void free_css_set_rcu(struct rcu_head *obj) 
>  { 
>  	struct css_set *cg = container_of(obj, struct css_set, rcu_head); 
> -	kfree(cg); 
> + 
> +	INIT_WORK(&cg->work, free_css_set_work); 
> +	schedule_work(&cg->work); 
>  } 
>   
>  /* We don't maintain the lists running through each css_set to its 
> @@ -348,8 +400,6 @@ static inline void get_css_set(struct css_set *cg) 
>   
>  static void put_css_set(struct css_set *cg) 
>  { 
> -	struct cg_cgroup_link *link; 
> -	struct cg_cgroup_link *saved_link; 
>  	/* 
>  	 * Ensure that the refcount doesn't hit zero while any readers 
>  	 * can see it. Similar to atomic_dec_and_lock(), but for an 
> @@ -363,21 +413,9 @@ static void put_css_set(struct css_set *cg) 
>  		return; 
>  	} 
>   
> -	/* This css_set is dead. unlink it and release cgroup refcounts */ 
>  	hlist_del(&cg->hlist); 
>  	css_set_count--; 
>   
> -	list_for_each_entry_safe(link, saved_link, &cg->cg_links, 
> -				 cg_link_list) { 
> -		struct cgroup *cgrp = link->cgrp; 
> -		list_del(&link->cg_link_list); 
> -		list_del(&link->cgrp_link_list); 
> -		if (atomic_dec_and_test(&cgrp->count)) 
> -			check_for_release(cgrp); 
> - 
> -		kfree(link); 
> -	} 
> - 
>  	write_unlock(&css_set_lock); 
>  	call_rcu(&cg->rcu_head, free_css_set_rcu); 
>  } 
> @@ -711,9 +749,9 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task, 
>   * cgroup_attach_task(), which overwrites one tasks cgroup pointer with 
>   * another.  It does so using cgroup_mutex, however there are 
>   * several performance critical places that need to reference 
> - * task->cgroup without the expense of grabbing a system global 
> + * task->cgroups without the expense of grabbing a system global 
>   * mutex.  Therefore except as noted below, when dereferencing or, as 
> - * in cgroup_attach_task(), modifying a task'ss cgroup pointer we use 
> + * in cgroup_attach_task(), modifying a task's cgroups pointer we use 
>   * task_lock(), which acts on a spinlock (task->alloc_lock) already in 
>   * the task_struct routinely used for such matters. 
>   * 
> @@ -895,33 +933,6 @@ static void cgroup_d_remove_dir(struct dentry *dentry) 
>  } 
>   
>  /* 
> - * A queue for waiters to do rmdir() cgroup. A tasks will sleep when 
> - * cgroup->count == 0 && list_empty(&cgroup->children) && subsys has some 
> - * reference to css->refcnt. In general, this refcnt is expected to goes down 
> - * to zero, soon. 
> - * 
> - * CGRP_WAIT_ON_RMDIR flag is set under cgroup's inode->i_mutex; 
> - */ 
> -DECLARE_WAIT_QUEUE_HEAD(cgroup_rmdir_waitq); 
> - 
> -static void cgroup_wakeup_rmdir_waiter(struct cgroup *cgrp) 
> -{ 
> -	if (unlikely(test_and_clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags))) 
> -		wake_up_all(&cgroup_rmdir_waitq); 
> -} 
> - 
> -void cgroup_exclude_rmdir(struct cgroup_subsys_state *css) 
> -{ 
> -	css_get(css); 
> -} 
> - 
> -void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css) 
> -{ 
> -	cgroup_wakeup_rmdir_waiter(css->cgroup); 
> -	css_put(css); 
> -} 
> - 
> -/* 
>   * Call with cgroup_mutex held. Drops reference counts on modules, including 
>   * any duplicate ones that parse_cgroupfs_options took. If this function 
>   * returns an error, no reference counts are touched. 
> @@ -1788,7 +1799,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 
>  			ss->attach(ss, cgrp, oldcgrp, tsk, false); 
>  	} 
>  	set_bit(CGRP_RELEASABLE, &cgrp->flags); 
> -	synchronize_rcu(); 
> +	/* put_css_set will not destroy cg until after an RCU grace period */ 
>  	put_css_set(cg); 
>   
>  	/* 
> @@ -3546,6 +3557,21 @@ static int cgroup_clear_css_refs(struct cgroup *cgrp) 
>  	return !failed; 
>  } 
>   
> +/* checks if all of the css_sets attached to a cgroup have a refcount of 0. 
> + * Must be called with css_set_lock held */ 
> +static int cgroup_css_sets_empty(struct cgroup *cgrp) 
> +{ 
> +	struct cg_cgroup_link *link; 
> + 
> +	list_for_each_entry(link, &cgrp->css_sets, cgrp_link_list) { 
> +		struct css_set *cg = link->cg; 
> +		if (atomic_read(&cg->refcount) > 0) 
> +			return 0; 
> +	} 
> + 
> +	return 1; 
> +} 
> + 
>  static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) 
>  { 
>  	struct cgroup *cgrp = dentry->d_fsdata; 
> @@ -3558,7 +3584,7 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) 
>  	/* the vfs holds both inode->i_mutex already */ 
>  again: 
>  	mutex_lock(&cgroup_mutex); 
> -	if (atomic_read(&cgrp->count) != 0) { 
> +	if (!cgroup_css_sets_empty(cgrp)) { 
>  		mutex_unlock(&cgroup_mutex); 
>  		return -EBUSY; 
>  	} 
> @@ -3591,7 +3617,7 @@ again: 
>   
>  	mutex_lock(&cgroup_mutex); 
>  	parent = cgrp->parent; 
> -	if (atomic_read(&cgrp->count) || !list_empty(&cgrp->children)) { 
> +	if (!cgroup_css_sets_empty(cgrp) || !list_empty(&cgrp->children)) { 
>  		clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags); 
>  		mutex_unlock(&cgroup_mutex); 
>  		return -EBUSY; 
 
Tested-by: Mike Bohan <mbohan@codeaurora.org> 
 
I'm responding on Mike's behalf and adding him to this thread.  This 
patch improves launch time of a test app from ~700ms to ~250ms on MSM, 
with much lower variance across tests.  We also see UI latency 
improvements, but have not quantified the gains. 
 
- Bryan 
 
--  
Sent by an employee of the Qualcomm Innovation Center, Inc. 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum. 
___
...
  
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH 1/2] cgroup: Set CGRP_RELEASABLE when adding to a cgroup [message #41950 is a reply to message #41924] | 
			Fri, 28 January 2011 01:17    | 
		 
		
			
				
				
				
					
						  
						Bryan Huntsman
						 Messages: 4 Registered: January 2011 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On 11/23/2010 09:37 PM, Colin Cross wrote: 
> Changes the meaning of CGRP_RELEASABLE to be set on any cgroup 
> that has ever had a task or cgroup in it, or had css_get called 
> on it.  The bit is set in cgroup_attach_task, cgroup_create, 
> and __css_get.  It is not necessary to set the bit in 
> cgroup_fork, as the task is either in the root cgroup, in 
> which can never be released, or the task it was forked from 
> already set the bit in croup_attach_task. 
>  
> Signed-off-by: Colin Cross <ccross@android.com> 
> --- 
>  include/linux/cgroup.h |   12 +-------- 
>  kernel/cgroup.c        |   54 ++++++++++++++++++++--------------------------- 
>  2 files changed, 25 insertions(+), 41 deletions(-) 
>  
> diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h 
> index ed4ba11..9e13078 100644 
> --- a/include/linux/cgroup.h 
> +++ b/include/linux/cgroup.h 
> @@ -84,12 +84,6 @@ enum { 
>  	CSS_REMOVED, /* This CSS is dead */ 
>  }; 
>   
> -/* Caller must verify that the css is not for root cgroup */ 
> -static inline void __css_get(struct cgroup_subsys_state *css, int count) 
> -{ 
> -	atomic_add(count, &css->refcnt); 
> -} 
> - 
>  /* 
>   * Call css_get() to hold a reference on the css; it can be used 
>   * for a reference obtained via: 
> @@ -97,6 +91,7 @@ static inline void __css_get(struct cgroup_subsys_state *css, int count) 
>   * - task->cgroups for a locked task 
>   */ 
>   
> +extern void __css_get(struct cgroup_subsys_state *css, int count); 
>  static inline void css_get(struct cgroup_subsys_state *css) 
>  { 
>  	/* We don't need to reference count the root state */ 
> @@ -143,10 +138,7 @@ static inline void css_put(struct cgroup_subsys_state *css) 
>  enum { 
>  	/* Control Group is dead */ 
>  	CGRP_REMOVED, 
> -	/* 
> -	 * Control Group has previously had a child cgroup or a task, 
> -	 * but no longer (only if CGRP_NOTIFY_ON_RELEASE is set) 
> -	 */ 
> +	/* Control Group has ever had a child cgroup or a task */ 
>  	CGRP_RELEASABLE, 
>  	/* Control Group requires release notifications to userspace */ 
>  	CGRP_NOTIFY_ON_RELEASE, 
> diff --git a/kernel/cgroup.c b/kernel/cgroup.c 
> index 66a416b..34e855e 100644 
> --- a/kernel/cgroup.c 
> +++ b/kernel/cgroup.c 
> @@ -338,7 +338,15 @@ static void free_css_set_rcu(struct rcu_head *obj) 
>   * compiled into their kernel but not actually in use */ 
>  static int use_task_css_set_links __read_mostly; 
>   
> -static void __put_css_set(struct css_set *cg, int taskexit) 
> +/* 
> + * refcounted get/put for css_set objects 
> + */ 
> +static inline void get_css_set(struct css_set *cg) 
> +{ 
> +	atomic_inc(&cg->refcount); 
> +} 
> + 
> +static void put_css_set(struct css_set *cg) 
>  { 
>  	struct cg_cgroup_link *link; 
>  	struct cg_cgroup_link *saved_link; 
> @@ -364,12 +372,8 @@ static void __put_css_set(struct css_set *cg, int taskexit) 
>  		struct cgroup *cgrp = link->cgrp; 
>  		list_del(&link->cg_link_list); 
>  		list_del(&link->cgrp_link_list); 
> -		if (atomic_dec_and_test(&cgrp->count) && 
> -		    notify_on_release(cgrp)) { 
> -			if (taskexit) 
> -				set_bit(CGRP_RELEASABLE, &cgrp->flags); 
> +		if (atomic_dec_and_test(&cgrp->count)) 
>  			check_for_release(cgrp); 
> -		} 
>   
>  		kfree(link); 
>  	} 
> @@ -379,24 +383,6 @@ static void __put_css_set(struct css_set *cg, int taskexit) 
>  } 
>   
>  /* 
> - * refcounted get/put for css_set objects 
> - */ 
> -static inline void get_css_set(struct css_set *cg) 
> -{ 
> -	atomic_inc(&cg->refcount); 
> -} 
> - 
> -static inline void put_css_set(struct css_set *cg) 
> -{ 
> -	__put_css_set(cg, 0); 
> -} 
> - 
> -static inline void put_css_set_taskexit(struct css_set *cg) 
> -{ 
> -	__put_css_set(cg, 1); 
> -} 
> - 
> -/* 
>   * compare_css_sets - helper function for find_existing_css_set(). 
>   * @cg: candidate css_set being tested 
>   * @old_cg: existing css_set for a task 
> @@ -1801,7 +1787,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 
>  		if (ss->attach) 
>  			ss->attach(ss, cgrp, oldcgrp, tsk, false); 
>  	} 
> -	set_bit(CGRP_RELEASABLE, &oldcgrp->flags); 
> +	set_bit(CGRP_RELEASABLE, &cgrp->flags); 
>  	synchronize_rcu(); 
>  	put_css_set(cg); 
>   
> @@ -3427,6 +3413,8 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, 
>  	if (err < 0) 
>  		goto err_remove; 
>   
> +	set_bit(CGRP_RELEASABLE, &parent->flags); 
> + 
>  	/* The cgroup directory was pre-locked for us */ 
>  	BUG_ON(!mutex_is_locked(&cgrp->dentry->d_inode->i_mutex)); 
>   
> @@ -3645,7 +3633,6 @@ again: 
>  	cgroup_d_remove_dir(d); 
>  	dput(d); 
>   
> -	set_bit(CGRP_RELEASABLE, &parent->flags); 
>  	check_for_release(parent); 
>   
>  	/* 
> @@ -4240,7 +4227,7 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks) 
>  	tsk->cgroups = &init_css_set; 
>  	task_unlock(tsk); 
>  	if (cg) 
> -		put_css_set_taskexit(cg); 
> +		put_css_set(cg); 
>  } 
>   
>  /** 
> @@ -4410,6 +4397,14 @@ static void check_for_release(struct cgroup *cgrp) 
>  } 
>   
>  /* Caller must verify that the css is not for root cgroup */ 
> +void __css_get(struct cgroup_subsys_state *css, int count) 
> +{ 
> +	atomic_add(count, &css->refcnt); 
> +	set_bit(CGRP_RELEASABLE, &css->cgroup->flags); 
> +} 
> +EXPORT_SYMBOL_GPL(__css_get); 
> + 
> +/* Caller must verify that the css is not for root cgroup */ 
>  void __css_put(struct cgroup_subsys_state *css, int count) 
>  { 
>  	struct cgroup *cgrp = css->cgroup; 
> @@ -4417,10 +4412,7 @@ void __css_put(struct cgroup_subsys_state *css, int count) 
>  	rcu_read_lock(); 
>  	val = atomic_sub_return(count, &css->refcnt); 
>  	if (val == 1) { 
> -		if (notify_on_release(cgrp)) { 
> -			set_bit(CGRP_RELEASABLE, &cgrp->flags); 
> -			check_for_release(cgrp); 
> -		} 
> +		check_for_release(cgrp); 
>  		cgroup_wakeup_rmdir_waiter(cgrp); 
>  	} 
>  	rcu_read_unlock(); 
 
Tested-by: Mike Bohan <mbohan@codeaurora.org> 
 
I'm responding on Mike's behalf and adding him to this thread.  This 
patch improves launch time of a test app from ~700ms to ~250ms on MSM, 
with much lower variance across tests.  We also see UI latency 
improvements, but have not quantified the gains. 
 
- Bryan 
 
--  
Sent by an employee of the Qualcomm Innovation Center, Inc. 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum. 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	
		
		
			| Re: [PATCH 1/2] cgroup: Set CGRP_RELEASABLE when adding to a cgroup [message #42024 is a reply to message #41924] | 
			Fri, 28 January 2011 01:48   | 
		 
		
			
				
				
				
					
						  
						Michael Bohan
						 Messages: 1 Registered: January 2011 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		On 1/27/2011 5:30 PM, Paul Menage wrote: 
> On Thu, Jan 27, 2011 at 5:17 PM, Bryan Huntsman<bryanh@codeaurora.org>  wrote: 
>> 
>> Tested-by: Mike Bohan<mbohan@codeaurora.org> 
>> 
>> I'm responding on Mike's behalf and adding him to this thread.  This 
>> patch improves launch time of a test app from ~700ms to ~250ms on MSM, 
>> with much lower variance across tests.  We also see UI latency 
>> improvements, but have not quantified the gains. 
>> 
> 
> Is this attached to the wrong patch? I'd thought that it was the other 
> patch (removing the rcu_synchronize()) that's the performance booster. 
> This one is more about preserving the semantics of the notification 
> API. 
 
You are correct. "[PATCH 2/2] cgroup: Remove call to synchronize_rcu in  
cgroup_attach_task" improved the performance. 
 
To be more correct, I tested this patch (eg. "cgroup: Set  
CGRP_RELEASABLE when adding to a cgroup") to the degree that it didn't  
appear to cause any stability or functional regressions when performing  
the simple benchmark procedure described above. I did also test "[PATCH  
2/2] cgroup: Remove call to synchronize_rcu in cgroup_attach_task"  
independently of this patch to verify that it alone improved the  
performance. 
 
Thanks, 
Mike 
 
--  
Employee of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum 
_______________________________________________ 
Containers mailing list 
Containers@lists.linux-foundation.org 
 https://lists.linux-foundation.org/mailman/listinfo/containe rs
		
		
		
 |  
	| 
		
	 | 
 
 
 |   
Goto Forum:
 
 Current Time: Tue Nov 04 15:52:10 GMT 2025 
 Total time taken to generate the page: 0.14069 seconds 
 |