Blame view

drivers/base/node.c 19 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
10fbcf4c6   Kay Sievers   convert 'memory' ...
2
   * Basic Node interface support
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/mm.h>
c04fc586c   Gary Hade   mm: show node to ...
7
  #include <linux/memory.h>
fa25c503d   KOSAKI Motohiro   mm: per-node vmst...
8
  #include <linux/vmstat.h>
6e259e7dc   Andrew Morton   drivers/base/node...
9
  #include <linux/notifier.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
  #include <linux/node.h>
  #include <linux/hugetlb.h>
ed4a6d7f0   Mel Gorman   mm: compaction: a...
12
  #include <linux/compaction.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
  #include <linux/cpumask.h>
  #include <linux/topology.h>
  #include <linux/nodemask.h>
76b67ed9d   KAMEZAWA Hiroyuki   [PATCH] node hotp...
16
  #include <linux/cpu.h>
bde631a51   Lee Schermerhorn   mm: add node stat...
17
  #include <linux/device.h>
af936a160   Lee Schermerhorn   vmscan: unevictab...
18
  #include <linux/swap.h>
18e5b539b   Tejun Heo   nodemask: include...
19
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20

10fbcf4c6   Kay Sievers   convert 'memory' ...
21
  static struct bus_type node_subsys = {
af5ca3f4e   Kay Sievers   Driver core: chan...
22
  	.name = "node",
10fbcf4c6   Kay Sievers   convert 'memory' ...
23
  	.dev_name = "node",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
  };
5aaba3631   Sudeep Holla   cpumask: factor o...
25
  static ssize_t node_read_cpumap(struct device *dev, bool list, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
  {
  	struct node *node_dev = to_node(dev);
10fbcf4c6   Kay Sievers   convert 'memory' ...
28
  	const struct cpumask *mask = cpumask_of_node(node_dev->dev.id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

39106dcf8   Mike Travis   cpumask: use new ...
30
31
  	/* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */
  	BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32

5aaba3631   Sudeep Holla   cpumask: factor o...
33
  	return cpumap_print_to_pagebuf(list, buf, mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  }
10fbcf4c6   Kay Sievers   convert 'memory' ...
35
36
  static inline ssize_t node_read_cpumask(struct device *dev,
  				struct device_attribute *attr, char *buf)
39106dcf8   Mike Travis   cpumask: use new ...
37
  {
5aaba3631   Sudeep Holla   cpumask: factor o...
38
  	return node_read_cpumap(dev, false, buf);
39106dcf8   Mike Travis   cpumask: use new ...
39
  }
10fbcf4c6   Kay Sievers   convert 'memory' ...
40
41
  static inline ssize_t node_read_cpulist(struct device *dev,
  				struct device_attribute *attr, char *buf)
39106dcf8   Mike Travis   cpumask: use new ...
42
  {
5aaba3631   Sudeep Holla   cpumask: factor o...
43
  	return node_read_cpumap(dev, true, buf);
39106dcf8   Mike Travis   cpumask: use new ...
44
  }
10fbcf4c6   Kay Sievers   convert 'memory' ...
45
46
  static DEVICE_ATTR(cpumap,  S_IRUGO, node_read_cpumask, NULL);
  static DEVICE_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
  
  #define K(x) ((x) << (PAGE_SHIFT - 10))
10fbcf4c6   Kay Sievers   convert 'memory' ...
49
50
  static ssize_t node_read_meminfo(struct device *dev,
  			struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
  {
  	int n;
  	int nid = dev->id;
599d0c954   Mel Gorman   mm, vmscan: move ...
54
  	struct pglist_data *pgdat = NODE_DATA(nid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  	struct sysinfo i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
  
  	si_meminfo_node(&i, nid);
7ee922554   KOSAKI Motohiro   drivers/base/node...
58
  	n = sprintf(buf,
4f98a2fee   Rik van Riel   vmscan: split LRU...
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
  		       "Node %d MemTotal:       %8lu kB
  "
  		       "Node %d MemFree:        %8lu kB
  "
  		       "Node %d MemUsed:        %8lu kB
  "
  		       "Node %d Active:         %8lu kB
  "
  		       "Node %d Inactive:       %8lu kB
  "
  		       "Node %d Active(anon):   %8lu kB
  "
  		       "Node %d Inactive(anon): %8lu kB
  "
  		       "Node %d Active(file):   %8lu kB
  "
  		       "Node %d Inactive(file): %8lu kB
  "
5344b7e64   Nick Piggin   vmstat: mlocked p...
77
78
  		       "Node %d Unevictable:    %8lu kB
  "
7ee922554   KOSAKI Motohiro   drivers/base/node...
79
80
81
82
83
  		       "Node %d Mlocked:        %8lu kB
  ",
  		       nid, K(i.totalram),
  		       nid, K(i.freeram),
  		       nid, K(i.totalram - i.freeram),
599d0c954   Mel Gorman   mm, vmscan: move ...
84
85
86
87
88
89
90
91
92
  		       nid, K(node_page_state(pgdat, NR_ACTIVE_ANON) +
  				node_page_state(pgdat, NR_ACTIVE_FILE)),
  		       nid, K(node_page_state(pgdat, NR_INACTIVE_ANON) +
  				node_page_state(pgdat, NR_INACTIVE_FILE)),
  		       nid, K(node_page_state(pgdat, NR_ACTIVE_ANON)),
  		       nid, K(node_page_state(pgdat, NR_INACTIVE_ANON)),
  		       nid, K(node_page_state(pgdat, NR_ACTIVE_FILE)),
  		       nid, K(node_page_state(pgdat, NR_INACTIVE_FILE)),
  		       nid, K(node_page_state(pgdat, NR_UNEVICTABLE)),
75ef71840   Mel Gorman   mm, vmstat: add i...
93
  		       nid, K(sum_zone_node_page_state(nid, NR_MLOCK)));
7ee922554   KOSAKI Motohiro   drivers/base/node...
94

182e8e237   Christoph Lameter   [PATCH] reduce MA...
95
  #ifdef CONFIG_HIGHMEM
7ee922554   KOSAKI Motohiro   drivers/base/node...
96
  	n += sprintf(buf + n,
4f98a2fee   Rik van Riel   vmscan: split LRU...
97
98
99
100
101
102
  		       "Node %d HighTotal:      %8lu kB
  "
  		       "Node %d HighFree:       %8lu kB
  "
  		       "Node %d LowTotal:       %8lu kB
  "
7ee922554   KOSAKI Motohiro   drivers/base/node...
103
104
105
106
107
108
  		       "Node %d LowFree:        %8lu kB
  ",
  		       nid, K(i.totalhigh),
  		       nid, K(i.freehigh),
  		       nid, K(i.totalram - i.totalhigh),
  		       nid, K(i.freeram - i.freehigh));
182e8e237   Christoph Lameter   [PATCH] reduce MA...
109
  #endif
7ee922554   KOSAKI Motohiro   drivers/base/node...
110
  	n += sprintf(buf + n,
4f98a2fee   Rik van Riel   vmscan: split LRU...
111
112
113
114
115
116
117
118
119
120
  		       "Node %d Dirty:          %8lu kB
  "
  		       "Node %d Writeback:      %8lu kB
  "
  		       "Node %d FilePages:      %8lu kB
  "
  		       "Node %d Mapped:         %8lu kB
  "
  		       "Node %d AnonPages:      %8lu kB
  "
4b02108ac   KOSAKI Motohiro   mm: oom analysis:...
121
122
  		       "Node %d Shmem:          %8lu kB
  "
c6a7f5728   KOSAKI Motohiro   mm: oom analysis:...
123
124
  		       "Node %d KernelStack:    %8lu kB
  "
4f98a2fee   Rik van Riel   vmscan: split LRU...
125
126
127
128
129
130
131
132
133
134
135
136
  		       "Node %d PageTables:     %8lu kB
  "
  		       "Node %d NFS_Unstable:   %8lu kB
  "
  		       "Node %d Bounce:         %8lu kB
  "
  		       "Node %d WritebackTmp:   %8lu kB
  "
  		       "Node %d Slab:           %8lu kB
  "
  		       "Node %d SReclaimable:   %8lu kB
  "
05b258e99   David Rientjes   thp: transparent ...
137
138
139
140
141
  		       "Node %d SUnreclaim:     %8lu kB
  "
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  		       "Node %d AnonHugePages:  %8lu kB
  "
65c453778   Kirill A. Shutemov   mm, rmap: account...
142
143
144
145
  		       "Node %d ShmemHugePages: %8lu kB
  "
  		       "Node %d ShmemPmdMapped: %8lu kB
  "
05b258e99   David Rientjes   thp: transparent ...
146
147
  #endif
  			,
11fb99898   Mel Gorman   mm: move most fil...
148
149
150
  		       nid, K(node_page_state(pgdat, NR_FILE_DIRTY)),
  		       nid, K(node_page_state(pgdat, NR_WRITEBACK)),
  		       nid, K(node_page_state(pgdat, NR_FILE_PAGES)),
50658e2e0   Mel Gorman   mm: move page map...
151
  		       nid, K(node_page_state(pgdat, NR_FILE_MAPPED)),
4b9d0fab7   Mel Gorman   mm: rename NR_ANO...
152
  		       nid, K(node_page_state(pgdat, NR_ANON_MAPPED)),
cc7452b6d   Rafael Aquini   mm: export NR_SHM...
153
  		       nid, K(i.sharedram),
d30dd8be0   Andy Lutomirski   mm: track NR_KERN...
154
  		       nid, sum_zone_node_page_state(nid, NR_KERNEL_STACK_KB),
75ef71840   Mel Gorman   mm, vmstat: add i...
155
  		       nid, K(sum_zone_node_page_state(nid, NR_PAGETABLE)),
11fb99898   Mel Gorman   mm: move most fil...
156
  		       nid, K(node_page_state(pgdat, NR_UNSTABLE_NFS)),
75ef71840   Mel Gorman   mm, vmstat: add i...
157
  		       nid, K(sum_zone_node_page_state(nid, NR_BOUNCE)),
11fb99898   Mel Gorman   mm: move most fil...
158
  		       nid, K(node_page_state(pgdat, NR_WRITEBACK_TEMP)),
75ef71840   Mel Gorman   mm, vmstat: add i...
159
160
161
  		       nid, K(sum_zone_node_page_state(nid, NR_SLAB_RECLAIMABLE) +
  				sum_zone_node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
  		       nid, K(sum_zone_node_page_state(nid, NR_SLAB_RECLAIMABLE)),
05b258e99   David Rientjes   thp: transparent ...
162
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
75ef71840   Mel Gorman   mm, vmstat: add i...
163
  		       nid, K(sum_zone_node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
11fb99898   Mel Gorman   mm: move most fil...
164
  		       nid, K(node_page_state(pgdat, NR_ANON_THPS) *
65c453778   Kirill A. Shutemov   mm, rmap: account...
165
  				       HPAGE_PMD_NR),
11fb99898   Mel Gorman   mm: move most fil...
166
  		       nid, K(node_page_state(pgdat, NR_SHMEM_THPS) *
65c453778   Kirill A. Shutemov   mm, rmap: account...
167
  				       HPAGE_PMD_NR),
11fb99898   Mel Gorman   mm: move most fil...
168
  		       nid, K(node_page_state(pgdat, NR_SHMEM_PMDMAPPED) *
65c453778   Kirill A. Shutemov   mm, rmap: account...
169
  				       HPAGE_PMD_NR));
91a13c281   Claudio Scordino   drivers/base/node...
170
  #else
75ef71840   Mel Gorman   mm, vmstat: add i...
171
  		       nid, K(sum_zone_node_page_state(nid, NR_SLAB_UNRECLAIMABLE)));
05b258e99   David Rientjes   thp: transparent ...
172
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
176
177
  	n += hugetlb_report_node_meminfo(nid, buf + n);
  	return n;
  }
  
  #undef K
10fbcf4c6   Kay Sievers   convert 'memory' ...
178
  static DEVICE_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179

10fbcf4c6   Kay Sievers   convert 'memory' ...
180
181
  static ssize_t node_read_numastat(struct device *dev,
  				struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
187
188
189
190
191
192
193
194
195
  	return sprintf(buf,
  		       "numa_hit %lu
  "
  		       "numa_miss %lu
  "
  		       "numa_foreign %lu
  "
  		       "interleave_hit %lu
  "
  		       "local_node %lu
  "
  		       "other_node %lu
  ",
75ef71840   Mel Gorman   mm, vmstat: add i...
196
197
198
199
200
201
  		       sum_zone_node_page_state(dev->id, NUMA_HIT),
  		       sum_zone_node_page_state(dev->id, NUMA_MISS),
  		       sum_zone_node_page_state(dev->id, NUMA_FOREIGN),
  		       sum_zone_node_page_state(dev->id, NUMA_INTERLEAVE_HIT),
  		       sum_zone_node_page_state(dev->id, NUMA_LOCAL),
  		       sum_zone_node_page_state(dev->id, NUMA_OTHER));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  }
10fbcf4c6   Kay Sievers   convert 'memory' ...
203
  static DEVICE_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204

10fbcf4c6   Kay Sievers   convert 'memory' ...
205
206
  static ssize_t node_read_vmstat(struct device *dev,
  				struct device_attribute *attr, char *buf)
2ac390370   Michael Rubin   writeback: add /s...
207
208
  {
  	int nid = dev->id;
75ef71840   Mel Gorman   mm, vmstat: add i...
209
  	struct pglist_data *pgdat = NODE_DATA(nid);
fa25c503d   KOSAKI Motohiro   mm: per-node vmst...
210
211
212
213
214
215
  	int i;
  	int n = 0;
  
  	for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
  		n += sprintf(buf+n, "%s %lu
  ", vmstat_text[i],
75ef71840   Mel Gorman   mm, vmstat: add i...
216
217
218
219
220
221
222
  			     sum_zone_node_page_state(nid, i));
  
  	for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
  		n += sprintf(buf+n, "%s %lu
  ",
  			     vmstat_text[i + NR_VM_ZONE_STAT_ITEMS],
  			     node_page_state(pgdat, i));
fa25c503d   KOSAKI Motohiro   mm: per-node vmst...
223
224
  
  	return n;
2ac390370   Michael Rubin   writeback: add /s...
225
  }
10fbcf4c6   Kay Sievers   convert 'memory' ...
226
  static DEVICE_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL);
2ac390370   Michael Rubin   writeback: add /s...
227

10fbcf4c6   Kay Sievers   convert 'memory' ...
228
  static ssize_t node_read_distance(struct device *dev,
518d3f38a   Ana Nedelcu   drivers: base: no...
229
  			struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
  {
  	int nid = dev->id;
  	int len = 0;
  	int i;
12ee3c0a0   David Rientjes   driver core: numa...
234
235
236
237
238
  	/*
  	 * buf is currently PAGE_SIZE in length and each node needs 4 chars
  	 * at the most (distance + space or newline).
  	 */
  	BUILD_BUG_ON(MAX_NUMNODES * 4 > PAGE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
242
243
244
245
246
  
  	for_each_online_node(i)
  		len += sprintf(buf + len, "%s%d", i ? " " : "", node_distance(nid, i));
  
  	len += sprintf(buf + len, "
  ");
  	return len;
  }
10fbcf4c6   Kay Sievers   convert 'memory' ...
247
  static DEVICE_ATTR(distance, S_IRUGO, node_read_distance, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248

3c9b8aaf9   Takashi Iwai   drivers/base/node...
249
250
251
252
253
254
255
256
257
  static struct attribute *node_dev_attrs[] = {
  	&dev_attr_cpumap.attr,
  	&dev_attr_cpulist.attr,
  	&dev_attr_meminfo.attr,
  	&dev_attr_numastat.attr,
  	&dev_attr_distance.attr,
  	&dev_attr_vmstat.attr,
  	NULL
  };
7ca7ec40f   Greg Kroah-Hartman   drivers/base/node...
258
  ATTRIBUTE_GROUPS(node_dev);
3c9b8aaf9   Takashi Iwai   drivers/base/node...
259

9a3052306   Lee Schermerhorn   hugetlb: add per ...
260
261
262
263
  #ifdef CONFIG_HUGETLBFS
  /*
   * hugetlbfs per node attributes registration interface:
   * When/if hugetlb[fs] subsystem initializes [sometime after this module],
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
264
265
   * it will register its per node attributes for all online nodes with
   * memory.  It will also call register_hugetlbfs_with_node(), below, to
9a3052306   Lee Schermerhorn   hugetlb: add per ...
266
267
268
269
270
271
   * register its attribute registration functions with this node driver.
   * Once these hooks have been initialized, the node driver will call into
   * the hugetlb module to [un]register attributes for hot-plugged nodes.
   */
  static node_registration_func_t __hugetlb_register_node;
  static node_registration_func_t __hugetlb_unregister_node;
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
272
  static inline bool hugetlb_register_node(struct node *node)
9a3052306   Lee Schermerhorn   hugetlb: add per ...
273
  {
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
274
  	if (__hugetlb_register_node &&
8cebfcd07   Lai Jiangshan   hugetlb: use N_ME...
275
  			node_state(node->dev.id, N_MEMORY)) {
9a3052306   Lee Schermerhorn   hugetlb: add per ...
276
  		__hugetlb_register_node(node);
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
277
278
279
  		return true;
  	}
  	return false;
9a3052306   Lee Schermerhorn   hugetlb: add per ...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  }
  
  static inline void hugetlb_unregister_node(struct node *node)
  {
  	if (__hugetlb_unregister_node)
  		__hugetlb_unregister_node(node);
  }
  
  void register_hugetlbfs_with_node(node_registration_func_t doregister,
  				  node_registration_func_t unregister)
  {
  	__hugetlb_register_node   = doregister;
  	__hugetlb_unregister_node = unregister;
  }
  #else
  static inline void hugetlb_register_node(struct node *node) {}
  
  static inline void hugetlb_unregister_node(struct node *node) {}
  #endif
8c7b5b4ed   Yasuaki Ishimatsu   memory-hotplug: s...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  static void node_device_release(struct device *dev)
  {
  	struct node *node = to_node(dev);
  
  #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HUGETLBFS)
  	/*
  	 * We schedule the work only when a memory section is
  	 * onlined/offlined on this node. When we come here,
  	 * all the memory on this node has been offlined,
  	 * so we won't enqueue new work to this work.
  	 *
  	 * The work is using node->node_work, so we should
  	 * flush work before freeing the memory.
  	 */
  	flush_work(&node->node_work);
  #endif
  	kfree(node);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
  
  /*
405ae7d38   Robert P. J. Day   Replace remaining...
319
   * register_node - Setup a sysfs device for a node.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
322
323
   * @num - Node number to use when creating the device.
   *
   * Initialize and register the node device.
   */
fa2643751   Yasuaki Ishimatsu   mm: cleanup regis...
324
  static int register_node(struct node *node, int num, struct node *parent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
  {
  	int error;
10fbcf4c6   Kay Sievers   convert 'memory' ...
327
328
  	node->dev.id = num;
  	node->dev.bus = &node_subsys;
8c7b5b4ed   Yasuaki Ishimatsu   memory-hotplug: s...
329
  	node->dev.release = node_device_release;
7ca7ec40f   Greg Kroah-Hartman   drivers/base/node...
330
  	node->dev.groups = node_dev_groups;
10fbcf4c6   Kay Sievers   convert 'memory' ...
331
  	error = device_register(&node->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
  
  	if (!error){
9a3052306   Lee Schermerhorn   hugetlb: add per ...
334
  		hugetlb_register_node(node);
ed4a6d7f0   Mel Gorman   mm: compaction: a...
335
336
  
  		compaction_register_node(node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
  	}
  	return error;
  }
4b45099b7   Keiichiro Tokunaga   [PATCH] Driver co...
340
341
342
343
344
345
346
347
348
  /**
   * unregister_node - unregister a node device
   * @node: node going away
   *
   * Unregisters a node device @node.  All the devices on the node must be
   * unregistered before calling this function.
   */
  void unregister_node(struct node *node)
  {
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
349
  	hugetlb_unregister_node(node);		/* no-op, if memoryless node */
af936a160   Lee Schermerhorn   vmscan: unevictab...
350

10fbcf4c6   Kay Sievers   convert 'memory' ...
351
  	device_unregister(&node->dev);
4b45099b7   Keiichiro Tokunaga   [PATCH] Driver co...
352
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353

8732794b1   Wen Congyang   numa: convert sta...
354
  struct node *node_devices[MAX_NUMNODES];
0fc44159b   Yasunori Goto   [PATCH] Register ...
355

76b67ed9d   KAMEZAWA Hiroyuki   [PATCH] node hotp...
356
357
358
359
360
  /*
   * register cpu under node
   */
  int register_cpu_under_node(unsigned int cpu, unsigned int nid)
  {
1830794ae   Alex Chiang   mm: add numa node...
361
  	int ret;
8a25a2fd1   Kay Sievers   cpu: convert 'cpu...
362
  	struct device *obj;
76b67ed9d   KAMEZAWA Hiroyuki   [PATCH] node hotp...
363

f8246f315   Alex Chiang   mm: refactor regi...
364
365
  	if (!node_online(nid))
  		return 0;
8a25a2fd1   Kay Sievers   cpu: convert 'cpu...
366
  	obj = get_cpu_device(cpu);
f8246f315   Alex Chiang   mm: refactor regi...
367
368
  	if (!obj)
  		return 0;
8732794b1   Wen Congyang   numa: convert sta...
369
  	ret = sysfs_create_link(&node_devices[nid]->dev.kobj,
f8246f315   Alex Chiang   mm: refactor regi...
370
371
  				&obj->kobj,
  				kobject_name(&obj->kobj));
1830794ae   Alex Chiang   mm: add numa node...
372
373
374
375
  	if (ret)
  		return ret;
  
  	return sysfs_create_link(&obj->kobj,
8732794b1   Wen Congyang   numa: convert sta...
376
377
  				 &node_devices[nid]->dev.kobj,
  				 kobject_name(&node_devices[nid]->dev.kobj));
76b67ed9d   KAMEZAWA Hiroyuki   [PATCH] node hotp...
378
379
380
381
  }
  
  int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
  {
8a25a2fd1   Kay Sievers   cpu: convert 'cpu...
382
  	struct device *obj;
b9d52dad9   Alex Chiang   mm: refactor unre...
383
384
385
  
  	if (!node_online(nid))
  		return 0;
8a25a2fd1   Kay Sievers   cpu: convert 'cpu...
386
  	obj = get_cpu_device(cpu);
b9d52dad9   Alex Chiang   mm: refactor unre...
387
388
  	if (!obj)
  		return 0;
8732794b1   Wen Congyang   numa: convert sta...
389
  	sysfs_remove_link(&node_devices[nid]->dev.kobj,
b9d52dad9   Alex Chiang   mm: refactor unre...
390
  			  kobject_name(&obj->kobj));
1830794ae   Alex Chiang   mm: add numa node...
391
  	sysfs_remove_link(&obj->kobj,
8732794b1   Wen Congyang   numa: convert sta...
392
  			  kobject_name(&node_devices[nid]->dev.kobj));
b9d52dad9   Alex Chiang   mm: refactor unre...
393

76b67ed9d   KAMEZAWA Hiroyuki   [PATCH] node hotp...
394
395
  	return 0;
  }
c04fc586c   Gary Hade   mm: show node to ...
396
397
  #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
  #define page_initialized(page)  (page->lru.next)
bd721ea73   Fabian Frederick   treewide: replace...
398
  static int __ref get_nid_for_pfn(unsigned long pfn)
c04fc586c   Gary Hade   mm: show node to ...
399
400
401
402
403
  {
  	struct page *page;
  
  	if (!pfn_valid_within(pfn))
  		return -1;
3a80a7fa7   Mel Gorman   mm: meminit: init...
404
405
406
407
  #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
  	if (system_state == SYSTEM_BOOTING)
  		return early_pfn_to_nid(pfn);
  #endif
c04fc586c   Gary Hade   mm: show node to ...
408
409
410
411
412
413
414
415
416
  	page = pfn_to_page(pfn);
  	if (!page_initialized(page))
  		return -1;
  	return pfn_to_nid(pfn);
  }
  
  /* register memory section under specified node if it spans that node */
  int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
  {
dee5d0d51   Alex Chiang   mm: add numa node...
417
  	int ret;
c04fc586c   Gary Hade   mm: show node to ...
418
419
420
421
422
423
  	unsigned long pfn, sect_start_pfn, sect_end_pfn;
  
  	if (!mem_blk)
  		return -EFAULT;
  	if (!node_online(nid))
  		return 0;
d33601644   Nathan Fontenot   memory hotplug: U...
424
425
426
427
  
  	sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr);
  	sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr);
  	sect_end_pfn += PAGES_PER_SECTION - 1;
c04fc586c   Gary Hade   mm: show node to ...
428
429
  	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
  		int page_nid;
04697858d   Yinghai Lu   mm: check if sect...
430
431
432
433
434
435
436
437
438
  		/*
  		 * memory block could have several absent sections from start.
  		 * skip pfn range from absent section
  		 */
  		if (!pfn_present(pfn)) {
  			pfn = round_down(pfn + PAGES_PER_SECTION,
  					 PAGES_PER_SECTION) - 1;
  			continue;
  		}
c04fc586c   Gary Hade   mm: show node to ...
439
440
441
442
443
  		page_nid = get_nid_for_pfn(pfn);
  		if (page_nid < 0)
  			continue;
  		if (page_nid != nid)
  			continue;
8732794b1   Wen Congyang   numa: convert sta...
444
  		ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
10fbcf4c6   Kay Sievers   convert 'memory' ...
445
446
  					&mem_blk->dev.kobj,
  					kobject_name(&mem_blk->dev.kobj));
dee5d0d51   Alex Chiang   mm: add numa node...
447
448
  		if (ret)
  			return ret;
10fbcf4c6   Kay Sievers   convert 'memory' ...
449
  		return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
8732794b1   Wen Congyang   numa: convert sta...
450
451
  				&node_devices[nid]->dev.kobj,
  				kobject_name(&node_devices[nid]->dev.kobj));
c04fc586c   Gary Hade   mm: show node to ...
452
453
454
455
456
457
  	}
  	/* mem section does not span the specified node */
  	return 0;
  }
  
  /* unregister memory section under all nodes that it spans */
d33601644   Nathan Fontenot   memory hotplug: U...
458
459
  int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
  				    unsigned long phys_index)
c04fc586c   Gary Hade   mm: show node to ...
460
  {
9ae49fab2   David Rientjes   mm: slab-allocate...
461
  	NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL);
c04fc586c   Gary Hade   mm: show node to ...
462
  	unsigned long pfn, sect_start_pfn, sect_end_pfn;
9ae49fab2   David Rientjes   mm: slab-allocate...
463
464
  	if (!mem_blk) {
  		NODEMASK_FREE(unlinked_nodes);
c04fc586c   Gary Hade   mm: show node to ...
465
  		return -EFAULT;
9ae49fab2   David Rientjes   mm: slab-allocate...
466
467
468
469
  	}
  	if (!unlinked_nodes)
  		return -ENOMEM;
  	nodes_clear(*unlinked_nodes);
d33601644   Nathan Fontenot   memory hotplug: U...
470
471
  
  	sect_start_pfn = section_nr_to_pfn(phys_index);
c04fc586c   Gary Hade   mm: show node to ...
472
473
  	sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
  	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
475049809   Roel Kluin   mm: get_nid_for_p...
474
  		int nid;
c04fc586c   Gary Hade   mm: show node to ...
475
476
477
478
479
480
  
  		nid = get_nid_for_pfn(pfn);
  		if (nid < 0)
  			continue;
  		if (!node_online(nid))
  			continue;
9ae49fab2   David Rientjes   mm: slab-allocate...
481
  		if (node_test_and_set(nid, *unlinked_nodes))
c04fc586c   Gary Hade   mm: show node to ...
482
  			continue;
8732794b1   Wen Congyang   numa: convert sta...
483
  		sysfs_remove_link(&node_devices[nid]->dev.kobj,
10fbcf4c6   Kay Sievers   convert 'memory' ...
484
485
  			 kobject_name(&mem_blk->dev.kobj));
  		sysfs_remove_link(&mem_blk->dev.kobj,
8732794b1   Wen Congyang   numa: convert sta...
486
  			 kobject_name(&node_devices[nid]->dev.kobj));
c04fc586c   Gary Hade   mm: show node to ...
487
  	}
9ae49fab2   David Rientjes   mm: slab-allocate...
488
  	NODEMASK_FREE(unlinked_nodes);
c04fc586c   Gary Hade   mm: show node to ...
489
490
491
492
493
494
495
496
  	return 0;
  }
  
  static int link_mem_sections(int nid)
  {
  	unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
  	unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
  	unsigned long pfn;
63d027a63   Robin Holt   driver core: Conv...
497
  	struct memory_block *mem_blk = NULL;
c04fc586c   Gary Hade   mm: show node to ...
498
499
500
501
502
  	int err = 0;
  
  	for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
  		unsigned long section_nr = pfn_to_section_nr(pfn);
  		struct mem_section *mem_sect;
c04fc586c   Gary Hade   mm: show node to ...
503
504
505
506
507
  		int ret;
  
  		if (!present_section_nr(section_nr))
  			continue;
  		mem_sect = __nr_to_section(section_nr);
321bf4ed5   Yinghai Lu   drivers/base/memo...
508
509
510
511
512
513
  
  		/* same memblock ? */
  		if (mem_blk)
  			if ((section_nr >= mem_blk->start_section_nr) &&
  			    (section_nr <= mem_blk->end_section_nr))
  				continue;
63d027a63   Robin Holt   driver core: Conv...
514
  		mem_blk = find_memory_block_hinted(mem_sect, mem_blk);
321bf4ed5   Yinghai Lu   drivers/base/memo...
515

c04fc586c   Gary Hade   mm: show node to ...
516
517
518
519
520
  		ret = register_mem_sect_under_node(mem_blk, nid);
  		if (!err)
  			err = ret;
  
  		/* discard ref obtained in find_memory_block() */
c04fc586c   Gary Hade   mm: show node to ...
521
  	}
63d027a63   Robin Holt   driver core: Conv...
522
523
  
  	if (mem_blk)
10fbcf4c6   Kay Sievers   convert 'memory' ...
524
  		kobject_put(&mem_blk->dev.kobj);
c04fc586c   Gary Hade   mm: show node to ...
525
526
  	return err;
  }
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
527

39da08cb0   Lee Schermerhorn   hugetlb: offload ...
528
  #ifdef CONFIG_HUGETLBFS
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
529
530
531
532
  /*
   * Handle per node hstate attribute [un]registration on transistions
   * to/from memoryless state.
   */
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
  static void node_hugetlb_work(struct work_struct *work)
  {
  	struct node *node = container_of(work, struct node, node_work);
  
  	/*
  	 * We only get here when a node transitions to/from memoryless state.
  	 * We can detect which transition occurred by examining whether the
  	 * node has memory now.  hugetlb_register_node() already check this
  	 * so we try to register the attributes.  If that fails, then the
  	 * node has transitioned to memoryless, try to unregister the
  	 * attributes.
  	 */
  	if (!hugetlb_register_node(node))
  		hugetlb_unregister_node(node);
  }
  
  static void init_node_hugetlb_work(int nid)
  {
8732794b1   Wen Congyang   numa: convert sta...
551
  	INIT_WORK(&node_devices[nid]->node_work, node_hugetlb_work);
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
552
  }
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
553
554
555
556
557
558
559
560
  
  static int node_memory_callback(struct notifier_block *self,
  				unsigned long action, void *arg)
  {
  	struct memory_notify *mnb = arg;
  	int nid = mnb->status_change_nid;
  
  	switch (action) {
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
561
562
563
564
565
566
  	case MEM_ONLINE:
  	case MEM_OFFLINE:
  		/*
  		 * offload per node hstate [un]registration to a work thread
  		 * when transitioning to/from memoryless state.
  		 */
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
567
  		if (nid != NUMA_NO_NODE)
8732794b1   Wen Congyang   numa: convert sta...
568
  			schedule_work(&node_devices[nid]->node_work);
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
569
  		break;
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
570

4faf8d950   Lee Schermerhorn   hugetlb: handle m...
571
572
573
574
575
576
577
578
579
580
  	case MEM_GOING_ONLINE:
  	case MEM_GOING_OFFLINE:
  	case MEM_CANCEL_ONLINE:
  	case MEM_CANCEL_OFFLINE:
  	default:
  		break;
  	}
  
  	return NOTIFY_OK;
  }
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
581
582
  #endif	/* CONFIG_HUGETLBFS */
  #else	/* !CONFIG_MEMORY_HOTPLUG_SPARSE */
c04fc586c   Gary Hade   mm: show node to ...
583
  static int link_mem_sections(int nid) { return 0; }
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
584
  #endif	/* CONFIG_MEMORY_HOTPLUG_SPARSE */
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
585

39da08cb0   Lee Schermerhorn   hugetlb: offload ...
586
587
  #if !defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || \
      !defined(CONFIG_HUGETLBFS)
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
588
589
590
591
592
  static inline int node_memory_callback(struct notifier_block *self,
  				unsigned long action, void *arg)
  {
  	return NOTIFY_OK;
  }
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
593
594
595
596
  
  static void init_node_hugetlb_work(int nid) { }
  
  #endif
c04fc586c   Gary Hade   mm: show node to ...
597

0fc44159b   Yasunori Goto   [PATCH] Register ...
598
599
600
  int register_one_node(int nid)
  {
  	int error = 0;
76b67ed9d   KAMEZAWA Hiroyuki   [PATCH] node hotp...
601
  	int cpu;
0fc44159b   Yasunori Goto   [PATCH] Register ...
602
603
604
605
606
607
  
  	if (node_online(nid)) {
  		int p_node = parent_node(nid);
  		struct node *parent = NULL;
  
  		if (p_node != nid)
8732794b1   Wen Congyang   numa: convert sta...
608
  			parent = node_devices[p_node];
0fc44159b   Yasunori Goto   [PATCH] Register ...
609

8732794b1   Wen Congyang   numa: convert sta...
610
611
612
613
614
  		node_devices[nid] = kzalloc(sizeof(struct node), GFP_KERNEL);
  		if (!node_devices[nid])
  			return -ENOMEM;
  
  		error = register_node(node_devices[nid], nid, parent);
76b67ed9d   KAMEZAWA Hiroyuki   [PATCH] node hotp...
615
616
617
618
619
620
  
  		/* link cpu under this node */
  		for_each_present_cpu(cpu) {
  			if (cpu_to_node(cpu) == nid)
  				register_cpu_under_node(cpu, nid);
  		}
c04fc586c   Gary Hade   mm: show node to ...
621
622
623
  
  		/* link memory sections under this node */
  		error = link_mem_sections(nid);
39da08cb0   Lee Schermerhorn   hugetlb: offload ...
624
625
626
  
  		/* initialize work queue for memory hot plug */
  		init_node_hugetlb_work(nid);
0fc44159b   Yasunori Goto   [PATCH] Register ...
627
628
629
630
631
632
633
634
  	}
  
  	return error;
  
  }
  
  void unregister_one_node(int nid)
  {
92d585ef0   Xishi Qiu   numa: fix NULL po...
635
636
  	if (!node_devices[nid])
  		return;
8732794b1   Wen Congyang   numa: convert sta...
637
  	unregister_node(node_devices[nid]);
8732794b1   Wen Congyang   numa: convert sta...
638
  	node_devices[nid] = NULL;
0fc44159b   Yasunori Goto   [PATCH] Register ...
639
  }
bde631a51   Lee Schermerhorn   mm: add node stat...
640
641
642
643
644
645
646
  /*
   * node states attributes
   */
  
  static ssize_t print_nodes_state(enum node_states state, char *buf)
  {
  	int n;
f799b1a7f   Tejun Heo   drivers/base: use...
647
648
  	n = scnprintf(buf, PAGE_SIZE - 1, "%*pbl",
  		      nodemask_pr_args(&node_states[state]));
f62388187   Ryota Ozaki   mm: fix off-by-on...
649
650
651
  	buf[n++] = '
  ';
  	buf[n] = '\0';
bde631a51   Lee Schermerhorn   mm: add node stat...
652
653
  	return n;
  }
b15f562fc   Andi Kleen   sysdev: Convert n...
654
  struct node_attr {
10fbcf4c6   Kay Sievers   convert 'memory' ...
655
  	struct device_attribute attr;
b15f562fc   Andi Kleen   sysdev: Convert n...
656
657
  	enum node_states state;
  };
bde631a51   Lee Schermerhorn   mm: add node stat...
658

10fbcf4c6   Kay Sievers   convert 'memory' ...
659
660
  static ssize_t show_node_state(struct device *dev,
  			       struct device_attribute *attr, char *buf)
bde631a51   Lee Schermerhorn   mm: add node stat...
661
  {
b15f562fc   Andi Kleen   sysdev: Convert n...
662
663
  	struct node_attr *na = container_of(attr, struct node_attr, attr);
  	return print_nodes_state(na->state, buf);
bde631a51   Lee Schermerhorn   mm: add node stat...
664
  }
b15f562fc   Andi Kleen   sysdev: Convert n...
665
  #define _NODE_ATTR(name, state) \
10fbcf4c6   Kay Sievers   convert 'memory' ...
666
  	{ __ATTR(name, 0444, show_node_state, NULL), state }
bde631a51   Lee Schermerhorn   mm: add node stat...
667

b15f562fc   Andi Kleen   sysdev: Convert n...
668
  static struct node_attr node_state_attr[] = {
fcf07d22f   Lai Jiangshan   drivers/base/node...
669
670
671
  	[N_POSSIBLE] = _NODE_ATTR(possible, N_POSSIBLE),
  	[N_ONLINE] = _NODE_ATTR(online, N_ONLINE),
  	[N_NORMAL_MEMORY] = _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
bde631a51   Lee Schermerhorn   mm: add node stat...
672
  #ifdef CONFIG_HIGHMEM
fcf07d22f   Lai Jiangshan   drivers/base/node...
673
  	[N_HIGH_MEMORY] = _NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
bde631a51   Lee Schermerhorn   mm: add node stat...
674
  #endif
20b2f52b7   Lai Jiangshan   numa: add CONFIG_...
675
676
677
  #ifdef CONFIG_MOVABLE_NODE
  	[N_MEMORY] = _NODE_ATTR(has_memory, N_MEMORY),
  #endif
fcf07d22f   Lai Jiangshan   drivers/base/node...
678
  	[N_CPU] = _NODE_ATTR(has_cpu, N_CPU),
bde631a51   Lee Schermerhorn   mm: add node stat...
679
  };
10fbcf4c6   Kay Sievers   convert 'memory' ...
680
  static struct attribute *node_state_attrs[] = {
fcf07d22f   Lai Jiangshan   drivers/base/node...
681
682
683
  	&node_state_attr[N_POSSIBLE].attr.attr,
  	&node_state_attr[N_ONLINE].attr.attr,
  	&node_state_attr[N_NORMAL_MEMORY].attr.attr,
3701cde6e   Andi Kleen   sysdev: Use sysde...
684
  #ifdef CONFIG_HIGHMEM
fcf07d22f   Lai Jiangshan   drivers/base/node...
685
  	&node_state_attr[N_HIGH_MEMORY].attr.attr,
3701cde6e   Andi Kleen   sysdev: Use sysde...
686
  #endif
20b2f52b7   Lai Jiangshan   numa: add CONFIG_...
687
688
689
  #ifdef CONFIG_MOVABLE_NODE
  	&node_state_attr[N_MEMORY].attr.attr,
  #endif
fcf07d22f   Lai Jiangshan   drivers/base/node...
690
  	&node_state_attr[N_CPU].attr.attr,
3701cde6e   Andi Kleen   sysdev: Use sysde...
691
692
  	NULL
  };
bde631a51   Lee Schermerhorn   mm: add node stat...
693

10fbcf4c6   Kay Sievers   convert 'memory' ...
694
695
696
697
698
699
700
701
  static struct attribute_group memory_root_attr_group = {
  	.attrs = node_state_attrs,
  };
  
  static const struct attribute_group *cpu_root_attr_groups[] = {
  	&memory_root_attr_group,
  	NULL,
  };
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
702
  #define NODE_CALLBACK_PRI	2	/* lower than SLAB */
4b45099b7   Keiichiro Tokunaga   [PATCH] Driver co...
703
  static int __init register_node_type(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  {
bde631a51   Lee Schermerhorn   mm: add node stat...
705
  	int ret;
3701cde6e   Andi Kleen   sysdev: Use sysde...
706
707
   	BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES);
   	BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES);
10fbcf4c6   Kay Sievers   convert 'memory' ...
708
  	ret = subsys_system_register(&node_subsys, cpu_root_attr_groups);
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
709
  	if (!ret) {
6e259e7dc   Andrew Morton   drivers/base/node...
710
711
712
713
714
  		static struct notifier_block node_memory_callback_nb = {
  			.notifier_call = node_memory_callback,
  			.priority = NODE_CALLBACK_PRI,
  		};
  		register_hotmemory_notifier(&node_memory_callback_nb);
4faf8d950   Lee Schermerhorn   hugetlb: handle m...
715
  	}
bde631a51   Lee Schermerhorn   mm: add node stat...
716
717
718
719
720
721
  
  	/*
  	 * Note:  we're not going to unregister the node class if we fail
  	 * to register the node state class attribute files.
  	 */
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
  }
  postcore_initcall(register_node_type);