With the current two exception store implementations (persistent and transient), snapshots are independent. Each snapshot has own cow disk and dm_snapshot struct. With shared exception store code, snapshots are not independent. They are stored in a single cow disk and has only one dm_snapshot struct. So the shared exception store code needs to identify snapshot in prepare_exception() and lookup_completed_exception(). Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx> --- drivers/md/dm-exception-store.c | 4 ++-- drivers/md/dm-snap.c | 22 ++++++++++++---------- drivers/md/dm-snap.h | 6 ++++-- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 8931364..60f33da 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -514,7 +514,7 @@ static int persistent_read_metadata(struct exception_store *store) } static int persistent_prepare(struct exception_store *store, - struct dm_snap_exception *e) + struct dm_snap_exception *e, u64 snapid) { struct pstore *ps = get_info(store); uint32_t stride; @@ -658,7 +658,7 @@ static int transient_read_metadata(struct exception_store *store) } static int transient_prepare(struct exception_store *store, - struct dm_snap_exception *e) + struct dm_snap_exception *e, u64 snapid) { struct transient_c *tc = (struct transient_c *) store->context; sector_t size = get_dev_size(store->snap->cow->bdev); diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index fa0e9f7..bea98b4 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -348,10 +348,12 @@ static struct dm_snap_exception *lookup_exception(struct exception_table *et, } struct dm_snap_exception *lookup_complete_exception(struct dm_snapshot *s, - chunk_t chunk) + chunk_t chunk, + u64 snapid) { if (s->store.lookup_completed_exception) - return s->store.lookup_completed_exception(&s->store, chunk); + return s->store.lookup_completed_exception(&s->store, chunk, + snapid); else return lookup_exception(&s->complete, chunk); } @@ -975,7 +977,7 @@ static void start_copy(struct dm_snap_pending_exception *pe) * this. */ static struct dm_snap_pending_exception * -__find_pending_exception(struct dm_snapshot *s, struct bio *bio) +__find_pending_exception(struct dm_snapshot *s, struct bio *bio, u64 snapid) { struct dm_snap_exception *e; struct dm_snap_pending_exception *pe; @@ -1018,7 +1020,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio) atomic_set(&pe->ref_count, 0); pe->started = 0; - if (s->store.prepare_exception(&s->store, &pe->e)) { + if (s->store.prepare_exception(&s->store, &pe->e, snapid)) { free_pending_exception(pe); return NULL; } @@ -1040,7 +1042,7 @@ static void remap_exception(struct dm_snapshot *s, struct dm_snap_exception *e, } static int do_snapshot_map(struct dm_snapshot *s, struct bio *bio, - union map_info *map_context) + union map_info *map_context, u64 snapid) { struct dm_snap_exception *e; int r = DM_MAPIO_REMAPPED; @@ -1064,7 +1066,7 @@ static int do_snapshot_map(struct dm_snapshot *s, struct bio *bio, } /* If the block is already remapped - use that, else remap it */ - e = lookup_complete_exception(s, chunk); + e = lookup_complete_exception(s, chunk, snapid); if (e) { remap_exception(s, e, bio, chunk); goto out_unlock; @@ -1076,7 +1078,7 @@ static int do_snapshot_map(struct dm_snapshot *s, struct bio *bio, * writeable. */ if (bio_rw(bio) == WRITE) { - pe = __find_pending_exception(s, bio); + pe = __find_pending_exception(s, bio, snapid); if (!pe) { __invalidate_snapshot(s, -ENOMEM); r = -EIO; @@ -1111,7 +1113,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, { struct dm_snapshot *s = ti->private; - return do_snapshot_map(s, bio, map_context); + return do_snapshot_map(s, bio, map_context, 0); } static int do_snapshot_end_io(struct dm_snapshot *s, struct bio *bio, @@ -1220,11 +1222,11 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) * ref_count is initialised to 1 so pending_complete() * won't destroy the primary_pe while we're inside this loop. */ - e = lookup_complete_exception(snap, chunk); + e = lookup_complete_exception(snap, chunk, ORIGIN_SNAPID); if (e) goto next_snapshot; - pe = __find_pending_exception(snap, bio); + pe = __find_pending_exception(snap, bio, ORIGIN_SNAPID); if (!pe) { __invalidate_snapshot(snap, -ENOMEM); goto next_snapshot; diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h index 4eefb90..dfbef9b 100644 --- a/drivers/md/dm-snap.h +++ b/drivers/md/dm-snap.h @@ -83,6 +83,8 @@ static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) # endif +#define ORIGIN_SNAPID ULLONG_MAX + /* * Abstraction to handle the meta/layout of exception stores (the * COW device). @@ -104,7 +106,7 @@ struct exception_store { * Find somewhere to store the next exception. */ int (*prepare_exception) (struct exception_store *store, - struct dm_snap_exception *e); + struct dm_snap_exception *e, u64 snapid); /* * Update the metadata with this exception. @@ -130,7 +132,7 @@ struct exception_store { * look up if a chunk is in completed exception. */ struct dm_snap_exception *(*lookup_completed_exception) - (struct exception_store *store, chunk_t chunk); + (struct exception_store *store, chunk_t chunk, u64 snapid); /* * let exception store code to handle the message hook in -- 1.5.5.GIT -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel