forked from mirrors/linux
		
	mm,hwpoison: refactor get_any_page
Patch series "HWPoison: Refactor get page interface", v2. This patch (of 3): When we want to grab a refcount via get_any_page, we call __get_any_page that calls get_hwpoison_page to get the actual refcount. get_any_page() is only there because we have a sort of retry mechanism in case the page we met is unknown to us or if we raced with an allocation. Also __get_any_page() prints some messages about the page type in case the page was a free page or the page type was unknown, but if anything, we only need to print a message in case the pagetype was unknown, as that is reporting an error down the chain. Let us merge get_any_page() and __get_any_page(), and let the message be printed in soft_offline_page. While we are it, we can also remove the 'pfn' parameter as it is no longer used. Link: https://lkml.kernel.org/r/20201204102558.31607-1-osalvador@suse.de Link: https://lkml.kernel.org/r/20201204102558.31607-2-osalvador@suse.de Signed-off-by: Oscar Salvador <osalvador@suse.de> Acked-by: Naoya Horiguchi <naoya.horiguchi@nec.com> Acked-by: Vlastimil Babka <Vbabka@suse.cz> Cc: Qian Cai <qcai@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									32409cba3f
								
							
						
					
					
						commit
						8295d535e2
					
				
					 1 changed files with 42 additions and 57 deletions
				
			
		|  | @ -1707,70 +1707,51 @@ EXPORT_SYMBOL(unpoison_memory); | |||
| 
 | ||||
| /*
 | ||||
|  * Safely get reference count of an arbitrary page. | ||||
|  * Returns 0 for a free page, -EIO for a zero refcount page | ||||
|  * that is not free, and 1 for any other page type. | ||||
|  * For 1 the page is returned with increased page count, otherwise not. | ||||
|  * Returns 0 for a free page, 1 for an in-use page, -EIO for a page-type we | ||||
|  * cannot handle and -EBUSY if we raced with an allocation. | ||||
|  * We only incremented refcount in case the page was already in-use and it is | ||||
|  * a known type we can handle. | ||||
|  */ | ||||
| static int __get_any_page(struct page *p, unsigned long pfn, int flags) | ||||
| static int get_any_page(struct page *p, int flags) | ||||
| { | ||||
| 	int ret; | ||||
| 	int ret = 0, pass = 0; | ||||
| 	bool count_increased = false; | ||||
| 
 | ||||
| 	if (flags & MF_COUNT_INCREASED) | ||||
| 		return 1; | ||||
| 		count_increased = true; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * When the target page is a free hugepage, just remove it | ||||
| 	 * from free hugepage list. | ||||
| 	 */ | ||||
| 	if (!get_hwpoison_page(p)) { | ||||
| 		if (PageHuge(p)) { | ||||
| 			pr_info("%s: %#lx free huge page\n", __func__, pfn); | ||||
| 			ret = 0; | ||||
| 		} else if (is_free_buddy_page(p)) { | ||||
| 			pr_info("%s: %#lx free buddy page\n", __func__, pfn); | ||||
| 			ret = 0; | ||||
| 		} else if (page_count(p)) { | ||||
| 			/* raced with allocation */ | ||||
| try_again: | ||||
| 	if (!count_increased && !get_hwpoison_page(p)) { | ||||
| 		if (page_count(p)) { | ||||
| 			/* We raced with an allocation, retry. */ | ||||
| 			if (pass++ < 3) | ||||
| 				goto try_again; | ||||
| 			ret = -EBUSY; | ||||
| 		} else { | ||||
| 			pr_info("%s: %#lx: unknown zero refcount page type %lx\n", | ||||
| 				__func__, pfn, p->flags); | ||||
| 		} else if (!PageHuge(p) && !is_free_buddy_page(p)) { | ||||
| 			/* We raced with put_page, retry. */ | ||||
| 			if (pass++ < 3) | ||||
| 				goto try_again; | ||||
| 			ret = -EIO; | ||||
| 		} | ||||
| 	} else { | ||||
| 		/* Not a free page */ | ||||
| 		ret = 1; | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int get_any_page(struct page *page, unsigned long pfn, int flags) | ||||
| { | ||||
| 	int ret = __get_any_page(page, pfn, flags); | ||||
| 
 | ||||
| 	if (ret == -EBUSY) | ||||
| 		ret = __get_any_page(page, pfn, flags); | ||||
| 
 | ||||
| 	if (ret == 1 && !PageHuge(page) && | ||||
| 	    !PageLRU(page) && !__PageMovable(page)) { | ||||
| 		/*
 | ||||
| 		 * Try to free it. | ||||
| 		 */ | ||||
| 		put_page(page); | ||||
| 		shake_page(page, 1); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Did it turn free? | ||||
| 		 */ | ||||
| 		ret = __get_any_page(page, pfn, 0); | ||||
| 		if (ret == 1 && !PageLRU(page)) { | ||||
| 			/* Drop page reference which is from __get_any_page() */ | ||||
| 			put_page(page); | ||||
| 			pr_info("soft_offline: %#lx: unknown non LRU page type %lx (%pGp)\n", | ||||
| 				pfn, page->flags, &page->flags); | ||||
| 			return -EIO; | ||||
| 		if (PageHuge(p) || PageLRU(p) || __PageMovable(p)) { | ||||
| 			ret = 1; | ||||
| 		} else { | ||||
| 			/*
 | ||||
| 			 * A page we cannot handle. Check whether we can turn | ||||
| 			 * it into something we can handle. | ||||
| 			 */ | ||||
| 			if (pass++ < 3) { | ||||
| 				put_page(p); | ||||
| 				shake_page(p, 1); | ||||
| 				count_increased = false; | ||||
| 				goto try_again; | ||||
| 			} | ||||
| 			put_page(p); | ||||
| 			ret = -EIO; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
|  | @ -1939,7 +1920,7 @@ int soft_offline_page(unsigned long pfn, int flags) | |||
| 		return -EIO; | ||||
| 
 | ||||
| 	if (PageHWPoison(page)) { | ||||
| 		pr_info("soft offline: %#lx page already poisoned\n", pfn); | ||||
| 		pr_info("%s: %#lx page already poisoned\n", __func__, pfn); | ||||
| 		if (flags & MF_COUNT_INCREASED) | ||||
| 			put_page(page); | ||||
| 		return 0; | ||||
|  | @ -1947,16 +1928,20 @@ int soft_offline_page(unsigned long pfn, int flags) | |||
| 
 | ||||
| retry: | ||||
| 	get_online_mems(); | ||||
| 	ret = get_any_page(page, pfn, flags); | ||||
| 	ret = get_any_page(page, flags); | ||||
| 	put_online_mems(); | ||||
| 
 | ||||
| 	if (ret > 0) | ||||
| 	if (ret > 0) { | ||||
| 		ret = soft_offline_in_use_page(page); | ||||
| 	else if (ret == 0) | ||||
| 	} else if (ret == 0) { | ||||
| 		if (soft_offline_free_page(page) && try_again) { | ||||
| 			try_again = false; | ||||
| 			goto retry; | ||||
| 		} | ||||
| 	} else if (ret == -EIO) { | ||||
| 		pr_info("%s: %#lx: unknown page type: %lx (%pGP)\n", | ||||
| 			 __func__, pfn, page->flags, &page->flags); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Oscar Salvador
						Oscar Salvador