All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Hildenbrand <dahi@linux.vnet.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: dahi@linux.vnet.ibm.com, mingo@redhat.com, peterz@infradead.org,
	yang.shi@windriver.com, bigeasy@linutronix.de,
	benh@kernel.crashing.org, paulus@samba.org,
	akpm@linux-foundation.org, heiko.carstens@de.ibm.com,
	schwidefsky@de.ibm.com, borntraeger@de.ibm.com, mst@redhat.com,
	tglx@linutronix.de, David.Laight@ACULAB.COM, hughd@google.com,
	hocko@suse.cz, ralf@linux-mips.org, herbert@gondor.apana.org.au,
	linux@arm.linux.org.uk, airlied@linux.ie,
	daniel.vetter@intel.com, linux-mm@kvack.org,
	linux-arch@vger.kernel.org
Subject: [PATCH RFC 01/15] uaccess: count pagefault_disable() levels in pagefault_disabled
Date: Wed,  6 May 2015 19:50:25 +0200	[thread overview]
Message-ID: <1430934639-2131-2-git-send-email-dahi@linux.vnet.ibm.com> (raw)
In-Reply-To: <1430934639-2131-1-git-send-email-dahi@linux.vnet.ibm.com>

Until now, pagefault_disable()/pagefault_enabled() used the preempt
count to track whether in an environment with pagefaults disabled (can
be queried via in_atomic()).

This patch introduces a separate counter in task_struct to count the
level of pagefault_disable() calls. We'll keep manipulating the preempt
count to retain compatibility to existing pagefault handlers.

It is now possible to verify whether in a pagefault_disable() envionment
by calling pagefault_disabled(). In contrast to in_atomic() it will not
be influenced by preempt_enable()/preempt_disable().

