Merge pushback and deferred lists into one list --- use deferred list for both deferred and pushed-back bios. This will be needed for proper support of barrier bios, it is impossible to support ordering correctly with two lists because the requests on both lists will be mixed up. Signed-off-by: Mikulas Patocka --- drivers/md/dm.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) Index: linux-2.6.29-rc1-devel/drivers/md/dm.c =================================================================== --- linux-2.6.29-rc1-devel.orig/drivers/md/dm.c 2009-01-19 02:17:24.000000000 +0100 +++ linux-2.6.29-rc1-devel/drivers/md/dm.c 2009-01-19 02:17:27.000000000 +0100 @@ -111,7 +111,6 @@ struct dm_wq_req { struct mapped_device { struct rw_semaphore io_lock; struct mutex suspend_lock; - spinlock_t pushback_lock; rwlock_t map_lock; atomic_t holders; atomic_t open_count; @@ -130,7 +129,7 @@ struct mapped_device { atomic_t pending; wait_queue_head_t wait; struct bio_list deferred; - struct bio_list pushback; + spinlock_t deferred_lock; /* * Processing queue (flush/barriers) @@ -453,7 +452,9 @@ static int queue_io(struct mapped_device return 1; } + spin_lock_irq(&md->deferred_lock); bio_list_add(&md->deferred, bio); + spin_unlock_irq(&md->deferred_lock); up_write(&md->io_lock); return 0; /* deferred successfully */ @@ -534,16 +535,14 @@ static void dec_pending(struct dm_io *io if (io->error == DM_ENDIO_REQUEUE) { /* * Target requested pushing back the I/O. - * This must be handled before the sleeper on - * suspend queue merges the pushback list. */ - spin_lock_irqsave(&io->md->pushback_lock, flags); + spin_lock_irqsave(&io->md->deferred_lock, flags); if (__noflush_suspending(io->md)) - bio_list_add(&io->md->pushback, io->bio); + bio_list_add(&io->md->deferred, io->bio); else /* noflush suspend was interrupted. */ io->error = -EIO; - spin_unlock_irqrestore(&io->md->pushback_lock, flags); + spin_unlock_irqrestore(&io->md->deferred_lock, flags); } end_io_acct(io); @@ -1100,7 +1099,7 @@ static struct mapped_device *alloc_dev(i init_rwsem(&md->io_lock); mutex_init(&md->suspend_lock); - spin_lock_init(&md->pushback_lock); + spin_lock_init(&md->deferred_lock); rwlock_init(&md->map_lock); atomic_set(&md->holders, 1); atomic_set(&md->open_count, 0); @@ -1411,25 +1410,20 @@ static void __flush_deferred_io(struct m { struct bio *c; - while ((c = bio_list_pop(&md->deferred))) { +next_bio: + spin_lock_irq(&md->deferred_lock); + c = bio_list_pop(&md->deferred); + spin_unlock_irq(&md->deferred_lock); + + if (c) { if (__split_bio(md, c)) bio_io_error(c); + goto next_bio; } clear_bit(DMF_BLOCK_IO, &md->flags); } -static void __merge_pushback_list(struct mapped_device *md) -{ - unsigned long flags; - - spin_lock_irqsave(&md->pushback_lock, flags); - clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); - bio_list_merge_head(&md->deferred, &md->pushback); - bio_list_init(&md->pushback); - spin_unlock_irqrestore(&md->pushback_lock, flags); -} - static void dm_wq_work(struct work_struct *work) { struct dm_wq_req *req = container_of(work, struct dm_wq_req, work); @@ -1590,7 +1584,7 @@ int dm_suspend(struct mapped_device *md, remove_wait_queue(&md->wait, &wait); if (noflush) - __merge_pushback_list(md); + clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); up_write(&md->io_lock); /* were we interrupted ? */