[PATCH 14/21] block, aio: batch completion for bios/kiocbs

2013-05-13 Thread Kent Overstreet
When completing a kiocb, there's some fixed overhead from touching the
kioctx's ring buffer the kiocb belongs to.  Some newer high end block
devices can complete multiple IOs per interrupt, much like many network
interfaces have been for some time.

This plumbs through infrastructure so we can take advantage of multiple
completions at the interrupt level, and complete multiple kiocbs at the
same time.

Drivers have to be converted to take advantage of this, but it's a simple
change and the next patches will convert a few drivers.

To use it, an interrupt handler (or any code that completes bios or
requests) declares and initializes a struct batch_complete:

struct batch_complete batch;
batch_complete_init();

Then, instead of calling bio_endio(), it calls
bio_endio_batch(bio, err, ). This just adds the bio to a list in
the batch_complete.

At the end, it calls

batch_complete();

This completes all the bios all at once, building up a list of kiocbs;
then the list of kiocbs are completed all at once.

[a...@linux-foundation.org: fix warning]
[a...@linux-foundation.org: fs/aio.c needs bio.h, move bio_endio_batch() 
declaration somewhere rational]
[a...@linux-foundation.org: fix warnings]
[minc...@kernel.org: fix build error due to bio_endio_batch]
[a...@linux-foundation.org: fix tracepoint in batch_complete()]
Signed-off-by: Kent Overstreet 
Cc: Zach Brown 
Cc: Felipe Balbi 
Cc: Greg Kroah-Hartman 
Cc: Mark Fasheh 
Cc: Joel Becker 
Cc: Rusty Russell 
Cc: Jens Axboe 
Cc: Asai Thambi S P 
Cc: Selvan Mani 
Cc: Sam Bradshaw 
Cc: Jeff Moyer 
Cc: Al Viro 
Cc: Benjamin LaHaise 
Cc: Theodore Ts'o 
Signed-off-by: Minchan Kim 
Signed-off-by: Andrew Morton 
---
 block/blk-core.c   |  35 +---
 block/blk-flush.c  |   2 +-
 block/blk.h|   3 +-
 drivers/block/swim3.c  |   2 +-
 drivers/md/dm.c|   2 +-
 fs/aio.c   | 196 +
 fs/bio.c   |  49 +++
 fs/direct-io.c |  12 +--
 include/linux/aio.h|  24 -
 include/linux/batch_complete.h |  22 +
 include/linux/bio.h|  36 ++--
 include/linux/blk_types.h  |   1 +
 include/linux/blkdev.h |  12 ++-
 13 files changed, 270 insertions(+), 126 deletions(-)
 create mode 100644 include/linux/batch_complete.h

