Commit 477702e9 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: endless loop in follow_page.

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

Fix endless loop in get_user_pages() on s390.  It happens only on s/390
because pte_dirty always returns 0.  For all other architectures this is an
optimization.

In the case of "write && !pte_dirty(pte)" follow_page() returns NULL.  On all
architectures except s390 handle_pte_fault() will then create a pte with
pte_dirty(pte)==1 because write_access==1.  In the following, second call to
follow_page() all is fine.  With the physical dirty bit patch pte_dirty() is
always 0 for s/390 because the dirty bit doesn't live in the pte.
parent 6fefc8fa
...@@ -651,7 +651,13 @@ follow_page(struct mm_struct *mm, unsigned long address, int write) ...@@ -651,7 +651,13 @@ follow_page(struct mm_struct *mm, unsigned long address, int write)
pte = *ptep; pte = *ptep;
pte_unmap(ptep); pte_unmap(ptep);
if (pte_present(pte)) { if (pte_present(pte)) {
if (!write || (pte_write(pte) && pte_dirty(pte))) { if (write && !pte_write(pte))
goto out;
if (write && !pte_dirty(pte)) {
struct page *page = pte_page(pte);
if (!PageDirty(page))
set_page_dirty(page);
}
pfn = pte_pfn(pte); pfn = pte_pfn(pte);
if (pfn_valid(pfn)) { if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn); struct page *page = pfn_to_page(pfn);
...@@ -660,7 +666,6 @@ follow_page(struct mm_struct *mm, unsigned long address, int write) ...@@ -660,7 +666,6 @@ follow_page(struct mm_struct *mm, unsigned long address, int write)
return page; return page;
} }
} }
}
out: out:
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment