Commit 208d54e5 authored by Dave Hansen's avatar Dave Hansen Committed by Linus Torvalds
Browse files

[PATCH] memory hotplug locking: node_size_lock



pgdat->node_size_lock is basically only neeeded in one place in the normal
code: show_mem(), which is the arch-specific sysrq-m printing function.

Strictly speaking, the architectures not doing memory hotplug do no need this
locking in show_mem().  However, they are all included for completeness.  This
should also make any future consolidation of all of the implementations a
little more straightforward.

This lock is also held in the sparsemem code during a memory removal, as
sections are invalidated.  This is the place there pfn_valid() is made false
for a memory area that's being removed.  The lock is only required when doing
pfn_valid() operations on memory which the user does not already have a
reference on the page, such as in show_mem().

Signed-off-by: default avatarDave Hansen <haveblue@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c6a57e19
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -371,6 +371,8 @@ show_mem(void)
	show_free_areas();
	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
	for_each_online_node(nid) {
		unsigned long flags;
		pgdat_resize_lock(NODE_DATA(nid), &flags);
		i = node_spanned_pages(nid);
		while (i-- > 0) {
			struct page *page = nid_page_nr(nid, i);
@@ -384,6 +386,7 @@ show_mem(void)
			else
				shared += page_count(page) - 1;
		}
		pgdat_resize_unlock(NODE_DATA(nid), &flags);
	}
	printk("%ld pages of RAM\n",total);
	printk("%ld free pages\n",free);
+3 −0
Original line number Diff line number Diff line
@@ -31,11 +31,13 @@ void show_mem(void)
	pg_data_t *pgdat;
	unsigned long i;
	struct page_state ps;
	unsigned long flags;

	printk(KERN_INFO "Mem-info:\n");
	show_free_areas();
	printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
	for_each_pgdat(pgdat) {
		pgdat_resize_lock(pgdat, &flags);
		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
			page = pgdat_page_nr(pgdat, i);
			total++;
@@ -48,6 +50,7 @@ void show_mem(void)
			else if (page_count(page))
				shared += page_count(page) - 1;
		}
		pgdat_resize_unlock(pgdat, &flags);
	}
	printk(KERN_INFO "%d pages of RAM\n", total);
	printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
+6 −1
Original line number Diff line number Diff line
@@ -555,9 +555,13 @@ void show_mem(void)
	show_free_areas();
	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
	for_each_pgdat(pgdat) {
		unsigned long present = pgdat->node_present_pages;
		unsigned long present;
		unsigned long flags;
		int shared = 0, cached = 0, reserved = 0;

		printk("Node ID: %d\n", pgdat->node_id);
		pgdat_resize_lock(pgdat, &flags);
		present = pgdat->node_present_pages;
		for(i = 0; i < pgdat->node_spanned_pages; i++) {
			struct page *page;
			if (pfn_valid(pgdat->node_start_pfn + i))
@@ -571,6 +575,7 @@ void show_mem(void)
			else if (page_count(page))
				shared += page_count(page)-1;
		}
		pgdat_resize_unlock(pgdat, &flags);
		total_present += present;
		total_reserved += reserved;
		total_cached += cached;
+8 −1
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ void show_mem(void)
	show_free_areas();
	printk("Free swap:       %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
	for_each_pgdat(pgdat) {
		unsigned long flags;
		pgdat_resize_lock(pgdat, &flags);
		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
			page = pgdat_page_nr(pgdat, i);
			total++;
@@ -60,6 +62,7 @@ void show_mem(void)
			else if (page_count(page))
				shared += page_count(page) - 1;
		}
		pgdat_resize_unlock(pgdat, &flags);
	}
	printk("%d pages of RAM\n", total);
	printk("%d pages of HIGHMEM\n",highmem);
@@ -150,10 +153,14 @@ int __init reservedpages_count(void)
	int reservedpages, nid, i;

	reservedpages = 0;
	for_each_online_node(nid)
	for_each_online_node(nid) {
		unsigned long flags;
		pgdat_resize_lock(NODE_DATA(nid), &flags);
		for (i = 0 ; i < MAX_LOW_PFN(nid) - START_PFN(nid) ; i++)
			if (PageReserved(nid_page_nr(nid, i)))
				reservedpages++;
		pgdat_resize_unlock(NODE_DATA(nid), &flags);
	}

	return reservedpages;
}
+3 −0
Original line number Diff line number Diff line
@@ -505,7 +505,9 @@ void show_mem(void)

		for (j = node_start_pfn(i); j < node_end_pfn(i); j++) {
			struct page *p;
			unsigned long flags;

			pgdat_resize_lock(NODE_DATA(i), &flags);
			p = nid_page_nr(i, j) - node_start_pfn(i);

			total++;
@@ -517,6 +519,7 @@ void show_mem(void)
				free++;
			else
				shared += page_count(p) - 1;
			pgdat_resize_unlock(NODE_DATA(i), &flags);
        	}
	}
#endif
Loading