ea45716
If there are too many pending per work I/O, too many
ea45716
high priority work thread can be generated so that
ea45716
system performance can be effected.
ea45716
ea45716
This patch limits the max pending per work I/O as 16,
ea45716
and will fackback to single queue mode when the max
ea45716
number is reached.
ea45716
ea45716
This patch fixes Fedora 22 live booting performance
ea45716
regression when it is booted from squashfs over dm
ea45716
based on loop, and looks the following reasons are
ea45716
related with the problem:
ea45716
ea45716
- not like other filesyststems(such as ext4), squashfs
ea45716
is a bit special, and I observed that increasing I/O jobs
ea45716
to access file in squashfs only improve I/O performance a
ea45716
little, but it can make big difference for ext4
ea45716
ea45716
- nested loop: both squashfs.img and ext3fs.img are mounted
ea45716
as loop block, and ext3fs.img is inside the squashfs
ea45716
ea45716
- during booting, lots of tasks may run concurrently
ea45716
ea45716
Fixes: b5dd2f6047ca108001328aac0e8588edd15f1778
ea45716
Cc: stable@vger.kernel.org (v4.0)
ea45716
Reported-by: Justin M. Forbes <jforbes@fedoraproject.org>
ea45716
Tested-by: Justin M. Forbes <jforbes@fedoraproject.org>
ea45716
Signed-off-by: Ming Lei <ming.lei@canonical.com>
ea45716
---
ea45716
 drivers/block/loop.c | 19 +++++++++++++++++--
ea45716
 drivers/block/loop.h |  2 ++
ea45716
 2 files changed, 19 insertions(+), 2 deletions(-)
ea45716
ea45716
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
ea45716
index ae3fcb4..5a728c6 100644
ea45716
--- a/drivers/block/loop.c
ea45716
+++ b/drivers/block/loop.c
ea45716
@@ -1425,13 +1425,24 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
ea45716
 		const struct blk_mq_queue_data *bd)
ea45716
 {
ea45716
 	struct loop_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
ea45716
+	struct loop_device *lo = cmd->rq->q->queuedata;
ea45716
+	bool single_queue = !!(cmd->rq->cmd_flags & REQ_WRITE);
ea45716
+
ea45716
+	/*
ea45716
+	 * Fallback to single queue mode if the pending per work
ea45716
+	 * I/O number reaches 16, otherwise too many high priority
ea45716
+	 * worker thread may effect system performance as reported
ea45716
+	 * in fedora live booting from squashfs over loop.
ea45716
+	 */
ea45716
+	if (atomic_read(&lo->pending_per_work_io) >= 16)
ea45716
+		single_queue = true;
ea45716
 
ea45716
 	blk_mq_start_request(bd->rq);
ea45716
 
ea45716
-	if (cmd->rq->cmd_flags & REQ_WRITE) {
ea45716
-		struct loop_device *lo = cmd->rq->q->queuedata;
ea45716
+	if (single_queue) {
ea45716
 		bool need_sched = true;
ea45716
 
ea45716
+		cmd->per_work_io = false;
ea45716
 		spin_lock_irq(&lo->lo_lock);
ea45716
 		if (lo->write_started)
ea45716
 			need_sched = false;
ea45716
@@ -1443,6 +1454,8 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
ea45716
 		if (need_sched)
ea45716
 			queue_work(loop_wq, &lo->write_work);
ea45716
 	} else {
ea45716
+		atomic_inc(&lo->pending_per_work_io);
ea45716
+		cmd->per_work_io = true;
ea45716
 		queue_work(loop_wq, &cmd->read_work);
ea45716
 	}
ea45716
 
ea45716
@@ -1467,6 +1480,8 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
ea45716
 	if (ret)
ea45716
 		cmd->rq->errors = -EIO;
ea45716
 	blk_mq_complete_request(cmd->rq);
ea45716
+	if (cmd->per_work_io)
ea45716
+		atomic_dec(&lo->pending_per_work_io);
ea45716
 }
ea45716
 
ea45716
 static void loop_queue_write_work(struct work_struct *work)
ea45716
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
ea45716
index 301c27f..eb855f5 100644
ea45716
--- a/drivers/block/loop.h
ea45716
+++ b/drivers/block/loop.h
ea45716
@@ -57,6 +57,7 @@ struct loop_device {
ea45716
 	struct list_head	write_cmd_head;
ea45716
 	struct work_struct	write_work;
ea45716
 	bool			write_started;
ea45716
+	atomic_t		pending_per_work_io;
ea45716
 	int			lo_state;
ea45716
 	struct mutex		lo_ctl_mutex;
ea45716
 
ea45716
@@ -68,6 +69,7 @@ struct loop_device {
ea45716
 struct loop_cmd {
ea45716
 	struct work_struct read_work;
ea45716
 	struct request *rq;
ea45716
+	bool per_work_io;
ea45716
 	struct list_head list;
ea45716
 };
ea45716
 
ea45716
-- 
ea45716
1.9.1