From: Milan Broz Release memory if snapshot is invalidated. All I/O operations on the full (invalidated) snapshot will cause -EIO so no memory is needed anymore. Snapshot is marked invalid and in workqueue is scheduled its deallocation. Signed-off-by: Milan Broz --- --- drivers/md/dm-snap.c | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) Index: linux-2.6.22/drivers/md/dm-snap.c =================================================================== --- linux-2.6.22.orig/drivers/md/dm-snap.c 2007-05-14 17:17:29.000000000 +0200 +++ linux-2.6.22/drivers/md/dm-snap.c 2007-05-14 18:51:47.000000000 +0200 @@ -563,7 +563,7 @@ static int snapshot_ctr(struct dm_target bad1: return r; } - +/* static void __free_exceptions(struct dm_snapshot *s) { kcopyd_client_destroy(s->kcopyd_client); @@ -574,18 +574,31 @@ static void __free_exceptions(struct dm_ s->store.destroy(&s->store); } +*/ +static void __schedule_drop_snapshot(struct dm_snapshot *s) +{ + /* invalidated -> already scheduled */ + if (!s->valid) + return; + + s->valid = 0; + + queue_work(ksnapd, &s->queued_bios_work); +} static void snapshot_dtr(struct dm_target *ti) { struct dm_snapshot *s = (struct dm_snapshot *) ti->private; - flush_workqueue(ksnapd); - /* Prevent further origin writes from using this snapshot. */ /* After this returns there can be no new kcopyd jobs. */ unregister_snapshot(s); - __free_exceptions(s); + down_write(&s->lock); + __schedule_drop_snapshot(s); + up_write(&s->lock); + + flush_workqueue(ksnapd); dm_put_device(ti, s->origin); dm_put_device(ti, s->cow); @@ -612,6 +625,7 @@ static void flush_queued_bios(struct wor { struct dm_snapshot *s = container_of(work, struct dm_snapshot, queued_bios_work); +/* struct bio *queued_bios; unsigned long flags; @@ -620,6 +634,23 @@ static void flush_queued_bios(struct wor spin_unlock_irqrestore(&s->pe_lock, flags); flush_bios(queued_bios); +*/ + BUG_ON(!s->kcopyd_client); + BUG_ON(s->valid); + + kcopyd_client_destroy(s->kcopyd_client); + s->kcopyd_client = NULL; + +// down_write(&s->lock); + if (s->store.drop_snapshot) + s->store.drop_snapshot(&s->store); + + exit_exception_table(&s->pending, pending_cache); + exit_exception_table(&s->complete, exception_cache); + + s->store.destroy(&s->store); + dm_table_event(s->table); +// up_write(&s->lock); } /* @@ -647,12 +678,7 @@ static void __invalidate_snapshot(struct else if (err == -ENOMEM) DMERR("Invalidating snapshot: Unable to allocate exception."); - if (s->store.drop_snapshot) - s->store.drop_snapshot(&s->store); - - s->valid = 0; - - dm_table_event(s->table); + __schedule_drop_snapshot(s); } static void get_pending_exception(struct pending_exception *pe)