summaryrefslogtreecommitdiffstats
path: root/block/bio.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2018-12-06 11:41:19 -0500
committerJens Axboe <axboe@kernel.dk>2018-12-10 10:30:37 -0500
commit5b18b5a737600fd20ba2045f320d5926ebbf341a (patch)
treefe35e150bf36785dfe3ed8c845e3b043e56f9f90 /block/bio.c
parent112f158f66cbe25fd561a5dfe9c3826e06abf757 (diff)
block: delete part_round_stats and switch to less precise counting
We want to convert to per-cpu in_flight counters. The function part_round_stats needs the in_flight counter every jiffy, it would be too costly to sum all the percpu variables every jiffy, so it must be deleted. part_round_stats is used to calculate two counters - time_in_queue and io_ticks. time_in_queue can be calculated without part_round_stats, by adding the duration of the I/O when the I/O ends (the value is almost as exact as the previously calculated value, except that time for in-progress I/Os is not counted). io_ticks can be approximated by increasing the value when I/O is started or ended and the jiffies value has changed. If the I/Os take less than a jiffy, the value is as exact as the previously calculated value. If the I/Os take more than a jiffy, io_ticks can drift behind the previously calculated value. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/bio.c')
-rw-r--r--block/bio.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/block/bio.c b/block/bio.c
index 0aca870331c3..036e3f0cc736 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1664,6 +1664,22 @@ defer:
1664} 1664}
1665EXPORT_SYMBOL_GPL(bio_check_pages_dirty); 1665EXPORT_SYMBOL_GPL(bio_check_pages_dirty);
1666 1666
1667void update_io_ticks(struct hd_struct *part, unsigned long now)
1668{
1669 unsigned long stamp;
1670again:
1671 stamp = READ_ONCE(part->stamp);
1672 if (unlikely(stamp != now)) {
1673 if (likely(cmpxchg(&part->stamp, stamp, now) == stamp)) {
1674 __part_stat_add(part, io_ticks, 1);
1675 }
1676 }
1677 if (part->partno) {
1678 part = &part_to_disk(part)->part0;
1679 goto again;
1680 }
1681}
1682
1667void generic_start_io_acct(struct request_queue *q, int op, 1683void generic_start_io_acct(struct request_queue *q, int op,
1668 unsigned long sectors, struct hd_struct *part) 1684 unsigned long sectors, struct hd_struct *part)
1669{ 1685{
@@ -1671,7 +1687,7 @@ void generic_start_io_acct(struct request_queue *q, int op,
1671 1687
1672 part_stat_lock(); 1688 part_stat_lock();
1673 1689
1674 part_round_stats(q, part); 1690 update_io_ticks(part, jiffies);
1675 part_stat_inc(part, ios[sgrp]); 1691 part_stat_inc(part, ios[sgrp]);
1676 part_stat_add(part, sectors[sgrp], sectors); 1692 part_stat_add(part, sectors[sgrp], sectors);
1677 part_inc_in_flight(q, part, op_is_write(op)); 1693 part_inc_in_flight(q, part, op_is_write(op));
@@ -1683,13 +1699,15 @@ EXPORT_SYMBOL(generic_start_io_acct);
1683void generic_end_io_acct(struct request_queue *q, int req_op, 1699void generic_end_io_acct(struct request_queue *q, int req_op,
1684 struct hd_struct *part, unsigned long start_time) 1700 struct hd_struct *part, unsigned long start_time)
1685{ 1701{
1686 unsigned long duration = jiffies - start_time; 1702 unsigned long now = jiffies;
1703 unsigned long duration = now - start_time;
1687 const int sgrp = op_stat_group(req_op); 1704 const int sgrp = op_stat_group(req_op);
1688 1705
1689 part_stat_lock(); 1706 part_stat_lock();
1690 1707
1708 update_io_ticks(part, now);
1691 part_stat_add(part, nsecs[sgrp], jiffies_to_nsecs(duration)); 1709 part_stat_add(part, nsecs[sgrp], jiffies_to_nsecs(duration));
1692 part_round_stats(q, part); 1710 part_stat_add(part, time_in_queue, duration);
1693 part_dec_in_flight(q, part, op_is_write(req_op)); 1711 part_dec_in_flight(q, part, op_is_write(req_op));
1694 1712
1695 part_stat_unlock(); 1713 part_stat_unlock();