From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from psmtp.com (na3sys010amx200.postini.com [74.125.245.200]) by kanga.kvack.org (Postfix) with SMTP id 761846B004D for ; Sun, 29 Jan 2012 10:24:14 -0500 (EST) Received: by wgbdt12 with SMTP id dt12so3012095wgb.26 for ; Sun, 29 Jan 2012 07:24:12 -0800 (PST) From: sagig@mellanox.com Subject: [PATCH RFC] mm: convert rcu_read_lock() to srcu_read_lock(), thus allowing to sleep in callbacks Date: Sun, 29 Jan 2012 17:23:55 +0200 Message-Id: <4f25649b.8253b40a.3800.319d@mx.google.com> In-Reply-To: References: Sender: owner-linux-mm@kvack.org List-ID: To: aarcange@redhat.com Cc: gleb@redhat.com, oren@mellanox.com, ogerlitz@mellanox.com, sagig@mellanox.com, linux-mm@kvack.org, sagi grimberg Callbacks: invalidate_page, invalidate_range_start/end, change_pte Now that anon_vma lock and i_mmap_mutex are both sleepable mutex, it is possible to schedule inside invalidation cllabacks This is essential for a scheduling HW sync in RDMA drivers which apply on demand paging methods Signed-off-by: sagi grimberg --- mm/mmu_notifier.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 55 insertions(+), 8 deletions(-) diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 9a611d3..70dadd5 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -123,10 +123,16 @@ int __mmu_notifier_test_young(struct mm_struct *mm, void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address, pte_t pte) { + int idx = -1; + struct srcu_struct srcu; struct mmu_notifier *mn; struct hlist_node *n; - rcu_read_lock(); + if (init_srcu_struct(&srcu)) + rcu_read_lock(); + else + idx = srcu_read_lock(&srcu); + hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->change_pte) mn->ops->change_pte(mn, mm, address, pte); @@ -137,49 +143,90 @@ void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address, else if (mn->ops->invalidate_page) mn->ops->invalidate_page(mn, mm, address); } - rcu_read_unlock(); + + if (idx < 0) + rcu_read_unlock(); + else + srcu_read_unlock(&srcu, idx); + + cleanup_srcu_struct(&srcu); } void __mmu_notifier_invalidate_page(struct mm_struct *mm, unsigned long address) { + int idx = -1; + struct srcu_struct srcu; struct mmu_notifier *mn; struct hlist_node *n; - rcu_read_lock(); + if (init_srcu_struct(&srcu)) + rcu_read_lock(); + else + idx = srcu_read_lock(&srcu); + hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->invalidate_page) mn->ops->invalidate_page(mn, mm, address); } - rcu_read_unlock(); + + if (idx < 0) + rcu_read_unlock(); + else + srcu_read_unlock(&srcu, idx); + + cleanup_srcu_struct(&srcu); } void __mmu_notifier_invalidate_range_start(struct mm_struct *mm, unsigned long start, unsigned long end) { + int idx = -1; + struct srcu_struct srcu; struct mmu_notifier *mn; struct hlist_node *n; - rcu_read_lock(); + if (init_srcu_struct(&srcu)) + rcu_read_lock(); + else + idx = srcu_read_lock(&srcu); + hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->invalidate_range_start) mn->ops->invalidate_range_start(mn, mm, start, end); } - rcu_read_unlock(); + + if (idx < 0) + rcu_read_unlock(); + else + srcu_read_unlock(&srcu, idx); + + cleanup_srcu_struct(&srcu); } void __mmu_notifier_invalidate_range_end(struct mm_struct *mm, unsigned long start, unsigned long end) { + int idx = -1; + struct srcu_struct srcu; struct mmu_notifier *mn; struct hlist_node *n; - rcu_read_lock(); + if (init_srcu_struct(&srcu)) + rcu_read_lock(); + else + idx = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->invalidate_range_end) mn->ops->invalidate_range_end(mn, mm, start, end); } - rcu_read_unlock(); + + if (idx < 0) + rcu_read_unlock(); + else + srcu_read_unlock(&srcu, idx); + + cleanup_srcu_struct(&srcu); } static int do_mmu_notifier_register(struct mmu_notifier *mn, -- 1.7.6.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: email@kvack.org