From: Milan Broz Add an asynchronous destruction option to kcopyd_client_destroy(). Return code indicates whether destruction was delayed. Signed-off-by: Milan Broz --- drivers/md/dm-raid1.c | 2 +- drivers/md/dm-snap.c | 9 +++++---- drivers/md/kcopyd.c | 8 +++++++- drivers/md/kcopyd.h | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) Index: linux-2.6.21/drivers/md/dm-raid1.c =================================================================== --- linux-2.6.21.orig/drivers/md/dm-raid1.c 2007-05-02 19:48:20.000000000 +0100 +++ linux-2.6.21/drivers/md/dm-raid1.c 2007-05-03 17:21:06.000000000 +0100 @@ -1167,7 +1167,7 @@ static void mirror_dtr(struct dm_target struct mirror_set *ms = (struct mirror_set *) ti->private; flush_workqueue(ms->kmirrord_wq); - kcopyd_client_destroy(ms->kcopyd_client); + kcopyd_client_destroy(ms->kcopyd_client, 0); destroy_workqueue(ms->kmirrord_wq); free_context(ms, ti, ms->nr_mirrors); } Index: linux-2.6.21/drivers/md/dm-snap.c =================================================================== --- linux-2.6.21.orig/drivers/md/dm-snap.c 2007-05-01 17:41:13.000000000 +0100 +++ linux-2.6.21/drivers/md/dm-snap.c 2007-05-03 17:21:06.000000000 +0100 @@ -544,7 +544,7 @@ static int snapshot_ctr(struct dm_target return 0; bad6: - kcopyd_client_destroy(s->kcopyd_client); + kcopyd_client_destroy(s->kcopyd_client, 0); bad5: s->store.destroy(&s->store); @@ -566,7 +566,7 @@ static int snapshot_ctr(struct dm_target static void __free_exceptions(struct dm_snapshot *s) { - kcopyd_client_destroy(s->kcopyd_client); + kcopyd_client_destroy(s->kcopyd_client, 0); s->kcopyd_client = NULL; exit_exception_table(&s->pending, pending_cache); @@ -700,8 +700,9 @@ static void pending_complete(struct pend struct bio *snapshot_bios = NULL; int error = 0; - if (!success) { - /* Read/write error - snapshot is unusable */ + if (!success || !s->valid) { + /* Read/write error or deferred kcopyd + * on invalidated snapshot - snapshot is unusable */ down_write(&s->lock); __invalidate_snapshot(s, -EIO); error = 1; Index: linux-2.6.21/drivers/md/kcopyd.c =================================================================== --- linux-2.6.21.orig/drivers/md/kcopyd.c 2007-05-01 18:01:32.000000000 +0100 +++ linux-2.6.21/drivers/md/kcopyd.c 2007-05-03 17:21:06.000000000 +0100 @@ -694,8 +694,12 @@ int kcopyd_client_create(unsigned int nr return 0; } -void kcopyd_client_destroy(struct kcopyd_client *kc) +int kcopyd_client_destroy(struct kcopyd_client *kc, unsigned async) { + /* Return immediately if there is still work in progress. */ + if (async && atomic_read(&kc->nr_jobs)) + return 1; + /* Wait for completion of all jobs submitted by this client. */ wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs)); @@ -704,6 +708,8 @@ void kcopyd_client_destroy(struct kcopyd client_del(kc); kfree(kc); kcopyd_exit(); + + return 0; } EXPORT_SYMBOL(kcopyd_client_create); Index: linux-2.6.21/drivers/md/kcopyd.h =================================================================== --- linux-2.6.21.orig/drivers/md/kcopyd.h 2007-05-01 17:41:13.000000000 +0100 +++ linux-2.6.21/drivers/md/kcopyd.h 2007-05-03 17:21:06.000000000 +0100 @@ -23,7 +23,7 @@ */ struct kcopyd_client; int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result); -void kcopyd_client_destroy(struct kcopyd_client *kc); +int kcopyd_client_destroy(struct kcopyd_client *kc, unsigned async); /* * Submit a copy job to kcopyd. This is built on top of the