Skip to content

Commit

Permalink
mips,s390,sh,sparc: gup: Work around the "COW can break either way" i…
Browse files Browse the repository at this point in the history
…ssue

In Linux 4.14 and 4.19 these architectures still have their own
implementations of get_user_pages_fast().  These also need to force
the write flag on when taking the fast path.

Fixes: 407faed ("gup: document and work around "COW can break either way" issue")
Fixes: 5e24029 ("gup: document and work around "COW can break either way" issue")
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
  • Loading branch information
Ben Hutchings authored and Greg Kroah-Hartman committed Jan 27, 2022
1 parent 1550a97 commit 294c7a9
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 4 deletions.
9 changes: 8 additions & 1 deletion arch/mips/mm/gup.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,14 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
next = pgd_addr_end(addr, end);
if (pgd_none(pgd))
goto slow;
if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
/*
* The FAST_GUP case requires FOLL_WRITE even for pure reads,
* because get_user_pages() may need to cause an early COW in
* order to avoid confusing the normal COW routines. So only
* targets that are already writable are safe to do by just
* looking at the page tables.
*/
if (!gup_pud_range(pgd, addr, next, 1, pages, &nr))
goto slow;
} while (pgdp++, addr = next, addr != end);
local_irq_enable();
Expand Down
9 changes: 8 additions & 1 deletion arch/s390/mm/gup.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,14 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,

might_sleep();
start &= PAGE_MASK;
nr = __get_user_pages_fast(start, nr_pages, write, pages);
/*
* The FAST_GUP case requires FOLL_WRITE even for pure reads,
* because get_user_pages() may need to cause an early COW in
* order to avoid confusing the normal COW routines. So only
* targets that are already writable are safe to do by just
* looking at the page tables.
*/
nr = __get_user_pages_fast(start, nr_pages, 1, pages);
if (nr == nr_pages)
return nr;

Expand Down
9 changes: 8 additions & 1 deletion arch/sh/mm/gup.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,14 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
next = pgd_addr_end(addr, end);
if (pgd_none(pgd))
goto slow;
if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
/*
* The FAST_GUP case requires FOLL_WRITE even for pure reads,
* because get_user_pages() may need to cause an early COW in
* order to avoid confusing the normal COW routines. So only
* targets that are already writable are safe to do by just
* looking at the page tables.
*/
if (!gup_pud_range(pgd, addr, next, 1, pages, &nr))
goto slow;
} while (pgdp++, addr = next, addr != end);
local_irq_enable();
Expand Down
9 changes: 8 additions & 1 deletion arch/sparc/mm/gup.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,14 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
next = pgd_addr_end(addr, end);
if (pgd_none(pgd))
goto slow;
if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
/*
* The FAST_GUP case requires FOLL_WRITE even for pure reads,
* because get_user_pages() may need to cause an early COW in
* order to avoid confusing the normal COW routines. So only
* targets that are already writable are safe to do by just
* looking at the page tables.
*/
if (!gup_pud_range(pgd, addr, next, 1, pages, &nr))
goto slow;
} while (pgdp++, addr = next, addr != end);

Expand Down

0 comments on commit 294c7a9

Please sign in to comment.