Set the ti->split_io field for the origin to the smallest chunk-size of its snapshots. This is done each time the origin is resumed, since new snapshots (with smaller chunk-sizes) could have been added. [Kevin Corry] --- diff/drivers/md/dm-snapshot.c 2003-11-26 10:19:22.000000000 +0000 +++ source/drivers/md/dm-snapshot.c 2003-11-26 10:19:27.000000000 +0000 @@ -1139,6 +1139,33 @@ return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; } +#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r)) + +/* + * Set the target "split_io" field to the minimum of all the snapshots' + * chunk sizes. + */ +static void origin_resume(struct dm_target *ti) +{ + struct dm_dev *dev = (struct dm_dev *) ti->private; + struct dm_snapshot *snap; + struct origin *o; + struct list_head *sl; + chunk_t chunk_size = 0; + + down_read(&_origins_lock); + o = __lookup_origin(dev->bdev); + if (o) { + list_for_each(sl, &o->snapshots) { + snap = list_entry(sl, struct dm_snapshot, list); + chunk_size = min_not_zero(chunk_size, snap->chunk_size); + } + } + up_read(&_origins_lock); + + ti->split_io = chunk_size; +} + static int origin_status(struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) { @@ -1165,6 +1192,7 @@ ctr: origin_ctr, dtr: origin_dtr, map: origin_map, + resume: origin_resume, status: origin_status, };