diff options
author | Haggai Eran <haggaie@mellanox.com> | 2012-10-08 19:33:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 03:22:58 -0400 |
commit | 6bdb913f0a70a4dfb7f066fb15e2d6f960701d00 (patch) | |
tree | 9a61960b27bf801794104b8bb8fccee1813f1b4b /kernel/events | |
parent | 2ec74c3ef2d8c58d71e0e00336fb6b891192155a (diff) |
mm: wrap calls to set_pte_at_notify with invalidate_range_start and invalidate_range_end
In order to allow sleeping during invalidate_page mmu notifier calls, we
need to avoid calling when holding the PT lock. In addition to its direct
calls, invalidate_page can also be called as a substitute for a change_pte
call, in case the notifier client hasn't implemented change_pte.
This patch drops the invalidate_page call from change_pte, and instead
wraps all calls to change_pte with invalidate_range_start and
invalidate_range_end calls.
Note that change_pte still cannot sleep after this patch, and that clients
implementing change_pte should not take action on it in case the number of
outstanding invalidate_range_start calls is larger than one, otherwise
they might miss a later invalidation.
Signed-off-by: Haggai Eran <haggaie@mellanox.com>
Cc: Andrea Arcangeli <andrea@qumranet.com>
Cc: Sagi Grimberg <sagig@mellanox.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Or Gerlitz <ogerlitz@mellanox.com>
Cc: Haggai Eran <haggaie@mellanox.com>
Cc: Shachar Raindel <raindel@mellanox.com>
Cc: Liran Liss <liranl@mellanox.com>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Avi Kivity <avi@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/events')
-rw-r--r-- | kernel/events/uprobes.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 1d9c0a985960..98256bc71ee1 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -141,10 +141,14 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, | |||
141 | spinlock_t *ptl; | 141 | spinlock_t *ptl; |
142 | pte_t *ptep; | 142 | pte_t *ptep; |
143 | int err; | 143 | int err; |
144 | /* For mmu_notifiers */ | ||
145 | const unsigned long mmun_start = addr; | ||
146 | const unsigned long mmun_end = addr + PAGE_SIZE; | ||
144 | 147 | ||
145 | /* For try_to_free_swap() and munlock_vma_page() below */ | 148 | /* For try_to_free_swap() and munlock_vma_page() below */ |
146 | lock_page(page); | 149 | lock_page(page); |
147 | 150 | ||
151 | mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); | ||
148 | err = -EAGAIN; | 152 | err = -EAGAIN; |
149 | ptep = page_check_address(page, mm, addr, &ptl, 0); | 153 | ptep = page_check_address(page, mm, addr, &ptl, 0); |
150 | if (!ptep) | 154 | if (!ptep) |
@@ -173,6 +177,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, | |||
173 | 177 | ||
174 | err = 0; | 178 | err = 0; |
175 | unlock: | 179 | unlock: |
180 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | ||
176 | unlock_page(page); | 181 | unlock_page(page); |
177 | return err; | 182 | return err; |
178 | } | 183 | } |