Skip to contentSkip to conversation

x86/proc: fix /proc/cpuinfo cpu offline bug

PATCH Superseded Lai Jiangshan 3 participants 5 messages Oct 17, 2008 – Oct 22, 2008 x86

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 x86/proc: fix /proc/cpuinfo cpu offline bug

In my test, I found that if a cpu has been offline, the next cpus may not be shown in the /proc/cpuinfo.

trivially reproduce this bug:

1) add these lines in the end of show_cpuinfo()

	if (m->size - m->count - 20 > 0)
		seq_printf(m, "%*s", (int)(m->size - m->count - 20), "show bug\n");

2) rebuilt kernel & reboot
3) offline cpu#1
4) cat /proc/cpuinfo
cpu#2 and cpu#3 .... cannot be shown in /proc/cpuinfo

---

arch/x86/kernel/cpu/proc.c +4 -2
index a26c480..01b1244 100644
@@ -160,14 +160,16 @@ static void *c_start(struct seq_file *m, loff_t *pos)
 {
 	if (*pos == 0)	/* just in case, cpu 0 is not the first */
 		*pos = first_cpu(cpu_online_map);
-	if ((*pos) < nr_cpu_ids && cpu_online(*pos))
+	else
+		*pos = next_cpu_nr(*pos - 1, cpu_online_map);
+	if ((*pos) < nr_cpu_ids)
 		return &cpu_data(*pos);
 	return NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	*pos = next_cpu(*pos, cpu_online_map);
+	(*pos)++;
 	return c_start(m, pos);
 }
 
#1 lore raw
Quoted 8 lines · Lai Jiangshan

In my test, I found that if a cpu has been offline, the next cpus may not be shown in the /proc/cpuinfo.

trivially reproduce this bug:

1) add these lines in the end of show_cpuinfo()

	if (m->size - m->count - 20 > 0)
		seq_printf(m, "%*s", (int)(m->size - m->count - 20), "show bug\n");

What is it?

Can you just show wrong /proc/cpuinfo ?

Can someone with at least 4-way box please do so?

Quoted 24 lines

3) offline cpu#1
4) cat /proc/cpuinfo
cpu#2 and cpu#3 .... cannot be shown in /proc/cpuinfo

arch/x86/kernel/cpu/proc.c +4 -2
@@ -160,14 +160,16 @@ static void *c_start(struct seq_file *m, loff_t *pos)
 {
 	if (*pos == 0)	/* just in case, cpu 0 is not the first */
 		*pos = first_cpu(cpu_online_map);
-	if ((*pos) < nr_cpu_ids && cpu_online(*pos))
+	else
+		*pos = next_cpu_nr(*pos - 1, cpu_online_map);
+	if ((*pos) < nr_cpu_ids)
 		return &cpu_data(*pos);
 	return NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	*pos = next_cpu(*pos, cpu_online_map);
+	(*pos)++;
 	return c_start(m, pos);
 }
#2 lore raw
Quoted 10 lines · Alexey Dobriyan
Quoted 8 lines · Lai Jiangshan

In my test, I found that if a cpu has been offline, the next cpus may not be shown in the /proc/cpuinfo.

trivially reproduce this bug:

1) add these lines in the end of show_cpuinfo()

      if (m->size - m->count - 20 > 0)
              seq_printf(m, "%*s", (int)(m->size - m->count - 20), "show bug\n");
Quoted 5 lines

What is it?

Can you just show wrong /proc/cpuinfo ?

Can someone with at least 4-way box please do so?

this is not wrong /proc/cpuinfo, this is an enlarged /proc/cpuinfo this trivial example just use "show bug\n" as the enlarged content.

if you boot your machine with enough cpu, your /proc/cpuinfo have been enlarged too, please use this:

#!/bin/sh
nr_cpus=16 # i386
for ((i=1; i<nr_cpus; i++))
do
echo 0 > /sys/devices/system/cpu/cpu$i/online cpus=$(grep processor /proc/cpuinfo | wc -l) (( cpus == nr_cpus -1 )) || break; # bug eccur echo 1 > /sys/devices/system/cpu/cpu$i/online
done
cat /proc/cpuinfo # it shows this bug.

Lai

Quoted 31 lines
Quoted 15 lines

3) offline cpu#1
4) cat /proc/cpuinfo
cpu#2 and cpu#3 .... cannot be shown in /proc/cpuinfo

