Add the new UTRACE_ATTACH_ATOMIC flag for utrace_attach_task().
If it is set, UTRACE_ATTACH_CREATE uses GFP_ATOMIC for memory
allocations and thus it can be used in atomic context.

Suggested-by: Mark Wielaard <m...@redhat.com>
Signed-off-by: Oleg Nesterov <o...@redhat.com>
---
 include/linux/utrace.h |    1 +
 kernel/utrace.c        |   12 ++++++++----
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/include/linux/utrace.h b/include/linux/utrace.h
index f37373b..46959af 100644
--- a/include/linux/utrace.h
+++ b/include/linux/utrace.h
@@ -317,6 +317,7 @@ static inline enum utrace_syscall_action 
utrace_syscall_action(u32 action)
 #define UTRACE_ATTACH_MATCH_MASK       0x000f
 #define UTRACE_ATTACH_CREATE           0x0010 /* Attach a new engine.  */
 #define UTRACE_ATTACH_EXCLUSIVE                0x0020 /* Refuse if existing 
match.  */
+#define UTRACE_ATTACH_ATOMIC           0x0040 /* For _CREATE, don't sleep  */
 
 /**
  * struct utrace_engine - per-engine structure
diff --git a/kernel/utrace.c b/kernel/utrace.c
index c817a46..a169e1b 100644
--- a/kernel/utrace.c
+++ b/kernel/utrace.c
@@ -113,9 +113,9 @@ void task_utrace_unlock(struct task_struct *task)
  *
  * This returns false only in case of a memory allocation failure.
  */
-static bool utrace_task_alloc(struct task_struct *task)
+static bool utrace_task_alloc(struct task_struct *task, gfp_t gfp_flags)
 {
-       struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL);
+       struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, gfp_flags);
        if (unlikely(!utrace))
                return false;
        spin_lock_init(&utrace->lock);
@@ -295,6 +295,7 @@ struct utrace_engine *utrace_attach_task(
 {
        struct utrace *utrace = task_utrace_struct(target);
        struct utrace_engine *engine;
+       gfp_t gfp_flags;
        int ret;
 
        if (!(flags & UTRACE_ATTACH_CREATE)) {
@@ -317,13 +318,16 @@ struct utrace_engine *utrace_attach_task(
                 */
                return ERR_PTR(-EPERM);
 
+       gfp_flags = (flags & UTRACE_ATTACH_ATOMIC)
+                               ? GFP_ATOMIC : GFP_KERNEL;
+
        if (!utrace) {
-               if (unlikely(!utrace_task_alloc(target)))
+               if (unlikely(!utrace_task_alloc(target, gfp_flags)))
                        return ERR_PTR(-ENOMEM);
                utrace = task_utrace_struct(target);
        }
 
-       engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL);
+       engine = kmem_cache_alloc(utrace_engine_cachep, gfp_flags);
        if (unlikely(!engine))
                return ERR_PTR(-ENOMEM);
 
-- 
1.5.5.1


Reply via email to