perf/core: fix MAX_ORDER usage in rb_alloc_aux_page()
[linux-2.6-block.git] / kernel / kthread.c
index f97fd01a29325f6d7f2e6d04ad5f87cb9d3577f3..470708c205e8982030966e41c5f3d4d8c4a9113b 100644 (file)
@@ -1382,6 +1382,10 @@ EXPORT_SYMBOL_GPL(kthread_flush_worker);
  * Flush and destroy @worker.  The simple flush is enough because the kthread
  * worker API is used only in trivial scenarios.  There are no multi-step state
  * machines needed.
+ *
+ * Note that this function is not responsible for handling delayed work, so
+ * caller should be responsible for queuing or canceling all delayed work items
+ * before invoke this function.
  */
 void kthread_destroy_worker(struct kthread_worker *worker)
 {
@@ -1393,6 +1397,7 @@ void kthread_destroy_worker(struct kthread_worker *worker)
 
        kthread_flush_worker(worker);
        kthread_stop(task);
+       WARN_ON(!list_empty(&worker->delayed_work_list));
        WARN_ON(!list_empty(&worker->work_list));
        kfree(worker);
 }
@@ -1410,14 +1415,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);
@@ -1434,12 +1443,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);
 
@@ -1467,10 +1473,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);