diff options
-rw-r--r-- | block/blk-core.c | 52 | ||||
-rw-r--r-- | block/blk-merge.c | 11 | ||||
-rw-r--r-- | block/genhd.c | 20 | ||||
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 15 | ||||
-rw-r--r-- | drivers/md/dm.c | 26 | ||||
-rw-r--r-- | drivers/md/linear.c | 7 | ||||
-rw-r--r-- | drivers/md/multipath.c | 7 | ||||
-rw-r--r-- | drivers/md/raid0.c | 7 | ||||
-rw-r--r-- | drivers/md/raid1.c | 8 | ||||
-rw-r--r-- | drivers/md/raid10.c | 7 | ||||
-rw-r--r-- | drivers/md/raid5.c | 8 | ||||
-rw-r--r-- | fs/partitions/check.c | 7 | ||||
-rw-r--r-- | include/linux/genhd.h | 139 |
13 files changed, 158 insertions, 156 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index d6128d9ad601..e0a5ee36849c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -56,25 +56,26 @@ static void drive_stat_acct(struct request *rq, int new_io) | |||
56 | { | 56 | { |
57 | struct hd_struct *part; | 57 | struct hd_struct *part; |
58 | int rw = rq_data_dir(rq); | 58 | int rw = rq_data_dir(rq); |
59 | int cpu; | ||
59 | 60 | ||
60 | if (!blk_fs_request(rq) || !rq->rq_disk) | 61 | if (!blk_fs_request(rq) || !rq->rq_disk) |
61 | return; | 62 | return; |
62 | 63 | ||
63 | rcu_read_lock(); | 64 | cpu = disk_stat_lock(); |
64 | |||
65 | part = disk_map_sector_rcu(rq->rq_disk, rq->sector); | 65 | part = disk_map_sector_rcu(rq->rq_disk, rq->sector); |
66 | |||
66 | if (!new_io) | 67 | if (!new_io) |
67 | __all_stat_inc(rq->rq_disk, part, merges[rw], rq->sector); | 68 | all_stat_inc(cpu, rq->rq_disk, part, merges[rw], rq->sector); |
68 | else { | 69 | else { |
69 | disk_round_stats(rq->rq_disk); | 70 | disk_round_stats(cpu, rq->rq_disk); |
70 | rq->rq_disk->in_flight++; | 71 | rq->rq_disk->in_flight++; |
71 | if (part) { | 72 | if (part) { |
72 | part_round_stats(part); | 73 | part_round_stats(cpu, part); |
73 | part->in_flight++; | 74 | part->in_flight++; |
74 | } | 75 | } |
75 | } | 76 | } |
76 | 77 | ||
77 | rcu_read_unlock(); | 78 | disk_stat_unlock(); |
78 | } | 79 | } |
79 | 80 | ||
80 | void blk_queue_congestion_threshold(struct request_queue *q) | 81 | void blk_queue_congestion_threshold(struct request_queue *q) |
@@ -997,7 +998,7 @@ static inline void add_request(struct request_queue *q, struct request *req) | |||
997 | * /proc/diskstats. This accounts immediately for all queue usage up to | 998 | * /proc/diskstats. This accounts immediately for all queue usage up to |
998 | * the current jiffies and restarts the counters again. | 999 | * the current jiffies and restarts the counters again. |
999 | */ | 1000 | */ |
1000 | void disk_round_stats(struct gendisk *disk) | 1001 | void disk_round_stats(int cpu, struct gendisk *disk) |
1001 | { | 1002 | { |
1002 | unsigned long now = jiffies; | 1003 | unsigned long now = jiffies; |
1003 | 1004 | ||
@@ -1005,15 +1006,15 @@ void disk_round_stats(struct gendisk *disk) | |||
1005 | return; | 1006 | return; |
1006 | 1007 | ||
1007 | if (disk->in_flight) { | 1008 | if (disk->in_flight) { |
1008 | __disk_stat_add(disk, time_in_queue, | 1009 | disk_stat_add(cpu, disk, time_in_queue, |
1009 | disk->in_flight * (now - disk->stamp)); | 1010 | disk->in_flight * (now - disk->stamp)); |
1010 | __disk_stat_add(disk, io_ticks, (now - disk->stamp)); | 1011 | disk_stat_add(cpu, disk, io_ticks, (now - disk->stamp)); |
1011 | } | 1012 | } |
1012 | disk->stamp = now; | 1013 | disk->stamp = now; |
1013 | } | 1014 | } |
1014 | EXPORT_SYMBOL_GPL(disk_round_stats); | 1015 | EXPORT_SYMBOL_GPL(disk_round_stats); |
1015 | 1016 | ||
1016 | void part_round_stats(struct hd_struct *part) | 1017 | void part_round_stats(int cpu, struct hd_struct *part) |
1017 | { | 1018 | { |
1018 | unsigned long now = jiffies; | 1019 | unsigned long now = jiffies; |
1019 | 1020 | ||
@@ -1021,9 +1022,9 @@ void part_round_stats(struct hd_struct *part) | |||
1021 | return; | 1022 | return; |
1022 | 1023 | ||
1023 | if (part->in_flight) { | 1024 | if (part->in_flight) { |
1024 | __part_stat_add(part, time_in_queue, | 1025 | part_stat_add(cpu, part, time_in_queue, |
1025 | part->in_flight * (now - part->stamp)); | 1026 | part->in_flight * (now - part->stamp)); |
1026 | __part_stat_add(part, io_ticks, (now - part->stamp)); | 1027 | part_stat_add(cpu, part, io_ticks, (now - part->stamp)); |
1027 | } | 1028 | } |
1028 | part->stamp = now; | 1029 | part->stamp = now; |
1029 | } | 1030 | } |
@@ -1563,12 +1564,13 @@ static int __end_that_request_first(struct request *req, int error, | |||
1563 | if (blk_fs_request(req) && req->rq_disk) { | 1564 | if (blk_fs_request(req) && req->rq_disk) { |
1564 | const int rw = rq_data_dir(req); | 1565 | const int rw = rq_data_dir(req); |
1565 | struct hd_struct *part; | 1566 | struct hd_struct *part; |
1567 | int cpu; | ||
1566 | 1568 | ||
1567 | rcu_read_lock(); | 1569 | cpu = disk_stat_lock(); |
1568 | part = disk_map_sector_rcu(req->rq_disk, req->sector); | 1570 | part = disk_map_sector_rcu(req->rq_disk, req->sector); |
1569 | all_stat_add(req->rq_disk, part, sectors[rw], | 1571 | all_stat_add(cpu, req->rq_disk, part, sectors[rw], |
1570 | nr_bytes >> 9, req->sector); | 1572 | nr_bytes >> 9, req->sector); |
1571 | rcu_read_unlock(); | 1573 | disk_stat_unlock(); |
1572 | } | 1574 | } |
1573 | 1575 | ||
1574 | total_bytes = bio_nbytes = 0; | 1576 | total_bytes = bio_nbytes = 0; |
@@ -1753,21 +1755,21 @@ static void end_that_request_last(struct request *req, int error) | |||
1753 | unsigned long duration = jiffies - req->start_time; | 1755 | unsigned long duration = jiffies - req->start_time; |
1754 | const int rw = rq_data_dir(req); | 1756 | const int rw = rq_data_dir(req); |
1755 | struct hd_struct *part; | 1757 | struct hd_struct *part; |
1758 | int cpu; | ||
1756 | 1759 | ||
1757 | rcu_read_lock(); | 1760 | cpu = disk_stat_lock(); |
1758 | |||
1759 | part = disk_map_sector_rcu(disk, req->sector); | 1761 | part = disk_map_sector_rcu(disk, req->sector); |
1760 | 1762 | ||
1761 | __all_stat_inc(disk, part, ios[rw], req->sector); | 1763 | all_stat_inc(cpu, disk, part, ios[rw], req->sector); |
1762 | __all_stat_add(disk, part, ticks[rw], duration, req->sector); | 1764 | all_stat_add(cpu, disk, part, ticks[rw], duration, req->sector); |
1763 | disk_round_stats(disk); | 1765 | disk_round_stats(cpu, disk); |
1764 | disk->in_flight--; | 1766 | disk->in_flight--; |
1765 | if (part) { | 1767 | if (part) { |
1766 | part_round_stats(part); | 1768 | part_round_stats(cpu, part); |
1767 | part->in_flight--; | 1769 | part->in_flight--; |
1768 | } | 1770 | } |
1769 | 1771 | ||
1770 | rcu_read_unlock(); | 1772 | disk_stat_unlock(); |
1771 | } | 1773 | } |
1772 | 1774 | ||
1773 | if (req->end_io) | 1775 | if (req->end_io) |
diff --git a/block/blk-merge.c b/block/blk-merge.c index eb2a3ca58303..d926a24bf1fd 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -388,18 +388,19 @@ static int attempt_merge(struct request_queue *q, struct request *req, | |||
388 | 388 | ||
389 | if (req->rq_disk) { | 389 | if (req->rq_disk) { |
390 | struct hd_struct *part; | 390 | struct hd_struct *part; |
391 | int cpu; | ||
391 | 392 | ||
392 | rcu_read_lock(); | 393 | cpu = disk_stat_lock(); |
393 | |||
394 | part = disk_map_sector_rcu(req->rq_disk, req->sector); | 394 | part = disk_map_sector_rcu(req->rq_disk, req->sector); |
395 | disk_round_stats(req->rq_disk); | 395 | |
396 | disk_round_stats(cpu, req->rq_disk); | ||
396 | req->rq_disk->in_flight--; | 397 | req->rq_disk->in_flight--; |
397 | if (part) { | 398 | if (part) { |
398 | part_round_stats(part); | 399 | part_round_stats(cpu, part); |
399 | part->in_flight--; | 400 | part->in_flight--; |
400 | } | 401 | } |
401 | 402 | ||
402 | rcu_read_unlock(); | 403 | disk_stat_unlock(); |
403 | } | 404 | } |
404 | 405 | ||
405 | req->ioprio = ioprio_best(req->ioprio, next->ioprio); | 406 | req->ioprio = ioprio_best(req->ioprio, next->ioprio); |
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)), |
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 84c03d65dcc5..17eed8c025d0 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
@@ -756,16 +756,17 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector | |||
756 | unsigned long n_sect = bio->bi_size >> 9; | 756 | unsigned long n_sect = bio->bi_size >> 9; |
757 | const int rw = bio_data_dir(bio); | 757 | const int rw = bio_data_dir(bio); |
758 | struct hd_struct *part; | 758 | struct hd_struct *part; |
759 | int cpu; | ||
759 | 760 | ||
760 | rcu_read_lock(); | 761 | cpu = disk_stat_lock(); |
761 | |||
762 | part = disk_map_sector_rcu(disk, sector); | 762 | part = disk_map_sector_rcu(disk, sector); |
763 | all_stat_inc(disk, part, ios[rw], sector); | ||
764 | all_stat_add(disk, part, ticks[rw], duration, sector); | ||
765 | all_stat_add(disk, part, sectors[rw], n_sect, sector); | ||
766 | all_stat_add(disk, part, io_ticks, duration, sector); | ||
767 | 763 | ||
768 | rcu_read_unlock(); | 764 | all_stat_inc(cpu, disk, part, ios[rw], sector); |
765 | all_stat_add(cpu, disk, part, ticks[rw], duration, sector); | ||
766 | all_stat_add(cpu, disk, part, sectors[rw], n_sect, sector); | ||
767 | all_stat_add(cpu, disk, part, io_ticks, duration, sector); | ||
768 | |||
769 | disk_stat_unlock(); | ||
769 | } | 770 | } |
770 | 771 | ||
771 | void | 772 | void |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index a78caad29996..653624792eaf 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -377,12 +377,13 @@ static void free_tio(struct mapped_device *md, struct dm_target_io *tio) | |||
377 | static void start_io_acct(struct dm_io *io) | 377 | static void start_io_acct(struct dm_io *io) |
378 | { | 378 | { |
379 | struct mapped_device *md = io->md; | 379 | struct mapped_device *md = io->md; |
380 | int cpu; | ||
380 | 381 | ||
381 | io->start_time = jiffies; | 382 | io->start_time = jiffies; |
382 | 383 | ||
383 | preempt_disable(); | 384 | cpu = disk_stat_lock(); |
384 | disk_round_stats(dm_disk(md)); | 385 | disk_round_stats(cpu, dm_disk(md)); |
385 | preempt_enable(); | 386 | disk_stat_unlock(); |
386 | dm_disk(md)->in_flight = atomic_inc_return(&md->pending); | 387 | dm_disk(md)->in_flight = atomic_inc_return(&md->pending); |
387 | } | 388 | } |
388 | 389 | ||
@@ -391,15 +392,15 @@ static int end_io_acct(struct dm_io *io) | |||
391 | struct mapped_device *md = io->md; | 392 | struct mapped_device *md = io->md; |
392 | struct bio *bio = io->bio; | 393 | struct bio *bio = io->bio; |
393 | unsigned long duration = jiffies - io->start_time; | 394 | unsigned long duration = jiffies - io->start_time; |
394 | int pending; | 395 | int pending, cpu; |
395 | int rw = bio_data_dir(bio); | 396 | int rw = bio_data_dir(bio); |
396 | 397 | ||
397 | preempt_disable(); | 398 | cpu = disk_stat_lock(); |
398 | disk_round_stats(dm_disk(md)); | 399 | disk_round_stats(cpu, dm_disk(md)); |
399 | preempt_enable(); | 400 | disk_stat_add(cpu, dm_disk(md), ticks[rw], duration); |
400 | dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); | 401 | disk_stat_unlock(); |
401 | 402 | ||
402 | disk_stat_add(dm_disk(md), ticks[rw], duration); | 403 | dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); |
403 | 404 | ||
404 | return !pending; | 405 | return !pending; |
405 | } | 406 | } |
@@ -885,6 +886,7 @@ static int dm_request(struct request_queue *q, struct bio *bio) | |||
885 | int r = -EIO; | 886 | int r = -EIO; |
886 | int rw = bio_data_dir(bio); | 887 | int rw = bio_data_dir(bio); |
887 | struct mapped_device *md = q->queuedata; | 888 | struct mapped_device *md = q->queuedata; |
889 | int cpu; | ||
888 | 890 | ||
889 | /* | 891 | /* |
890 | * There is no use in forwarding any barrier request since we can't | 892 | * There is no use in forwarding any barrier request since we can't |
@@ -897,8 +899,10 @@ static int dm_request(struct request_queue *q, struct bio *bio) | |||
897 | 899 | ||
898 | down_read(&md->io_lock); | 900 | down_read(&md->io_lock); |
899 | 901 | ||
900 | disk_stat_inc(dm_disk(md), ios[rw]); | 902 | cpu = disk_stat_lock(); |
901 | disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio)); | 903 | disk_stat_inc(cpu, dm_disk(md), ios[rw]); |
904 | disk_stat_add(cpu, dm_disk(md), sectors[rw], bio_sectors(bio)); | ||
905 | disk_stat_unlock(); | ||
902 | 906 | ||
903 | /* | 907 | /* |
904 | * If we're suspended we have to queue | 908 | * If we're suspended we have to queue |
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index b1eebf88c209..00cbc8e47294 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -318,14 +318,17 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) | |||
318 | mddev_t *mddev = q->queuedata; | 318 | mddev_t *mddev = q->queuedata; |
319 | dev_info_t *tmp_dev; | 319 | dev_info_t *tmp_dev; |
320 | sector_t block; | 320 | sector_t block; |
321 | int cpu; | ||
321 | 322 | ||
322 | if (unlikely(bio_barrier(bio))) { | 323 | if (unlikely(bio_barrier(bio))) { |
323 | bio_endio(bio, -EOPNOTSUPP); | 324 | bio_endio(bio, -EOPNOTSUPP); |
324 | return 0; | 325 | return 0; |
325 | } | 326 | } |
326 | 327 | ||
327 | disk_stat_inc(mddev->gendisk, ios[rw]); | 328 | cpu = disk_stat_lock(); |
328 | disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); | 329 | disk_stat_inc(cpu, mddev->gendisk, ios[rw]); |
330 | disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); | ||
331 | disk_stat_unlock(); | ||
329 | 332 | ||
330 | tmp_dev = which_dev(mddev, bio->bi_sector); | 333 | tmp_dev = which_dev(mddev, bio->bi_sector); |
331 | block = bio->bi_sector >> 1; | 334 | block = bio->bi_sector >> 1; |
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index c4779ccba1c3..182f5a94cdc5 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
@@ -147,6 +147,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) | |||
147 | struct multipath_bh * mp_bh; | 147 | struct multipath_bh * mp_bh; |
148 | struct multipath_info *multipath; | 148 | struct multipath_info *multipath; |
149 | const int rw = bio_data_dir(bio); | 149 | const int rw = bio_data_dir(bio); |
150 | int cpu; | ||
150 | 151 | ||
151 | if (unlikely(bio_barrier(bio))) { | 152 | if (unlikely(bio_barrier(bio))) { |
152 | bio_endio(bio, -EOPNOTSUPP); | 153 | bio_endio(bio, -EOPNOTSUPP); |
@@ -158,8 +159,10 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) | |||
158 | mp_bh->master_bio = bio; | 159 | mp_bh->master_bio = bio; |
159 | mp_bh->mddev = mddev; | 160 | mp_bh->mddev = mddev; |
160 | 161 | ||
161 | disk_stat_inc(mddev->gendisk, ios[rw]); | 162 | cpu = disk_stat_lock(); |
162 | disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); | 163 | disk_stat_inc(cpu, mddev->gendisk, ios[rw]); |
164 | disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); | ||
165 | disk_stat_unlock(); | ||
163 | 166 | ||
164 | mp_bh->path = multipath_map(conf); | 167 | mp_bh->path = multipath_map(conf); |
165 | if (mp_bh->path < 0) { | 168 | if (mp_bh->path < 0) { |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 183610635661..e26030fa59ab 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -399,14 +399,17 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) | |||
399 | sector_t chunk; | 399 | sector_t chunk; |
400 | sector_t block, rsect; | 400 | sector_t block, rsect; |
401 | const int rw = bio_data_dir(bio); | 401 | const int rw = bio_data_dir(bio); |
402 | int cpu; | ||
402 | 403 | ||
403 | if (unlikely(bio_barrier(bio))) { | 404 | if (unlikely(bio_barrier(bio))) { |
404 | bio_endio(bio, -EOPNOTSUPP); | 405 | bio_endio(bio, -EOPNOTSUPP); |
405 | return 0; | 406 | return 0; |
406 | } | 407 | } |
407 | 408 | ||
408 | disk_stat_inc(mddev->gendisk, ios[rw]); | 409 | cpu = disk_stat_lock(); |
409 | disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); | 410 | disk_stat_inc(cpu, mddev->gendisk, ios[rw]); |
411 | disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); | ||
412 | disk_stat_unlock(); | ||
410 | 413 | ||
411 | chunk_size = mddev->chunk_size >> 10; | 414 | chunk_size = mddev->chunk_size >> 10; |
412 | chunk_sects = mddev->chunk_size >> 9; | 415 | chunk_sects = mddev->chunk_size >> 9; |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 0b82030c265d..babb13036f93 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -779,7 +779,7 @@ static int make_request(struct request_queue *q, struct bio * bio) | |||
779 | struct page **behind_pages = NULL; | 779 | struct page **behind_pages = NULL; |
780 | const int rw = bio_data_dir(bio); | 780 | const int rw = bio_data_dir(bio); |
781 | const int do_sync = bio_sync(bio); | 781 | const int do_sync = bio_sync(bio); |
782 | int do_barriers; | 782 | int cpu, do_barriers; |
783 | mdk_rdev_t *blocked_rdev; | 783 | mdk_rdev_t *blocked_rdev; |
784 | 784 | ||
785 | /* | 785 | /* |
@@ -804,8 +804,10 @@ static int make_request(struct request_queue *q, struct bio * bio) | |||
804 | 804 | ||
805 | bitmap = mddev->bitmap; | 805 | bitmap = mddev->bitmap; |
806 | 806 | ||
807 | disk_stat_inc(mddev->gendisk, ios[rw]); | 807 | cpu = disk_stat_lock(); |
808 | disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); | 808 | disk_stat_inc(cpu, mddev->gendisk, ios[rw]); |
809 | disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); | ||
810 | disk_stat_unlock(); | ||
809 | 811 | ||
810 | /* | 812 | /* |
811 | * make_request() can abort the operation when READA is being | 813 | * make_request() can abort the operation when READA is being |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index d3b9aa096285..5ec80da0a9d7 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -789,6 +789,7 @@ static int make_request(struct request_queue *q, struct bio * bio) | |||
789 | mirror_info_t *mirror; | 789 | mirror_info_t *mirror; |
790 | r10bio_t *r10_bio; | 790 | r10bio_t *r10_bio; |
791 | struct bio *read_bio; | 791 | struct bio *read_bio; |
792 | int cpu; | ||
792 | int i; | 793 | int i; |
793 | int chunk_sects = conf->chunk_mask + 1; | 794 | int chunk_sects = conf->chunk_mask + 1; |
794 | const int rw = bio_data_dir(bio); | 795 | const int rw = bio_data_dir(bio); |
@@ -843,8 +844,10 @@ static int make_request(struct request_queue *q, struct bio * bio) | |||
843 | */ | 844 | */ |
844 | wait_barrier(conf); | 845 | wait_barrier(conf); |
845 | 846 | ||
846 | disk_stat_inc(mddev->gendisk, ios[rw]); | 847 | cpu = disk_stat_lock(); |
847 | disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); | 848 | disk_stat_inc(cpu, mddev->gendisk, ios[rw]); |
849 | disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); | ||
850 | disk_stat_unlock(); | ||
848 | 851 | ||
849 | r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO); | 852 | r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO); |
850 | 853 | ||
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 37e546528f9c..5899f211515f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3387,7 +3387,7 @@ static int make_request(struct request_queue *q, struct bio * bi) | |||
3387 | sector_t logical_sector, last_sector; | 3387 | sector_t logical_sector, last_sector; |
3388 | struct stripe_head *sh; | 3388 | struct stripe_head *sh; |
3389 | const int rw = bio_data_dir(bi); | 3389 | const int rw = bio_data_dir(bi); |
3390 | int remaining; | 3390 | int cpu, remaining; |
3391 | 3391 | ||
3392 | if (unlikely(bio_barrier(bi))) { | 3392 | if (unlikely(bio_barrier(bi))) { |
3393 | bio_endio(bi, -EOPNOTSUPP); | 3393 | bio_endio(bi, -EOPNOTSUPP); |
@@ -3396,8 +3396,10 @@ static int make_request(struct request_queue *q, struct bio * bi) | |||
3396 | 3396 | ||
3397 | md_write_start(mddev, bi); | 3397 | md_write_start(mddev, bi); |
3398 | 3398 | ||
3399 | disk_stat_inc(mddev->gendisk, ios[rw]); | 3399 | cpu = disk_stat_lock(); |
3400 | disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi)); | 3400 | disk_stat_inc(cpu, mddev->gendisk, ios[rw]); |
3401 | disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bi)); | ||
3402 | disk_stat_unlock(); | ||
3401 | 3403 | ||
3402 | if (rw == READ && | 3404 | if (rw == READ && |
3403 | mddev->reshape_position == MaxSector && | 3405 | mddev->reshape_position == MaxSector && |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 96c8bf41e455..c442f0aadac3 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -219,10 +219,11 @@ static ssize_t part_stat_show(struct device *dev, | |||
219 | struct device_attribute *attr, char *buf) | 219 | struct device_attribute *attr, char *buf) |
220 | { | 220 | { |
221 | struct hd_struct *p = dev_to_part(dev); | 221 | struct hd_struct *p = dev_to_part(dev); |
222 | int cpu; | ||
222 | 223 | ||
223 | preempt_disable(); | 224 | cpu = disk_stat_lock(); |
224 | part_round_stats(p); | 225 | part_round_stats(cpu, p); |
225 | preempt_enable(); | 226 | disk_stat_unlock(); |
226 | return sprintf(buf, | 227 | return sprintf(buf, |
227 | "%8lu %8lu %8llu %8u " | 228 | "%8lu %8lu %8llu %8u " |
228 | "%8lu %8lu %8llu %8u " | 229 | "%8lu %8lu %8llu %8u " |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 7fbba19e076b..ac8a901f2002 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -209,16 +209,24 @@ extern void disk_part_iter_exit(struct disk_part_iter *piter); | |||
209 | extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, | 209 | extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, |
210 | sector_t sector); | 210 | sector_t sector); |
211 | 211 | ||
212 | /* | 212 | /* |
213 | * Macros to operate on percpu disk statistics: | 213 | * Macros to operate on percpu disk statistics: |
214 | * | 214 | * |
215 | * The __ variants should only be called in critical sections. The full | 215 | * {disk|part|all}_stat_{add|sub|inc|dec}() modify the stat counters |
216 | * variants disable/enable preemption. | 216 | * and should be called between disk_stat_lock() and |
217 | * disk_stat_unlock(). | ||
218 | * | ||
219 | * part_stat_read() can be called at any time. | ||
220 | * | ||
221 | * part_stat_{add|set_all}() and {init|free}_part_stats are for | ||
222 | * internal use only. | ||
217 | */ | 223 | */ |
218 | |||
219 | #ifdef CONFIG_SMP | 224 | #ifdef CONFIG_SMP |
220 | #define __disk_stat_add(gendiskp, field, addnd) \ | 225 | #define disk_stat_lock() ({ rcu_read_lock(); get_cpu(); }) |
221 | (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) | 226 | #define disk_stat_unlock() do { put_cpu(); rcu_read_unlock(); } while (0) |
227 | |||
228 | #define disk_stat_add(cpu, gendiskp, field, addnd) \ | ||
229 | (per_cpu_ptr(gendiskp->dkstats, cpu)->field += addnd) | ||
222 | 230 | ||
223 | #define disk_stat_read(gendiskp, field) \ | 231 | #define disk_stat_read(gendiskp, field) \ |
224 | ({ \ | 232 | ({ \ |
@@ -229,7 +237,8 @@ extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, | |||
229 | res; \ | 237 | res; \ |
230 | }) | 238 | }) |
231 | 239 | ||
232 | static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { | 240 | static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) |
241 | { | ||
233 | int i; | 242 | int i; |
234 | 243 | ||
235 | for_each_possible_cpu(i) | 244 | for_each_possible_cpu(i) |
@@ -237,14 +246,14 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { | |||
237 | sizeof(struct disk_stats)); | 246 | sizeof(struct disk_stats)); |
238 | } | 247 | } |
239 | 248 | ||
240 | #define __part_stat_add(part, field, addnd) \ | 249 | #define part_stat_add(cpu, part, field, addnd) \ |
241 | (per_cpu_ptr(part->dkstats, smp_processor_id())->field += addnd) | 250 | (per_cpu_ptr(part->dkstats, cpu)->field += addnd) |
242 | 251 | ||
243 | #define __all_stat_add(gendiskp, part, field, addnd, sector) \ | 252 | #define all_stat_add(cpu, gendiskp, part, field, addnd, sector) \ |
244 | ({ \ | 253 | ({ \ |
245 | if (part) \ | 254 | if (part) \ |
246 | __part_stat_add(part, field, addnd); \ | 255 | part_stat_add(cpu, part, field, addnd); \ |
247 | __disk_stat_add(gendiskp, field, addnd); \ | 256 | disk_stat_add(cpu, gendiskp, field, addnd); \ |
248 | }) | 257 | }) |
249 | 258 | ||
250 | #define part_stat_read(part, field) \ | 259 | #define part_stat_read(part, field) \ |
@@ -264,10 +273,13 @@ static inline void part_stat_set_all(struct hd_struct *part, int value) | |||
264 | memset(per_cpu_ptr(part->dkstats, i), value, | 273 | memset(per_cpu_ptr(part->dkstats, i), value, |
265 | sizeof(struct disk_stats)); | 274 | sizeof(struct disk_stats)); |
266 | } | 275 | } |
267 | 276 | ||
268 | #else /* !CONFIG_SMP */ | 277 | #else /* !CONFIG_SMP */ |
269 | #define __disk_stat_add(gendiskp, field, addnd) \ | 278 | #define disk_stat_lock() ({ rcu_read_lock(); 0; }) |
270 | (gendiskp->dkstats.field += addnd) | 279 | #define disk_stat_unlock() rcu_read_unlock() |
280 | |||
281 | #define disk_stat_add(cpu, gendiskp, field, addnd) \ | ||
282 | (gendiskp->dkstats.field += addnd) | ||
271 | #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) | 283 | #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) |
272 | 284 | ||
273 | static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) | 285 | static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) |
@@ -275,14 +287,14 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) | |||
275 | memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); | 287 | memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); |
276 | } | 288 | } |
277 | 289 | ||
278 | #define __part_stat_add(part, field, addnd) \ | 290 | #define part_stat_add(cpu, part, field, addnd) \ |
279 | (part->dkstats.field += addnd) | 291 | (part->dkstats.field += addnd) |
280 | 292 | ||
281 | #define __all_stat_add(gendiskp, part, field, addnd, sector) \ | 293 | #define all_stat_add(cpu, gendiskp, part, field, addnd, sector) \ |
282 | ({ \ | 294 | ({ \ |
283 | if (part) \ | 295 | if (part) \ |
284 | part->dkstats.field += addnd; \ | 296 | part_stat_add(cpu, part, field, addnd); \ |
285 | __disk_stat_add(gendiskp, field, addnd); \ | 297 | disk_stat_add(cpu, gendiskp, field, addnd); \ |
286 | }) | 298 | }) |
287 | 299 | ||
288 | #define part_stat_read(part, field) (part->dkstats.field) | 300 | #define part_stat_read(part, field) (part->dkstats.field) |
@@ -294,63 +306,26 @@ static inline void part_stat_set_all(struct hd_struct *part, int value) | |||
294 | 306 | ||
295 | #endif /* CONFIG_SMP */ | 307 | #endif /* CONFIG_SMP */ |
296 | 308 | ||
297 | #define disk_stat_add(gendiskp, field, addnd) \ | 309 | #define disk_stat_dec(cpu, gendiskp, field) \ |
298 | do { \ | 310 | disk_stat_add(cpu, gendiskp, field, -1) |
299 | preempt_disable(); \ | 311 | #define disk_stat_inc(cpu, gendiskp, field) \ |
300 | __disk_stat_add(gendiskp, field, addnd); \ | 312 | disk_stat_add(cpu, gendiskp, field, 1) |
301 | preempt_enable(); \ | 313 | #define disk_stat_sub(cpu, gendiskp, field, subnd) \ |
302 | } while (0) | 314 | disk_stat_add(cpu, gendiskp, field, -subnd) |
303 | 315 | ||
304 | #define __disk_stat_dec(gendiskp, field) __disk_stat_add(gendiskp, field, -1) | 316 | #define part_stat_dec(cpu, gendiskp, field) \ |
305 | #define disk_stat_dec(gendiskp, field) disk_stat_add(gendiskp, field, -1) | 317 | part_stat_add(cpu, gendiskp, field, -1) |
306 | 318 | #define part_stat_inc(cpu, gendiskp, field) \ | |
307 | #define __disk_stat_inc(gendiskp, field) __disk_stat_add(gendiskp, field, 1) | 319 | part_stat_add(cpu, gendiskp, field, 1) |
308 | #define disk_stat_inc(gendiskp, field) disk_stat_add(gendiskp, field, 1) | 320 | #define part_stat_sub(cpu, gendiskp, field, subnd) \ |
309 | 321 | part_stat_add(cpu, gendiskp, field, -subnd) | |
310 | #define __disk_stat_sub(gendiskp, field, subnd) \ | 322 | |
311 | __disk_stat_add(gendiskp, field, -subnd) | 323 | #define all_stat_dec(cpu, gendiskp, field, sector) \ |
312 | #define disk_stat_sub(gendiskp, field, subnd) \ | 324 | all_stat_add(cpu, gendiskp, field, -1, sector) |
313 | disk_stat_add(gendiskp, field, -subnd) | 325 | #define all_stat_inc(cpu, gendiskp, part, field, sector) \ |
314 | 326 | all_stat_add(cpu, gendiskp, part, field, 1, sector) | |
315 | #define part_stat_add(gendiskp, field, addnd) \ | 327 | #define all_stat_sub(cpu, gendiskp, part, field, subnd, sector) \ |
316 | do { \ | 328 | all_stat_add(cpu, gendiskp, part, field, -subnd, sector) |
317 | preempt_disable(); \ | ||
318 | __part_stat_add(gendiskp, field, addnd);\ | ||
319 | preempt_enable(); \ | ||
320 | } while (0) | ||
321 | |||
322 | #define __part_stat_dec(gendiskp, field) __part_stat_add(gendiskp, field, -1) | ||
323 | #define part_stat_dec(gendiskp, field) part_stat_add(gendiskp, field, -1) | ||
324 | |||
325 | #define __part_stat_inc(gendiskp, field) __part_stat_add(gendiskp, field, 1) | ||
326 | #define part_stat_inc(gendiskp, field) part_stat_add(gendiskp, field, 1) | ||
327 | |||
328 | #define __part_stat_sub(gendiskp, field, subnd) \ | ||
329 | __part_stat_add(gendiskp, field, -subnd) | ||
330 | #define part_stat_sub(gendiskp, field, subnd) \ | ||
331 | part_stat_add(gendiskp, field, -subnd) | ||
332 | |||
333 | #define all_stat_add(gendiskp, part, field, addnd, sector) \ | ||
334 | do { \ | ||
335 | preempt_disable(); \ | ||
336 | __all_stat_add(gendiskp, part, field, addnd, sector); \ | ||
337 | preempt_enable(); \ | ||
338 | } while (0) | ||
339 | |||
340 | #define __all_stat_dec(gendiskp, field, sector) \ | ||
341 | __all_stat_add(gendiskp, field, -1, sector) | ||
342 | #define all_stat_dec(gendiskp, field, sector) \ | ||
343 | all_stat_add(gendiskp, field, -1, sector) | ||
344 | |||
345 | #define __all_stat_inc(gendiskp, part, field, sector) \ | ||
346 | __all_stat_add(gendiskp, part, field, 1, sector) | ||
347 | #define all_stat_inc(gendiskp, part, field, sector) \ | ||
348 | all_stat_add(gendiskp, part, field, 1, sector) | ||
349 | |||
350 | #define __all_stat_sub(gendiskp, part, field, subnd, sector) \ | ||
351 | __all_stat_add(gendiskp, part, field, -subnd, sector) | ||
352 | #define all_stat_sub(gendiskp, part, field, subnd, sector) \ | ||
353 | all_stat_add(gendiskp, part, field, -subnd, sector) | ||
354 | 329 | ||
355 | /* Inlines to alloc and free disk stats in struct gendisk */ | 330 | /* Inlines to alloc and free disk stats in struct gendisk */ |
356 | #ifdef CONFIG_SMP | 331 | #ifdef CONFIG_SMP |
@@ -401,8 +376,8 @@ static inline void free_part_stats(struct hd_struct *part) | |||
401 | #endif /* CONFIG_SMP */ | 376 | #endif /* CONFIG_SMP */ |
402 | 377 | ||
403 | /* drivers/block/ll_rw_blk.c */ | 378 | /* drivers/block/ll_rw_blk.c */ |
404 | extern void disk_round_stats(struct gendisk *disk); | 379 | extern void disk_round_stats(int cpu, struct gendisk *disk); |
405 | extern void part_round_stats(struct hd_struct *part); | 380 | extern void part_round_stats(int cpu, struct hd_struct *part); |
406 | 381 | ||
407 | /* drivers/block/genhd.c */ | 382 | /* drivers/block/genhd.c */ |
408 | extern int get_blkdev_list(char *, int); | 383 | extern int get_blkdev_list(char *, int); |