From: FUJITA Tomonori The current two exception store implementations (persistent and transient) always keep completed exceptions in memory. This patch enables exception store implementations to use the own function to look for a completed exception so that they can store exceptions at any place such as disk. Signed-off-by: FUJITA Tomonori --- drivers/md/dm-snap.c | 38 +++++++++++++++++++++++++------------- drivers/md/dm-snap.h | 6 ++++++ 2 files changed, 31 insertions(+), 13 deletions(-) Index: linux-2.6.28-rc3/drivers/md/dm-snap.c =================================================================== --- linux-2.6.28-rc3.orig/drivers/md/dm-snap.c 2008-11-06 17:30:26.000000000 +0000 +++ linux-2.6.28-rc3/drivers/md/dm-snap.c 2008-11-07 13:15:35.000000000 +0000 @@ -349,6 +349,15 @@ static struct dm_snap_exception *lookup_ return NULL; } +struct dm_snap_exception *lookup_complete_exception(struct dm_snapshot *s, + chunk_t chunk) +{ + if (s->store.lookup_completed_exception) + return s->store.lookup_completed_exception(&s->store, chunk); + else + return lookup_exception(&s->complete, chunk); +} + static struct dm_snap_exception *alloc_exception(void) { struct dm_snap_exception *e; @@ -856,7 +865,7 @@ static struct bio *put_pending_exception static void pending_complete(struct dm_snap_pending_exception *pe, int success) { - struct dm_snap_exception *e; + struct dm_snap_exception *e = NULL; struct dm_snapshot *s = pe->snap; struct bio *origin_bios = NULL; struct bio *snapshot_bios = NULL; @@ -870,18 +879,21 @@ static void pending_complete(struct dm_s goto out; } - e = alloc_exception(); - if (!e) { - down_write(&s->lock); - __invalidate_snapshot(s, -ENOMEM); - error = 1; - goto out; + if (!s->store.lookup_completed_exception) { + e = alloc_exception(); + if (!e) { + down_write(&s->lock); + __invalidate_snapshot(s, -ENOMEM); + error = 1; + goto out; + } + *e = pe->e; } - *e = pe->e; down_write(&s->lock); if (!s->valid) { - free_exception(e); + if (e) + free_exception(e); error = 1; goto out; } @@ -897,8 +909,8 @@ static void pending_complete(struct dm_s * Add a proper exception, and remove the * in-flight exception from the list. */ - insert_completed_exception(s, e); - + if (e) + insert_completed_exception(s, e); out: remove_exception(&pe->e); snapshot_bios = bio_list_get(&pe->snapshot_bios); @@ -1064,7 +1076,7 @@ static int snapshot_map(struct dm_target } /* If the block is already remapped - use that, else remap it */ - e = lookup_exception(&s->complete, chunk); + e = lookup_complete_exception(s, chunk); if (e) { remap_exception(s, e, bio, chunk); goto out_unlock; @@ -1206,7 +1218,7 @@ static int __origin_write(struct list_he * ref_count is initialised to 1 so pending_complete() * won't destroy the primary_pe while we're inside this loop. */ - e = lookup_exception(&snap->complete, chunk); + e = lookup_complete_exception(snap, chunk); if (e) goto next_snapshot; Index: linux-2.6.28-rc3/drivers/md/dm-snap.h =================================================================== --- linux-2.6.28-rc3.orig/drivers/md/dm-snap.h 2008-11-04 14:10:54.000000000 +0000 +++ linux-2.6.28-rc3/drivers/md/dm-snap.h 2008-11-07 13:15:35.000000000 +0000 @@ -126,6 +126,12 @@ struct exception_store { sector_t *numerator, sector_t *denominator); + /* + * look up if a chunk is in completed exception. + */ + struct dm_snap_exception *(*lookup_completed_exception) + (struct exception_store *store, chunk_t chunk); + struct dm_snapshot *snap; void *context; };