ceph: Use sendmsg(MSG_SPLICE_PAGES) rather than sendpage()
[platform/kernel/linux-rpi.git] / kernel / kthread.c
index 7e6751b..490792b 100644 (file)
@@ -38,6 +38,7 @@ struct task_struct *kthreadd_task;
 struct kthread_create_info
 {
        /* Information passed to kthread() from kthreadd. */
+       char *full_name;
        int (*threadfn)(void *data);
        void *data;
        int node;
@@ -343,10 +344,12 @@ static int kthread(void *_create)
        /* Release the structure when caller killed by a fatal signal. */
        done = xchg(&create->done, NULL);
        if (!done) {
+               kfree(create->full_name);
                kfree(create);
                kthread_exit(-EINTR);
        }
 
+       self->full_name = create->full_name;
        self->threadfn = threadfn;
        self->data = data;
 
@@ -396,11 +399,13 @@ static void create_kthread(struct kthread_create_info *create)
        current->pref_node_fork = create->node;
 #endif
        /* We want our own signal handler (we take no signals by default). */
-       pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
+       pid = kernel_thread(kthread, create, create->full_name,
+                           CLONE_FS | CLONE_FILES | SIGCHLD);
        if (pid < 0) {
                /* Release the structure when caller killed by a fatal signal. */
                struct completion *done = xchg(&create->done, NULL);
 
+               kfree(create->full_name);
                if (!done) {
                        kfree(create);
                        return;
@@ -427,6 +432,11 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
        create->data = data;
        create->node = node;
        create->done = &done;
+       create->full_name = kvasprintf(GFP_KERNEL, namefmt, args);
+       if (!create->full_name) {
+               task = ERR_PTR(-ENOMEM);
+               goto free_create;
+       }
 
        spin_lock(&kthread_create_lock);
        list_add_tail(&create->list, &kthread_create_list);
@@ -453,26 +463,7 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
                wait_for_completion(&done);
        }
        task = create->result;
-       if (!IS_ERR(task)) {
-               char name[TASK_COMM_LEN];
-               va_list aq;
-               int len;
-
-               /*
-                * task is already visible to other tasks, so updating
-                * COMM must be protected.
-                */
-               va_copy(aq, args);
-               len = vsnprintf(name, sizeof(name), namefmt, aq);
-               va_end(aq);
-               if (len >= TASK_COMM_LEN) {
-                       struct kthread *kthread = to_kthread(task);
-
-                       /* leave it truncated when out of memory. */
-                       kthread->full_name = kvasprintf(GFP_KERNEL, namefmt, args);
-               }
-               set_task_comm(task, name);
-       }
+free_create:
        kfree(create);
        return task;
 }
@@ -1415,14 +1406,18 @@ void kthread_use_mm(struct mm_struct *mm)
        WARN_ON_ONCE(!(tsk->flags & PF_KTHREAD));
        WARN_ON_ONCE(tsk->mm);
 
+       /*
+        * It is possible for mm to be the same as tsk->active_mm, but
+        * we must still mmgrab(mm) and mmdrop_lazy_tlb(active_mm),
+        * because these references are not equivalent.
+        */
+       mmgrab(mm);
+
        task_lock(tsk);
        /* Hold off tlb flush IPIs while switching mm's */
        local_irq_disable();
        active_mm = tsk->active_mm;
-       if (active_mm != mm) {
-               mmgrab(mm);
-               tsk->active_mm = mm;
-       }
+       tsk->active_mm = mm;
        tsk->mm = mm;
        membarrier_update_current_mm(mm);
        switch_mm_irqs_off(active_mm, mm, tsk);
@@ -1439,12 +1434,9 @@ void kthread_use_mm(struct mm_struct *mm)
         * memory barrier after storing to tsk->mm, before accessing
         * user-space memory. A full memory barrier for membarrier
         * {PRIVATE,GLOBAL}_EXPEDITED is implicitly provided by
-        * mmdrop(), or explicitly with smp_mb().
+        * mmdrop_lazy_tlb().
         */
-       if (active_mm != mm)
-               mmdrop(active_mm);
-       else
-               smp_mb();
+       mmdrop_lazy_tlb(active_mm);
 }
 EXPORT_SYMBOL_GPL(kthread_use_mm);
 
@@ -1472,10 +1464,13 @@ void kthread_unuse_mm(struct mm_struct *mm)
        local_irq_disable();
        tsk->mm = NULL;
        membarrier_update_current_mm(NULL);
+       mmgrab_lazy_tlb(mm);
        /* active_mm is still 'mm' */
        enter_lazy_tlb(mm, tsk);
        local_irq_enable();
        task_unlock(tsk);
+
+       mmdrop(mm);
 }
 EXPORT_SYMBOL_GPL(kthread_unuse_mm);