From: Milan Broz When processing the second part of a split bio resubmitted to the same device we should skip the bookkeeping and avoid requesting io_lock recursively. Also fix a possible deadlock if the wait loop gets interrupted. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm.c | 25 +++++++++++++++++++++---- 1 files changed, 21 insertions(+), 4 deletions(-) Index: current-quilt/drivers/md/dm.c =================================================================== --- current-quilt.orig/drivers/md/dm.c 2007-07-25 21:04:54.000000000 +0100 +++ current-quilt/drivers/md/dm.c 2007-07-25 21:04:55.000000000 +0100 @@ -564,6 +564,12 @@ static int clone2_endio(struct bio *bio, return error; } +static int is_clone2(struct mapped_device *md, struct bio *bio) +{ + return (bio->bi_end_io == clone2_endio && + bio->bi_private == md); +} + static sector_t max_io_len(struct mapped_device *md, sector_t sector, struct dm_target *ti) { @@ -817,6 +823,15 @@ static int dm_request(request_queue_t *q return 0; } + /* + * If this is the second part of a split bio, + * always map it immediately. + */ + if (is_clone2(md, bio)) { + r = __split_bio(md, bio); + goto out_req; + } + down_read(&md->io_lock); disk_stat_inc(dm_disk(md), ios[rw]); @@ -1265,10 +1280,11 @@ EXPORT_SYMBOL_GPL(dm_put); /* * Process the deferred bios */ -static void __flush_deferred_io(struct mapped_device *md, struct bio *c) +static void flush_deferred_io(struct mapped_device *md, struct bio *c) { struct bio *n; + down_read(&md->io_lock); while (c) { n = c->bi_next; c->bi_next = NULL; @@ -1276,6 +1292,7 @@ static void __flush_deferred_io(struct m bio_io_error(c, c->bi_size); c = n; } + up_read(&md->io_lock); } /* @@ -1436,8 +1453,8 @@ int dm_suspend(struct mapped_device *md, if (atomic_read(&md->pending)) { clear_bit(DMF_BLOCK_IO, &md->flags); def = bio_list_get(&md->deferred); - __flush_deferred_io(md, def); up_write(&md->io_lock); + flush_deferred_io(md, def); unlock_fs(md); goto out; /* pushback list is already flushed, so skip flush */ } @@ -1464,8 +1481,8 @@ flush_and_out: spin_unlock_irqrestore(&md->pushback_lock, flags); def = bio_list_get(&md->deferred); - __flush_deferred_io(md, def); up_write(&md->io_lock); + flush_deferred_io(md, def); } out: @@ -1503,8 +1520,8 @@ int dm_resume(struct mapped_device *md) clear_bit(DMF_BLOCK_IO, &md->flags); def = bio_list_get(&md->deferred); - __flush_deferred_io(md, def); up_write(&md->io_lock); + flush_deferred_io(md, def); unlock_fs(md);