Change __find_pending_exception() so that it takes an old chunk index and "prepare" flag rather than a bio structure. Rationale is that the merged target will use the pending exception table for tracking writes which have been mapped to the COW device. In such cases, we won't want a new exception to be prepared in the exception store. Also, the merged target will want to trigger an exception in all associated snapshots without a corresponding bio structure. We'll need to do this when initiating a copy from the COW device to the origin device. Index: linux-2.6.16.i686/drivers/md/dm-snap.c =================================================================== --- linux-2.6.16.i686.orig/drivers/md/dm-snap.c 2006-05-05 13:59:48.000000000 +0100 +++ linux-2.6.16.i686/drivers/md/dm-snap.c 2006-05-05 14:20:50.000000000 +0100 @@ -819,11 +819,10 @@ static void start_copy(struct pending_ex * this. */ static struct pending_exception * -__find_pending_exception(struct dm_snapshot *s, struct bio *bio) +__find_pending_exception(struct dm_snapshot *s, chunk_t chunk, int prepare) { struct exception *e; struct pending_exception *pe; - chunk_t chunk = sector_to_chunk(s, bio->bi_sector); unsigned long flags; spin_lock_irqsave(&s->pe_lock, flags); @@ -872,7 +871,7 @@ __find_pending_exception(struct dm_snaps insert_exception(&s->pending, &pe->e); ref_and_out: - if (bio_rw(bio) != WRITE) + if (!prepare) ref_pending_exception(pe); else if (!pe->started) { if (s->store.prepare_exception(&s->store, &pe->e)) { @@ -930,7 +929,7 @@ static int snapshot_map(struct dm_target goto out_unlock; } - pe = __find_pending_exception(s, bio); + pe = __find_pending_exception(s, chunk, bio_rw(bio) == WRITE); if (!pe) { __invalidate_snapshot(s, pe, -ENOMEM); r = -EIO; @@ -1083,7 +1082,7 @@ static int __origin_write(struct list_he if (e) goto next_snapshot; - pe = __find_pending_exception(snap, bio); + pe = __find_pending_exception(snap, chunk, 1); if (!pe) { __invalidate_snapshot(snap, pe, ENOMEM); goto next_snapshot;