diff options
Diffstat (limited to 'drivers/base/node.c')
-rw-r--r-- | drivers/base/node.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c index 2872e86837b2..793f796c4da3 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/mm.h> | 8 | #include <linux/mm.h> |
9 | #include <linux/memory.h> | 9 | #include <linux/memory.h> |
10 | #include <linux/vmstat.h> | ||
10 | #include <linux/node.h> | 11 | #include <linux/node.h> |
11 | #include <linux/hugetlb.h> | 12 | #include <linux/hugetlb.h> |
12 | #include <linux/compaction.h> | 13 | #include <linux/compaction.h> |
@@ -117,12 +118,21 @@ static ssize_t node_read_meminfo(struct sys_device * dev, | |||
117 | "Node %d WritebackTmp: %8lu kB\n" | 118 | "Node %d WritebackTmp: %8lu kB\n" |
118 | "Node %d Slab: %8lu kB\n" | 119 | "Node %d Slab: %8lu kB\n" |
119 | "Node %d SReclaimable: %8lu kB\n" | 120 | "Node %d SReclaimable: %8lu kB\n" |
120 | "Node %d SUnreclaim: %8lu kB\n", | 121 | "Node %d SUnreclaim: %8lu kB\n" |
122 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
123 | "Node %d AnonHugePages: %8lu kB\n" | ||
124 | #endif | ||
125 | , | ||
121 | nid, K(node_page_state(nid, NR_FILE_DIRTY)), | 126 | nid, K(node_page_state(nid, NR_FILE_DIRTY)), |
122 | nid, K(node_page_state(nid, NR_WRITEBACK)), | 127 | nid, K(node_page_state(nid, NR_WRITEBACK)), |
123 | nid, K(node_page_state(nid, NR_FILE_PAGES)), | 128 | nid, K(node_page_state(nid, NR_FILE_PAGES)), |
124 | nid, K(node_page_state(nid, NR_FILE_MAPPED)), | 129 | nid, K(node_page_state(nid, NR_FILE_MAPPED)), |
125 | nid, K(node_page_state(nid, NR_ANON_PAGES)), | 130 | nid, K(node_page_state(nid, NR_ANON_PAGES) |
131 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
132 | + node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) * | ||
133 | HPAGE_PMD_NR | ||
134 | #endif | ||
135 | ), | ||
126 | nid, K(node_page_state(nid, NR_SHMEM)), | 136 | nid, K(node_page_state(nid, NR_SHMEM)), |
127 | nid, node_page_state(nid, NR_KERNEL_STACK) * | 137 | nid, node_page_state(nid, NR_KERNEL_STACK) * |
128 | THREAD_SIZE / 1024, | 138 | THREAD_SIZE / 1024, |
@@ -133,7 +143,13 @@ static ssize_t node_read_meminfo(struct sys_device * dev, | |||
133 | nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) + | 143 | nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) + |
134 | node_page_state(nid, NR_SLAB_UNRECLAIMABLE)), | 144 | node_page_state(nid, NR_SLAB_UNRECLAIMABLE)), |
135 | nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)), | 145 | nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)), |
136 | nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))); | 146 | nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)) |
147 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
148 | , nid, | ||
149 | K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) * | ||
150 | HPAGE_PMD_NR) | ||
151 | #endif | ||
152 | ); | ||
137 | n += hugetlb_report_node_meminfo(nid, buf + n); | 153 | n += hugetlb_report_node_meminfo(nid, buf + n); |
138 | return n; | 154 | return n; |
139 | } | 155 | } |
@@ -160,6 +176,21 @@ static ssize_t node_read_numastat(struct sys_device * dev, | |||
160 | } | 176 | } |
161 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); | 177 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); |
162 | 178 | ||
179 | static ssize_t node_read_vmstat(struct sys_device *dev, | ||
180 | struct sysdev_attribute *attr, char *buf) | ||
181 | { | ||
182 | int nid = dev->id; | ||
183 | int i; | ||
184 | int n = 0; | ||
185 | |||
186 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) | ||
187 | n += sprintf(buf+n, "%s %lu\n", vmstat_text[i], | ||
188 | node_page_state(nid, i)); | ||
189 | |||
190 | return n; | ||
191 | } | ||
192 | static SYSDEV_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL); | ||
193 | |||
163 | static ssize_t node_read_distance(struct sys_device * dev, | 194 | static ssize_t node_read_distance(struct sys_device * dev, |
164 | struct sysdev_attribute *attr, char * buf) | 195 | struct sysdev_attribute *attr, char * buf) |
165 | { | 196 | { |
@@ -243,6 +274,7 @@ int register_node(struct node *node, int num, struct node *parent) | |||
243 | sysdev_create_file(&node->sysdev, &attr_meminfo); | 274 | sysdev_create_file(&node->sysdev, &attr_meminfo); |
244 | sysdev_create_file(&node->sysdev, &attr_numastat); | 275 | sysdev_create_file(&node->sysdev, &attr_numastat); |
245 | sysdev_create_file(&node->sysdev, &attr_distance); | 276 | sysdev_create_file(&node->sysdev, &attr_distance); |
277 | sysdev_create_file(&node->sysdev, &attr_vmstat); | ||
246 | 278 | ||
247 | scan_unevictable_register_node(node); | 279 | scan_unevictable_register_node(node); |
248 | 280 | ||
@@ -267,6 +299,7 @@ void unregister_node(struct node *node) | |||
267 | sysdev_remove_file(&node->sysdev, &attr_meminfo); | 299 | sysdev_remove_file(&node->sysdev, &attr_meminfo); |
268 | sysdev_remove_file(&node->sysdev, &attr_numastat); | 300 | sysdev_remove_file(&node->sysdev, &attr_numastat); |
269 | sysdev_remove_file(&node->sysdev, &attr_distance); | 301 | sysdev_remove_file(&node->sysdev, &attr_distance); |
302 | sysdev_remove_file(&node->sysdev, &attr_vmstat); | ||
270 | 303 | ||
271 | scan_unevictable_unregister_node(node); | 304 | scan_unevictable_unregister_node(node); |
272 | hugetlb_unregister_node(node); /* no-op, if memoryless node */ | 305 | hugetlb_unregister_node(node); /* no-op, if memoryless node */ |
@@ -346,8 +379,10 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) | |||
346 | return -EFAULT; | 379 | return -EFAULT; |
347 | if (!node_online(nid)) | 380 | if (!node_online(nid)) |
348 | return 0; | 381 | return 0; |
349 | sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); | 382 | |
350 | sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; | 383 | sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr); |
384 | sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr); | ||
385 | sect_end_pfn += PAGES_PER_SECTION - 1; | ||
351 | for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { | 386 | for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { |
352 | int page_nid; | 387 | int page_nid; |
353 | 388 | ||
@@ -371,7 +406,8 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) | |||
371 | } | 406 | } |
372 | 407 | ||
373 | /* unregister memory section under all nodes that it spans */ | 408 | /* unregister memory section under all nodes that it spans */ |
374 | int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) | 409 | int unregister_mem_sect_under_nodes(struct memory_block *mem_blk, |
410 | unsigned long phys_index) | ||
375 | { | 411 | { |
376 | NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL); | 412 | NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL); |
377 | unsigned long pfn, sect_start_pfn, sect_end_pfn; | 413 | unsigned long pfn, sect_start_pfn, sect_end_pfn; |
@@ -383,7 +419,8 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) | |||
383 | if (!unlinked_nodes) | 419 | if (!unlinked_nodes) |
384 | return -ENOMEM; | 420 | return -ENOMEM; |
385 | nodes_clear(*unlinked_nodes); | 421 | nodes_clear(*unlinked_nodes); |
386 | sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); | 422 | |
423 | sect_start_pfn = section_nr_to_pfn(phys_index); | ||
387 | sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; | 424 | sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; |
388 | for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { | 425 | for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { |
389 | int nid; | 426 | int nid; |
@@ -409,25 +446,27 @@ static int link_mem_sections(int nid) | |||
409 | unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn; | 446 | unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn; |
410 | unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages; | 447 | unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages; |
411 | unsigned long pfn; | 448 | unsigned long pfn; |
449 | struct memory_block *mem_blk = NULL; | ||
412 | int err = 0; | 450 | int err = 0; |
413 | 451 | ||
414 | for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) { | 452 | for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) { |
415 | unsigned long section_nr = pfn_to_section_nr(pfn); | 453 | unsigned long section_nr = pfn_to_section_nr(pfn); |
416 | struct mem_section *mem_sect; | 454 | struct mem_section *mem_sect; |
417 | struct memory_block *mem_blk; | ||
418 | int ret; | 455 | int ret; |
419 | 456 | ||
420 | if (!present_section_nr(section_nr)) | 457 | if (!present_section_nr(section_nr)) |
421 | continue; | 458 | continue; |
422 | mem_sect = __nr_to_section(section_nr); | 459 | mem_sect = __nr_to_section(section_nr); |
423 | mem_blk = find_memory_block(mem_sect); | 460 | mem_blk = find_memory_block_hinted(mem_sect, mem_blk); |
424 | ret = register_mem_sect_under_node(mem_blk, nid); | 461 | ret = register_mem_sect_under_node(mem_blk, nid); |
425 | if (!err) | 462 | if (!err) |
426 | err = ret; | 463 | err = ret; |
427 | 464 | ||
428 | /* discard ref obtained in find_memory_block() */ | 465 | /* discard ref obtained in find_memory_block() */ |
429 | kobject_put(&mem_blk->sysdev.kobj); | ||
430 | } | 466 | } |
467 | |||
468 | if (mem_blk) | ||
469 | kobject_put(&mem_blk->sysdev.kobj); | ||
431 | return err; | 470 | return err; |
432 | } | 471 | } |
433 | 472 | ||