Skip to contentSkip to conversation

cpuset: rcu_read_lock() to protect task_cs()

PATCH In review Lai Jiangshan 3 participants 3 messages Nov 21, 2008 1 message not in the archive

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 cpuset: rcu_read_lock() to protect task_cs()

task_cs() calls cgroup_subsys_state().

we must use rcu_read_lock() to protect cgroup_subsys_state().

it's correct that top_cpuset is never freed, but cgroup_subsys_state() accesses css_set, this css_set maybe freed when task_cs() called.

we use use rcu_read_lock() to protect it.

---

kernel/cpuset.c +3 -8
index 3e00526..e0e087e 100644
@@ -363,14 +363,9 @@ void cpuset_update_task_memory_state(void)
 	struct task_struct *tsk = current;
 	struct cpuset *cs;
 
-	if (task_cs(tsk) == &top_cpuset) {
-		/* Don't need rcu for top_cpuset.  It's never freed. */
-		my_cpusets_mem_gen = top_cpuset.mems_generation;
-	} else {
-		rcu_read_lock();
-		my_cpusets_mem_gen = task_cs(tsk)->mems_generation;
-		rcu_read_unlock();
-	}
+	rcu_read_lock();
+	my_cpusets_mem_gen = task_cs(tsk)->mems_generation;
+	rcu_read_unlock();
 
 	if (my_cpusets_mem_gen != tsk->cpuset_mems_generation) {
 		mutex_lock(&callback_mutex);

A message that is not in the archive (sent off-list or not yet received): [email protected]

Acked-by
#2 lore raw
Quoted 2 lines · Lai Jiangshan

task_cs() calls cgroup_subsys_state().

You mean it calls task_subsys_state().

Quoted 5 lines

we must use rcu_read_lock() to protect cgroup_subsys_state().

it's correct that top_cpuset is never freed, but cgroup_subsys_state() accesses css_set, this css_set maybe freed when task_cs() called.

It would be nice to have an RCU debug mode where rcu_dereference() does a WARN() if it's invoked not under rcu_read_lock().

Quoted 14 lines

we use use rcu_read_lock() to protect it.

---

kernel/cpuset.c +0 -1
index 3e00526..e0e087e 100644
@@ -363,14 +363,9 @@ void cpuset_update_task_memory_state(void)
       struct task_struct *tsk = current;
       struct cpuset *cs;
 
-       if (task_cs(tsk) == &top_cpuset) {

kernel/cpuset.c void cpuset_update_task_memory_state(void) · line 368

Quoted 10 lines
kernel/cpuset.c +3 -7
-               /* Don't need rcu for top_cpuset.  It's never freed. */
-               my_cpusets_mem_gen = top_cpuset.mems_generation;
-       } else {
-               rcu_read_lock();
-               my_cpusets_mem_gen = task_cs(tsk)->mems_generation;
-               rcu_read_unlock();
-       }
+       rcu_read_lock();
+       my_cpusets_mem_gen = task_cs(tsk)->mems_generation;
+       rcu_read_unlock();

Yes, I guess this old cpusets assumption is no longer valid in cgroups.

Thanks

Paul

Acked-by on v1 1/1
#3 lore raw
In reply to Lai Jiangshan
Quoted 2 lines · Lai Jiangshan

task_cs() calls cgroup_subsys_state().

You mean it calls task_subsys_state().

Quoted 5 lines

we must use rcu_read_lock() to protect cgroup_subsys_state().

it's correct that top_cpuset is never freed, but cgroup_subsys_state() accesses css_set, this css_set maybe freed when task_cs() called.

It would be nice to have an RCU debug mode where rcu_dereference() does a WARN() if it's invoked not under rcu_read_lock().

Quoted 14 lines

we use use rcu_read_lock() to protect it.

---

kernel/cpuset.c +0 -1
index 3e00526..e0e087e 100644
@@ -363,14 +363,9 @@ void cpuset_update_task_memory_state(void)
       struct task_struct *tsk = current;
       struct cpuset *cs;
 
-       if (task_cs(tsk) == &top_cpuset) {

kernel/cpuset.c void cpuset_update_task_memory_state(void) · line 368

Quoted 10 lines
kernel/cpuset.c +3 -7
-               /* Don't need rcu for top_cpuset.  It's never freed. */
-               my_cpusets_mem_gen = top_cpuset.mems_generation;
-       } else {
-               rcu_read_lock();
-               my_cpusets_mem_gen = task_cs(tsk)->mems_generation;
-               rcu_read_unlock();
-       }
+       rcu_read_lock();
+       my_cpusets_mem_gen = task_cs(tsk)->mems_generation;
+       rcu_read_unlock();

Yes, I guess this old cpusets assumption is no longer valid in cgroups.

Thanks

Paul