This patch is based on a patch from Ingo Molnar.

Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 include/linux/sched.h   |  1 +
 include/linux/uaccess.h | 36 +++++++++++++++++++++++++++++-------
 kernel/fork.c           |  3 +++
 3 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index ede26ca..75778cb 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1724,6 +1724,7 @@ struct task_struct {
 #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
 	unsigned long	task_state_change;
 #endif
+	int pagefault_disabled;
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index ecd3319..23290cc 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -2,20 +2,36 @@
 #define __LINUX_UACCESS_H__
 
 #include <linux/preempt.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 
+static __always_inline void pagefault_disabled_inc(void)
+{
+	current->pagefault_disabled++;
+}
+
+static __always_inline void pagefault_disabled_dec(void)
+{
+	current->pagefault_disabled--;
+	WARN_ON(current->pagefault_disabled < 0);
+}
+
 /*
- * These routines enable/disable the pagefault handler in that
- * it will not take any locks and go straight to the fixup table.
+ * These routines enable/disable the pagefault handler. If disabled, it will
+ * not take any locks and go straight to the fixup table.
+ *
+ * We increase the preempt and the pagefault count, to be able to distinguish
+ * whether we run in simple atomic context or in a real pagefault_disable()
+ * context.
+ *
+ * For now, after pagefault_disabled() has been called, we run in atomic
+ * context. User access methods will not sleep.
  *
- * They have great resemblance to the preempt_disable/enable calls
- * and in fact they are identical; this is because currently there is
- * no other way to make the pagefault handlers do this. So we do
- * disable preemption but we don't necessarily care about that.
  */
 static inline void pagefault_disable(void)
 {
 	preempt_count_inc();
+	pagefault_disabled_inc();
 	/*
 	 * make sure to have issued the store before a pagefault
 	 * can hit.
@@ -25,18 +41,24 @@ static inline void pagefault_disable(void)
 
 static inline void pagefault_enable(void)
 {
-#ifndef CONFIG_PREEMPT
 	/*
 	 * make sure to issue those last loads/stores before enabling
 	 * the pagefault handler again.
 	 */
 	barrier();
+	pagefault_disabled_dec();
+#ifndef CONFIG_PREEMPT
 	preempt_count_dec();
 #else
 	preempt_enable();
 #endif
 }
 
+/*
+ * Is the pagefault handler disabled? If so, user access methods will not sleep.
+ */
+#define pagefault_disabled() (current->pagefault_disabled != 0)
+
 #ifndef ARCH_HAS_NOCACHE_UACCESS
 
 static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
diff --git a/kernel/fork.c b/kernel/fork.c
index 03c1eaa..c344d27 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1396,6 +1396,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	p->hardirq_context = 0;
 	p->softirq_context = 0;
 #endif
+
+	p->pagefault_disabled = 0;
+
 #ifdef CONFIG_LOCKDEP
 	p->lockdep_depth = 0; /* no locks held yet */
 	p->curr_chain_key = 0;
-- 
2.1.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/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

WARNING: multiple messages have this Message-ID (diff)
From: David Hildenbrand <dahi@linux.vnet.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: dahi@linux.vnet.ibm.com, mingo@redhat.com, peterz@infradead.org,
	yang.shi@windriver.com, bigeasy@linutronix.de,
	benh@kernel.crashing.org, paulus@samba.org,
	akpm@linux-foundation.org, heiko.carstens@de.ibm.com,
	schwidefsky@de.ibm.com, borntraeger@de.ibm.com, mst@redhat.com,
	tglx@linutronix.de, David.Laight@ACULAB.COM, hughd@google.com,
	hocko@suse.cz, ralf@linux-mips.org, herbert@gondor.apana.org.au,
	linux@arm.linux.org.uk, airlied@linux.ie,
	daniel.vetter@intel.com, linux-mm@kvack.org,
	linux-arch@vger.kernel.org
Subject: [PATCH RFC 01/15] uaccess: count pagefault_disable() levels in pagefault_disabled
Date: Wed,  6 May 2015 19:50:25 +0200	[thread overview]
Message-ID: <1430934639-2131-2-git-send-email-dahi@linux.vnet.ibm.com> (raw)
Message-ID: <20150506175025.NKklBI2GsztBxAYCqcOq0OxGx1CYqQaEN8M1bIj72D0@z> (raw)
In-Reply-To: <1430934639-2131-1-git-send-email-dahi@linux.vnet.ibm.com>

Until now, pagefault_disable()/pagefault_enabled() used the preempt
count to track whether in an environment with pagefaults disabled (can
be queried via in_atomic()).

This patch introduces a separate counter in task_struct to count the
level of pagefault_disable() calls. We'll keep manipulating the preempt
count to retain compatibility to existing pagefault handlers.

It is now possible to verify whether in a pagefault_disable() envionment
by calling pagefault_disabled(). In contrast to in_atomic() it will not
be influenced by preempt_enable()/preempt_disable().

This patch is based on a patch from Ingo Molnar.

Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 include/linux/sched.h   |  1 +
 include/linux/uaccess.h | 36 +++++++++++++++++++++++++++++-------
 kernel/fork.c           |  3 +++
 3 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index ede26ca..75778cb 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1724,6 +1724,7 @@ struct task_struct {
 #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
 	unsigned long	task_state_change;
 #endif
+	int pagefault_disabled;
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index ecd3319..23290cc 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -2,20 +2,36 @@
 #define __LINUX_UACCESS_H__
 
 #include <linux/preempt.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 
+static __always_inline void pagefault_disabled_inc(void)
+{
+	current->pagefault_disabled++;
+}
+
+static __always_inline void pagefault_disabled_dec(void)
+{
+	current->pagefault_disabled--;
+	WARN_ON(current->pagefault_disabled < 0);
+}
+
 /*
- * These routines enable/disable the pagefault handler in that
- * it will not take any locks and go straight to the fixup table.
+ * These routines enable/disable the pagefault handler. If disabled, it will
+ * not take any locks and go straight to the fixup table.
+ *
+ * We increase the preempt and the pagefault count, to be able to distinguish
+ * whether we run in simple atomic context or in a real pagefault_disable()
+ * context.
+ *
+ * For now, after pagefault_disabled() has been called, we run in atomic
+ * context. User access methods will not sleep.
  *
- * They have great resemblance to the preempt_disable/enable calls
- * and in fact they are identical; this is because currently there is
- * no other way to make the pagefault handlers do this. So we do
- * disable preemption but we don't necessarily care about that.
  */
 static inline void pagefault_disable(void)
 {
 	preempt_count_inc();
+	pagefault_disabled_inc();
 	/*
 	 * make sure to have issued the store before a pagefault
 	 * can hit.
@@ -25,18 +41,24 @@ static inline void pagefault_disable(void)
 
 static inline void pagefault_enable(void)
 {
-#ifndef CONFIG_PREEMPT
 	/*
 	 * make sure to issue those last loads/stores before enabling
 	 * the pagefault handler again.
 	 */
 	barrier();
+	pagefault_disabled_dec();
+#ifndef CONFIG_PREEMPT
 	preempt_count_dec();
 #else
 	preempt_enable();
 #endif
 }
 
+/*
+ * Is the pagefault handler disabled? If so, user access methods will not sleep.
+ */
+#define pagefault_disabled() (current->pagefault_disabled != 0)
+
 #ifndef ARCH_HAS_NOCACHE_UACCESS
 
 static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
diff --git a/kernel/fork.c b/kernel/fork.c
index 03c1eaa..c344d27 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1396,6 +1396,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	p->hardirq_context = 0;
 	p->softirq_context = 0;
 #endif
+
+	p->pagefault_disabled = 0;
+
 #ifdef CONFIG_LOCKDEP
 	p->lockdep_depth = 0; /* no locks held yet */
 	p->curr_chain_key = 0;
-- 
2.1.4


  reply	other threads:[~2015-05-06 17:50 UTC|newest]

Thread overview: 79+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-06 17:50 [PATCH RFC 00/15] decouple pagefault_disable() from preempt_disable() David Hildenbrand
2015-05-06 17:50 ` David Hildenbrand
2015-05-06 17:50 ` David Hildenbrand [this message]
2015-05-06 17:50   ` [PATCH RFC 01/15] uaccess: count pagefault_disable() levels in pagefault_disabled David Hildenbrand
2015-05-07 10:22   ` Peter Zijlstra
2015-05-07 10:22     ` Peter Zijlstra
2015-05-07 10:50     ` David Hildenbrand
2015-05-07 10:50       ` David Hildenbrand
2015-05-07 10:50       ` David Hildenbrand
2015-05-07 11:12       ` Peter Zijlstra
2015-05-07 11:12         ` Peter Zijlstra
2015-05-07 11:23         ` David Hildenbrand
2015-05-07 11:23           ` David Hildenbrand
2015-05-07 11:25           ` Ingo Molnar
2015-05-07 11:25             ` Ingo Molnar
2015-05-07 11:30             ` David Hildenbrand
2015-05-07 11:30               ` David Hildenbrand
2015-05-07 11:42           ` Peter Zijlstra
2015-05-07 11:42             ` Peter Zijlstra
2015-05-07 11:40         ` David Hildenbrand
2015-05-07 11:40           ` David Hildenbrand
2015-05-07 11:48           ` Peter Zijlstra
2015-05-07 11:48             ` Peter Zijlstra
2015-05-07 11:51           ` Peter Zijlstra
2015-05-07 11:51             ` Peter Zijlstra
2015-05-07 12:14             ` David Hildenbrand
2015-05-07 12:14               ` David Hildenbrand
2015-05-07 12:27               ` Ingo Molnar
2015-05-07 12:27                 ` Ingo Molnar
2015-05-07 12:32               ` Peter Zijlstra
2015-05-07 12:32                 ` Peter Zijlstra
2015-05-07 15:45             ` [PATCH draft] mm: use pagefault_disable() to check for disabled pagefaults in the handler David Hildenbrand
2015-05-07 15:45               ` David Hildenbrand
2015-05-07 11:12       ` [PATCH RFC 01/15] uaccess: count pagefault_disable() levels in pagefault_disabled Ingo Molnar
2015-05-07 11:12         ` Ingo Molnar
2015-05-06 17:50 ` [PATCH RFC 02/15] mm, uaccess: trigger might_sleep() in might_fault() with disabled pagefaults David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 03/15] uaccess: clarify that uaccess may only sleep if pagefaults are enabled David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 04/15] mm: explicitly disable/enable preemption in kmap_atomic_* David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 05/15] mips: kmap_coherent relies on disabled preemption David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 06/15] mm: use pagefault_disabled() to check for disabled pagefaults David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 07/15] drm/i915: " David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 08/15] futex: UP futex_atomic_op_inuser() relies on disabled preemption David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 09/15] futex: UP futex_atomic_cmpxchg_inatomic() " David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 10/15] arm/futex: " David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 11/15] arm/futex: UP futex_atomic_op_inuser() " David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 12/15] futex: clarify that preemption doesn't have to be disabled David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 13/15] powerpc: enable_kernel_altivec() requires disabled preemption David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-07  0:21   ` Benjamin Herrenschmidt
2015-05-07  0:21     ` Benjamin Herrenschmidt
2015-05-06 17:50 ` [PATCH RFC 14/15] mips: properly lock access to the fpu David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 17:50 ` [PATCH RFC 15/15] uaccess: decouple preemption from the pagefault logic David Hildenbrand
2015-05-06 17:50   ` David Hildenbrand
2015-05-06 22:01 ` [PATCH RFC 00/15] decouple pagefault_disable() from preempt_disable() Andrew Morton
2015-05-06 22:01   ` Andrew Morton
2015-05-07  6:23   ` David Hildenbrand
2015-05-07  6:23     ` David Hildenbrand
2015-05-07  9:48   ` Ingo Molnar
2015-05-07  9:48     ` Ingo Molnar
2015-05-07 10:51     ` Christian Borntraeger
2015-05-07 10:51       ` Christian Borntraeger
2015-05-07 11:08       ` Ingo Molnar
2015-05-07 11:08         ` Ingo Molnar
2015-05-07 11:40         ` Peter Zijlstra
2015-05-07 11:40           ` Peter Zijlstra

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=1430934639-2131-2-git-send-email-dahi@linux.vnet.ibm.com \
    --to=dahi@linux.vnet.ibm.com \
    --cc=David.Laight@ACULAB.COM \
    --cc=airlied@linux.ie \
    --cc=akpm@linux-foundation.org \
    --cc=benh@kernel.crashing.org \
    --cc=bigeasy@linutronix.de \
    --cc=borntraeger@de.ibm.com \
    --cc=daniel.vetter@intel.com \
    --cc=heiko.carstens@de.ibm.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=hocko@suse.cz \
    --cc=hughd@google.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux@arm.linux.org.uk \
    --cc=mingo@redhat.com \
    --cc=mst@redhat.com \
    --cc=paulus@samba.org \
    --cc=peterz@infradead.org \
    --cc=ralf@linux-mips.org \
    --cc=schwidefsky@de.ibm.com \
    --cc=tglx@linutronix.de \
    --cc=yang.shi@windriver.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.