From: Jens Axboe <axboe@suse.de>

At SUSE I reproduced a problem with dm and ide disks on a 4-way where ide
request_fn would discover the queue plugged all of a sudden, and then give
up on doing io.  The problem is due to the fact that dm now sets
QUEUE_FLAG_PLUGGED without holding the target queue lock.  I think the best
fix is simply not to set the PLUGGED bit outside of the queue lock, and
just let __generic_unplug_device() always call down into the request_fn()
even if the queue wasn't plugged.  This should be a very rare occurence.


---

 25-akpm/drivers/block/ll_rw_blk.c |    7 +++++--
 25-akpm/drivers/md/dm-table.c     |    4 +---
 2 files changed, 6 insertions(+), 5 deletions(-)

diff -puN drivers/block/ll_rw_blk.c~per-backing_dev-unplugging-dm-fix drivers/block/ll_rw_blk.c
--- 25/drivers/block/ll_rw_blk.c~per-backing_dev-unplugging-dm-fix	2004-03-16 13:17:49.754333688 -0800
+++ 25-akpm/drivers/block/ll_rw_blk.c	2004-03-16 13:17:49.760332776 -0800
@@ -1134,8 +1134,11 @@ static inline void __generic_unplug_devi
 	if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
 		return;
 
-	if (!blk_remove_plug(q))
-		return;
+	/*
+	 * always call down, since we can race now with setting the plugged
+	 * bit outside of the queue lock
+	 */
+	(void) blk_remove_plug(q);
 
 	/*
 	 * was plugged, fire request_fn if queue has stuff to do
diff -puN drivers/md/dm-table.c~per-backing_dev-unplugging-dm-fix drivers/md/dm-table.c
--- 25/drivers/md/dm-table.c~per-backing_dev-unplugging-dm-fix	2004-03-16 13:17:49.755333536 -0800
+++ 25-akpm/drivers/md/dm-table.c	2004-03-16 13:17:49.761332624 -0800
@@ -893,10 +893,8 @@ void dm_table_unplug_all(struct dm_table
 		struct dm_dev *dd = list_entry(d, struct dm_dev, list);
 		request_queue_t *q = bdev_get_queue(dd->bdev);
 
-		if (q->unplug_fn) {
-			set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags);
+		if (q->unplug_fn)
 			q->unplug_fn(q);
-		}
 	}
 }
 

_