diff options
author | Tejun Heo <tj@kernel.org> | 2008-08-25 06:47:21 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-10-09 02:56:06 -0400 |
commit | c9959059161ddd7bf4670cf47367033d6b2f79c4 (patch) | |
tree | 6454db55f8e34361fe472358e10e0c5cfac1e366 /block/genhd.c | |
parent | e71bf0d0ee89e51b92776391c5634938236977d5 (diff) |
block: fix diskstats access
There are two variants of stat functions - ones prefixed with double
underbars which don't care about preemption and ones without which
disable preemption before manipulating per-cpu counters. It's unclear
whether the underbarred ones assume that preemtion is disabled on
entry as some callers don't do that.
This patch unifies diskstats access by implementing disk_stat_lock()
and disk_stat_unlock() which take care of both RCU (for partition
access) and preemption (for per-cpu counter access). diskstats access
should always be enclosed between the two functions. As such, there's
no need for the versions which disables preemption. They're removed
and double underbars ones are renamed to drop the underbars. As an
extra argument is added, there's no danger of using the old version
unconverted.
disk_stat_lock() uses get_cpu() and returns the cpu index and all
diskstat functions which access per-cpu counters now has @cpu
argument to help RT.
This change adds RCU or preemption operations at some places but also
collapses several preemption ops into one at others. Overall, the
performance difference should be negligible as all involved ops are
very lightweight per-cpu ones.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/genhd.c')
-rw-r--r-- | block/genhd.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/block/genhd.c b/block/genhd.c index b431d6543942..430626e440f0 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -633,10 +633,11 @@ static ssize_t disk_stat_show(struct device *dev, | |||
633 | struct device_attribute *attr, char *buf) | 633 | struct device_attribute *attr, char *buf) |
634 | { | 634 | { |
635 | struct gendisk *disk = dev_to_disk(dev); | 635 | struct gendisk *disk = dev_to_disk(dev); |
636 | int cpu; | ||
636 | 637 | ||
637 | preempt_disable(); | 638 | cpu = disk_stat_lock(); |
638 | disk_round_stats(disk); | 639 | disk_round_stats(cpu, disk); |
639 | preempt_enable(); | 640 | disk_stat_unlock(); |
640 | return sprintf(buf, | 641 | return sprintf(buf, |
641 | "%8lu %8lu %8llu %8u " | 642 | "%8lu %8lu %8llu %8u " |
642 | "%8lu %8lu %8llu %8u " | 643 | "%8lu %8lu %8llu %8u " |
@@ -749,6 +750,7 @@ static int diskstats_show(struct seq_file *seqf, void *v) | |||
749 | struct disk_part_iter piter; | 750 | struct disk_part_iter piter; |
750 | struct hd_struct *hd; | 751 | struct hd_struct *hd; |
751 | char buf[BDEVNAME_SIZE]; | 752 | char buf[BDEVNAME_SIZE]; |
753 | int cpu; | ||
752 | 754 | ||
753 | /* | 755 | /* |
754 | if (&gp->dev.kobj.entry == block_class.devices.next) | 756 | if (&gp->dev.kobj.entry == block_class.devices.next) |
@@ -758,9 +760,9 @@ static int diskstats_show(struct seq_file *seqf, void *v) | |||
758 | "\n\n"); | 760 | "\n\n"); |
759 | */ | 761 | */ |
760 | 762 | ||
761 | preempt_disable(); | 763 | cpu = disk_stat_lock(); |
762 | disk_round_stats(gp); | 764 | disk_round_stats(cpu, gp); |
763 | preempt_enable(); | 765 | disk_stat_unlock(); |
764 | seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", | 766 | seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", |
765 | MAJOR(disk_devt(gp)), MINOR(disk_devt(gp)), | 767 | MAJOR(disk_devt(gp)), MINOR(disk_devt(gp)), |
766 | disk_name(gp, 0, buf), | 768 | disk_name(gp, 0, buf), |
@@ -777,9 +779,9 @@ static int diskstats_show(struct seq_file *seqf, void *v) | |||
777 | /* now show all non-0 size partitions of it */ | 779 | /* now show all non-0 size partitions of it */ |
778 | disk_part_iter_init(&piter, gp, 0); | 780 | disk_part_iter_init(&piter, gp, 0); |
779 | while ((hd = disk_part_iter_next(&piter))) { | 781 | while ((hd = disk_part_iter_next(&piter))) { |
780 | preempt_disable(); | 782 | cpu = disk_stat_lock(); |
781 | part_round_stats(hd); | 783 | part_round_stats(cpu, hd); |
782 | preempt_enable(); | 784 | disk_stat_unlock(); |
783 | seq_printf(seqf, "%4d %4d %s %lu %lu %llu " | 785 | seq_printf(seqf, "%4d %4d %s %lu %lu %llu " |
784 | "%u %lu %lu %llu %u %u %u %u\n", | 786 | "%u %lu %lu %llu %u %u %u %u\n", |
785 | MAJOR(part_devt(hd)), MINOR(part_devt(hd)), | 787 | MAJOR(part_devt(hd)), MINOR(part_devt(hd)), |