mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: shaohua.li@intel.com
To: linux-kernel@vger.kernel.org, linux-ide@vger.kernel.org
Cc: jaxboe@fusionio.com, htejun@gmail.com, hch@infradead.org,
	jgarzik@pobox.com, djwong@us.ibm.com, sshtylyov@mvista.com,
	Shaohua Li <shaohua.li@intel.com>
Subject: [patch v3 2/3] block: hold queue if flush is running for non-queueable flush drive
Date: Thu, 05 May 2011 09:59:34 +0800	[thread overview]
Message-ID: <20110505020417.817084678@sli10-conroe.sh.intel.com> (raw)
In-Reply-To: <20110505015932.306763905@sli10-conroe.sh.intel.com>

[-- Attachment #1: blk-hold-queue-for-nonqueueable-flush.patch --]
[-- Type: text/plain, Size: 4197 bytes --]

In some drives, flush requests are non-queueable. When flush request is running,
normal read/write requests can't run. If block layer dispatches such request,
driver can't handle it and requeue it.
Tejun suggested we can hold the queue when flush is running. This can avoid
unnecessary requeue.
Also this can improve performance. For example, we have request flush1, write1,
flush 2. flush1 is dispatched, then queue is hold, write1 isn't inserted to
queue. After flush1 is finished, flush2 will be dispatched. Since disk cache
is already clean, flush2 will be finished very soon, so looks like flush2 is
folded to flush1.
In my test, the queue holding completely solves a regression introduced by
commit 53d63e6b0dfb95882ec0219ba6bbd50cde423794:
    block: make the flush insertion use the tail of the dispatch list

    It's not a preempt type request, in fact we have to insert it
    behind requests that do specify INSERT_FRONT.
which causes about 20% regression running a sysbench fileio
workload.

Signed-off-by: Shaohua Li <shaohua.li@intel.com>
---
 block/blk-flush.c      |   16 +++++++++++-----
 block/blk.h            |   21 ++++++++++++++++++++-
 include/linux/blkdev.h |    1 +
 3 files changed, 32 insertions(+), 6 deletions(-)

Index: linux/block/blk-flush.c
===================================================================
--- linux.orig/block/blk-flush.c	2011-05-05 08:36:51.000000000 +0800
+++ linux/block/blk-flush.c	2011-05-05 09:28:37.000000000 +0800
@@ -212,13 +212,19 @@ static void flush_end_io(struct request
 	}
 
 	/*
-	 * Moving a request silently to empty queue_head may stall the
-	 * queue.  Kick the queue in those cases.  This function is called
-	 * from request completion path and calling directly into
-	 * request_fn may confuse the driver.  Always use kblockd.
+	 * Kick the queue to avoid stall for two cases:
+	 * 1. Moving a request silently to empty queue_head may stall the
+	 * queue.
+	 * 2. When flush request is running in non-queueable queue, the
+	 * queue is hold. Restart the queue after flush request is finished
+	 * to avoid stall.
+	 * This function is called from request completion path and calling
+	 * directly into request_fn may confuse the driver.  Always use
+	 * kblockd.
 	 */
-	if (queued)
+	if (queued || q->flush_queue_delayed)
 		blk_run_queue_async(q);
+	q->flush_queue_delayed = 0;
 }
 
 /**
Index: linux/include/linux/blkdev.h
===================================================================
--- linux.orig/include/linux/blkdev.h	2011-05-05 09:05:18.000000000 +0800
+++ linux/include/linux/blkdev.h	2011-05-05 09:06:08.000000000 +0800
@@ -365,6 +365,7 @@ struct request_queue
 	 */
 	unsigned int		flush_flags;
 	unsigned int		flush_not_queueable:1;
+	unsigned int		flush_queue_delayed:1;
 	unsigned int		flush_pending_idx:1;
 	unsigned int		flush_running_idx:1;
 	unsigned long		flush_pending_since;
Index: linux/block/blk.h
===================================================================
--- linux.orig/block/blk.h	2011-05-05 08:36:51.000000000 +0800
+++ linux/block/blk.h	2011-05-05 09:49:34.000000000 +0800
@@ -61,7 +61,26 @@ static inline struct request *__elv_next
 			rq = list_entry_rq(q->queue_head.next);
 			return rq;
 		}
-
+		/*
+		 * Flush request is running and flush request isn't queueable
+		 * in the drive, we can hold the queue till flush request is
+		 * finished. Even we don't do this, driver can't dispatch next
+		 * requests and will requeue them. And this can improve
+		 * throughput too. For example, we have request flush1, write1,
+		 * flush 2. flush1 is dispatched, then queue is hold, write1
+		 * isn't inserted to queue. After flush1 is finished, flush2
+		 * will be dispatched. Since disk cache is already clean,
+		 * flush2 will be finished very soon, so looks like flush2 is
+		 * folded to flush1.
+		 * Since the queue is hold, a flag is set to indicate the queue
+		 * should be restarted later. Please see flush_end_io() for
+		 * details.
+		 */
+		if (q->flush_pending_idx != q->flush_running_idx &&
+				!queue_flush_queueable(q)) {
+			q->flush_queue_delayed = 1;
+			return NULL;
+		}
 		if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
 			return NULL;
 	}


  parent reply	other threads:[~2011-05-05  2:04 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-05  1:59 [patch v3 0/3] block: optimize flush " shaohua.li
2011-05-05  1:59 ` [patch v3 1/3] block: add a non-queueable flush flag shaohua.li
2011-05-05  2:17   ` Jeff Garzik
2011-05-05  2:21     ` Shaohua Li
2011-05-05  7:53   ` Tejun Heo
2011-05-05  1:59 ` shaohua.li [this message]
2011-05-05  8:38   ` [patch v3 2/3] block: hold queue if flush is running for non-queueable flush drive Tejun Heo
2011-05-06  4:32     ` Shaohua Li
2011-05-06  6:53       ` Tejun Heo
2011-05-06 17:28         ` Jens Axboe
2011-05-09 13:03     ` Vivek Goyal
2011-05-09 13:50       ` Shaohua Li
2011-05-09 13:58         ` Vivek Goyal
2011-05-09 14:37           ` Tejun Heo
2011-05-05  1:59 ` [patch v3 3/3] SATA: enable non-queueable flush flag shaohua.li
2011-05-05  7:54   ` Tejun Heo
2011-05-05 12:33   ` Jeff Garzik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110505020417.817084678@sli10-conroe.sh.intel.com \
    --to=shaohua.li@intel.com \
    --cc=djwong@us.ibm.com \
    --cc=hch@infradead.org \
    --cc=htejun@gmail.com \
    --cc=jaxboe@fusionio.com \
    --cc=jgarzik@pobox.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sshtylyov@mvista.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®