diff options
Diffstat (limited to 'drivers/base/node.c')
| -rw-r--r-- | drivers/base/node.c | 55 | 
1 files changed, 26 insertions, 29 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c index 75b7e6f6535b..296546ffed6c 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -427,6 +427,8 @@ static ssize_t node_read_meminfo(struct device *dev,  		       "Node %d AnonHugePages:  %8lu kB\n"  		       "Node %d ShmemHugePages: %8lu kB\n"  		       "Node %d ShmemPmdMapped: %8lu kB\n" +		       "Node %d FileHugePages: %8lu kB\n" +		       "Node %d FilePmdMapped: %8lu kB\n"  #endif  			,  		       nid, K(node_page_state(pgdat, NR_FILE_DIRTY)), @@ -452,6 +454,10 @@ static ssize_t node_read_meminfo(struct device *dev,  		       nid, K(node_page_state(pgdat, NR_SHMEM_THPS) *  				       HPAGE_PMD_NR),  		       nid, K(node_page_state(pgdat, NR_SHMEM_PMDMAPPED) * +				       HPAGE_PMD_NR), +		       nid, K(node_page_state(pgdat, NR_FILE_THPS) * +				       HPAGE_PMD_NR), +		       nid, K(node_page_state(pgdat, NR_FILE_PMDMAPPED) *  				       HPAGE_PMD_NR)  #endif  		       ); @@ -756,15 +762,13 @@ static int __ref get_nid_for_pfn(unsigned long pfn)  static int register_mem_sect_under_node(struct memory_block *mem_blk,  					 void *arg)  { +	unsigned long memory_block_pfns = memory_block_size_bytes() / PAGE_SIZE; +	unsigned long start_pfn = section_nr_to_pfn(mem_blk->start_section_nr); +	unsigned long end_pfn = start_pfn + memory_block_pfns - 1;  	int ret, nid = *(int *)arg; -	unsigned long pfn, sect_start_pfn, sect_end_pfn; +	unsigned long pfn; -	mem_blk->nid = nid; - -	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; -	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { +	for (pfn = start_pfn; pfn <= end_pfn; pfn++) {  		int page_nid;  		/* @@ -789,6 +793,13 @@ static int register_mem_sect_under_node(struct memory_block *mem_blk,  			if (page_nid != nid)  				continue;  		} + +		/* +		 * If this memory block spans multiple nodes, we only indicate +		 * the last processed node. +		 */ +		mem_blk->nid = nid; +  		ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,  					&mem_blk->dev.kobj,  					kobject_name(&mem_blk->dev.kobj)); @@ -804,32 +815,18 @@ static int register_mem_sect_under_node(struct memory_block *mem_blk,  }  /* - * Unregister memory block device under all nodes that it spans. - * Has to be called with mem_sysfs_mutex held (due to unlinked_nodes). + * Unregister a memory block device under the node it spans. Memory blocks + * with multiple nodes cannot be offlined and therefore also never be removed.   */  void unregister_memory_block_under_nodes(struct memory_block *mem_blk)  { -	unsigned long pfn, sect_start_pfn, sect_end_pfn; -	static nodemask_t unlinked_nodes; - -	nodes_clear(unlinked_nodes); -	sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr); -	sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr); -	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { -		int nid; +	if (mem_blk->nid == NUMA_NO_NODE) +		return; -		nid = get_nid_for_pfn(pfn); -		if (nid < 0) -			continue; -		if (!node_online(nid)) -			continue; -		if (node_test_and_set(nid, unlinked_nodes)) -			continue; -		sysfs_remove_link(&node_devices[nid]->dev.kobj, -			 kobject_name(&mem_blk->dev.kobj)); -		sysfs_remove_link(&mem_blk->dev.kobj, -			 kobject_name(&node_devices[nid]->dev.kobj)); -	} +	sysfs_remove_link(&node_devices[mem_blk->nid]->dev.kobj, +			  kobject_name(&mem_blk->dev.kobj)); +	sysfs_remove_link(&mem_blk->dev.kobj, +			  kobject_name(&node_devices[mem_blk->nid]->dev.kobj));  }  int link_mem_sections(int nid, unsigned long start_pfn, unsigned long end_pfn)  |