aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-08-25 06:56:14 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-10-09 02:56:08 -0400
commit074a7aca7afa6f230104e8e65eba3420263714a5 (patch)
treef418313e45bd55be8156c8a3e8f9a216cf63058d /block
parenteddb2e26b5ee3c5da68ba4bf1921ba20e2097bff (diff)
block: move stats from disk to part0
Move stats related fields - stamp, in_flight, dkstats - from disk to part0 and unify stat handling such that... * part_stat_*() now updates part0 together if the specified partition is not part0. ie. part_stat_*() are now essentially all_stat_*(). * {disk|all}_stat_*() are gone. * part_round_stats() is updated similary. It handles part0 stats automatically and disk_round_stats() is killed. * part_{inc|dec}_in_fligh() is implemented which automatically updates part0 stats for parts other than part0. * disk_map_sector_rcu() is updated to return part0 if no part matches. Combined with the above changes, this makes NULL special case handling in callers unnecessary. * Separate stats show code paths for disk are collapsed into part stats show code paths. * Rename disk_stat_lock/unlock() to part_stat_lock/unlock() While at it, reposition stat handling macros a bit and add missing parentheses around macro parameters. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r--block/blk-core.c84
-rw-r--r--block/blk-merge.c12
-rw-r--r--block/genhd.c97
3 files changed, 62 insertions, 131 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 505ec61067df..98138f002524 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -61,21 +61,17 @@ static void drive_stat_acct(struct request *rq, int new_io)
61 if (!blk_fs_request(rq) || !rq->rq_disk) 61 if (!blk_fs_request(rq) || !rq->rq_disk)
62 return; 62 return;
63 63
64 cpu = disk_stat_lock(); 64 cpu = part_stat_lock();
65 part = disk_map_sector_rcu(rq->rq_disk, rq->sector); 65 part = disk_map_sector_rcu(rq->rq_disk, rq->sector);
66 66
67 if (!new_io) 67 if (!new_io)
68 all_stat_inc(cpu, rq->rq_disk, part, merges[rw], rq->sector); 68 part_stat_inc(cpu, part, merges[rw]);
69 else { 69 else {
70 disk_round_stats(cpu, rq->rq_disk); 70 part_round_stats(cpu, part);
71 rq->rq_disk->in_flight++; 71 part_inc_in_flight(part);
72 if (part) {
73 part_round_stats(cpu, part);
74 part->in_flight++;
75 }
76 } 72 }
77 73
78 disk_stat_unlock(); 74 part_stat_unlock();
79} 75}
80 76
81void blk_queue_congestion_threshold(struct request_queue *q) 77void blk_queue_congestion_threshold(struct request_queue *q)
@@ -983,8 +979,22 @@ static inline void add_request(struct request_queue *q, struct request *req)
983 __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); 979 __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0);
984} 980}
985 981
986/* 982static void part_round_stats_single(int cpu, struct hd_struct *part,
987 * disk_round_stats() - Round off the performance stats on a struct 983 unsigned long now)
984{
985 if (now == part->stamp)
986 return;
987
988 if (part->in_flight) {
989 __part_stat_add(cpu, part, time_in_queue,
990 part->in_flight * (now - part->stamp));
991 __part_stat_add(cpu, part, io_ticks, (now - part->stamp));
992 }
993 part->stamp = now;
994}
995
996/**
997 * part_round_stats() - Round off the performance stats on a struct
988 * disk_stats. 998 * disk_stats.
989 * 999 *
990 * The average IO queue length and utilisation statistics are maintained 1000 * The average IO queue length and utilisation statistics are maintained
@@ -998,36 +1008,15 @@ static inline void add_request(struct request_queue *q, struct request *req)
998 * /proc/diskstats. This accounts immediately for all queue usage up to 1008 * /proc/diskstats. This accounts immediately for all queue usage up to
999 * the current jiffies and restarts the counters again. 1009 * the current jiffies and restarts the counters again.
1000 */ 1010 */
1001void disk_round_stats(int cpu, struct gendisk *disk)
1002{
1003 unsigned long now = jiffies;
1004
1005 if (now == disk->stamp)
1006 return;
1007
1008 if (disk->in_flight) {
1009 disk_stat_add(cpu, disk, time_in_queue,
1010 disk->in_flight * (now - disk->stamp));
1011 disk_stat_add(cpu, disk, io_ticks, (now - disk->stamp));
1012 }
1013 disk->stamp = now;
1014}
1015EXPORT_SYMBOL_GPL(disk_round_stats);
1016
1017void part_round_stats(int cpu, struct hd_struct *part) 1011void part_round_stats(int cpu, struct hd_struct *part)
1018{ 1012{
1019 unsigned long now = jiffies; 1013 unsigned long now = jiffies;
1020 1014
1021 if (now == part->stamp) 1015 if (part->partno)
1022 return; 1016 part_round_stats_single(cpu, &part_to_disk(part)->part0, now);
1023 1017 part_round_stats_single(cpu, part, now);
1024 if (part->in_flight) {
1025 part_stat_add(cpu, part, time_in_queue,
1026 part->in_flight * (now - part->stamp));
1027 part_stat_add(cpu, part, io_ticks, (now - part->stamp));
1028 }
1029 part->stamp = now;
1030} 1018}
1019EXPORT_SYMBOL_GPL(part_round_stats);
1031 1020
1032/* 1021/*
1033 * queue lock must be held 1022 * queue lock must be held
@@ -1567,11 +1556,10 @@ static int __end_that_request_first(struct request *req, int error,
1567 struct hd_struct *part; 1556 struct hd_struct *part;
1568 int cpu; 1557 int cpu;
1569 1558
1570 cpu = disk_stat_lock(); 1559 cpu = part_stat_lock();
1571 part = disk_map_sector_rcu(req->rq_disk, req->sector); 1560 part = disk_map_sector_rcu(req->rq_disk, req->sector);
1572 all_stat_add(cpu, req->rq_disk, part, sectors[rw], 1561 part_stat_add(cpu, part, sectors[rw], nr_bytes >> 9);
1573 nr_bytes >> 9, req->sector); 1562 part_stat_unlock();
1574 disk_stat_unlock();
1575 } 1563 }
1576 1564
1577 total_bytes = bio_nbytes = 0; 1565 total_bytes = bio_nbytes = 0;
@@ -1758,19 +1746,15 @@ static void end_that_request_last(struct request *req, int error)
1758 struct hd_struct *part; 1746 struct hd_struct *part;
1759 int cpu; 1747 int cpu;
1760 1748
1761 cpu = disk_stat_lock(); 1749 cpu = part_stat_lock();
1762 part = disk_map_sector_rcu(disk, req->sector); 1750 part = disk_map_sector_rcu(disk, req->sector);
1763 1751
1764 all_stat_inc(cpu, disk, part, ios[rw], req->sector); 1752 part_stat_inc(cpu, part, ios[rw]);
1765 all_stat_add(cpu, disk, part, ticks[rw], duration, req->sector); 1753 part_stat_add(cpu, part, ticks[rw], duration);
1766 disk_round_stats(cpu, disk); 1754 part_round_stats(cpu, part);
1767 disk->in_flight--; 1755 part_dec_in_flight(part);
1768 if (part) {
1769 part_round_stats(cpu, part);
1770 part->in_flight--;
1771 }
1772 1756
1773 disk_stat_unlock(); 1757 part_stat_unlock();
1774 } 1758 }
1775 1759
1776 if (req->end_io) 1760 if (req->end_io)
diff --git a/block/blk-merge.c b/block/blk-merge.c
index d926a24bf1fd..c77196d55899 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -390,17 +390,13 @@ static int attempt_merge(struct request_queue *q, struct request *req,
390 struct hd_struct *part; 390 struct hd_struct *part;
391 int cpu; 391 int cpu;
392 392
393 cpu = disk_stat_lock(); 393 cpu = part_stat_lock();
394 part = disk_map_sector_rcu(req->rq_disk, req->sector); 394 part = disk_map_sector_rcu(req->rq_disk, req->sector);
395 395
396 disk_round_stats(cpu, req->rq_disk); 396 part_round_stats(cpu, part);
397 req->rq_disk->in_flight--; 397 part_dec_in_flight(part);
398 if (part) {
399 part_round_stats(cpu, part);
400 part->in_flight--;
401 }
402 398
403 disk_stat_unlock(); 399 part_stat_unlock();
404 } 400 }
405 401
406 req->ioprio = ioprio_best(req->ioprio, next->ioprio); 402 req->ioprio = ioprio_best(req->ioprio, next->ioprio);
diff --git a/block/genhd.c b/block/genhd.c
index 06a252f2b967..e1cb96fb883e 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -176,7 +176,7 @@ EXPORT_SYMBOL_GPL(disk_part_iter_exit);
176 * while preemption is disabled. 176 * while preemption is disabled.
177 * 177 *
178 * RETURNS: 178 * RETURNS:
179 * Found partition on success, NULL if there's no matching partition. 179 * Found partition on success, part0 is returned if no partition matches
180 */ 180 */
181struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) 181struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector)
182{ 182{
@@ -189,7 +189,7 @@ struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector)
189 sector < part->start_sect + part->nr_sects) 189 sector < part->start_sect + part->nr_sects)
190 return part; 190 return part;
191 } 191 }
192 return NULL; 192 return &disk->part0;
193} 193}
194EXPORT_SYMBOL_GPL(disk_map_sector_rcu); 194EXPORT_SYMBOL_GPL(disk_map_sector_rcu);
195 195
@@ -580,24 +580,24 @@ void __init printk_all_partitions(void)
580 * numbers in hex - the same format as the root= 580 * numbers in hex - the same format as the root=
581 * option takes. 581 * option takes.
582 */ 582 */
583 printk("%s %10llu %s", 583 disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
584 bdevt_str(disk_devt(disk), devt_buf), 584 while ((part = disk_part_iter_next(&piter))) {
585 (unsigned long long)get_capacity(disk) >> 1, 585 bool is_part0 = part == &disk->part0;
586 disk_name(disk, 0, name_buf));
587 if (disk->driverfs_dev != NULL &&
588 disk->driverfs_dev->driver != NULL)
589 printk(" driver: %s\n",
590 disk->driverfs_dev->driver->name);
591 else
592 printk(" (driver?)\n");
593 586
594 /* now show the partitions */ 587 printk("%s%s %10llu %s", is_part0 ? "" : " ",
595 disk_part_iter_init(&piter, disk, 0);
596 while ((part = disk_part_iter_next(&piter)))
597 printk(" %s %10llu %s\n",
598 bdevt_str(part_devt(part), devt_buf), 588 bdevt_str(part_devt(part), devt_buf),
599 (unsigned long long)part->nr_sects >> 1, 589 (unsigned long long)part->nr_sects >> 1,
600 disk_name(disk, part->partno, name_buf)); 590 disk_name(disk, part->partno, name_buf));
591 if (is_part0) {
592 if (disk->driverfs_dev != NULL &&
593 disk->driverfs_dev->driver != NULL)
594 printk(" driver: %s\n",
595 disk->driverfs_dev->driver->name);
596 else
597 printk(" (driver?)\n");
598 } else
599 printk("\n");
600 }
601 disk_part_iter_exit(&piter); 601 disk_part_iter_exit(&piter);
602 } 602 }
603 class_dev_iter_exit(&iter); 603 class_dev_iter_exit(&iter);
@@ -674,12 +674,7 @@ static int show_partition(struct seq_file *seqf, void *v)
674 return 0; 674 return 0;
675 675
676 /* show the full disk and all non-0 size partitions of it */ 676 /* show the full disk and all non-0 size partitions of it */
677 seq_printf(seqf, "%4d %7d %10llu %s\n", 677 disk_part_iter_init(&piter, sgp, DISK_PITER_INCL_PART0);
678 MAJOR(disk_devt(sgp)), MINOR(disk_devt(sgp)),
679 (unsigned long long)get_capacity(sgp) >> 1,
680 disk_name(sgp, 0, buf));
681
682 disk_part_iter_init(&piter, sgp, 0);
683 while ((part = disk_part_iter_next(&piter))) 678 while ((part = disk_part_iter_next(&piter)))
684 seq_printf(seqf, "%4d %7d %10llu %s\n", 679 seq_printf(seqf, "%4d %7d %10llu %s\n",
685 MAJOR(part_devt(part)), MINOR(part_devt(part)), 680 MAJOR(part_devt(part)), MINOR(part_devt(part)),
@@ -768,40 +763,13 @@ static ssize_t disk_capability_show(struct device *dev,
768 return sprintf(buf, "%x\n", disk->flags); 763 return sprintf(buf, "%x\n", disk->flags);
769} 764}
770 765
771static ssize_t disk_stat_show(struct device *dev,
772 struct device_attribute *attr, char *buf)
773{
774 struct gendisk *disk = dev_to_disk(dev);
775 int cpu;
776
777 cpu = disk_stat_lock();
778 disk_round_stats(cpu, disk);
779 disk_stat_unlock();
780 return sprintf(buf,
781 "%8lu %8lu %8llu %8u "
782 "%8lu %8lu %8llu %8u "
783 "%8u %8u %8u"
784 "\n",
785 disk_stat_read(disk, ios[READ]),
786 disk_stat_read(disk, merges[READ]),
787 (unsigned long long)disk_stat_read(disk, sectors[READ]),
788 jiffies_to_msecs(disk_stat_read(disk, ticks[READ])),
789 disk_stat_read(disk, ios[WRITE]),
790 disk_stat_read(disk, merges[WRITE]),
791 (unsigned long long)disk_stat_read(disk, sectors[WRITE]),
792 jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])),
793 disk->in_flight,
794 jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
795 jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
796}
797
798static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); 766static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
799static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); 767static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL);
800static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); 768static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
801static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); 769static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL);
802static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); 770static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
803static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); 771static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL);
804static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL); 772static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL);
805#ifdef CONFIG_FAIL_MAKE_REQUEST 773#ifdef CONFIG_FAIL_MAKE_REQUEST
806static struct device_attribute dev_attr_fail = 774static struct device_attribute dev_attr_fail =
807 __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store); 775 __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
@@ -836,7 +804,7 @@ static void disk_release(struct device *dev)
836 804
837 kfree(disk->random); 805 kfree(disk->random);
838 kfree(disk->__part); 806 kfree(disk->__part);
839 free_disk_stats(disk); 807 free_part_stats(&disk->part0);
840 kfree(disk); 808 kfree(disk);
841} 809}
842struct class block_class = { 810struct class block_class = {
@@ -873,28 +841,11 @@ static int diskstats_show(struct seq_file *seqf, void *v)
873 "\n\n"); 841 "\n\n");
874 */ 842 */
875 843
876 cpu = disk_stat_lock(); 844 disk_part_iter_init(&piter, gp, DISK_PITER_INCL_PART0);
877 disk_round_stats(cpu, gp);
878 disk_stat_unlock();
879 seq_printf(seqf, "%4d %7d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n",
880 MAJOR(disk_devt(gp)), MINOR(disk_devt(gp)),
881 disk_name(gp, 0, buf),
882 disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]),
883 (unsigned long long)disk_stat_read(gp, sectors[0]),
884 jiffies_to_msecs(disk_stat_read(gp, ticks[0])),
885 disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]),
886 (unsigned long long)disk_stat_read(gp, sectors[1]),
887 jiffies_to_msecs(disk_stat_read(gp, ticks[1])),
888 gp->in_flight,
889 jiffies_to_msecs(disk_stat_read(gp, io_ticks)),
890 jiffies_to_msecs(disk_stat_read(gp, time_in_queue)));
891
892 /* now show all non-0 size partitions of it */
893 disk_part_iter_init(&piter, gp, 0);
894 while ((hd = disk_part_iter_next(&piter))) { 845 while ((hd = disk_part_iter_next(&piter))) {
895 cpu = disk_stat_lock(); 846 cpu = part_stat_lock();
896 part_round_stats(cpu, hd); 847 part_round_stats(cpu, hd);
897 disk_stat_unlock(); 848 part_stat_unlock();
898 seq_printf(seqf, "%4d %7d %s %lu %lu %llu " 849 seq_printf(seqf, "%4d %7d %s %lu %lu %llu "
899 "%u %lu %lu %llu %u %u %u %u\n", 850 "%u %lu %lu %llu %u %u %u %u\n",
900 MAJOR(part_devt(hd)), MINOR(part_devt(hd)), 851 MAJOR(part_devt(hd)), MINOR(part_devt(hd)),
@@ -1000,7 +951,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id)
1000 int tot_minors = minors + ext_minors; 951 int tot_minors = minors + ext_minors;
1001 int size = tot_minors * sizeof(struct hd_struct *); 952 int size = tot_minors * sizeof(struct hd_struct *);
1002 953
1003 if (!init_disk_stats(disk)) { 954 if (!init_part_stats(&disk->part0)) {
1004 kfree(disk); 955 kfree(disk);
1005 return NULL; 956 return NULL;
1006 } 957 }
@@ -1008,7 +959,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id)
1008 disk->__part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, 959 disk->__part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO,
1009 node_id); 960 node_id);
1010 if (!disk->__part) { 961 if (!disk->__part) {
1011 free_disk_stats(disk); 962 free_part_stats(&disk->part0);
1012 kfree(disk); 963 kfree(disk);
1013 return NULL; 964 return NULL;
1014 } 965 }