Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block

* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
Enhanced partition statistics: documentation update
Enhanced partition statistics: remove old partition statistics
Enhanced partition statistics: procfs
Enhanced partition statistics: sysfs
Enhanced partition statistics: aoe fix
Enhanced partition statistics: update partition statitics
Enhanced partition statistics: core statistics
block: fixup rq_init() a bit

Manually fixed conflict in drivers/block/aoe/aoecmd.c due to statistics
support.

+320 -48
+22
Documentation/ABI/testing/procfs-diskstats
···
··· 1 + What: /proc/diskstats 2 + Date: February 2008 3 + Contact: Jerome Marchand <jmarchan@redhat.com> 4 + Description: 5 + The /proc/diskstats file displays the I/O statistics 6 + of block devices. Each line contains the following 14 7 + fields: 8 + 1 - major number 9 + 2 - minor mumber 10 + 3 - device name 11 + 4 - reads completed succesfully 12 + 5 - reads merged 13 + 6 - sectors read 14 + 7 - time spent reading (ms) 15 + 8 - writes completed 16 + 9 - writes merged 17 + 10 - sectors written 18 + 11 - time spent writing (ms) 19 + 12 - I/Os currently in progress 20 + 13 - time spent doing I/Os (ms) 21 + 14 - weighted time spent doing I/Os (ms) 22 + For more details refer to Documentation/iostats.txt
+28
Documentation/ABI/testing/sysfs-block
···
··· 1 + What: /sys/block/<disk>/stat 2 + Date: February 2008 3 + Contact: Jerome Marchand <jmarchan@redhat.com> 4 + Description: 5 + The /sys/block/<disk>/stat files displays the I/O 6 + statistics of disk <disk>. They contain 11 fields: 7 + 1 - reads completed succesfully 8 + 2 - reads merged 9 + 3 - sectors read 10 + 4 - time spent reading (ms) 11 + 5 - writes completed 12 + 6 - writes merged 13 + 7 - sectors written 14 + 8 - time spent writing (ms) 15 + 9 - I/Os currently in progress 16 + 10 - time spent doing I/Os (ms) 17 + 11 - weighted time spent doing I/Os (ms) 18 + For more details refer Documentation/iostats.txt 19 + 20 + 21 + What: /sys/block/<disk>/<part>/stat 22 + Date: February 2008 23 + Contact: Jerome Marchand <jmarchan@redhat.com> 24 + Description: 25 + The /sys/block/<disk>/<part>/stat files display the 26 + I/O statistics of partition <part>. The format is the 27 + same as the above-written /sys/block/<disk>/stat 28 + format.
+14 -1
Documentation/iostats.txt
··· 58 Each set of stats only applies to the indicated device; if you want 59 system-wide stats you'll have to find all the devices and sum them all up. 60 61 - Field 1 -- # of reads issued 62 This is the total number of reads completed successfully. 63 Field 2 -- # of reads merged, field 6 -- # of writes merged 64 Reads and writes which are adjacent to each other may be merged for ··· 131 words, the number of reads for partitions is counted slightly before time 132 of queuing for partitions, and at completion for whole disks. This is 133 a subtle distinction that is probably uninteresting for most cases. 134 135 Additional notes 136 ----------------
··· 58 Each set of stats only applies to the indicated device; if you want 59 system-wide stats you'll have to find all the devices and sum them all up. 60 61 + Field 1 -- # of reads completed 62 This is the total number of reads completed successfully. 63 Field 2 -- # of reads merged, field 6 -- # of writes merged 64 Reads and writes which are adjacent to each other may be merged for ··· 131 words, the number of reads for partitions is counted slightly before time 132 of queuing for partitions, and at completion for whole disks. This is 133 a subtle distinction that is probably uninteresting for most cases. 134 + 135 + More significant is the error induced by counting the numbers of 136 + reads/writes before merges for partitions and after for disks. Since a 137 + typical workload usually contains a lot of successive and adjacent requests, 138 + the number of reads/writes issued can be several times higher than the 139 + number of reads/writes completed. 140 + 141 + In 2.6.25, the full statistic set is again available for partitions and 142 + disk and partition statistics are consistent again. Since we still don't 143 + keep record of the partition-relative address, an operation is attributed to 144 + the partition which contains the first sector of the request after the 145 + eventual merges. As requests can be merged across partition, this could lead 146 + to some (probably insignificant) innacuracy. 147 148 Additional notes 149 ----------------
+51 -18
block/blk-core.c
··· 60 return; 61 62 if (!new_io) { 63 - __disk_stat_inc(rq->rq_disk, merges[rw]); 64 } else { 65 disk_round_stats(rq->rq_disk); 66 rq->rq_disk->in_flight++; 67 } 68 } 69 ··· 107 } 108 EXPORT_SYMBOL(blk_get_backing_dev_info); 109 110 void rq_init(struct request_queue *q, struct request *rq) 111 { 112 INIT_LIST_HEAD(&rq->queuelist); 113 INIT_LIST_HEAD(&rq->donelist); 114 - 115 - rq->errors = 0; 116 rq->bio = rq->biotail = NULL; 117 INIT_HLIST_NODE(&rq->hash); 118 RB_CLEAR_NODE(&rq->rb_node); 119 - rq->ioprio = 0; 120 - rq->buffer = NULL; 121 - rq->ref_count = 1; 122 - rq->q = q; 123 - rq->special = NULL; 124 - rq->data_len = 0; 125 - rq->data = NULL; 126 rq->nr_phys_segments = 0; 127 rq->sense = NULL; 128 rq->end_io = NULL; 129 rq->end_io_data = NULL; 130 - rq->completion_data = NULL; 131 rq->next_rq = NULL; 132 } 133 ··· 1002 } 1003 EXPORT_SYMBOL_GPL(disk_round_stats); 1004 1005 /* 1006 * queue lock must be held 1007 */ ··· 1219 1220 if (bio_sectors(bio) && bdev != bdev->bd_contains) { 1221 struct hd_struct *p = bdev->bd_part; 1222 - const int rw = bio_data_dir(bio); 1223 - 1224 - p->sectors[rw] += bio_sectors(bio); 1225 - p->ios[rw]++; 1226 1227 bio->bi_sector += p->start_sect; 1228 bio->bi_bdev = bdev->bd_contains; ··· 1546 if (blk_fs_request(req) && req->rq_disk) { 1547 const int rw = rq_data_dir(req); 1548 1549 - disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9); 1550 } 1551 1552 total_bytes = bio_nbytes = 0; ··· 1732 if (disk && blk_fs_request(req) && req != &req->q->bar_rq) { 1733 unsigned long duration = jiffies - req->start_time; 1734 const int rw = rq_data_dir(req); 1735 1736 - __disk_stat_inc(disk, ios[rw]); 1737 - __disk_stat_add(disk, ticks[rw], duration); 1738 disk_round_stats(disk); 1739 disk->in_flight--; 1740 } 1741 1742 if (req->end_io)
··· 60 return; 61 62 if (!new_io) { 63 + __all_stat_inc(rq->rq_disk, merges[rw], rq->sector); 64 } else { 65 + struct hd_struct *part = get_part(rq->rq_disk, rq->sector); 66 disk_round_stats(rq->rq_disk); 67 rq->rq_disk->in_flight++; 68 + if (part) { 69 + part_round_stats(part); 70 + part->in_flight++; 71 + } 72 } 73 } 74 ··· 102 } 103 EXPORT_SYMBOL(blk_get_backing_dev_info); 104 105 + /* 106 + * We can't just memset() the structure, since the allocation path 107 + * already stored some information in the request. 108 + */ 109 void rq_init(struct request_queue *q, struct request *rq) 110 { 111 INIT_LIST_HEAD(&rq->queuelist); 112 INIT_LIST_HEAD(&rq->donelist); 113 + rq->q = q; 114 + rq->sector = rq->hard_sector = (sector_t) -1; 115 + rq->nr_sectors = rq->hard_nr_sectors = 0; 116 + rq->current_nr_sectors = rq->hard_cur_sectors = 0; 117 rq->bio = rq->biotail = NULL; 118 INIT_HLIST_NODE(&rq->hash); 119 RB_CLEAR_NODE(&rq->rb_node); 120 + rq->rq_disk = NULL; 121 rq->nr_phys_segments = 0; 122 + rq->nr_hw_segments = 0; 123 + rq->ioprio = 0; 124 + rq->special = NULL; 125 + rq->buffer = NULL; 126 + rq->tag = -1; 127 + rq->errors = 0; 128 + rq->ref_count = 1; 129 + rq->cmd_len = 0; 130 + memset(rq->cmd, 0, sizeof(rq->cmd)); 131 + rq->data_len = 0; 132 + rq->sense_len = 0; 133 + rq->data = NULL; 134 rq->sense = NULL; 135 rq->end_io = NULL; 136 rq->end_io_data = NULL; 137 rq->next_rq = NULL; 138 } 139 ··· 986 } 987 EXPORT_SYMBOL_GPL(disk_round_stats); 988 989 + void part_round_stats(struct hd_struct *part) 990 + { 991 + unsigned long now = jiffies; 992 + 993 + if (now == part->stamp) 994 + return; 995 + 996 + if (part->in_flight) { 997 + __part_stat_add(part, time_in_queue, 998 + part->in_flight * (now - part->stamp)); 999 + __part_stat_add(part, io_ticks, (now - part->stamp)); 1000 + } 1001 + part->stamp = now; 1002 + } 1003 + 1004 /* 1005 * queue lock must be held 1006 */ ··· 1188 1189 if (bio_sectors(bio) && bdev != bdev->bd_contains) { 1190 struct hd_struct *p = bdev->bd_part; 1191 1192 bio->bi_sector += p->start_sect; 1193 bio->bi_bdev = bdev->bd_contains; ··· 1519 if (blk_fs_request(req) && req->rq_disk) { 1520 const int rw = rq_data_dir(req); 1521 1522 + all_stat_add(req->rq_disk, sectors[rw], 1523 + nr_bytes >> 9, req->sector); 1524 } 1525 1526 total_bytes = bio_nbytes = 0; ··· 1704 if (disk && blk_fs_request(req) && req != &req->q->bar_rq) { 1705 unsigned long duration = jiffies - req->start_time; 1706 const int rw = rq_data_dir(req); 1707 + struct hd_struct *part = get_part(disk, req->sector); 1708 1709 + __all_stat_inc(disk, ios[rw], req->sector); 1710 + __all_stat_add(disk, ticks[rw], duration, req->sector); 1711 disk_round_stats(disk); 1712 disk->in_flight--; 1713 + if (part) { 1714 + part_round_stats(part); 1715 + part->in_flight--; 1716 + } 1717 } 1718 1719 if (req->end_io)
+6
block/blk-merge.c
··· 454 elv_merge_requests(q, req, next); 455 456 if (req->rq_disk) { 457 disk_round_stats(req->rq_disk); 458 req->rq_disk->in_flight--; 459 } 460 461 req->ioprio = ioprio_best(req->ioprio, next->ioprio);
··· 454 elv_merge_requests(q, req, next); 455 456 if (req->rq_disk) { 457 + struct hd_struct *part 458 + = get_part(req->rq_disk, req->sector); 459 disk_round_stats(req->rq_disk); 460 req->rq_disk->in_flight--; 461 + if (part) { 462 + part_round_stats(part); 463 + part->in_flight--; 464 + } 465 } 466 467 req->ioprio = ioprio_best(req->ioprio, next->ioprio);
+22 -6
block/genhd.c
··· 584 for (n = 0; n < gp->minors - 1; n++) { 585 struct hd_struct *hd = gp->part[n]; 586 587 - if (hd && hd->nr_sects) 588 - seq_printf(s, "%4d %4d %s %u %u %u %u\n", 589 - gp->major, n + gp->first_minor + 1, 590 - disk_name(gp, n + 1, buf), 591 - hd->ios[0], hd->sectors[0], 592 - hd->ios[1], hd->sectors[1]); 593 } 594 595 return 0;
··· 584 for (n = 0; n < gp->minors - 1; n++) { 585 struct hd_struct *hd = gp->part[n]; 586 587 + if (!hd || !hd->nr_sects) 588 + continue; 589 + 590 + preempt_disable(); 591 + part_round_stats(hd); 592 + preempt_enable(); 593 + seq_printf(s, "%4d %4d %s %lu %lu %llu " 594 + "%u %lu %lu %llu %u %u %u %u\n", 595 + gp->major, n + gp->first_minor + 1, 596 + disk_name(gp, n + 1, buf), 597 + part_stat_read(hd, ios[0]), 598 + part_stat_read(hd, merges[0]), 599 + (unsigned long long)part_stat_read(hd, sectors[0]), 600 + jiffies_to_msecs(part_stat_read(hd, ticks[0])), 601 + part_stat_read(hd, ios[1]), 602 + part_stat_read(hd, merges[1]), 603 + (unsigned long long)part_stat_read(hd, sectors[1]), 604 + jiffies_to_msecs(part_stat_read(hd, ticks[1])), 605 + hd->in_flight, 606 + jiffies_to_msecs(part_stat_read(hd, io_ticks)), 607 + jiffies_to_msecs(part_stat_read(hd, time_in_queue)) 608 + ); 609 } 610 611 return 0;
+6 -6
drivers/block/aoe/aoecmd.c
··· 751 } 752 753 static inline void 754 - diskstats(struct gendisk *disk, struct bio *bio, ulong duration) 755 { 756 unsigned long n_sect = bio->bi_size >> 9; 757 const int rw = bio_data_dir(bio); 758 759 - disk_stat_inc(disk, ios[rw]); 760 - disk_stat_add(disk, ticks[rw], duration); 761 - disk_stat_add(disk, sectors[rw], n_sect); 762 - disk_stat_add(disk, io_ticks, duration); 763 } 764 765 void ··· 879 } 880 881 if (buf && --buf->nframesout == 0 && buf->resid == 0) { 882 - diskstats(d->gd, buf->bio, jiffies - buf->stime); 883 n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; 884 bio_endio(buf->bio, n); 885 mempool_free(buf, d->bufpool);
··· 751 } 752 753 static inline void 754 + diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector) 755 { 756 unsigned long n_sect = bio->bi_size >> 9; 757 const int rw = bio_data_dir(bio); 758 759 + all_stat_inc(disk, ios[rw], sector); 760 + all_stat_add(disk, ticks[rw], duration, sector); 761 + all_stat_add(disk, sectors[rw], n_sect, sector); 762 + all_stat_add(disk, io_ticks, duration, sector); 763 } 764 765 void ··· 879 } 880 881 if (buf && --buf->nframesout == 0 && buf->resid == 0) { 882 + diskstats(d->gd, buf->bio, jiffies - buf->stime, buf->sector); 883 n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; 884 bio_endio(buf->bio, n); 885 mempool_free(buf, d->bufpool);
+26 -5
fs/partitions/check.c
··· 18 #include <linux/fs.h> 19 #include <linux/kmod.h> 20 #include <linux/ctype.h> 21 22 #include "check.h" 23 ··· 216 { 217 struct hd_struct *p = dev_to_part(dev); 218 219 - return sprintf(buf, "%8u %8llu %8u %8llu\n", 220 - p->ios[0], (unsigned long long)p->sectors[0], 221 - p->ios[1], (unsigned long long)p->sectors[1]); 222 } 223 224 #ifdef CONFIG_FAIL_MAKE_REQUEST ··· 290 static void part_release(struct device *dev) 291 { 292 struct hd_struct *p = dev_to_part(dev); 293 kfree(p); 294 } 295 ··· 330 disk->part[part-1] = NULL; 331 p->start_sect = 0; 332 p->nr_sects = 0; 333 - p->ios[0] = p->ios[1] = 0; 334 - p->sectors[0] = p->sectors[1] = 0; 335 kobject_put(p->holder_dir); 336 device_del(&p->dev); 337 put_device(&p->dev); ··· 353 if (!p) 354 return; 355 356 p->start_sect = start; 357 p->nr_sects = len; 358 p->partno = part;
··· 18 #include <linux/fs.h> 19 #include <linux/kmod.h> 20 #include <linux/ctype.h> 21 + #include <linux/genhd.h> 22 23 #include "check.h" 24 ··· 215 { 216 struct hd_struct *p = dev_to_part(dev); 217 218 + preempt_disable(); 219 + part_round_stats(p); 220 + preempt_enable(); 221 + return sprintf(buf, 222 + "%8lu %8lu %8llu %8u " 223 + "%8lu %8lu %8llu %8u " 224 + "%8u %8u %8u" 225 + "\n", 226 + part_stat_read(p, ios[READ]), 227 + part_stat_read(p, merges[READ]), 228 + (unsigned long long)part_stat_read(p, sectors[READ]), 229 + jiffies_to_msecs(part_stat_read(p, ticks[READ])), 230 + part_stat_read(p, ios[WRITE]), 231 + part_stat_read(p, merges[WRITE]), 232 + (unsigned long long)part_stat_read(p, sectors[WRITE]), 233 + jiffies_to_msecs(part_stat_read(p, ticks[WRITE])), 234 + p->in_flight, 235 + jiffies_to_msecs(part_stat_read(p, io_ticks)), 236 + jiffies_to_msecs(part_stat_read(p, time_in_queue))); 237 } 238 239 #ifdef CONFIG_FAIL_MAKE_REQUEST ··· 273 static void part_release(struct device *dev) 274 { 275 struct hd_struct *p = dev_to_part(dev); 276 + free_part_stats(p); 277 kfree(p); 278 } 279 ··· 312 disk->part[part-1] = NULL; 313 p->start_sect = 0; 314 p->nr_sects = 0; 315 + part_stat_set_all(p, 0); 316 kobject_put(p->holder_dir); 317 device_del(&p->dev); 318 put_device(&p->dev); ··· 336 if (!p) 337 return; 338 339 + if (!init_part_stats(p)) { 340 + kfree(p); 341 + return; 342 + } 343 p->start_sect = start; 344 p->nr_sects = len; 345 p->partno = part;
+3 -1
include/linux/blkdev.h
··· 137 #define BLK_MAX_CDB 16 138 139 /* 140 - * try to put the fields that are referenced together in the same cacheline 141 */ 142 struct request { 143 struct list_head queuelist;
··· 137 #define BLK_MAX_CDB 16 138 139 /* 140 + * try to put the fields that are referenced together in the same cacheline. 141 + * if you modify this structure, be sure to check block/blk-core.c:rq_init() 142 + * as well! 143 */ 144 struct request { 145 struct list_head queuelist;
+142 -11
include/linux/genhd.h
··· 91 __le32 nr_sects; /* nr of sectors in partition */ 92 } __attribute__((packed)); 93 94 struct hd_struct { 95 sector_t start_sect; 96 sector_t nr_sects; 97 struct device dev; 98 struct kobject *holder_dir; 99 - unsigned ios[2], sectors[2]; /* READs and WRITEs */ 100 int policy, partno; 101 #ifdef CONFIG_FAIL_MAKE_REQUEST 102 int make_it_fail; 103 #endif 104 }; 105 ··· 126 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 127 #define GENHD_FL_FAIL 64 128 129 - struct disk_stats { 130 - unsigned long sectors[2]; /* READs and WRITEs */ 131 - unsigned long ios[2]; 132 - unsigned long merges[2]; 133 - unsigned long ticks[2]; 134 - unsigned long io_ticks; 135 - unsigned long time_in_queue; 136 - }; 137 - 138 struct gendisk { 139 int major; /* major number of driver */ 140 int first_minor; ··· 165 * The __ variants should only be called in critical sections. The full 166 * variants disable/enable preemption. 167 */ 168 #ifdef CONFIG_SMP 169 #define __disk_stat_add(gendiskp, field, addnd) \ 170 (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) ··· 198 memset(per_cpu_ptr(gendiskp->dkstats, i), value, 199 sizeof (struct disk_stats)); 200 } 201 202 #else 203 #define __disk_stat_add(gendiskp, field, addnd) \ 204 (gendiskp->dkstats.field += addnd) 205 #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) 206 207 - static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { 208 memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); 209 } 210 #endif 211 212 #define disk_stat_add(gendiskp, field, addnd) \ ··· 274 #define disk_stat_sub(gendiskp, field, subnd) \ 275 disk_stat_add(gendiskp, field, -subnd) 276 277 278 /* Inlines to alloc and free disk stats in struct gendisk */ 279 #ifdef CONFIG_SMP ··· 328 { 329 free_percpu(disk->dkstats); 330 } 331 #else /* CONFIG_SMP */ 332 static inline int init_disk_stats(struct gendisk *disk) 333 { ··· 351 static inline void free_disk_stats(struct gendisk *disk) 352 { 353 } 354 #endif /* CONFIG_SMP */ 355 356 /* drivers/block/ll_rw_blk.c */ 357 extern void disk_round_stats(struct gendisk *disk); 358 359 /* drivers/block/genhd.c */ 360 extern int get_blkdev_list(char *, int);
··· 91 __le32 nr_sects; /* nr of sectors in partition */ 92 } __attribute__((packed)); 93 94 + struct disk_stats { 95 + unsigned long sectors[2]; /* READs and WRITEs */ 96 + unsigned long ios[2]; 97 + unsigned long merges[2]; 98 + unsigned long ticks[2]; 99 + unsigned long io_ticks; 100 + unsigned long time_in_queue; 101 + }; 102 + 103 struct hd_struct { 104 sector_t start_sect; 105 sector_t nr_sects; 106 struct device dev; 107 struct kobject *holder_dir; 108 int policy, partno; 109 #ifdef CONFIG_FAIL_MAKE_REQUEST 110 int make_it_fail; 111 + #endif 112 + unsigned long stamp; 113 + int in_flight; 114 + #ifdef CONFIG_SMP 115 + struct disk_stats *dkstats; 116 + #else 117 + struct disk_stats dkstats; 118 #endif 119 }; 120 ··· 111 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 112 #define GENHD_FL_FAIL 64 113 114 + 115 struct gendisk { 116 int major; /* major number of driver */ 117 int first_minor; ··· 158 * The __ variants should only be called in critical sections. The full 159 * variants disable/enable preemption. 160 */ 161 + static inline struct hd_struct *get_part(struct gendisk *gendiskp, 162 + sector_t sector) 163 + { 164 + struct hd_struct *part; 165 + int i; 166 + for (i = 0; i < gendiskp->minors - 1; i++) { 167 + part = gendiskp->part[i]; 168 + if (part && part->start_sect <= sector 169 + && sector < part->start_sect + part->nr_sects) 170 + return part; 171 + } 172 + return NULL; 173 + } 174 + 175 #ifdef CONFIG_SMP 176 #define __disk_stat_add(gendiskp, field, addnd) \ 177 (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) ··· 177 memset(per_cpu_ptr(gendiskp->dkstats, i), value, 178 sizeof (struct disk_stats)); 179 } 180 + 181 + #define __part_stat_add(part, field, addnd) \ 182 + (per_cpu_ptr(part->dkstats, smp_processor_id())->field += addnd) 183 + 184 + #define __all_stat_add(gendiskp, field, addnd, sector) \ 185 + ({ \ 186 + struct hd_struct *part = get_part(gendiskp, sector); \ 187 + if (part) \ 188 + __part_stat_add(part, field, addnd); \ 189 + __disk_stat_add(gendiskp, field, addnd); \ 190 + }) 191 + 192 + #define part_stat_read(part, field) \ 193 + ({ \ 194 + typeof(part->dkstats->field) res = 0; \ 195 + int i; \ 196 + for_each_possible_cpu(i) \ 197 + res += per_cpu_ptr(part->dkstats, i)->field; \ 198 + res; \ 199 + }) 200 + 201 + static inline void part_stat_set_all(struct hd_struct *part, int value) { 202 + int i; 203 + for_each_possible_cpu(i) 204 + memset(per_cpu_ptr(part->dkstats, i), value, 205 + sizeof(struct disk_stats)); 206 + } 207 208 #else 209 #define __disk_stat_add(gendiskp, field, addnd) \ 210 (gendiskp->dkstats.field += addnd) 211 #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) 212 213 + static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) 214 + { 215 memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); 216 } 217 + 218 + #define __part_stat_add(part, field, addnd) \ 219 + (part->dkstats.field += addnd) 220 + 221 + #define __all_stat_add(gendiskp, field, addnd, sector) \ 222 + ({ \ 223 + struct hd_struct *part = get_part(gendiskp, sector); \ 224 + if (part) \ 225 + part->dkstats.field += addnd; \ 226 + __disk_stat_add(gendiskp, field, addnd); \ 227 + }) 228 + 229 + #define part_stat_read(part, field) (part->dkstats.field) 230 + 231 + static inline void part_stat_set_all(struct hd_struct *part, int value) 232 + { 233 + memset(&part->dkstats, value, sizeof(struct disk_stats)); 234 + } 235 + 236 #endif 237 238 #define disk_stat_add(gendiskp, field, addnd) \ ··· 206 #define disk_stat_sub(gendiskp, field, subnd) \ 207 disk_stat_add(gendiskp, field, -subnd) 208 209 + #define part_stat_add(gendiskp, field, addnd) \ 210 + do { \ 211 + preempt_disable(); \ 212 + __part_stat_add(gendiskp, field, addnd);\ 213 + preempt_enable(); \ 214 + } while (0) 215 + 216 + #define __part_stat_dec(gendiskp, field) __part_stat_add(gendiskp, field, -1) 217 + #define part_stat_dec(gendiskp, field) part_stat_add(gendiskp, field, -1) 218 + 219 + #define __part_stat_inc(gendiskp, field) __part_stat_add(gendiskp, field, 1) 220 + #define part_stat_inc(gendiskp, field) part_stat_add(gendiskp, field, 1) 221 + 222 + #define __part_stat_sub(gendiskp, field, subnd) \ 223 + __part_stat_add(gendiskp, field, -subnd) 224 + #define part_stat_sub(gendiskp, field, subnd) \ 225 + part_stat_add(gendiskp, field, -subnd) 226 + 227 + #define all_stat_add(gendiskp, field, addnd, sector) \ 228 + do { \ 229 + preempt_disable(); \ 230 + __all_stat_add(gendiskp, field, addnd, sector); \ 231 + preempt_enable(); \ 232 + } while (0) 233 + 234 + #define __all_stat_dec(gendiskp, field, sector) \ 235 + __all_stat_add(gendiskp, field, -1, sector) 236 + #define all_stat_dec(gendiskp, field, sector) \ 237 + all_stat_add(gendiskp, field, -1, sector) 238 + 239 + #define __all_stat_inc(gendiskp, field, sector) \ 240 + __all_stat_add(gendiskp, field, 1, sector) 241 + #define all_stat_inc(gendiskp, field, sector) \ 242 + all_stat_add(gendiskp, field, 1, sector) 243 + 244 + #define __all_stat_sub(gendiskp, field, subnd, sector) \ 245 + __all_stat_add(gendiskp, field, -subnd, sector) 246 + #define all_stat_sub(gendiskp, field, subnd, sector) \ 247 + all_stat_add(gendiskp, field, -subnd, sector) 248 249 /* Inlines to alloc and free disk stats in struct gendisk */ 250 #ifdef CONFIG_SMP ··· 221 { 222 free_percpu(disk->dkstats); 223 } 224 + 225 + static inline int init_part_stats(struct hd_struct *part) 226 + { 227 + part->dkstats = alloc_percpu(struct disk_stats); 228 + if (!part->dkstats) 229 + return 0; 230 + return 1; 231 + } 232 + 233 + static inline void free_part_stats(struct hd_struct *part) 234 + { 235 + free_percpu(part->dkstats); 236 + } 237 + 238 #else /* CONFIG_SMP */ 239 static inline int init_disk_stats(struct gendisk *disk) 240 { ··· 230 static inline void free_disk_stats(struct gendisk *disk) 231 { 232 } 233 + 234 + static inline int init_part_stats(struct hd_struct *part) 235 + { 236 + return 1; 237 + } 238 + 239 + static inline void free_part_stats(struct hd_struct *part) 240 + { 241 + } 242 #endif /* CONFIG_SMP */ 243 244 /* drivers/block/ll_rw_blk.c */ 245 extern void disk_round_stats(struct gendisk *disk); 246 + extern void part_round_stats(struct hd_struct *part); 247 248 /* drivers/block/genhd.c */ 249 extern int get_blkdev_list(char *, int);