arch/x86/kernel/cpu/proc.c +3 -1
@@ -160,14 +160,16 @@ static void *c_start(struct seq_file *m, loff_t *pos)
 {
      if (*pos == 0)  /* just in case, cpu 0 is not the first */
              *pos = first_cpu(cpu_online_map);
-     if ((*pos) < nr_cpu_ids && cpu_online(*pos))
+     else
+             *pos = next_cpu_nr(*pos - 1, cpu_online_map);
+     if ((*pos) < nr_cpu_ids)

arch/x86/kernel/cpu/proc.c static void *c_start(struct seq_file *m, loff_t *pos) · line 174

Quoted 10 lines
arch/x86/kernel/cpu/proc.c +1 -1
              return &cpu_data(*pos);
      return NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
-     *pos = next_cpu(*pos, cpu_online_map);
+     (*pos)++;
      return c_start(m, pos);
 }

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#3 lore raw

Hi, Ingo and Alexey,

I have changed my changelog. please review again.

Thanks, Lai.

Quoted 67 lines · Lai Jiangshan
Quoted 6 lines · Alexey Dobriyan
Quoted 5 lines · Lai Jiangshan

In my test, I found that if a cpu has been offline, the next cpus may not be shown in the /proc/cpuinfo.

trivially reproduce this bug:

Quoted 8 lines
Quoted 3 lines

1) add these lines in the end of show_cpuinfo()

      if (m->size - m->count - 20 > 0)
              seq_printf(m, "%*s", (int)(m->size - m->count - 20), "show bug\n");

What is it?

Can you just show wrong /proc/cpuinfo ?

Can someone with at least 4-way box please do so?

this is not wrong /proc/cpuinfo, this is an enlarged /proc/cpuinfo this trivial example just use "show bug\n" as the enlarged content.

if you boot your machine with enough cpu, your /proc/cpuinfo have been enlarged too, please use this:

#!/bin/sh
nr_cpus=16 # i386
for ((i=1; i<nr_cpus; i++))
do
echo 0 > /sys/devices/system/cpu/cpu$i/online cpus=$(grep processor /proc/cpuinfo | wc -l) (( cpus == nr_cpus -1 )) || break; # bug eccur echo 1 > /sys/devices/system/cpu/cpu$i/online
done
cat /proc/cpuinfo # it shows this bug.

Lai

Quoted 29 lines
Quoted 13 lines

3) offline cpu#1
4) cat /proc/cpuinfo
cpu#2 and cpu#3 .... cannot be shown in /proc/cpuinfo

arch/x86/kernel/cpu/proc.c +3 -1
@@ -160,14 +160,16 @@ static void *c_start(struct seq_file *m, loff_t *pos)
 {
      if (*pos == 0)  /* just in case, cpu 0 is not the first */
              *pos = first_cpu(cpu_online_map);
-     if ((*pos) < nr_cpu_ids && cpu_online(*pos))
+     else
+             *pos = next_cpu_nr(*pos - 1, cpu_online_map);
+     if ((*pos) < nr_cpu_ids)

arch/x86/kernel/cpu/proc.c static void *c_start(struct seq_file *m, loff_t *pos) · line 174

Quoted 10 lines
arch/x86/kernel/cpu/proc.c +1 -1
              return &cpu_data(*pos);
      return NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
-     *pos = next_cpu(*pos, cpu_online_map);
+     (*pos)++;
      return c_start(m, pos);
 }

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#4 lore raw
Quoted 6 lines · Lai Jiangshan

Hi, Ingo and Alexey,

I have changed my changelog. please review again.

Thanks, Lai.

In my test, I found that if a cpu has been offline, the next cpus may not be shown in the /proc/cpuinfo.

if one read() cannot consume the whole /proc/cpuinfo, c_start() will be called again in the next read() calls. And *pos has been increased by 1 by the caller(seq_read()). if this time the cpu#*pos is offline, c_start() will return NULL, and the next cpus can not be shown.

this fix use next_cpu_nr(*pos - 1, cpu_online_map) to search the next unshown cpu.

the most easy way to reproduce this bug:
1) offline cpu#1 (cpu#0 is online)
2) dd ibs=2 if=/proc/cpuinfo
the result is that only cpu#0 is shown. cpu#2 and cpu#3 .... cannot be shown in /proc/cpuinfo it's bug.

---

arch/x86/kernel/cpu/proc.c +4 -2
index a26c480..01b1244 100644
@@ -160,14 +160,16 @@ static void *c_start(struct seq_file *m, loff_t *pos)
 {
 	if (*pos == 0)	/* just in case, cpu 0 is not the first */
 		*pos = first_cpu(cpu_online_map);
-	if ((*pos) < nr_cpu_ids && cpu_online(*pos))
+	else
+		*pos = next_cpu_nr(*pos - 1, cpu_online_map);
+	if ((*pos) < nr_cpu_ids)
 		return &cpu_data(*pos);
 	return NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	*pos = next_cpu(*pos, cpu_online_map);
+	(*pos)++;
 	return c_start(m, pos);
 }