Commit 0348d2eb authored by Naoya Horiguchi's avatar Naoya Horiguchi Committed by Linus Torvalds
Browse files

mm: hwpoison: introduce idenfity_page_state

parent ddd40d8a
Loading
Loading
Loading
Loading
+25 −32
Original line number Diff line number Diff line
@@ -1022,9 +1022,31 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
	return unmap_success;
}

static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags)
static int identify_page_state(unsigned long pfn, struct page *p,
				unsigned long page_flags)
{
	struct page_state *ps;

	/*
	 * The first check uses the current page flags which may not have any
	 * relevant information. The second check with the saved page flags is
	 * carried out only if the first check can't determine the page status.
	 */
	for (ps = error_states;; ps++)
		if ((p->flags & ps->mask) == ps->res)
			break;

	page_flags |= (p->flags & (1UL << PG_dirty));

	if (!ps->mask)
		for (ps = error_states;; ps++)
			if ((page_flags & ps->mask) == ps->res)
				break;
	return page_action(ps, p, pfn);
}

static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags)
{
	struct page *p = pfn_to_page(pfn);
	struct page *head = compound_head(p);
	int res;
@@ -1074,19 +1096,7 @@ static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags)
		goto out;
	}

	res = -EBUSY;

	for (ps = error_states;; ps++)
		if ((p->flags & ps->mask) == ps->res)
			break;

	page_flags |= (p->flags & (1UL << PG_dirty));

	if (!ps->mask)
		for (ps = error_states;; ps++)
			if ((page_flags & ps->mask) == ps->res)
				break;
	res = page_action(ps, p, pfn);
	res = identify_page_state(pfn, p, page_flags);
out:
	unlock_page(head);
	return res;
@@ -1112,7 +1122,6 @@ out:
 */
int memory_failure(unsigned long pfn, int trapno, int flags)
{
	struct page_state *ps;
	struct page *p;
	struct page *hpage;
	struct page *orig_head;
@@ -1273,23 +1282,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
	}

identify_page_state:
	res = -EBUSY;
	/*
	 * The first check uses the current page flags which may not have any
	 * relevant information. The second check with the saved page flagss is
	 * carried out only if the first check can't determine the page status.
	 */
	for (ps = error_states;; ps++)
		if ((p->flags & ps->mask) == ps->res)
			break;

	page_flags |= (p->flags & (1UL << PG_dirty));

	if (!ps->mask)
		for (ps = error_states;; ps++)
			if ((page_flags & ps->mask) == ps->res)
				break;
	res = page_action(ps, p, pfn);
	res = identify_page_state(pfn, p, page_flags);
out:
	unlock_page(p);
	return res;