===================================================================
@@ -645,6 +645,13 @@ static void persistent_commit(struct exc
de.new_chunk = e->new_chunk;
write_exception(ps, ps->current_committed++, &de);
+ for (i = 0; i < ps->callback_count; i++) {
+ cb = ps->callbacks + i;
+ pe = cb->context;
+ BUG_ON(pe->e.hash_list.next == LIST_POISON1);
+ BUG_ON(pe->e.hash_list.prev == LIST_POISON2);
+ BUG_ON(pe == callback_context);
+ }
/*
* Add the callback to the back of the array. This code
* is the only place where the callback array is
===================================================================
@@ -979,6 +979,10 @@ static void start_copy(struct dm_snap_pe
struct dm_io_region src, dest;
struct block_device *bdev = s->origin->bdev;
sector_t dev_size;
+ BUG_ON(!pe->started);
+ BUG_ON(pe->started == 2);
+ BUG_ON(pe->started != 1);
+ pe->started = 2;
dev_size = get_dev_size(bdev);
===================================================================
@@ -60,6 +60,7 @@ struct dm_kcopyd_client {
struct list_head complete_jobs;
struct list_head io_jobs;
struct list_head pages_jobs;
+ struct list_head all_jobs;
};
static void wake(struct dm_kcopyd_client *kc)
@@ -209,6 +210,8 @@ struct kcopyd_job {
dm_kcopyd_notify_fn fn;
void *context;
+ struct list_head list_all;
+
/*
* These fields are only used if the job has been split
* into more manageable parts.
@@ -280,6 +283,9 @@ static void push_head(struct list_head *
spin_unlock_irqrestore(&kc->job_lock, flags);
}
+static void segment_complete(int read_err, unsigned long write_err,
+ void *context);
+
/*
* These three functions process 1 item from the corresponding
* job list.
@@ -291,6 +297,8 @@ static void push_head(struct list_head *
*/
static int run_complete_job(struct kcopyd_job *job)
{
+ struct kcopyd_job *jobb;
+ unsigned long flags;
void *context = job->context;
int read_err = job->read_err;
unsigned long write_err = job->write_err;
@@ -299,6 +307,18 @@ static int run_complete_job(struct kcopy
if (job->pages)
kcopyd_put_pages(kc, job->pages);
+
+ if (fn != segment_complete) {
+ spin_lock_irqsave(&kc->job_lock, flags);
+ list_del(&job->list_all);
+ spin_unlock_irqrestore(&kc->job_lock, flags);
+
+ spin_lock_irqsave(&kc->job_lock, flags);
+ list_for_each_entry(jobb, &kc->all_jobs, list_all)
+ BUG_ON(jobb->fn == fn && jobb->context == context);
+ spin_unlock_irqrestore(&kc->job_lock, flags);
+ }
+
mempool_free(job, kc->job_pool);
fn(read_err, write_err, context);
@@ -535,7 +555,8 @@ int dm_kcopyd_copy(struct dm_kcopyd_clie
unsigned int num_dests, struct dm_io_region *dests,
unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
{
- struct kcopyd_job *job;
+ struct kcopyd_job *job, *jobb;
+ unsigned long fflags;
/*
* Allocate a new job.
@@ -563,6 +584,15 @@ int dm_kcopyd_copy(struct dm_kcopyd_clie
job->fn = fn;
job->context = context;
+ spin_lock_irqsave(&kc->job_lock, fflags);
+ list_for_each_entry(jobb, &kc->all_jobs, list_all)
+ BUG_ON(jobb->fn == fn && jobb->context == context);
+ spin_unlock_irqrestore(&kc->job_lock, fflags);
+
+ spin_lock_irqsave(&kc->job_lock, fflags);
+ list_add_tail(&job->list_all, &kc->all_jobs);
+ spin_unlock_irqrestore(&kc->job_lock, fflags);
+
if (job->source.count < SUB_JOB_SIZE)
dispatch_job(job);
@@ -603,6 +633,7 @@ int dm_kcopyd_client_create(unsigned int
spin_lock_init(&kc->lock);
spin_lock_init(&kc->job_lock);
+ INIT_LIST_HEAD(&kc->all_jobs);
INIT_LIST_HEAD(&kc->complete_jobs);
INIT_LIST_HEAD(&kc->io_jobs);
INIT_LIST_HEAD(&kc->pages_jobs);
@@ -652,6 +683,7 @@ void dm_kcopyd_client_destroy(struct dm_
/* Wait for completion of all jobs submitted by this client. */
wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
+ BUG_ON(!list_empty(&kc->all_jobs));
BUG_ON(!list_empty(&kc->complete_jobs));
BUG_ON(!list_empty(&kc->io_jobs));
BUG_ON(!list_empty(&kc->pages_jobs));