aboutsummaryrefslogtreecommitdiffstats
path: root/block/bio.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@fb.com>2015-04-17 18:15:18 -0400
committerJens Axboe <axboe@fb.com>2015-05-05 15:32:47 -0400
commitc4cf5261f8bffd9de132b50660a69148e7575bd6 (patch)
treec3ff2d0d2db5f7392e8651b4f0d2958895faf8b2 /block/bio.c
parentd9cee5d4f66ef36f69b0108dedbad7f7009bb6a8 (diff)
bio: skip atomic inc/dec of ->bi_remaining for non-chains
Struct bio has an atomic ref count for chained bio's, and we use this to know when to end IO on the bio. However, most bio's are not chained, so we don't need to always introduce this atomic operation as part of ending IO. Add a helper to elevate the bi_remaining count, and flag the bio as now actually needing the decrement at end_io time. Rename the field to __bi_remaining to catch any current users of this doing the incrementing manually. For high IOPS workloads, this reduces the overhead of bio_endio() substantially. Tested-by: Robert Elliott <elliott@hp.com> Acked-by: Kent Overstreet <kent.overstreet@gmail.com> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/bio.c')
-rw-r--r--block/bio.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/block/bio.c b/block/bio.c
index f66a4eae16ee..117da319afb6 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -270,7 +270,7 @@ void bio_init(struct bio *bio)
270{ 270{
271 memset(bio, 0, sizeof(*bio)); 271 memset(bio, 0, sizeof(*bio));
272 bio->bi_flags = 1 << BIO_UPTODATE; 272 bio->bi_flags = 1 << BIO_UPTODATE;
273 atomic_set(&bio->bi_remaining, 1); 273 atomic_set(&bio->__bi_remaining, 1);
274 atomic_set(&bio->bi_cnt, 1); 274 atomic_set(&bio->bi_cnt, 1);
275} 275}
276EXPORT_SYMBOL(bio_init); 276EXPORT_SYMBOL(bio_init);
@@ -292,8 +292,8 @@ void bio_reset(struct bio *bio)
292 __bio_free(bio); 292 __bio_free(bio);
293 293
294 memset(bio, 0, BIO_RESET_BYTES); 294 memset(bio, 0, BIO_RESET_BYTES);
295 bio->bi_flags = flags|(1 << BIO_UPTODATE); 295 bio->bi_flags = flags | (1 << BIO_UPTODATE);
296 atomic_set(&bio->bi_remaining, 1); 296 atomic_set(&bio->__bi_remaining, 1);
297} 297}
298EXPORT_SYMBOL(bio_reset); 298EXPORT_SYMBOL(bio_reset);
299 299
@@ -320,7 +320,7 @@ void bio_chain(struct bio *bio, struct bio *parent)
320 320
321 bio->bi_private = parent; 321 bio->bi_private = parent;
322 bio->bi_end_io = bio_chain_endio; 322 bio->bi_end_io = bio_chain_endio;
323 atomic_inc(&parent->bi_remaining); 323 bio_inc_remaining(parent);
324} 324}
325EXPORT_SYMBOL(bio_chain); 325EXPORT_SYMBOL(bio_chain);
326 326
@@ -1741,6 +1741,23 @@ void bio_flush_dcache_pages(struct bio *bi)
1741EXPORT_SYMBOL(bio_flush_dcache_pages); 1741EXPORT_SYMBOL(bio_flush_dcache_pages);
1742#endif 1742#endif
1743 1743
1744static inline bool bio_remaining_done(struct bio *bio)
1745{
1746 /*
1747 * If we're not chaining, then ->__bi_remaining is always 1 and
1748 * we always end io on the first invocation.
1749 */
1750 if (!bio_flagged(bio, BIO_CHAIN))
1751 return true;
1752
1753 BUG_ON(atomic_read(&bio->__bi_remaining) <= 0);
1754
1755 if (atomic_dec_and_test(&bio->__bi_remaining))
1756 return true;
1757
1758 return false;
1759}
1760
1744/** 1761/**
1745 * bio_endio - end I/O on a bio 1762 * bio_endio - end I/O on a bio
1746 * @bio: bio 1763 * @bio: bio
@@ -1758,15 +1775,13 @@ EXPORT_SYMBOL(bio_flush_dcache_pages);
1758void bio_endio(struct bio *bio, int error) 1775void bio_endio(struct bio *bio, int error)
1759{ 1776{
1760 while (bio) { 1777 while (bio) {
1761 BUG_ON(atomic_read(&bio->bi_remaining) <= 0);
1762
1763 if (error) 1778 if (error)
1764 clear_bit(BIO_UPTODATE, &bio->bi_flags); 1779 clear_bit(BIO_UPTODATE, &bio->bi_flags);
1765 else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) 1780 else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
1766 error = -EIO; 1781 error = -EIO;
1767 1782
1768 if (!atomic_dec_and_test(&bio->bi_remaining)) 1783 if (unlikely(!bio_remaining_done(bio)))
1769 return; 1784 break;
1770 1785
1771 /* 1786 /*
1772 * Need to have a real endio function for chained bios, 1787 * Need to have a real endio function for chained bios,
@@ -1799,7 +1814,12 @@ EXPORT_SYMBOL(bio_endio);
1799 **/ 1814 **/
1800void bio_endio_nodec(struct bio *bio, int error) 1815void bio_endio_nodec(struct bio *bio, int error)
1801{ 1816{
1802 atomic_inc(&bio->bi_remaining); 1817 /*
1818 * If it's not flagged as a chain, we are not going to dec the count
1819 */
1820 if (bio_flagged(bio, BIO_CHAIN))
1821 bio_inc_remaining(bio);
1822
1803 bio_endio(bio, error); 1823 bio_endio(bio, error);
1804} 1824}
1805EXPORT_SYMBOL(bio_endio_nodec); 1825EXPORT_SYMBOL(bio_endio_nodec);