aboutsummaryrefslogtreecommitdiffstats
path: root/block/genhd.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-08-25 06:47:21 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-10-09 02:56:06 -0400
commitc9959059161ddd7bf4670cf47367033d6b2f79c4 (patch)
tree6454db55f8e34361fe472358e10e0c5cfac1e366 /block/genhd.c
parente71bf0d0ee89e51b92776391c5634938236977d5 (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.c20
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)),