diff options
author | Andrew Dodd <atd7@cornell.edu> | 2013-02-16 18:41:04 -0500 |
---|---|---|
committer | Andrew Dodd <atd7@cornell.edu> | 2013-02-27 09:19:08 -0500 |
commit | b08797f2afdfc604c3143f8725d058aeef8ddcb2 (patch) | |
tree | c59e963bd6931d4e9f9526034ab402cc551f18ae /mm/mmu_notifier.c | |
parent | cbfae70f1dcaf3cc6e93061179dad80caa1597fe (diff) | |
parent | 54ea5b40f067cf098cac639973c6628c6944cfb2 (diff) | |
download | kernel_samsung_smdk4412-b08797f2afdfc604c3143f8725d058aeef8ddcb2.zip kernel_samsung_smdk4412-b08797f2afdfc604c3143f8725d058aeef8ddcb2.tar.gz kernel_samsung_smdk4412-b08797f2afdfc604c3143f8725d058aeef8ddcb2.tar.bz2 |
Merge remote-tracking branch 'kernelorg/linux-3.0.y' into 3_0_64
Conflicts:
arch/arm/Kconfig
arch/arm/include/asm/hwcap.h
arch/arm/kernel/smp.c
arch/arm/plat-samsung/adc.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_drv.h
drivers/mmc/core/sd.c
drivers/net/tun.c
drivers/net/usb/usbnet.c
drivers/regulator/max8997.c
drivers/usb/core/hub.c
drivers/usb/host/xhci.h
drivers/usb/serial/qcserial.c
fs/jbd2/transaction.c
include/linux/migrate.h
kernel/sys.c
kernel/time/timekeeping.c
lib/genalloc.c
mm/memory-failure.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/page_alloc.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
scripts/Kbuild.include
Change-Id: I91e2d85c07320c7ccfc04cf98a448e89bed6ade6
Diffstat (limited to 'mm/mmu_notifier.c')
-rw-r--r-- | mm/mmu_notifier.c | 45 |
1 files changed, 23 insertions, 22 deletions
diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 8d032de..71c7811 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -33,6 +33,24 @@ void __mmu_notifier_release(struct mm_struct *mm) { struct mmu_notifier *mn; + struct hlist_node *n; + + /* + * RCU here will block mmu_notifier_unregister until + * ->release returns. + */ + rcu_read_lock(); + hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) + /* + * if ->release runs before mmu_notifier_unregister it + * must be handled as it's the only way for the driver + * to flush all existing sptes and stop the driver + * from establishing any more sptes before all the + * pages in the mm are freed. + */ + if (mn->ops->release) + mn->ops->release(mn, mm); + rcu_read_unlock(); spin_lock(&mm->mmu_notifier_mm->lock); while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) { @@ -46,23 +64,6 @@ void __mmu_notifier_release(struct mm_struct *mm) * mmu_notifier_unregister to return. */ hlist_del_init_rcu(&mn->hlist); - /* - * RCU here will block mmu_notifier_unregister until - * ->release returns. - */ - rcu_read_lock(); - spin_unlock(&mm->mmu_notifier_mm->lock); - /* - * if ->release runs before mmu_notifier_unregister it - * must be handled as it's the only way for the driver - * to flush all existing sptes and stop the driver - * from establishing any more sptes before all the - * pages in the mm are freed. - */ - if (mn->ops->release) - mn->ops->release(mn, mm); - rcu_read_unlock(); - spin_lock(&mm->mmu_notifier_mm->lock); } spin_unlock(&mm->mmu_notifier_mm->lock); @@ -284,16 +285,13 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) { BUG_ON(atomic_read(&mm->mm_count) <= 0); - spin_lock(&mm->mmu_notifier_mm->lock); if (!hlist_unhashed(&mn->hlist)) { - hlist_del_rcu(&mn->hlist); - /* * RCU here will force exit_mmap to wait ->release to finish * before freeing the pages. */ rcu_read_lock(); - spin_unlock(&mm->mmu_notifier_mm->lock); + /* * exit_mmap will block in mmu_notifier_release to * guarantee ->release is called before freeing the @@ -302,8 +300,11 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) if (mn->ops->release) mn->ops->release(mn, mm); rcu_read_unlock(); - } else + + spin_lock(&mm->mmu_notifier_mm->lock); + hlist_del_rcu(&mn->hlist); spin_unlock(&mm->mmu_notifier_mm->lock); + } /* * Wait any running method to finish, of course including |