aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-05-07 22:54:16 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-05-11 03:52:18 -0400
commit9934c8c04561413609d2bc38c6b9f268cba774a4 (patch)
tree30dd8f7be54f9b2e03094de9cd03b6a9ee2909cd /block
parent2343046826a8ca426b07601d9593ee046c298b68 (diff)
block: implement and enforce request peek/start/fetch
Till now block layer allowed two separate modes of request execution. A request is always acquired from the request queue via elv_next_request(). After that, drivers are free to either dequeue it or process it without dequeueing. Dequeue allows elv_next_request() to return the next request so that multiple requests can be in flight. Executing requests without dequeueing has its merits mostly in allowing drivers for simpler devices which can't do sg to deal with segments only without considering request boundary. However, the benefit this brings is dubious and declining while the cost of the API ambiguity is increasing. Segment based drivers are usually for very old or limited devices and as converting to dequeueing model isn't difficult, it doesn't justify the API overhead it puts on block layer and its more modern users. Previous patches converted all block low level drivers to dequeueing model. This patch completes the API transition by... * renaming elv_next_request() to blk_peek_request() * renaming blkdev_dequeue_request() to blk_start_request() * adding blk_fetch_request() which is combination of peek and start * disallowing completion of queued (not started) requests * applying new API to all LLDs Renamings are for consistency and to break out of tree code so that it's apparent that out of tree drivers need updating. [ Impact: block request issue API cleanup, no functional change ] Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Mike Miller <mike.miller@hp.com> Cc: unsik Kim <donari75@gmail.com> Cc: Paul Clements <paul.clements@steeleye.com> Cc: Tim Waugh <tim@cyberelk.net> Cc: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> Cc: David S. Miller <davem@davemloft.net> Cc: Laurent Vivier <Laurent@lvivier.info> Cc: Jeff Garzik <jgarzik@pobox.com> Cc: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Adrian McMenamin <adrian@mcmen.demon.co.uk> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Cc: Borislav Petkov <petkovbb@googlemail.com> Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> Cc: Alex Dubov <oakad@yahoo.com> Cc: Pierre Ossman <drzeus@drzeus.cx> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Markus Lidel <Markus.Lidel@shadowconnect.com> Cc: Stefan Weinhuber <wein@de.ibm.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Pete Zaitcev <zaitcev@redhat.com> Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r--block/blk-barrier.c4
-rw-r--r--block/blk-core.c105
-rw-r--r--block/blk-tag.c2
-rw-r--r--block/blk.h1
4 files changed, 81 insertions, 31 deletions
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
index 8713c2fbc4f6..0ab81a0a7502 100644
--- a/block/blk-barrier.c
+++ b/block/blk-barrier.c
@@ -180,7 +180,7 @@ static inline bool start_ordered(struct request_queue *q, struct request **rqp)
180 } 180 }
181 181
182 /* stash away the original request */ 182 /* stash away the original request */
183 elv_dequeue_request(q, rq); 183 blk_dequeue_request(rq);
184 q->orig_bar_rq = rq; 184 q->orig_bar_rq = rq;
185 rq = NULL; 185 rq = NULL;
186 186
@@ -248,7 +248,7 @@ bool blk_do_ordered(struct request_queue *q, struct request **rqp)
248 * Queue ordering not supported. Terminate 248 * Queue ordering not supported. Terminate
249 * with prejudice. 249 * with prejudice.
250 */ 250 */
251 elv_dequeue_request(q, rq); 251 blk_dequeue_request(rq);
252 __blk_end_request_all(rq, -EOPNOTSUPP); 252 __blk_end_request_all(rq, -EOPNOTSUPP);
253 *rqp = NULL; 253 *rqp = NULL;
254 return false; 254 return false;
diff --git a/block/blk-core.c b/block/blk-core.c
index 6226a380fb6d..93691d2ac5a0 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -902,6 +902,8 @@ EXPORT_SYMBOL(blk_get_request);
902 */ 902 */
903void blk_requeue_request(struct request_queue *q, struct request *rq) 903void blk_requeue_request(struct request_queue *q, struct request *rq)
904{ 904{
905 BUG_ON(blk_queued_rq(rq));
906
905 blk_delete_timer(rq); 907 blk_delete_timer(rq);
906 blk_clear_rq_complete(rq); 908 blk_clear_rq_complete(rq);
907 trace_block_rq_requeue(q, rq); 909 trace_block_rq_requeue(q, rq);
@@ -1610,28 +1612,6 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
1610} 1612}
1611EXPORT_SYMBOL_GPL(blk_insert_cloned_request); 1613EXPORT_SYMBOL_GPL(blk_insert_cloned_request);
1612 1614
1613/**
1614 * blkdev_dequeue_request - dequeue request and start timeout timer
1615 * @req: request to dequeue
1616 *
1617 * Dequeue @req and start timeout timer on it. This hands off the
1618 * request to the driver.
1619 *
1620 * Block internal functions which don't want to start timer should
1621 * call elv_dequeue_request().
1622 */
1623void blkdev_dequeue_request(struct request *req)
1624{
1625 elv_dequeue_request(req->q, req);
1626
1627 /*
1628 * We are now handing the request to the hardware, add the
1629 * timeout handler.
1630 */
1631 blk_add_timer(req);
1632}
1633EXPORT_SYMBOL(blkdev_dequeue_request);
1634
1635static void blk_account_io_completion(struct request *req, unsigned int bytes) 1615static void blk_account_io_completion(struct request *req, unsigned int bytes)
1636{ 1616{
1637 if (blk_do_io_stat(req)) { 1617 if (blk_do_io_stat(req)) {
@@ -1671,7 +1651,23 @@ static void blk_account_io_done(struct request *req)
1671 } 1651 }
1672} 1652}
1673 1653
1674struct request *elv_next_request(struct request_queue *q) 1654/**
1655 * blk_peek_request - peek at the top of a request queue
1656 * @q: request queue to peek at
1657 *
1658 * Description:
1659 * Return the request at the top of @q. The returned request
1660 * should be started using blk_start_request() before LLD starts
1661 * processing it.
1662 *
1663 * Return:
1664 * Pointer to the request at the top of @q if available. Null
1665 * otherwise.
1666 *
1667 * Context:
1668 * queue_lock must be held.
1669 */
1670struct request *blk_peek_request(struct request_queue *q)
1675{ 1671{
1676 struct request *rq; 1672 struct request *rq;
1677 int ret; 1673 int ret;
@@ -1748,10 +1744,12 @@ struct request *elv_next_request(struct request_queue *q)
1748 1744
1749 return rq; 1745 return rq;
1750} 1746}
1751EXPORT_SYMBOL(elv_next_request); 1747EXPORT_SYMBOL(blk_peek_request);
1752 1748
1753void elv_dequeue_request(struct request_queue *q, struct request *rq) 1749void blk_dequeue_request(struct request *rq)
1754{ 1750{
1751 struct request_queue *q = rq->q;
1752
1755 BUG_ON(list_empty(&rq->queuelist)); 1753 BUG_ON(list_empty(&rq->queuelist));
1756 BUG_ON(ELV_ON_HASH(rq)); 1754 BUG_ON(ELV_ON_HASH(rq));
1757 1755
@@ -1767,6 +1765,58 @@ void elv_dequeue_request(struct request_queue *q, struct request *rq)
1767} 1765}
1768 1766
1769/** 1767/**
1768 * blk_start_request - start request processing on the driver
1769 * @req: request to dequeue
1770 *
1771 * Description:
1772 * Dequeue @req and start timeout timer on it. This hands off the
1773 * request to the driver.
1774 *
1775 * Block internal functions which don't want to start timer should
1776 * call blk_dequeue_request().
1777 *
1778 * Context:
1779 * queue_lock must be held.
1780 */
1781void blk_start_request(struct request *req)
1782{
1783 blk_dequeue_request(req);
1784
1785 /*
1786 * We are now handing the request to the hardware, add the
1787 * timeout handler.
1788 */
1789 blk_add_timer(req);
1790}
1791EXPORT_SYMBOL(blk_start_request);
1792
1793/**
1794 * blk_fetch_request - fetch a request from a request queue
1795 * @q: request queue to fetch a request from
1796 *
1797 * Description:
1798 * Return the request at the top of @q. The request is started on
1799 * return and LLD can start processing it immediately.
1800 *
1801 * Return:
1802 * Pointer to the request at the top of @q if available. Null
1803 * otherwise.
1804 *
1805 * Context:
1806 * queue_lock must be held.
1807 */
1808struct request *blk_fetch_request(struct request_queue *q)
1809{
1810 struct request *rq;
1811
1812 rq = blk_peek_request(q);
1813 if (rq)
1814 blk_start_request(rq);
1815 return rq;
1816}
1817EXPORT_SYMBOL(blk_fetch_request);
1818
1819/**
1770 * blk_update_request - Special helper function for request stacking drivers 1820 * blk_update_request - Special helper function for request stacking drivers
1771 * @rq: the request being processed 1821 * @rq: the request being processed
1772 * @error: %0 for success, < %0 for error 1822 * @error: %0 for success, < %0 for error
@@ -1937,12 +1987,11 @@ static bool blk_update_bidi_request(struct request *rq, int error,
1937 */ 1987 */
1938static void blk_finish_request(struct request *req, int error) 1988static void blk_finish_request(struct request *req, int error)
1939{ 1989{
1990 BUG_ON(blk_queued_rq(req));
1991
1940 if (blk_rq_tagged(req)) 1992 if (blk_rq_tagged(req))
1941 blk_queue_end_tag(req->q, req); 1993 blk_queue_end_tag(req->q, req);
1942 1994
1943 if (blk_queued_rq(req))
1944 elv_dequeue_request(req->q, req);
1945
1946 if (unlikely(laptop_mode) && blk_fs_request(req)) 1995 if (unlikely(laptop_mode) && blk_fs_request(req))
1947 laptop_io_completion(); 1996 laptop_io_completion();
1948 1997
diff --git a/block/blk-tag.c b/block/blk-tag.c
index 3c518e3303ae..c260f7c30dda 100644
--- a/block/blk-tag.c
+++ b/block/blk-tag.c
@@ -374,7 +374,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq)
374 rq->cmd_flags |= REQ_QUEUED; 374 rq->cmd_flags |= REQ_QUEUED;
375 rq->tag = tag; 375 rq->tag = tag;
376 bqt->tag_index[tag] = rq; 376 bqt->tag_index[tag] = rq;
377 blkdev_dequeue_request(rq); 377 blk_start_request(rq);
378 list_add(&rq->queuelist, &q->tag_busy_list); 378 list_add(&rq->queuelist, &q->tag_busy_list);
379 return 0; 379 return 0;
380} 380}
diff --git a/block/blk.h b/block/blk.h
index ab54529103c0..9e0042ca9495 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -13,6 +13,7 @@ extern struct kobj_type blk_queue_ktype;
13void init_request_from_bio(struct request *req, struct bio *bio); 13void init_request_from_bio(struct request *req, struct bio *bio);
14void blk_rq_bio_prep(struct request_queue *q, struct request *rq, 14void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
15 struct bio *bio); 15 struct bio *bio);
16void blk_dequeue_request(struct request *rq);
16void __blk_queue_free_tags(struct request_queue *q); 17void __blk_queue_free_tags(struct request_queue *q);
17 18
18void blk_unplug_work(struct work_struct *work); 19void blk_unplug_work(struct work_struct *work);