Re: Smart plugging of multiple devices connected to a single controller

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Elias Oltmanns <eo@xxxxxxxxxxxxxx> wrote:
> Hi Jens,
>
> in an effort to avoid calling the ->request_fn() from hard irq context
> in ide, a patch like the one attached below would seem convenient (not
> even compile tested yet).

Well, I should have actually attach the patch. Here it is then.

> However, before implementing this or, indeed, in case you should
> outright reject this patch, I'd like to ask for your opinion about a
> more general approach: Since ide, scsi and libata (once it has moved
> out of scsi) have very similar issues with devices that cannot process
> the request queue in parallel (typically because they are connected to
> the same controller), would it be appropriate to deal with that in the
> block layer directly? Currently, I'm mainly concerned with the problem
> that devices connected to the same controller are served without too
> much discrimination due to races in the (un)plug logic, which is
> currently being dealt with more or less cleverly in scsi / ide.
> Generally though, there might be other shared resources (like a tag
> map, etc.) that could be maintained in a in a block layer structure
> similar to struct Scsi_Host. All request queues belonging to such a
> group could be added to a circular link list rooted at the structure
> containing the shared resources, i.e. the unplug_timer and whatever
> you deem adequate to be moved there.
>
> What do you think about it?
>
> Regards,
>
> Elias

---
 block/blk-core.c       |   27 ++++++++++++++++++---------
 include/linux/blkdev.h |    1 +
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index c3df30c..fcdcb09 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -322,6 +322,15 @@ void blk_unplug(struct request_queue *q)
 }
 EXPORT_SYMBOL(blk_unplug);
 
+void blk_schedule_queue_run(struct request_queue *q)
+{
+	if (!elv_queue_empty(q)) {
+		queue_flag_set(QUEUE_FLAG_PLUGGED, q);
+		kblockd_schedule_work(q, &q->unplug_work);
+	}
+}
+EXPORT_SYMBOL_GPL(blk_schedule_queue_run);
+
 static void blk_invoke_request_fn(struct request_queue *q)
 {
 	if (unlikely(blk_queue_stopped(q)))
@@ -331,13 +340,14 @@ static void blk_invoke_request_fn(struct request_queue *q)
 	 * one level of recursion is ok and is much faster than kicking
 	 * the unplug handling
 	 */
-	if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
-		q->request_fn(q);
-		queue_flag_clear(QUEUE_FLAG_REENTER, q);
-	} else {
-		queue_flag_set(QUEUE_FLAG_PLUGGED, q);
-		kblockd_schedule_work(q, &q->unplug_work);
-	}
+	if (!test_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
+		if (!elv_queue_empty(q)) {
+			queue_flag_set(QUEUE_FLAG_REENTER, q);
+			q->request_fn(q);
+			queue_flag_clear(QUEUE_FLAG_REENTER, q);
+		}
+	} else
+		blk_schedule_queue_run(q);
 }
 
 /**
@@ -417,8 +427,7 @@ void __blk_run_queue(struct request_queue *q)
 	 * Only recurse once to avoid overrunning the stack, let the unplug
 	 * handling reinvoke the handler shortly if we already got there.
 	 */
-	if (!elv_queue_empty(q))
-		blk_invoke_request_fn(q);
+	blk_invoke_request_fn(q);
 }
 EXPORT_SYMBOL(__blk_run_queue);
 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index b4fe68f..516851e 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -753,6 +753,7 @@ extern void blk_sync_queue(struct request_queue *q);
 extern void __blk_stop_queue(struct request_queue *q);
 extern void __blk_run_queue(struct request_queue *);
 extern void blk_run_queue(struct request_queue *);
+extern void blk_schedule_queue_run(struct request_queue *q);
 extern void blk_start_queueing(struct request_queue *);
 extern int blk_rq_map_user(struct request_queue *, struct request *,
 			   struct rq_map_data *, void __user *, unsigned long,
--
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux