summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2009-06-22 10:12:18 +0100
committerAlasdair G Kergon <agk@redhat.com>2009-06-22 10:12:18 +0100
commit2761e95fe40ca0d01864310fa4d488d7c5e34e18 (patch)
treea49245e8ebb022605c5d1ce04948cf4a7f9a5c3b /drivers
parent531fe96364f30879753d46c1f52ab839e12d2e5d (diff)
dm: process requeue in dm_wq_work
If barrier request was returned with DM_ENDIO_REQUEUE, requeue it in dm_wq_work instead of dec_pending. This allows us to correctly handle a situation when some targets are asking for a requeue and other targets signal an error. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/dm.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index e34d694ddd0..910bce85f44 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -536,9 +536,11 @@ static void dec_pending(struct dm_io *io, int error)
* Target requested pushing back the I/O.
*/
spin_lock_irqsave(&md->deferred_lock, flags);
- if (__noflush_suspending(md))
- bio_list_add_head(&md->deferred, io->bio);
- else
+ if (__noflush_suspending(md)) {
+ if (!bio_barrier(io->bio))
+ bio_list_add_head(&md->deferred,
+ io->bio);
+ } else
/* noflush suspend was interrupted. */
io->error = -EIO;
spin_unlock_irqrestore(&md->deferred_lock, flags);
@@ -1458,6 +1460,11 @@ static void process_barrier(struct mapped_device *md, struct bio *bio)
if (md->barrier_error != DM_ENDIO_REQUEUE)
bio_endio(bio, md->barrier_error);
+ else {
+ spin_lock_irq(&md->deferred_lock);
+ bio_list_add_head(&md->deferred, bio);
+ spin_unlock_irq(&md->deferred_lock);
+ }
}
/*