diff --git a/block/blk-core.c b/block/blk-core.c
index 33c33bc..94aa4e7 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -153,7 +153,8 @@ void blk_rq_init(struct request_queue *q, struct request 
*rq)
 EXPORT_SYMBOL(blk_rq_init);
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
- unsigned int nbytes, int error)
+ unsigned int nbytes, int error,
+ struct batch_complete *batch)
 {
if (error)
clear_bit(BIO_UPTODATE, >bi_flags);
@@ -167,7 +168,7 @@ static void req_bio_endio(struct request *rq, struct bio 
*bio,
 
/* don't actually finish bio if it's part of flush sequence */
if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
-   bio_endio(bio, error);
+   bio_endio_batch(bio, error, batch);
 }
 
 void blk_dump_rq_flags(struct request *rq, char *msg)
@@ -2281,7 +2282,8 @@ EXPORT_SYMBOL(blk_fetch_request);
  * %false - this request doesn't have any more data
  * %true  - this request has more data
  **/
-bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
+bool blk_update_request(struct request *req, int error, unsigned int nr_bytes,
+   struct batch_complete *batch)
 {
int total_bytes;
 
@@ -2337,7 +2339,7 @@ bool blk_update_request(struct request *req, int error, 
unsigned int nr_bytes)
if (bio_bytes == bio->bi_size)
req->bio = bio->bi_next;
 
-   req_bio_endio(req, bio, bio_bytes, error);
+   req_bio_endio(req, bio, bio_bytes, error, batch);
 
total_bytes += bio_bytes;
nr_bytes -= bio_bytes;
@@ -2390,14 +2392,15 @@ EXPORT_SYMBOL_GPL(blk_update_request);
 
 static bool blk_update_bidi_request(struct request *rq, int error,
unsigned int nr_bytes,
-   unsigned int bidi_bytes)
+   unsigned int bidi_bytes,
+   struct batch_complete *batch)
 {
-   if (blk_update_request(rq, error, nr_bytes))
+   if (blk_update_request(rq, error, nr_bytes, batch))
return true;
 
/* Bidi request must be completed as a whole */
if (unlikely(blk_bidi_rq(rq)) &&
-   blk_update_request(rq->next_rq, error, bidi_bytes))
+   blk_update_request(rq->next_rq, error, bidi_bytes, batch))
return true;
 
if (blk_queue_add_random(rq->q))
@@ -2480,7 +2483,7 @@ static bool 

[PATCH 14/21] block, aio: batch completion for bios/kiocbs

2013-05-13 Thread Kent Overstreet
When completing a kiocb, there's some fixed overhead from touching the
kioctx's ring buffer the kiocb belongs to.  Some newer high end block
devices can complete multiple IOs per interrupt, much like many network
interfaces have been for some time.

This plumbs through infrastructure so we can take advantage of multiple
completions at the interrupt level, and complete multiple kiocbs at the
same time.

Drivers have to be converted to take advantage of this, but it's a simple
change and the next patches will convert a few drivers.

To use it, an interrupt handler (or any code that completes bios or
requests) declares and initializes a struct batch_complete:

struct batch_complete batch;
batch_complete_init(batch);

Then, instead of calling bio_endio(), it calls
bio_endio_batch(bio, err, batch). This just adds the bio to a list in
the batch_complete.

At the end, it calls

batch_complete(batch);

This completes all the bios all at once, building up a list of kiocbs;
then the list of kiocbs are completed all at once.

[a...@linux-foundation.org: fix warning]
[a...@linux-foundation.org: fs/aio.c needs bio.h, move bio_endio_batch() 
declaration somewhere rational]
[a...@linux-foundation.org: fix warnings]
[minc...@kernel.org: fix build error due to bio_endio_batch]
[a...@linux-foundation.org: fix tracepoint in batch_complete()]
Signed-off-by: Kent Overstreet koverstr...@google.com
Cc: Zach Brown z...@redhat.com
Cc: Felipe Balbi ba...@ti.com
Cc: Greg Kroah-Hartman gre...@linuxfoundation.org
Cc: Mark Fasheh mfas...@suse.com
Cc: Joel Becker jl...@evilplan.org
Cc: Rusty Russell ru...@rustcorp.com.au
Cc: Jens Axboe ax...@kernel.dk
Cc: Asai Thambi S P asamymuth...@micron.com
Cc: Selvan Mani sm...@micron.com
Cc: Sam Bradshaw sbrads...@micron.com
Cc: Jeff Moyer jmo...@redhat.com
Cc: Al Viro v...@zeniv.linux.org.uk
Cc: Benjamin LaHaise b...@kvack.org
Cc: Theodore Ts'o ty...@mit.edu
Signed-off-by: Minchan Kim minc...@kernel.org
Signed-off-by: Andrew Morton a...@linux-foundation.org
---
 block/blk-core.c   |  35 +---
 block/blk-flush.c  |   2 +-
 block/blk.h|   3 +-
 drivers/block/swim3.c  |   2 +-
 drivers/md/dm.c|   2 +-
 fs/aio.c   | 196 +
 fs/bio.c   |  49 +++
 fs/direct-io.c |  12 +--
 include/linux/aio.h|  24 -
 include/linux/batch_complete.h |  22 +
 include/linux/bio.h|  36 ++--
 include/linux/blk_types.h  |   1 +
 include/linux/blkdev.h |  12 ++-
 13 files changed, 270 insertions(+), 126 deletions(-)
 create mode 100644 include/linux/batch_complete.h

diff --git a/block/blk-core.c b/block/blk-core.c
index 33c33bc..94aa4e7 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -153,7 +153,8 @@ void blk_rq_init(struct request_queue *q, struct request 
*rq)
 EXPORT_SYMBOL(blk_rq_init);
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
- unsigned int nbytes, int error)
+ unsigned int nbytes, int error,
+ struct batch_complete *batch)
 {
if (error)
clear_bit(BIO_UPTODATE, bio-bi_flags);
@@ -167,7 +168,7 @@ static void req_bio_endio(struct request *rq, struct bio 
*bio,
 
/* don't actually finish bio if it's part of flush sequence */
if (bio-bi_size == 0  !(rq-cmd_flags  REQ_FLUSH_SEQ))
-   bio_endio(bio, error);
+   bio_endio_batch(bio, error, batch);
 }
 
 void blk_dump_rq_flags(struct request *rq, char *msg)
@@ -2281,7 +2282,8 @@ EXPORT_SYMBOL(blk_fetch_request);
  * %false - this request doesn't have any more data
  * %true  - this request has more data
  **/
-bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
+bool blk_update_request(struct request *req, int error, unsigned int nr_bytes,
+   struct batch_complete *batch)
 {
int total_bytes;
 
@@ -2337,7 +2339,7 @@ bool blk_update_request(struct request *req, int error, 
unsigned int nr_bytes)
if (bio_bytes == bio-bi_size)
req-bio = bio-bi_next;
 
-   req_bio_endio(req, bio, bio_bytes, error);
+   req_bio_endio(req, bio, bio_bytes, error, batch);
 
total_bytes += bio_bytes;
nr_bytes -= bio_bytes;
@@ -2390,14 +2392,15 @@ EXPORT_SYMBOL_GPL(blk_update_request);
 
 static bool blk_update_bidi_request(struct request *rq, int error,
unsigned int nr_bytes,
-   unsigned int bidi_bytes)
+   unsigned int bidi_bytes,
+   struct batch_complete *batch)
 {
-   if (blk_update_request(rq, error, nr_bytes))
+   if (blk_update_request(rq, error, nr_bytes, batch))
return true;
 
/* Bidi request