From patchwork Thu Sep 24 19:25:19 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Goyal X-Patchwork-Id: 50034 Received: from hormel.redhat.com (hormel1.redhat.com [209.132.177.33]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n8OJgOM5004928 for ; Thu, 24 Sep 2009 19:42:25 GMT Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110]) by hormel.redhat.com (Postfix) with ESMTP id A39F761AB0A; Thu, 24 Sep 2009 15:33:28 -0400 (EDT) Received: from int-mx02.intmail.prod.int.phx2.redhat.com (nat-pool.util.phx.redhat.com [10.8.5.200]) by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id n8OJPaaB006029 for ; Thu, 24 Sep 2009 15:25:36 -0400 Received: from machine.usersys.redhat.com (dhcp-100-19-148.bos.redhat.com [10.16.19.148]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id n8OJPZdG007098; Thu, 24 Sep 2009 15:25:35 -0400 Received: by machine.usersys.redhat.com (Postfix, from userid 10451) id 60F6526682; Thu, 24 Sep 2009 15:25:33 -0400 (EDT) From: Vivek Goyal To: linux-kernel@vger.kernel.org, jens.axboe@oracle.com Date: Thu, 24 Sep 2009 15:25:19 -0400 Message-Id: <1253820332-10246-16-git-send-email-vgoyal@redhat.com> In-Reply-To: <1253820332-10246-1-git-send-email-vgoyal@redhat.com> References: <1253820332-10246-1-git-send-email-vgoyal@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-loop: dm-devel@redhat.com Cc: dhaval@linux.vnet.ibm.com, peterz@infradead.org, dm-devel@redhat.com, dpshah@google.com, agk@redhat.com, balbir@linux.vnet.ibm.com, paolo.valente@unimore.it, jmarchan@redhat.com, guijianfeng@cn.fujitsu.com, fernando@oss.ntt.co.jp, mikew@google.com, jmoyer@redhat.com, nauman@google.com, mingo@elte.hu, vgoyal@redhat.com, m-ikeda@ds.jp.nec.com, riel@redhat.com, lizf@cn.fujitsu.com, fchecconi@gmail.com, s-uchida@ap.jp.nec.com, containers@lists.linux-foundation.org, akpm@linux-foundation.org, righi.andrea@gmail.com, torvalds@linux-foundation.org Subject: [dm-devel] [PATCH 15/28] io-controller: Allow CFQ specific extra preemptions X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.5 Precedence: junk Reply-To: device-mapper development List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com o CFQ allows a reader preemting a writer. So far we allow this with-in group but not across groups. But there seems to be following special case where this preemption might make sense. root / \ R Group | W Now here reader should be able to preempt the writer. Think of there are 10 groups each running a writer and an admin trying to do "ls" and he experiences suddenly high latencies for ls. Same is true for meta data requests. If there is a meta data request and a reader is running inside a sibling group, preemption will be allowed. Note, following is not allowed. root / \ group1 group2 | | R W Here reader can't preempt writer. o Put meta data requesting queues at the front of the service tree. Generally such queues will preempt currently running queue but not in following case. root / \ group1 group2 | / \ R1 R3 R2 (meta data) Here R2 is having a meta data request but it will not preempt R1. We need to make sure that R2 gets queued ahead of R3 so taht once group2 gets going, we first service R2 and then R3 and not vice versa. Signed-off-by: Vivek Goyal --- block/elevator-fq.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- block/elevator-fq.h | 3 +++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/block/elevator-fq.c b/block/elevator-fq.c index 25beaf7..8ff8a19 100644 --- a/block/elevator-fq.c +++ b/block/elevator-fq.c @@ -701,6 +701,7 @@ static void enqueue_io_entity(struct io_entity *entity) struct io_service_tree *st; struct io_sched_data *sd = io_entity_sched_data(entity); struct io_queue *ioq = ioq_of(entity); + int add_front = 0; if (entity->on_idle_st) dequeue_io_entity_idle(entity); @@ -716,12 +717,22 @@ static void enqueue_io_entity(struct io_entity *entity) st = entity->st; st->nr_active++; sd->nr_active++; + /* Keep a track of how many sync queues are backlogged on this group */ if (ioq && elv_ioq_sync(ioq) && !elv_ioq_class_idle(ioq)) sd->nr_sync++; entity->on_st = 1; - place_entity(st, entity, 0); - __enqueue_io_entity(st, entity, 0); + + /* + * If a meta data request is pending in this queue, put this + * queue at the front so that it gets a chance to run first + * as soon as the associated group becomes eligbile to run. + */ + if (ioq && ioq->meta_pending) + add_front = 1; + + place_entity(st, entity, add_front); + __enqueue_io_entity(st, entity, add_front); debug_update_stats_enqueue(entity); } @@ -2280,6 +2291,31 @@ static int elv_should_preempt(struct request_queue *q, struct io_queue *new_ioq, return 1; /* + * Allow some additional preemptions where a reader queue gets + * backlogged and some writer queue is running under any of the + * sibling groups. + * + * root + * / \ + * R group + * | + * W + */ + + if (ioq_of(new_entity) == new_ioq && iog_of(entity)) { + /* Let reader queue preempt writer in sibling group */ + if (elv_ioq_sync(new_ioq) && !elv_ioq_sync(active_ioq)) + return 1; + /* + * So both queues are sync. Let the new request get disk time if + * it's a metadata request and the current queue is doing + * regular IO. + */ + if (new_ioq->meta_pending && !active_ioq->meta_pending) + return 1; + } + + /* * If both the queues belong to same group, check with io scheduler * if it has additional criterion based on which it wants to * preempt existing queue. @@ -2335,6 +2371,8 @@ void elv_ioq_request_add(struct request_queue *q, struct request *rq) BUG_ON(!efqd); BUG_ON(!ioq); ioq->nr_queued++; + if (rq_is_meta(rq)) + ioq->meta_pending++; elv_log_ioq(efqd, ioq, "add rq: rq_queued=%d", ioq->nr_queued); if (!elv_ioq_busy(ioq)) @@ -2669,6 +2707,11 @@ void elv_ioq_request_removed(struct elevator_queue *e, struct request *rq) ioq = rq->ioq; BUG_ON(!ioq); ioq->nr_queued--; + + if (rq_is_meta(rq)) { + WARN_ON(!ioq->meta_pending); + ioq->meta_pending--; + } } /* A request got dispatched. Do the accounting. */ diff --git a/block/elevator-fq.h b/block/elevator-fq.h index 2992d93..27ff5c4 100644 --- a/block/elevator-fq.h +++ b/block/elevator-fq.h @@ -100,6 +100,9 @@ struct io_queue { /* Pointer to io scheduler's queue */ void *sched_queue; + + /* pending metadata requests */ + int meta_pending; }; #ifdef CONFIG_GROUP_IOSCHED /* CONFIG_GROUP_IOSCHED */