]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/md/kcopyd.c
[PATCH] Remove __devinit and __cpuinit from notifier_call definitions
[linux-2.6-omap-h63xx.git] / drivers / md / kcopyd.c
index 9dcb2c8a38537cab675f765e9e17a13999fd8546..72480a48d88b7c883635ce46a41a00079ee6e1a3 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/workqueue.h>
+#include <linux/mutex.h>
 
 #include "kcopyd.h"
 
@@ -44,6 +45,9 @@ struct kcopyd_client {
        struct page_list *pages;
        unsigned int nr_pages;
        unsigned int nr_free_pages;
+
+       wait_queue_head_t destroyq;
+       atomic_t nr_jobs;
 };
 
 static struct page_list *alloc_pl(void)
@@ -292,10 +296,15 @@ static int run_complete_job(struct kcopyd_job *job)
        int read_err = job->read_err;
        unsigned int write_err = job->write_err;
        kcopyd_notify_fn fn = job->fn;
+       struct kcopyd_client *kc = job->kc;
 
-       kcopyd_put_pages(job->kc, job->pages);
+       kcopyd_put_pages(kc, job->pages);
        mempool_free(job, _job_pool);
        fn(read_err, write_err, context);
+
+       if (atomic_dec_and_test(&kc->nr_jobs))
+               wake_up(&kc->destroyq);
+
        return 0;
 }
 
@@ -430,6 +439,7 @@ static void do_work(void *ignored)
  */
 static void dispatch_job(struct kcopyd_job *job)
 {
+       atomic_inc(&job->kc->nr_jobs);
        push(&_pages_jobs, job);
        wake();
 }
@@ -572,21 +582,21 @@ int kcopyd_cancel(struct kcopyd_job *job, int block)
 /*-----------------------------------------------------------------
  * Unit setup
  *---------------------------------------------------------------*/
-static DECLARE_MUTEX(_client_lock);
+static DEFINE_MUTEX(_client_lock);
 static LIST_HEAD(_clients);
 
 static void client_add(struct kcopyd_client *kc)
 {
-       down(&_client_lock);
+       mutex_lock(&_client_lock);
        list_add(&kc->list, &_clients);
-       up(&_client_lock);
+       mutex_unlock(&_client_lock);
 }
 
 static void client_del(struct kcopyd_client *kc)
 {
-       down(&_client_lock);
+       mutex_lock(&_client_lock);
        list_del(&kc->list);
-       up(&_client_lock);
+       mutex_unlock(&_client_lock);
 }
 
 static DEFINE_MUTEX(kcopyd_init_lock);
@@ -669,6 +679,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
                return r;
        }
 
+       init_waitqueue_head(&kc->destroyq);
+       atomic_set(&kc->nr_jobs, 0);
+
        client_add(kc);
        *result = kc;
        return 0;
@@ -676,6 +689,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
 
 void kcopyd_client_destroy(struct kcopyd_client *kc)
 {
+       /* Wait for completion of all jobs submitted by this client. */
+       wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
+
        dm_io_put(kc->nr_pages);
        client_free_pages(kc);
        client_del(kc);