From: Hugh Dickins <hugh@veritas.com>
To: Andrew Morton <akpm@osdl.org>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 16/21] mm: unlink vma before pagetables
Date: Thu, 13 Oct 2005 02:17:34 +0100 (BST) [thread overview]
Message-ID: <Pine.LNX.4.61.0510130216450.4343@goblin.wat.veritas.com> (raw)
In-Reply-To: <Pine.LNX.4.61.0510130143240.4060@goblin.wat.veritas.com>
In most places the descent from pgd to pud to pmd to pte holds mmap_sem
(exclusively or not), which ensures that free_pgtables cannot be freeing
page tables from any level at the same time. But truncation and reverse
mapping descend without mmap_sem.
No problem: just make sure that a vma is unlinked from its prio_tree (or
nonlinear list) and from its anon_vma list, after zapping the vma, but
before freeing its page tables. Then neither vmtruncate nor rmap can
reach that vma whose page tables are now volatile (nor do they need to
reach it, since all its page entries have been zapped by this stage).
The i_mmap_lock and anon_vma->lock already serialize this correctly;
but the locking hierarchy is such that we cannot take them while holding
page_table_lock. Well, we're trying to push that down anyway. So in
this patch, move anon_vma_unlink and unlink_file_vma into free_pgtables,
at the same time as moving page_table_lock around calls to unmap_vmas.
tlb_gather_mmu and tlb_finish_mmu then fall outside the page_table_lock,
but we made them preempt_disable and preempt_enable earlier; and a long
source audit of all the architectures has shown no problem with removing
page_table_lock from them. free_pgtables doesn't need page_table_lock
for itself, nor for what it calls; tlb->mm->nr_ptes is usually protected
by page_table_lock, but partly by non-exclusive mmap_sem - here it's
decremented with exclusive mmap_sem, or mm_users 0. update_hiwater_rss
and vm_unacct_memory don't need page_table_lock either.
Signed-off-by: Hugh Dickins <hugh@veritas.com>
---
mm/memory.c | 12 ++++++++++--
mm/mmap.c | 23 ++++++-----------------
2 files changed, 16 insertions(+), 19 deletions(-)
--- mm15/mm/memory.c 2005-10-11 23:56:56.000000000 +0100
+++ mm16/mm/memory.c 2005-10-11 23:57:45.000000000 +0100
@@ -260,6 +260,12 @@ void free_pgtables(struct mmu_gather **t
struct vm_area_struct *next = vma->vm_next;
unsigned long addr = vma->vm_start;
+ /*
+ * Hide vma from rmap and vmtruncate before freeing pgtables
+ */
+ anon_vma_unlink(vma);
+ unlink_file_vma(vma);
+
if (is_hugepage_only_range(vma->vm_mm, addr, HPAGE_SIZE)) {
hugetlb_free_pgd_range(tlb, addr, vma->vm_end,
floor, next? next->vm_start: ceiling);
@@ -272,6 +278,8 @@ void free_pgtables(struct mmu_gather **t
HPAGE_SIZE)) {
vma = next;
next = vma->vm_next;
+ anon_vma_unlink(vma);
+ unlink_file_vma(vma);
}
free_pgd_range(tlb, addr, vma->vm_end,
floor, next? next->vm_start: ceiling);
@@ -798,12 +806,12 @@ unsigned long zap_page_range(struct vm_a
}
lru_add_drain();
- spin_lock(&mm->page_table_lock);
tlb = tlb_gather_mmu(mm, 0);
update_hiwater_rss(mm);
+ spin_lock(&mm->page_table_lock);
end = unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted, details);
- tlb_finish_mmu(tlb, address, end);
spin_unlock(&mm->page_table_lock);
+ tlb_finish_mmu(tlb, address, end);
return end;
}
--- mm15/mm/mmap.c 2005-10-11 23:55:38.000000000 +0100
+++ mm16/mm/mmap.c 2005-10-11 23:57:46.000000000 +0100
@@ -199,14 +199,6 @@ static struct vm_area_struct *remove_vma
{
struct vm_area_struct *next = vma->vm_next;
- /*
- * Hide vma from rmap and vmtruncate before freeing page tables:
- * to be moved into free_pgtables once page_table_lock is lifted
- * from it, but until then lock ordering forbids that move.
- */
- anon_vma_unlink(vma);
- unlink_file_vma(vma);
-
might_sleep();
if (vma->vm_ops && vma->vm_ops->close)
vma->vm_ops->close(vma);
@@ -1675,15 +1667,15 @@ static void unmap_region(struct mm_struc
unsigned long nr_accounted = 0;
lru_add_drain();
- spin_lock(&mm->page_table_lock);
tlb = tlb_gather_mmu(mm, 0);
update_hiwater_rss(mm);
+ spin_lock(&mm->page_table_lock);
unmap_vmas(&tlb, mm, vma, start, end, &nr_accounted, NULL);
+ spin_unlock(&mm->page_table_lock);
vm_unacct_memory(nr_accounted);
free_pgtables(&tlb, vma, prev? prev->vm_end: FIRST_USER_ADDRESS,
next? next->vm_start: 0);
tlb_finish_mmu(tlb, start, end);
- spin_unlock(&mm->page_table_lock);
}
/*
@@ -1958,23 +1950,20 @@ void exit_mmap(struct mm_struct *mm)
unsigned long end;
lru_add_drain();
-
- spin_lock(&mm->page_table_lock);
-
flush_cache_mm(mm);
tlb = tlb_gather_mmu(mm, 1);
/* Don't update_hiwater_rss(mm) here, do_exit already did */
/* Use -1 here to ensure all VMAs in the mm are unmapped */
+ spin_lock(&mm->page_table_lock);
end = unmap_vmas(&tlb, mm, vma, 0, -1, &nr_accounted, NULL);
+ spin_unlock(&mm->page_table_lock);
vm_unacct_memory(nr_accounted);
free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0);
tlb_finish_mmu(tlb, 0, end);
- spin_unlock(&mm->page_table_lock);
-
/*
- * Walk the list again, actually closing and freeing it
- * without holding any MM locks.
+ * Walk the list again, actually closing and freeing it,
+ * with preemption enabled, without holding any MM locks.
*/
while (vma)
vma = remove_vma(vma);
next prev parent reply other threads:[~2005-10-13 1:18 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-10-13 0:44 [PATCH 00/21] mm: page fault scalability nearer Hugh Dickins
2005-10-13 0:45 ` [PATCH 01/21] mm: copy_one_pte inc rss Hugh Dickins
2005-10-13 0:46 ` [PATCH 02/21] mm: zap_pte_range dec rss Hugh Dickins
2005-10-13 0:47 ` [PATCH 03/21] mm: do_swap_page race major Hugh Dickins
2005-10-13 0:47 ` [PATCH 04/21] mm: do_mremap current mm Hugh Dickins
2005-10-13 0:48 ` [PATCH 05/21] mm: zap_pte out of line Hugh Dickins
2005-10-13 0:50 ` [PATCH 06/21] mm: update_hiwaters just in time Hugh Dickins
2005-10-13 1:17 ` Christoph Lameter
2005-10-13 19:18 ` Jay Lan
2005-10-13 0:52 ` [PATCH 07/21] mm: mm_struct hiwaters moved Hugh Dickins
2005-10-13 0:53 ` [PATCH 08/21] mm: ia64 use expand_upwards Hugh Dickins
2005-10-13 0:55 ` [PATCH 09/21] mm: init_mm without ptlock Hugh Dickins
2005-10-13 0:55 ` [PATCH 10/21] mm: ptd_alloc inline and out Hugh Dickins
2005-10-13 0:56 ` [PATCH 11/21] mm: ptd_alloc take ptlock Hugh Dickins
2005-10-13 0:59 ` [PATCH 12/21] mm: arches skip ptlock Hugh Dickins
2005-10-13 1:13 ` [PATCH 13/21] mm: page fault handler locking Hugh Dickins
2005-10-13 1:14 ` [PATCH 14/21] mm: pte_offset_map_lock loops Hugh Dickins
2005-10-13 1:16 ` [PATCH 15/21] mm: flush_tlb_range outside ptlock Hugh Dickins
2005-10-13 1:17 ` Hugh Dickins [this message]
2005-10-13 1:18 ` [PATCH 17/21] mm: unmap_vmas with inner ptlock Hugh Dickins
2005-10-13 1:20 ` [PATCH 18/21] mm: xip_unmap ZERO_PAGE fix Hugh Dickins
2005-10-13 12:39 ` Carsten Otte
2005-10-13 1:21 ` [PATCH 19/21] mm: rmap with inner ptlock Hugh Dickins
2005-10-13 1:22 ` [PATCH 20/21] mm: kill check_user_page_readable Hugh Dickins
2005-10-13 1:23 ` [PATCH 21/21] mm: follow_page with inner ptlock Hugh Dickins
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.61.0510130216450.4343@goblin.wat.veritas.com \
--to=hugh@veritas.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®