Core sysfs Topology 2.5.45 (1/5)
Subsystems (7)
PATCH 1/1 Core sysfs Topology 2.5.45 (1/5)
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
arch/i386/kernel/cpu/common.c +0 -35
@@ -1,7 +1,6 @@#include <linux/init.h> #include <linux/string.h> #include <linux/delay.h> -#include <linux/cpu.h> #include <linux/smp.h> #include <asm/semaphore.h> #include <asm/processor.h>
@@ -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);
drivers/base/Makefile +3 -1
@@ -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
drivers/base/cpu.c +32 -6
@@ -1,5 +1,5 @@/* -* cpu.c - basic cpu class support +* drivers/base/cpu.c - basic CPU class support */ #include <linux/device.h>
@@ -7,22 +7,48 @@#include <linux/init.h> #include <linux/cpu.h> +#include <asm/topology.h> + +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);
drivers/base/memblk.c +55 -0
55 lines not on this page · raw message
drivers/base/node.c +70 -0
70 lines not on this page · raw message
drivers/base/sys.c +3 -0
@@ -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);
include/linux/cpu.h +8 -4
@@ -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 <linux/device.h> - -extern struct device_class cpu_devclass; +#include <linux/node.h> 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_ */
include/linux/memblk.h +32 -0
@@ -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 <linux/device.h> +#include <linux/node.h> + +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_ */
include/linux/node.h +34 -0
@@ -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 <linux/device.h> + +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_ */
PATCH 1/1 i386 sysfs Topology 2.5.45 (2/5)
Quoted 429 lines · Matthew Dobson
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 amemblk_online_map, much likecpu_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 anode_online_map, much likecpu_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.clinux-2.5.45-core_additions/arch/i386/kernel/cpu/common.carch/i386/kernel/cpu/common.c +0
-35@@ -1,7 +1,6 @@#include <linux/init.h> #include <linux/string.h> #include <linux/delay.h> -#include <linux/cpu.h> #include <linux/smp.h> #include <asm/semaphore.h> #include <asm/processor.h> @@ -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
drivers/base/Makefile +3
-1@@ -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.makediff -Nur --exclude-from=/usr/src/.dontdiff
linux-2.5.45-base/drivers/base/cpu.clinux-2.5.45-core_additions/drivers/base/cpu.cdrivers/base/cpu.c +32
-6@@ -1,5 +1,5 @@/* -* cpu.c - basic cpu class support +* drivers/base/cpu.c - basic CPU class support */ #include <linux/device.h> @@ -7,22 +7,48 @@#include <linux/init.h> #include <linux/cpu.h> +#include <asm/topology.h> + +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.clinux-2.5.45-core_additions/drivers/base/memblk.cdrivers/base/memblk.c +55
-0@@ -0,0 +1,55 @@ +/* +* drivers/base/memblk.c - basic Memory Block class support +*/ + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/memblk.h> +#include <linux/node.h> + +#include <asm/topology.h> + + +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.clinux-2.5.45-core_additions/drivers/base/node.cdrivers/base/node.c +70
-0@@ -0,0 +1,70 @@ +/* +* drivers/base/node.c - basic Node class support +*/ + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/node.h> + +#include <asm/topology.h> + + +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.clinux-2.5.45-core_additions/drivers/base/sys.cdrivers/base/sys.c +3
-0@@ -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.hlinux-2.5.45-core_additions/include/linux/cpu.hinclude/linux/cpu.h +8
-4@@ -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 <linux/device.h> - -extern struct device_class cpu_devclass; +#include <linux/node.h> 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.hlinux-2.5.45-core_additions/include/linux/memblk.hinclude/linux/memblk.h +32
-0@@ -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 <linux/device.h> +#include <linux/node.h> + +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.hlinux-2.5.45-core_additions/include/linux/node.hinclude/linux/node.h +24
-0@@ -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 <linux/device.h> + +struct node {
include/linux/node.h line 34
Quoted 10 lines
include/linux/node.h +10
-0+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_ */
arch/i386/mach-generic/Makefile +1 -1
@@ -4,6 +4,6 @@ EXTRA_CFLAGS += -I../kernel -obj-y := setup.o +obj-y := setup.o topology.o include $(TOPDIR)/Rules.make
arch/i386/mach-generic/topology.c +69 -0
69 lines not on this page · raw message
include/asm-i386/cpu.h +28 -0
@@ -0,0 +1,28 @@ +#ifndef _ASM_I386_CPU_H_ +#define _ASM_I386_CPU_H_ + +#include <linux/device.h> +#include <linux/cpu.h> + +#include <asm/topology.h> +#include <asm/node.h> + +struct i386_cpu { +struct cpu cpu; +}; +extern struct i386_cpu cpu_devices[NR_CPUS ]; + + +static inline int arch_register_cpu (int num){ +int error, p_node =__cpu_to_node (num); +struct node *parent =NULL ; + +#ifdef CONFIG_NUMA + parent = &node_devices[p_node].node; +#endif /* CONFIG_NUMA */ + + error =register_cpu (&cpu_devices[num].cpu, num, parent); +return error; +} + +#endif /* _ASM_I386_CPU_H_ */
include/asm-i386/memblk.h +23 -0
@@ -0,0 +1,23 @@ +#ifndef _ASM_I386_MEMBLK_H_ +#define _ASM_I386_MEMBLK_H_ + +#include <linux/device.h> +#include <linux/mmzone.h> +#include <linux/memblk.h> + +#include <asm/topology.h> +#include <asm/node.h> + +struct i386_memblk { +struct memblk memblk; +}; +extern struct i386_memblk memblk_devices[MAX_NR_MEMBLKS ]; + +static inline int arch_register_memblk (int num){ +int p_node =__memblk_to_node (num); + +return register_memblk (&memblk_devices[num].memblk, num, + &node_devices[p_node].node); +} + +#endif /* _ASM_I386_MEMBLK_H_ */
include/asm-i386/node.h +25 -0
@@ -0,0 +1,25 @@ +#ifndef _ASM_I386_NODE_H_ +#define _ASM_I386_NODE_H_ + +#include <linux/device.h> +#include <linux/mmzone.h> +#include <linux/node.h> + +#include <asm/topology.h> + +struct i386_node { +struct node node; +}; +extern struct i386_node node_devices[MAX_NUMNODES ]; + +static inline int arch_register_node (int num){ +int p_node =__parent_node (num); +struct node *parent =NULL ; + +if (p_node != num) + parent = &node_devices[p_node].node; + +return register_node (&node_devices[num].node, num, parent); +} + +#endif /* _ASM_I386_NODE_H_ */
PATCH 1/1 per-node (NUMA) meminfo for sysfs Topology 2.5.45 (3/5)
Quoted 47 lines · Matthew Dobson
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 amemblk_online_map, much likecpu_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 anode_online_map, much likecpu_online_map. It also creates the standard helper functions, ie:
node_online(),num_online_nodes(),node_set_online(),node_set_offline().
Quoted 6 lines
This is used by driverFS topology to keep track of which Nodes are in the system and online.
Cheers!
-Matt
drivers/base/node.c +29 -0
@@ -35,6 +35,34 @@ } static DEVICE_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL); +#define K (x) ((x) << (PAGE_SHIFT - 10)) +static ssize_t node_read_meminfo (struct device * dev,char * buf,size_t count,loff_t off) +{ +struct sys_root *node =to_root (dev); +int nid = node->id; +struct sysinfo i; +si_meminfo_node (&i, nid); +return off ?0 :sprintf (buf,"\n" +"Node %d MemTotal: %8lu kB\n" +"Node %d MemFree: %8lu kB\n" +"Node %d MemUsed: %8lu kB\n" +"Node %d HighTotal: %8lu kB\n" +"Node %d HighFree: %8lu kB\n" +"Node %d LowTotal: %8lu kB\n" +"Node %d LowFree: %8lu kB\n" , + nid,K (i.totalram), + nid,K (i.freeram), + nid,K (i.totalram-i.freeram), + nid,K (i.totalhigh), + nid,K (i.freehigh), + nid,K (i.totalram-i.totalhigh), + nid,K (i.freeram-i.freehigh)); + +return 0 ; +} +#undef K +static DEVICE_ATTR(meminfo,S_IRUGO,node_read_meminfo,NULL); +/* * register_node - Setup a driverfs device for a node.
@@ -57,6 +85,7 @@ error =sys_register_root (&node->sysroot);if (!error){device_create_file (&node->sysroot.dev, &dev_attr_cpumap); +device_create_file (&node->sysroot.dev, &dev_attr_meminfo); }return error; }
include/linux/mm.h +3 -0
@@ -449,6 +449,9 @@extern void mem_init (void );extern void show_mem (void );extern void si_meminfo (struct sysinfo * val); +#ifdef CONFIG_NUMA +extern void si_meminfo_node (struct sysinfo *val,int nid); +#endif extern void swapin_readahead (swp_entry_t );extern int can_share_swap_page (struct page *);
include/linux/swap.h +3 -0
@@ -131,6 +131,9 @@extern unsigned long totalram_pages;extern unsigned long totalhigh_pages;extern unsigned int nr_free_pages (void ); +#ifdef CONFIG_NUMA +extern unsigned int nr_free_pages_pgdat (pg_data_t *pgdat); +#endif extern unsigned int nr_free_buffer_pages (void );extern unsigned int nr_free_pagecache_pages (void );
mm/page_alloc.c +25 -0
@@ -594,6 +594,18 @@return pages; } +#ifdef CONFIG_NUMA +unsigned int nr_free_pages_pgdat (pg_data_t *pgdat) +{ +unsigned int i, sum =0 ; + +for (i =0 ; i <MAX_NR_ZONES ; i++) + sum += pgdat->node_zones[i].free_pages; + +return sum; +} +#endif +static unsigned int nr_free_zone_pages (int offset) {pg_data_t *pgdat;
@@ -721,6 +733,19 @@ val->mem_unit =PAGE_SIZE ; } +#ifdef CONFIG_NUMA +void si_meminfo_node (struct sysinfo *val,int nid) +{ +pg_data_t *pgdat =NODE_DATA (nid); + + val->totalram = pgdat->node_size; + val->freeram =nr_free_pages_pgdat (pgdat); + val->totalhigh = pgdat->node_zones[ZONE_HIGHMEM ].spanned_pages; + val->freehigh = pgdat->node_zones[ZONE_HIGHMEM ].free_pages; + val->mem_unit =PAGE_SIZE ; +} +#endif +#define K (x) ((x) << (PAGE_SHIFT-10))/*
PATCH 1/1 memblk_online_map 2.5.45 (4/5)
Quoted 49 lines · Matthew Dobson
Quoted 47 lines · Matthew Dobson
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 amemblk_online_map, much likecpu_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 anode_online_map, much likecpu_online_map. It also creates the standard helper functions, ie:
node_online(),num_online_nodes(),node_set_online(),node_set_offline().
Quoted 6 lines
Quoted 6 lines
This is used by driverFS topology to keep track of which Nodes are in the system and online.
Cheers!
-Matt
arch/i386/mach-generic/topology.c +1 -1
@@ -48,7 +48,7 @@arch_register_node (i);for (i =0 ; i <NR_CPUS ; i++)if (cpu_possible (i))arch_register_cpu (i); -for (i =0 ; i < numnodes; i++) +for (i =0 ; i <num_online_memblks (); i++)arch_register_memblk (i);return 0 ; }
include/linux/mmzone.h +32 -0
@@ -279,6 +279,38 @@#endif /* !CONFIG_DISCONTIGMEM */ + +extern DECLARE_BITMAP(memblk_online_map, MAX_NR_MEMBLKS); + +#if defined(CONFIG_DISCONTIGMEM ) || defined(CONFIG_NUMA ) + +#define memblk_online (memblk) test_bit(memblk, memblk_online_map) +#define memblk_set_online (memblk) set_bit(memblk, memblk_online_map) +#define memblk_set_offline (memblk) clear_bit(memblk, memblk_online_map) +static inline unsigned int num_online_memblks (void ) +{ +int i, num =0 ; + +for (i =0 ; i <MAX_NR_MEMBLKS ; i++){ +if (memblk_online (i)) + num++; + } +return num; +} + +#else /* !CONFIG_DISCONTIGMEM && !CONFIG_NUMA */ + +#define memblk_online (memblk) \ + ({ BUG_ON((memblk) != 0); test_bit(memblk, memblk_online_map); }) +#define memblk_set_online (memblk) \ + ({ BUG_ON((memblk) != 0); set_bit(memblk, memblk_online_map); }) +#define memblk_set_offline (memblk) \ + ({ BUG_ON((memblk) != 0); clear_bit(memblk, memblk_online_map); }) +#define num_online_memblks () 1 + +#endif /* CONFIG_DISCONTIGMEM || CONFIG_NUMA */ + +#define MAP_ALIGN (x) ((((x) % sizeof(struct page)) == 0) ? (x) : ((x) + \ sizeof(struct page) - ((x) % sizeof(struct page))))
mm/page_alloc.c +4 -0
@@ -29,6 +29,9 @@#include <linux/slab.h> #include <linux/notifier.h> +#include <asm/topology.h> + +DECLARE_BITMAP (memblk_online_map,MAX_NR_MEMBLKS );struct pglist_data *pgdat_list;unsigned long totalram_pages;unsigned long totalhigh_pages;
@@ -1163,6 +1166,7 @@ pgdat->node_mem_map = node_mem_map;free_area_init_core (pgdat, zones_size, zholes_size); +memblk_set_online (__node_to_memblk (nid));calculate_zone_bitmap (pgdat, zones_size); }
PATCH 1/1 node_online_map 2.5.45 (5/5)
Quoted 50 lines · Matthew Dobson
Quoted 49 lines · Matthew Dobson
Quoted 47 lines · Matthew Dobson
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 amemblk_online_map, much likecpu_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 anode_online_map, much likecpu_online_map. It also creates the standard helper functions, ie:
node_online(),num_online_nodes(),node_set_online(),node_set_offline().
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
This is used by driverFS topology to keep track of which Nodes are in the system and online.
Cheers!
-Matt
arch/i386/kernel/numaq.c +1 -0
@@ -52,6 +52,7 @@ numnodes =0 ;for (node =0 ; node <MAX_NUMNODES ; node++) {if (scd->quads_present31_0 & (1 << node)) { +node_set_online (node); numnodes++; eq = &scd->eq[node];/* Convert to pages */
arch/i386/mach-generic/topology.c +1 -3
@@ -38,13 +38,11 @@struct i386_node node_devices[MAX_NUMNODES ];struct i386_memblk memblk_devices[MAX_NR_MEMBLKS ]; -extern int numnodes; -static int __init topology_init (void ) {int i; -for (i =0 ; i < numnodes; i++) +for (i =0 ; i <num_online_nodes (); i++)arch_register_node (i);for (i =0 ; i <NR_CPUS ; i++)if (cpu_possible (i))arch_register_cpu (i);
include/linux/mmzone.h +23 -0
@@ -280,10 +280,25 @@#endif /* !CONFIG_DISCONTIGMEM */ +extern DECLARE_BITMAP(node_online_map, MAX_NUMNODES); extern DECLARE_BITMAP(memblk_online_map, MAX_NR_MEMBLKS);#if defined(CONFIG_DISCONTIGMEM ) || defined(CONFIG_NUMA ) +#define node_online (node) test_bit(node, node_online_map) +#define node_set_online (node) set_bit(node, node_online_map) +#define node_set_offline (node) clear_bit(node, node_online_map) +static inline unsigned int num_online_nodes (void ) +{ +int i, num =0 ; + +for (i =0 ; i <MAX_NUMNODES ; i++){ +if (node_online (i)) + num++; + } +return num; +} +#define memblk_online (memblk) test_bit(memblk, memblk_online_map)#define memblk_set_online (memblk) set_bit(memblk, memblk_online_map)#define memblk_set_offline (memblk) clear_bit(memblk, memblk_online_map)
@@ -300,6 +315,14 @@#else /* !CONFIG_DISCONTIGMEM && !CONFIG_NUMA */ +#define node_online (node) \ + ({ BUG_ON((node) != 0); test_bit(node, node_online_map); }) +#define node_set_online (node) \ + ({ BUG_ON((node) != 0); set_bit(node, node_online_map); }) +#define node_set_offline (node) \ + ({ BUG_ON((node) != 0); clear_bit(node, node_online_map); }) +#define num_online_nodes () 1 +#define memblk_online (memblk) \ ({ BUG_ON((memblk) != 0); test_bit(memblk, memblk_online_map); })#define memblk_set_online (memblk) \
mm/page_alloc.c +1 -0
@@ -31,6 +31,7 @@#include <asm/topology.h> +DECLARE_BITMAP (node_online_map,MAX_NUMNODES );DECLARE_BITMAP (memblk_online_map,MAX_NR_MEMBLKS );struct pglist_data *pgdat_list;unsigned long totalram_pages;
PATCH 1/1 (resend) i386 sysfs Topology 2.5.45 (2/5)
In reply to Matthew DobsonForgot to clear out the patch at the bottom the first time. Resending for clarity's sake.
Quoted 46 lines · Matthew Dobson
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 amemblk_online_map, much likecpu_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 anode_online_map, much likecpu_online_map. It also creates the standard helper functions, ie:
node_online(),num_online_nodes(),node_set_online(),node_set_offline().
Quoted 6 lines
This is used by driverFS topology to keep track of which Nodes are in the system and online.
Cheers!
-Matt
arch/i386/mach-generic/Makefile +1 -1
@@ -4,6 +4,6 @@ EXTRA_CFLAGS += -I../kernel -obj-y := setup.o +obj-y := setup.o topology.o include $(TOPDIR)/Rules.make
arch/i386/mach-generic/topology.c +69 -0
69 lines not on this page · raw message
include/asm-i386/cpu.h +28 -0
@@ -0,0 +1,28 @@ +#ifndef _ASM_I386_CPU_H_ +#define _ASM_I386_CPU_H_ + +#include <linux/device.h> +#include <linux/cpu.h> + +#include <asm/topology.h> +#include <asm/node.h> + +struct i386_cpu { +struct cpu cpu; +}; +extern struct i386_cpu cpu_devices[NR_CPUS ]; + + +static inline int arch_register_cpu (int num){ +int error, p_node =__cpu_to_node (num); +struct node *parent =NULL ; + +#ifdef CONFIG_NUMA + parent = &node_devices[p_node].node; +#endif /* CONFIG_NUMA */ + + error =register_cpu (&cpu_devices[num].cpu, num, parent); +return error; +} + +#endif /* _ASM_I386_CPU_H_ */
include/asm-i386/memblk.h +23 -0
@@ -0,0 +1,23 @@ +#ifndef _ASM_I386_MEMBLK_H_ +#define _ASM_I386_MEMBLK_H_ + +#include <linux/device.h> +#include <linux/mmzone.h> +#include <linux/memblk.h> + +#include <asm/topology.h> +#include <asm/node.h> + +struct i386_memblk { +struct memblk memblk; +}; +extern struct i386_memblk memblk_devices[MAX_NR_MEMBLKS ]; + +static inline int arch_register_memblk (int num){ +int p_node =__memblk_to_node (num); + +return register_memblk (&memblk_devices[num].memblk, num, + &node_devices[p_node].node); +} + +#endif /* _ASM_I386_MEMBLK_H_ */
include/asm-i386/node.h +25 -0
@@ -0,0 +1,25 @@ +#ifndef _ASM_I386_NODE_H_ +#define _ASM_I386_NODE_H_ + +#include <linux/device.h> +#include <linux/mmzone.h> +#include <linux/node.h> + +#include <asm/topology.h> + +struct i386_node { +struct node node; +}; +extern struct i386_node node_devices[MAX_NUMNODES ]; + +static inline int arch_register_node (int num){ +int p_node =__parent_node (num); +struct node *parent =NULL ; + +if (p_node != num) + parent = &node_devices[p_node].node; + +return register_node (&node_devices[num].node, num, parent); +} + +#endif /* _ASM_I386_NODE_H_ */