cpumask: add sysfs displays for configured and disabled cpu maps
authorMike Travis <travis@sgi.com>
Tue, 16 Dec 2008 04:26:48 +0000 (20:26 -0800)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 19 Dec 2008 07:17:04 +0000 (17:47 +1030)
Impact: add new sysfs files.

Add sysfs files "kernel_max" and "offline" to display the max CPU index
allowed (NR_CPUS-1), and the map of cpus that are offline.

Cpus can be offlined via HOTPLUG, disabled by the BIOS ACPI tables, or
if they exceed the number of cpus allowed by the NR_CPUS config option,
or the "maxcpus=NUM" kernel start parameter.

The "possible_cpus=NUM" parameter can also extend the number of possible
cpus allowed, in which case the cpus not present at startup will be
in the offline state.  (These cpus can be HOTPLUGGED ON after system
startup [pending a follow-on patch to provide the capability via the
/sys/devices/sys/cpu/cpuN/online mechanism to bring them online.])

By design, the "offlined cpus > possible cpus" display will always
use the following formats:

  * all possible cpus online:   "x$"    or "x-y$"
  * some possible cpus offline: ".*,x$" or ".*,x-y$"

where:
  x == number of possible cpus (nr_cpu_ids); and
  y == number of cpus >= NR_CPUS or maxcpus (if y > x).

One use of this feature is for distros to select (or configure) the
appropriate kernel to install for the resident system.

Notes:
  * cpus offlined <= possible cpus will be printed for all architectures.
  * cpus offlined >  possible cpus will only be printed for arches that
   set 'total_cpus' [X86 only in this patch].

Based on tip/cpus4096 + .../rusty/linux-2.6-for-ingo.git/master +
 x86-only-patches sent 12/15.

Signed-off-by: Mike Travis <travis@sgi.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
drivers/base/cpu.c
include/linux/smp.h

index 4259072f5bd0960e113bb97d0f8aaa1818a8ab58..2aef96f20b30d2297ce9ca45e5ee2f3c4f38efa0 100644 (file)
@@ -128,10 +128,54 @@ print_cpus_func(online);
 print_cpus_func(possible);
 print_cpus_func(present);
 
+/*
+ * Print values for NR_CPUS and offlined cpus
+ */
+static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf)
+{
+       int n = snprintf(buf, PAGE_SIZE-2, "%d\n", CONFIG_NR_CPUS - 1);
+       return n;
+}
+static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
+
+/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
+unsigned int total_cpus;
+
+static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf)
+{
+       int n = 0, len = PAGE_SIZE-2;
+       cpumask_var_t offline;
+
+       /* display offline cpus < nr_cpu_ids */
+       if (!alloc_cpumask_var(&offline, GFP_KERNEL))
+               return -ENOMEM;
+       cpumask_complement(offline, cpu_online_mask);
+       n = cpulist_scnprintf(buf, len, offline);
+       free_cpumask_var(offline);
+
+       /* display offline cpus >= nr_cpu_ids */
+       if (total_cpus && nr_cpu_ids < total_cpus) {
+               if (n && n < len)
+                       buf[n++] = ',';
+
+               if (nr_cpu_ids == total_cpus-1)
+                       n += snprintf(&buf[n], len - n, "%d", nr_cpu_ids);
+               else
+                       n += snprintf(&buf[n], len - n, "%d-%d",
+                                                     nr_cpu_ids, total_cpus-1);
+       }
+
+       n += snprintf(&buf[n], len - n, "\n");
+       return n;
+}
+static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
+
 static struct sysdev_class_attribute *cpu_state_attr[] = {
        &attr_online_map,
        &attr_possible_map,
        &attr_present_map,
+       &attr_kernel_max,
+       &attr_offline,
 };
 
 static int cpu_states_init(void)
index 3f9a60043a975617a3b8217f8e69b24751c13e01..0d5770c2e43af4441c55995ad9ae2be1529706b0 100644 (file)
@@ -21,6 +21,9 @@ struct call_single_data {
        u16 priv;
 };
 
+/* total number of cpus in this system (may exceed NR_CPUS) */
+extern unsigned int total_cpus;
+
 #ifdef CONFIG_SMP
 
 #include <linux/preempt.h>