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.19/drivers/md/dm-raid1.c =================================================================== --- linux-2.6.19.orig/drivers/md/dm-raid1.c 2006-12-06 20:49:40.000000000 +0000 +++ linux-2.6.19/drivers/md/dm-raid1.c 2006-12-06 20:49:41.000000000 +0000 @@ -1170,7 +1170,7 @@ static void mirror_dtr(struct dm_target struct mirror_set *ms = (struct mirror_set *) ti->private; del_mirror_set(ms); - kcopyd_client_destroy(ms->kcopyd_client); + kcopyd_client_destroy(ms->kcopyd_client, 0); free_context(ms, ti, ms->nr_mirrors); } Index: linux-2.6.19/drivers/md/dm-snap.c =================================================================== --- linux-2.6.19.orig/drivers/md/dm-snap.c 2006-12-06 20:49:33.000000000 +0000 +++ linux-2.6.19/drivers/md/dm-snap.c 2006-12-06 20:49:41.000000000 +0000 @@ -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); @@ -699,8 +699,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.19/drivers/md/kcopyd.c =================================================================== --- linux-2.6.19.orig/drivers/md/kcopyd.c 2006-12-06 20:49:39.000000000 +0000 +++ linux-2.6.19/drivers/md/kcopyd.c 2006-12-06 20:49:41.000000000 +0000 @@ -692,8 +692,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)); @@ -702,6 +706,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.19/drivers/md/kcopyd.h =================================================================== --- linux-2.6.19.orig/drivers/md/kcopyd.h 2006-12-06 20:48:28.000000000 +0000 +++ linux-2.6.19/drivers/md/kcopyd.h 2006-12-06 20:49:41.000000000 +0000 @@ -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