Introduce an end_io method to the target types. --- diff/drivers/md/dm.c 2003-01-10 10:08:09.000000000 +0000 +++ source/drivers/md/dm.c 2003-01-10 11:43:50.000000000 +0000 @@ -28,6 +28,8 @@ struct dm_io { struct mapped_device *md; + struct dm_target *ti; + int rw; void (*end_io) (struct buffer_head * bh, int uptodate); void *context; }; @@ -313,7 +315,19 @@ */ static void dec_pending(struct buffer_head *bh, int uptodate) { + int r; struct dm_io *io = bh->b_private; + dm_endio_fn endio = io->ti->type->end_io; + + if (endio) { + r = endio(io->ti, bh, io->rw, uptodate ? 0 : -EIO); + if (r < 0) + uptodate = 0; + + else if (r > 0) + /* the target wants another shot at the io */ + return; + } if (atomic_dec_and_test(&io->md->pending)) /* nudge anyone waiting on suspend queue */ @@ -346,6 +360,8 @@ /* hook the end io request fn */ atomic_inc(&md->pending); io->md = md; + io->ti = ti; + io->rw = rw; io->end_io = bh->b_end_io; io->context = bh->b_private; bh->b_end_io = dec_pending; --- diff/include/linux/device-mapper.h 2002-11-29 09:45:17.000000000 +0000 +++ source/include/linux/device-mapper.h 2003-01-10 11:36:08.000000000 +0000 @@ -34,6 +34,16 @@ * > 0: simple remap complete */ typedef int (*dm_map_fn) (struct dm_target *ti, struct buffer_head *bh, int rw); + +/* + * Returns: + * < 0 : error (currently ignored) + * 0 : ended successfully + * 1 : for some reason the io has still not completed (eg, + * multipath target might want to requeue a failed io). + */ +typedef int (*dm_endio_fn) (struct dm_target *ti, + struct buffer_head *bh, int rw, int error); typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, char *result, int maxlen); @@ -57,6 +67,7 @@ dm_ctr_fn ctr; dm_dtr_fn dtr; dm_map_fn map; + dm_endio_fn end_io; dm_status_fn status; };