Merge tag 'v5.8-rc1' into regulator-5.8
[linux-2.6-microblaze.git] / kernel / kthread.c
index b84fc7e..8e3d2d7 100644 (file)
@@ -1,13 +1,17 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Kernel thread helper functions.
  *   Copyright (C) 2004 IBM Corporation, Rusty Russell.
+ *   Copyright (C) 2009 Red Hat, Inc.
  *
  * Creation is done via kthreadd, so that we get a clean environment
  * even if we're invoked from userspace (think modprobe, hotplug cpu,
  * etc.).
  */
 #include <uapi/linux/sched/types.h>
+#include <linux/mm.h>
+#include <linux/mmu_context.h>
 #include <linux/sched.h>
+#include <linux/sched/mm.h>
 #include <linux/sched/task.h>
 #include <linux/kthread.h>
 #include <linux/completion.h>
@@ -25,6 +29,7 @@
 #include <linux/numa.h>
 #include <trace/events/sched.h>
 
+
 static DEFINE_SPINLOCK(kthread_create_lock);
 static LIST_HEAD(kthread_create_list);
 struct task_struct *kthreadd_task;
@@ -48,6 +53,7 @@ struct kthread {
        unsigned int cpu;
        int (*threadfn)(void *);
        void *data;
+       mm_segment_t oldfs;
        struct completion parked;
        struct completion exited;
 #ifdef CONFIG_BLK_CGROUP
@@ -1220,6 +1226,61 @@ void kthread_destroy_worker(struct kthread_worker *worker)
 }
 EXPORT_SYMBOL(kthread_destroy_worker);
 
+/**
+ * kthread_use_mm - make the calling kthread operate on an address space
+ * @mm: address space to operate on
+ */
+void kthread_use_mm(struct mm_struct *mm)
+{
+       struct mm_struct *active_mm;
+       struct task_struct *tsk = current;
+
+       WARN_ON_ONCE(!(tsk->flags & PF_KTHREAD));
+       WARN_ON_ONCE(tsk->mm);
+
+       task_lock(tsk);
+       active_mm = tsk->active_mm;
+       if (active_mm != mm) {
+               mmgrab(mm);
+               tsk->active_mm = mm;
+       }
+       tsk->mm = mm;
+       switch_mm(active_mm, mm, tsk);
+       task_unlock(tsk);
+#ifdef finish_arch_post_lock_switch
+       finish_arch_post_lock_switch();
+#endif
+
+       if (active_mm != mm)
+               mmdrop(active_mm);
+
+       to_kthread(tsk)->oldfs = get_fs();
+       set_fs(USER_DS);
+}
+EXPORT_SYMBOL_GPL(kthread_use_mm);
+
+/**
+ * kthread_unuse_mm - reverse the effect of kthread_use_mm()
+ * @mm: address space to operate on
+ */
+void kthread_unuse_mm(struct mm_struct *mm)
+{
+       struct task_struct *tsk = current;
+
+       WARN_ON_ONCE(!(tsk->flags & PF_KTHREAD));
+       WARN_ON_ONCE(!tsk->mm);
+
+       set_fs(to_kthread(tsk)->oldfs);
+
+       task_lock(tsk);
+       sync_mm_rss(mm);
+       tsk->mm = NULL;
+       /* active_mm is still 'mm' */
+       enter_lazy_tlb(mm, tsk);
+       task_unlock(tsk);
+}
+EXPORT_SYMBOL_GPL(kthread_unuse_mm);
+
 #ifdef CONFIG_BLK_CGROUP
 /**
  * kthread_associate_blkcg - associate blkcg to current kthread