diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-07-09 13:19:49 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-25 13:15:03 -0700 |
commit | 1b2de5d039c883c9d44ae5b2b6eca4ff9bd82dac (patch) | |
tree | ecae1ad75f1b24eba699b6aa0e2a2cb09a7d1c7f | |
parent | e0fcfe1f1acf2f129e0809ea89b9187e89e84246 (diff) | |
download | linux-rpi3-1b2de5d039c883c9d44ae5b2b6eca4ff9bd82dac.tar.gz linux-rpi3-1b2de5d039c883c9d44ae5b2b6eca4ff9bd82dac.tar.bz2 linux-rpi3-1b2de5d039c883c9d44ae5b2b6eca4ff9bd82dac.zip |
mm/cow: don't bother write protecting already write-protected pages
This is not normally noticeable, but repeated forks are unnecessarily
expensive because they repeatedly dirty the parent page tables during
the page table copy operation.
It's trivial to just avoid write protecting the page table entry if it
was already not writable.
This patch was inspired by
https://bugzilla.kernel.org/show_bug.cgi?id=200447
which points to an ancient "waste time re-doing fork" issue in the
presence of lots of signals.
That bug was fixed by Eric Biederman's signal handling series
culminating in commit c3ad2c3b02e9 ("signal: Don't restart fork when
signals come in"), but the unnecessary work for repeated forks is still
work just fixing, particularly since the fix is trivial.
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/memory.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/mm/memory.c b/mm/memory.c index 83aef222f11b..c467102a5cbc 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1022,7 +1022,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, * If it's a COW mapping, write protect it both * in the parent and the child */ - if (is_cow_mapping(vm_flags)) { + if (is_cow_mapping(vm_flags) && pte_write(pte)) { ptep_set_wrprotect(src_mm, addr, src_pte); pte = pte_wrprotect(pte); } |