Matthew Dobson wrote: > Linus, > This series of patches creates a directory-based Topology in sysfs > (driverfs). This includes the per-node meminfo patch you wanted, as > well as UP/SMP/NUMA topology. > There were discussions between myself, Andrew, Rusty, and Patrick, > and these are what we agreed on. > > (1/5) Core sysfs Topology: > This patch creates the generic structures that are (will be) > embedded in the per-arch structures. Also creates calls to > register these generic structures (CPUs, MemBlks, & Nodes). > > Note that without arch-specific structures in which to embed > these structures, and an arch-specific initialization routine, > these functions/structures remain unused. > > (2/5) i386 sysfs Topology > This patch creates the i386 specific files/functions/structures > to implement driverfs Topology. These structures have the > generic CPU/MemBlk/Node structures embedded in them. > > This patch also creates the arch-specific initialization routine > to instantiate the topology. > > (3/5) per-node (NUMA) meminfo for sysfs Topology > This patch adds code to DriverFS Topology to expose per-node > memory statistics. > This information is exposed via the nodeX/meminfo file. > > The patch also adds 2 helper functions to gather per-node memory > info. > > (4/5) memblk_online_map > This patch creates a memblk_online_map, much like > cpu_online_map. It also creates the standard helper functions, > ie: memblk_online(), num_online_memblks(), memblk_set_online(), > memblk_set_offline(). > > This is used by driverFS topology to keep track of which memory > blocks are in the system and online. > > (5/5) node_online_map > This patch creates a node_online_map, much like cpu_online_map. > It also creates the standard helper functions, ie: > node_online(), num_online_nodes(), node_set_online(), > node_set_offline(). > > This is used by driverFS topology to keep track of which Nodes > are in the system and online. > > Cheers! > > -Matt > > > ------------------------------------------------------------------------ > > diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.45-base/arch/i386/kernel/cpu/common.c linux-2.5.45-core_additions/arch/i386/kernel/cpu/common.c > --- linux-2.5.45-base/arch/i386/kernel/cpu/common.c Wed Oct 30 16:41:39 2002 > +++ linux-2.5.45-core_additions/arch/i386/kernel/cpu/common.c Wed Oct 30 17:51:04 2002 > @@ -1,7 +1,6 @@ > #include > #include > #include > -#include > #include > #include > #include > @@ -507,37 +506,3 @@ > current->used_math = 0; > stts(); > } > - > -/* > - * Bulk registration of the cpu devices with the system. > - * Some of this stuff could possibly be moved into a shared > - * location.. > - * Also, these devices should be integrated with other CPU data.. > - */ > - > -static struct cpu cpu_devices[NR_CPUS]; > - > -static struct device_driver cpu_driver = { > - .name = "cpu", > - .bus = &system_bus_type, > - .devclass = &cpu_devclass, > -}; > - > -static int __init register_cpus(void) > -{ > - int i; > - > - driver_register(&cpu_driver); > - > - for (i = 0; i < NR_CPUS; i++) { > - struct sys_device * sysdev = &cpu_devices[i].sysdev; > - sysdev->name = "cpu"; > - sysdev->id = i; > - sysdev->dev.driver = &cpu_driver; > - if (cpu_possible(i)) > - sys_device_register(sysdev); > - } > - return 0; > -} > - > -subsys_initcall(register_cpus); > diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.45-base/drivers/base/Makefile linux-2.5.45-core_additions/drivers/base/Makefile > --- linux-2.5.45-base/drivers/base/Makefile Wed Oct 30 16:43:38 2002 > +++ linux-2.5.45-core_additions/drivers/base/Makefile Wed Oct 30 17:51:04 2002 > @@ -4,11 +4,13 @@ > driver.o class.o intf.o platform.o \ > cpu.o > > +obj-$(CONFIG_NUMA) += node.o memblk.o > + > obj-y += fs/ > > obj-$(CONFIG_HOTPLUG) += hotplug.o > > export-objs := core.o power.o sys.o bus.o driver.o \ > - class.o intf.o platform.o cpu.o > + class.o intf.o platform.o > > include $(TOPDIR)/Rules.make > diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.45-base/drivers/base/cpu.c linux-2.5.45-core_additions/drivers/base/cpu.c > --- linux-2.5.45-base/drivers/base/cpu.c Wed Oct 30 16:42:24 2002 > +++ linux-2.5.45-core_additions/drivers/base/cpu.c Wed Oct 30 17:51:10 2002 > @@ -1,5 +1,5 @@ > /* > - * cpu.c - basic cpu class support > + * drivers/base/cpu.c - basic CPU class support > */ > > #include > @@ -7,22 +7,48 @@ > #include > #include > > +#include > + > + > static int cpu_add_device(struct device * dev) > { > return 0; > } > - > struct device_class cpu_devclass = { > .name = "cpu", > .add_device = cpu_add_device, > }; > > > -static int __init cpu_devclass_init(void) > +struct device_driver cpu_driver = { > + .name = "cpu", > + .bus = &system_bus_type, > + .devclass = &cpu_devclass, > +}; > + > + > +/* > + * register_cpu - Setup a driverfs device for a CPU. > + * @num - CPU number to use when creating the device. > + * > + * Initialize and register the CPU device. > + */ > +int __init register_cpu(struct cpu *cpu, int num, struct node *root) > { > - return devclass_register(&cpu_devclass); > + cpu->node_id = __cpu_to_node(num); > + cpu->sysdev.name = "cpu"; > + cpu->sysdev.id = num; > + if (root) > + cpu->sysdev.root = &root->sysroot; > + snprintf(cpu->sysdev.dev.name, DEVICE_NAME_SIZE, "CPU %u", num); > + cpu->sysdev.dev.driver = &cpu_driver; > + return sys_device_register(&cpu->sysdev); > } > > -postcore_initcall(cpu_devclass_init); > > -EXPORT_SYMBOL(cpu_devclass); > +static int __init register_cpu_type(void) > +{ > + driver_register(&cpu_driver); > + return devclass_register(&cpu_devclass); > +} > +postcore_initcall(register_cpu_type); > diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.45-base/drivers/base/memblk.c linux-2.5.45-core_additions/drivers/base/memblk.c > --- linux-2.5.45-base/drivers/base/memblk.c Wed Dec 31 16:00:00 1969 > +++ linux-2.5.45-core_additions/drivers/base/memblk.c Wed Oct 30 17:51:10 2002 > @@ -0,0 +1,55 @@ > +/* > + * drivers/base/memblk.c - basic Memory Block class support > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +#include > + > + > +static int memblk_add_device(struct device * dev) > +{ > + return 0; > +} > +struct device_class memblk_devclass = { > + .name = "memblk", > + .add_device = memblk_add_device, > +}; > + > + > +struct device_driver memblk_driver = { > + .name = "memblk", > + .bus = &system_bus_type, > + .devclass = &memblk_devclass, > +}; > + > + > +/* > + * register_memblk - Setup a driverfs device for a MemBlk > + * @num - MemBlk number to use when creating the device. > + * > + * Initialize and register the MemBlk device. > + */ > +int __init register_memblk(struct memblk *memblk, int num, struct node *root) > +{ > + memblk->node_id = __memblk_to_node(num); > + memblk->sysdev.name = "memblk"; > + memblk->sysdev.id = num; > + if (root) > + memblk->sysdev.root = &root->sysroot; > + snprintf(memblk->sysdev.dev.name, DEVICE_NAME_SIZE, "Memory Block %u", num); > + memblk->sysdev.dev.driver = &memblk_driver; > + return sys_device_register(&memblk->sysdev); > +} > + > + > +static int __init register_memblk_type(void) > +{ > + driver_register(&memblk_driver); > + return devclass_register(&memblk_devclass); > +} > +postcore_initcall(register_memblk_type); > diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.45-base/drivers/base/node.c linux-2.5.45-core_additions/drivers/base/node.c > --- linux-2.5.45-base/drivers/base/node.c Wed Dec 31 16:00:00 1969 > +++ linux-2.5.45-core_additions/drivers/base/node.c Wed Oct 30 17:52:41 2002 > @@ -0,0 +1,70 @@ > +/* > + * drivers/base/node.c - basic Node class support > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +#include > + > + > +static int node_add_device(struct device * dev) > +{ > + return 0; > +} > +struct device_class node_devclass = { > + .name = "node", > + .add_device = node_add_device, > +}; > + > + > +struct device_driver node_driver = { > + .name = "node", > + .bus = &system_bus_type, > + .devclass = &node_devclass, > +}; > + > + > +static ssize_t node_read_cpumap(struct device * dev, char * buf, size_t count, loff_t off) > +{ > + struct node *node_dev = to_node(to_root(dev)); > + return off ? 0 : sprintf(buf,"%lx\n",node_dev->cpumap); > +} > +static DEVICE_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL); > + > + > +/* > + * register_node - Setup a driverfs device for a node. > + * @num - Node number to use when creating the device. > + * > + * Initialize and register the node device. > + */ > +int __init register_node(struct node *node, int num, struct node *parent) > +{ > + int error; > + > + node->cpumap = __node_to_cpu_mask(num); > + node->sysroot.id = num; > + if (parent) > + node->sysroot.dev.parent = &parent->sysroot.sysdev; > + snprintf(node->sysroot.dev.name, DEVICE_NAME_SIZE, "Node %u", num); > + snprintf(node->sysroot.dev.bus_id, BUS_ID_SIZE, "node%u", num); > + node->sysroot.dev.driver = &node_driver; > + node->sysroot.dev.bus = &system_bus_type; > + error = sys_register_root(&node->sysroot); > + if (!error){ > + device_create_file(&node->sysroot.dev, &dev_attr_cpumap); > + } > + return error; > +} > + > + > +static int __init register_node_type(void) > +{ > + driver_register(&node_driver); > + return devclass_register(&node_devclass); > +} > +postcore_initcall(register_node_type); > diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.45-base/drivers/base/sys.c linux-2.5.45-core_additions/drivers/base/sys.c > --- linux-2.5.45-base/drivers/base/sys.c Wed Oct 30 16:41:30 2002 > +++ linux-2.5.45-core_additions/drivers/base/sys.c Wed Oct 30 17:51:04 2002 > @@ -55,6 +55,9 @@ > if (!root) > return -EINVAL; > > + if (!root->dev.parent) > + root->dev.parent = &system_bus; > + > pr_debug("Registering system board %d\n",root->id); > > error = device_register(&root->dev); > diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.45-base/include/linux/cpu.h linux-2.5.45-core_additions/include/linux/cpu.h > --- linux-2.5.45-base/include/linux/cpu.h Wed Oct 30 16:42:19 2002 > +++ linux-2.5.45-core_additions/include/linux/cpu.h Wed Oct 30 17:51:10 2002 > @@ -1,5 +1,5 @@ > /* > - * cpu.h - generic cpu defition > + * include/linux/cpu.h - generic cpu definition > * > * This is mainly for topological representation. We define the > * basic 'struct cpu' here, which can be embedded in per-arch > @@ -15,14 +15,18 @@ > * See the following for how to do this: > * - drivers/base/intf.c > * - Documentation/driver-model/interface.txt > - * > */ > +#ifndef _LINUX_CPU_H_ > +#define _LINUX_CPU_H_ > > #include > - > -extern struct device_class cpu_devclass; > +#include > > struct cpu { > + int node_id; /* The node which contains the CPU */ > struct sys_device sysdev; > }; > > +extern int register_cpu(struct cpu *, int, struct node *); > + > +#endif /* _LINUX_CPU_H_ */ > diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.45-base/include/linux/memblk.h linux-2.5.45-core_additions/include/linux/memblk.h > --- linux-2.5.45-base/include/linux/memblk.h Wed Dec 31 16:00:00 1969 > +++ linux-2.5.45-core_additions/include/linux/memblk.h Wed Oct 30 17:51:10 2002 > @@ -0,0 +1,32 @@ > +/* > + * include/linux/memblk.h - generic memblk definition > + * > + * This is mainly for topological representation. We define the > + * basic 'struct memblk' here, which can be embedded in per-arch > + * definitions of memory blocks. > + * > + * Basic handling of the devices is done in drivers/base/memblk.c > + * and system devices are handled in drivers/base/sys.c. > + * > + * MemBlks are exported via driverfs in the class/memblk/devices/ > + * directory. > + * > + * Per-memblk interfaces can be implemented using a struct device_interface. > + * See the following for how to do this: > + * - drivers/base/intf.c > + * - Documentation/driver-model/interface.txt > + */ > +#ifndef _LINUX_MEMBLK_H_ > +#define _LINUX_MEMBLK_H_ > + > +#include > +#include > + > +struct memblk { > + int node_id; /* The node which contains the MemBlk */ > + struct sys_device sysdev; > +}; > + > +extern int register_memblk(struct memblk *, int, struct node *); > + > +#endif /* _LINUX_MEMBLK_H_ */ > diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.45-base/include/linux/node.h linux-2.5.45-core_additions/include/linux/node.h > --- linux-2.5.45-base/include/linux/node.h Wed Dec 31 16:00:00 1969 > +++ linux-2.5.45-core_additions/include/linux/node.h Wed Oct 30 17:51:10 2002 > @@ -0,0 +1,34 @@ > +/* > + * include/linux/node.h - generic node definition > + * > + * This is mainly for topological representation. We define the > + * basic 'struct node' here, which can be embedded in per-arch > + * definitions of processors. > + * > + * Basic handling of the devices is done in drivers/base/node.c > + * and system devices are handled in drivers/base/sys.c. > + * > + * Nodes are exported via driverfs in the class/node/devices/ > + * directory. > + * > + * Per-node interfaces can be implemented using a struct device_interface. > + * See the following for how to do this: > + * - drivers/base/intf.c > + * - Documentation/driver-model/interface.txt > + */ > +#ifndef _LINUX_NODE_H_ > +#define _LINUX_NODE_H_ > + > +#include > + > +struct node { > + unsigned long cpumap; /* Bitmap of CPUs on the Node */ > + struct sys_root sysroot; > +}; > + > +extern int register_node(struct node *, int, struct node *); > + > +#define to_node(_root) container_of(_root, struct node, sysroot) > +#define to_root(_dev) container_of(_dev, struct sys_root, dev) > + > +#endif /* _LINUX_NODE_H_ */