Subject: [PATCH 18/18] sadump: check if given cpu is online in per-cpu related helper functions

This is a backport of

	http://lists.infradead.org/pipermail/kexec/2012-February/006072.html

	Per-cpu helper functions sanity check given cpu ids if they are
	not-minus and less than the maximal but it should have checked if they
	are online. By this mistake, one cannot see generated vmcore correctly
	if sadump collects vmcore when some cpus are offline e.g. using cpu
	hotplug or panic and so all the cpus except for a unique CPU halting.

	Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>

---
diff -Nrup kexec-tools-2.0.0.old/makedumpfile-1.3.5/sadump_info.c kexec-tools-2.0.0/makedumpfile-1.3.5/sadump_info.c
--- kexec-tools-2.0.0.old/makedumpfile-1.3.5/sadump_info.c	2012-04-18 04:08:29.003041051 -0400
+++ kexec-tools-2.0.0/makedumpfile-1.3.5/sadump_info.c	2012-04-18 04:12:27.016191380 -0400
@@ -44,7 +44,7 @@
 			  KEXEC_CORE_NOTE_DESC_BYTES )
 
 #define for_each_online_cpu(cpu)					\
-	for (cpu = 0; cpu < BITPERBYTE * si->cpumask_size; ++cpu)	\
+	for (cpu = 0; cpu < max_mask_cpu(); ++cpu)	\
 		if (is_online_cpu(cpu))
 
 enum {
@@ -93,6 +93,7 @@ static int read_sadump_header_diskset(in
 static unsigned long long pfn_to_block(unsigned long long pfn);
 static int lookup_diskset(unsigned long long whole_offset, int *diskid,
 			  unsigned long long *disk_offset);
+static int max_mask_cpu(void);
 static int cpu_online_mask_init(void);
 static int per_cpu_init(void);
 static int get_data_from_elf_note_desc(const char *note_buf, uint32_t n_descsz,
@@ -799,6 +800,12 @@ sadump_initialize_bitmap_memory(void)
 }
 
 static int
+max_mask_cpu(void)
+{
+	return BITPERBYTE * si->cpumask_size;
+}
+
+static int
 cpu_online_mask_init(void)
 {
 	ulong cpu_online_mask_addr;
@@ -1289,6 +1296,9 @@ is_online_cpu(int cpu)
 {
 	unsigned long mask;
 
+	if (cpu < 0 || cpu >= max_mask_cpu())
+		return FALSE;
+
 	mask = ULONG(si->cpu_online_mask_buf +
 		     (cpu / BITPERWORD) * sizeof(unsigned long));
 
@@ -1300,7 +1310,7 @@ legacy_per_cpu_ptr(unsigned long ptr, in
 {
 	unsigned long addr;
 
-	if (cpu < 0 || cpu >= info->nr_cpus)
+	if (!is_online_cpu(cpu))
 		return 0UL;
 
 	if (!readmem(VADDR, ~ptr + cpu*sizeof(unsigned long), &addr,
@@ -1313,7 +1323,7 @@ legacy_per_cpu_ptr(unsigned long ptr, in
 static unsigned long
 per_cpu_ptr(unsigned long ptr, int cpu)
 {
-	if (cpu < 0 || cpu >= info->nr_cpus)
+	if (!is_online_cpu(cpu))
 		return 0UL;
 
 	if (si->__per_cpu_offset[cpu] == si->__per_cpu_load)
@@ -1329,7 +1339,7 @@ get_prstatus_from_crash_notes(int cpu, c
 	char note_buf[KEXEC_NOTE_BYTES], zero_buf[KEXEC_NOTE_BYTES];
 	char *prstatus_ptr;
 
-	if (cpu < 0 || info->nr_cpus <= cpu)
+	if (!is_online_cpu(cpu))
 		return FALSE;
 
 	if (SYMBOL(crash_notes) == NOT_FOUND_SYMBOL)
