Similar to the previous patch, change the arguments to __origin_write() so that rather than requiring a bio structure, we take a origin device sector index and optional bio structure. Rationale is that the merged target will want to trigger an exception in all associated snapshots before merging the chunk from the COW to the origin and at this point we don't have a bio structure corresponding to that copy. 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 14:21:28.000000000 +0100 +++ linux-2.6.16.i686/drivers/md/dm-snap.c 2006-05-05 14:45:01.000000000 +0100 @@ -1043,7 +1043,8 @@ static int snapshot_status(struct dm_tar /*----------------------------------------------------------------- * Origin methods *---------------------------------------------------------------*/ -static int __origin_write(struct list_head *snapshots, struct bio *bio) +static int __origin_write(struct list_head *snapshots, sector_t sector, + struct bio *bio) { int r = 1; struct dm_snapshot *snap; @@ -1063,14 +1064,14 @@ static int __origin_write(struct list_he goto next_snapshot; /* Nothing to do if writing beyond end of snapshot */ - if (bio->bi_sector >= dm_table_get_size(snap->table)) + if (sector >= dm_table_get_size(snap->table)) goto next_snapshot; /* * Remember, different snapshots can have * different chunk sizes. */ - chunk = sector_to_chunk(snap, bio->bi_sector); + chunk = sector_to_chunk(snap, sector); /* * Check exception table to see if block @@ -1107,7 +1108,8 @@ static int __origin_write(struct list_he */ ref_pending_exception(primary_pe); - bio_list_add(&primary_pe->origin_bios, bio); + if (bio) + bio_list_add(&primary_pe->origin_bios, bio); r = 0; } @@ -1152,7 +1154,8 @@ static int __origin_write(struct list_he /* * Called on a write from the origin driver. */ -static int do_origin(struct dm_dev *origin, struct bio *bio) +static int do_origin(struct dm_dev *origin, sector_t sector, + struct bio *bio) { struct origin *o; int r = 1; @@ -1160,7 +1163,7 @@ static int do_origin(struct dm_dev *orig down_read(&_origins_lock); o = __lookup_origin(origin->bdev); if (o) - r = __origin_write(&o->snapshots, bio); + r = __origin_write(&o->snapshots, sector, bio); up_read(&_origins_lock); return r; @@ -1212,7 +1215,10 @@ static int origin_map(struct dm_target * return -EOPNOTSUPP; /* Only tell snapshots if this is a write */ - return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; + if (bio_rw(bio) != WRITE) + return 1; + + return do_origin(dev, bio->bi_sector, bio); } #define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))